--- name: infer-conventions description: "Use this skill to analyze how a Laravel application is actually written and record its conventions as shared rules. Trigger when the user wants to detect, infer, document, or standardize project conventions or coding style, set up or grow ___SINGLE_BACKTICK___.ai/rules___SINGLE_BACKTICK___, resolve mixed or conflicting patterns (e.g. \"are we using Form Requests or inline validation?\"), or onboard agents and teammates to \"how we do things here\". Covers: a systematic sweep of ~49 Laravel convention dimensions (validation, models, architecture, testing, frontend, database, console), open-ended house-pattern discovery, conflict reporting, and recording rules scoped to the right paths via the Boost ___SINGLE_BACKTICK___record-rule___SINGLE_BACKTICK___ MCP tool. Do not use for one-off code review, enforcing formatting a linter already handles, or editing ___SINGLE_BACKTICK___.ai/rules___SINGLE_BACKTICK___ files by hand." license: MIT metadata: author: laravel --- # Infer Conventions Learn how this application writes Laravel, then record what you learn as durable, path-scoped rules other agents will read. You are documenting reality, not improving it. ## Ground Rules (read before you start) - Consistency first. The codebase's majority style is the convention. Never judge it, never propose a "better" pattern, never record what the code should do. If the app validates inline everywhere, that is the rule, even if Form Requests would be nicer. - Skip what an active tool produces, keep what a tool would fight. Inspect the project's Pint and Rector configuration first; a Rector transformation is tooling-owned only when its package and relevant rule or set are installed and enabled. Active tools may rewrite code toward one canonical form: ___SINGLE_BACKTICK___$casts___SINGLE_BACKTICK___ to ___SINGLE_BACKTICK___casts()___SINGLE_BACKTICK___, ___SINGLE_BACKTICK___$fillable___SINGLE_BACKTICK___ to attributes, magic accessors to the ___SINGLE_BACKTICK___Attribute___SINGLE_BACKTICK___ class, pipe-string rules to arrays, ___SINGLE_BACKTICK___$signature___SINGLE_BACKTICK___ to ___SINGLE_BACKTICK___#[Signature]___SINGLE_BACKTICK___, named migrations to anonymous, and many more. When the app already sits at an active tool's target form, the tool owns it, so record nothing. But when the app deliberately holds a form an active tool would refactor away, such as legacy ___SINGLE_BACKTICK___getXxxAttribute()___SINGLE_BACKTICK___ accessors the ___SINGLE_BACKTICK___Attribute___SINGLE_BACKTICK___ class would replace, no tool can reproduce that choice and an agent defaults the other way. That against-the-grain hold is exactly what to record. - Record decisions, not defaults. A consistent pattern earns a rule only when it reflects a choice: the app took one valid option where the framework or common practice offered others, or the pattern would surprise a competent agent. Framework defaults steer nothing, so skip them: anonymous migrations, ___SINGLE_BACKTICK___$signature___SINGLE_BACKTICK___ commands, ___SINGLE_BACKTICK___ShouldQueue___SINGLE_BACKTICK___ jobs, ___SINGLE_BACKTICK___casts()___SINGLE_BACKTICK___ on Laravel 11+, named routes, Rule objects in ___SINGLE_BACKTICK___app/Rules___SINGLE_BACKTICK___, and ___SINGLE_BACKTICK___Mail::fake()___SINGLE_BACKTICK___ or ___SINGLE_BACKTICK___Bus::fake()___SINGLE_BACKTICK___ to isolate framework services. A real fork is not enough on its own. Weigh the side the app took, and record only the side an agent would not reach for by itself: inline closures everywhere, legacy accessors, a bespoke query layer. Watch for the false fork too. "No Mockery" next to facade fakes is not a choice against Mockery, because they double different things. The test for every candidate: without this rule, would the next agent plausibly write it differently? Only "yes" earns a rule. - Architecture choices are the gold. Record presence and deliberate absence. The structural pattern the app commits to is the highest-signal convention and the one no tool can decide: Action classes and how they are invoked (___SINGLE_BACKTICK___handle___SINGLE_BACKTICK___ / ___SINGLE_BACKTICK___execute___SINGLE_BACKTICK___ / ___SINGLE_BACKTICK_____invoke___SINGLE_BACKTICK___), service objects, dedicated query objects exposing ___SINGLE_BACKTICK___builder()___SINGLE_BACKTICK___, DTOs (spatie/laravel-data vs readonly classes), Form Request validation vs inline, an events and listeners spine vs direct calls, and domain or module folders. Also record a consistent non-pattern, such as "query Eloquent directly in controllers, no repository layer", so the next agent matches the app's altitude instead of over-engineering. - Never duplicate ___SINGLE_BACKTICK___.ai/rules___SINGLE_BACKTICK___. Read ___SINGLE_BACKTICK___.ai/rules/index.md___SINGLE_BACKTICK___ and the area files before the sweep. A dimension already covered there is marked done and skipped. - Evidence or silence. A convention needs at least 3 consistent examples and no meaningful rival to become a candidate. Every Step 1 verdict applies this bar. - The recorded rule states the convention, nothing else. One or two imperative lines: this project does X, so do X here. Keep detection evidence out. No counts, ratios, current usage, file lists, or example paths, because that is proof for the confirm step, not part of the rule. One short syntax fragment at most, and point to ___SINGLE_BACKTICK___search-docs___SINGLE_BACKTICK___ for API details. ## Process Each step ends on a checkable completion criterion. Do not advance until it holds. Fan out when you can. The sweep is embarrassingly parallel. If your environment can spawn subagents (a Task, dispatch, or equivalent tool), do Step 0 yourself, then hand each checklist group (A to J) and the architecture map to its own subagent. Each subagent runs the greps, reads a few representative files, and returns structured verdicts (dimension, verdict, evidence, proposed glob / title / note). You aggregate, dedupe, then run Steps 3 to 5. It is far faster on a real app. No subagents available? Run the steps in sequence, with the same bar and the same output. ### Step 0: Orient Read ___SINGLE_BACKTICK___composer.json___SINGLE_BACKTICK___ (installed packages tell you which checklist groups apply), the ___SINGLE_BACKTICK___pint.json___SINGLE_BACKTICK___ / PHPStan / Rector config, ___SINGLE_BACKTICK___.ai/rules/index.md___SINGLE_BACKTICK___ if present, and most important, map the ___SINGLE_BACKTICK___app/___SINGLE_BACKTICK___ tree. List every directory under ___SINGLE_BACKTICK___app/___SINGLE_BACKTICK___ (and any ___SINGLE_BACKTICK___Modules/___SINGLE_BACKTICK___, ___SINGLE_BACKTICK___src/___SINGLE_BACKTICK___, ___SINGLE_BACKTICK___packages/___SINGLE_BACKTICK___, or domain root). Every folder beyond Laravel's default skeleton (___SINGLE_BACKTICK___Http___SINGLE_BACKTICK___, ___SINGLE_BACKTICK___Models___SINGLE_BACKTICK___, ___SINGLE_BACKTICK___Providers___SINGLE_BACKTICK___, ___SINGLE_BACKTICK___Console___SINGLE_BACKTICK___, ___SINGLE_BACKTICK___Exceptions___SINGLE_BACKTICK___) is a structural pattern the app committed to and a high-value rule waiting to be written: ___SINGLE_BACKTICK___Actions___SINGLE_BACKTICK___, ___SINGLE_BACKTICK___Services___SINGLE_BACKTICK___, ___SINGLE_BACKTICK___Data___SINGLE_BACKTICK___ or DTOs, ___SINGLE_BACKTICK___Queries___SINGLE_BACKTICK___, ___SINGLE_BACKTICK___Repositories___SINGLE_BACKTICK___, ___SINGLE_BACKTICK___ViewModels___SINGLE_BACKTICK___, ___SINGLE_BACKTICK___Pipelines___SINGLE_BACKTICK___, ___SINGLE_BACKTICK___Support___SINGLE_BACKTICK___, ___SINGLE_BACKTICK___Enums___SINGLE_BACKTICK___, ___SINGLE_BACKTICK___Contracts___SINGLE_BACKTICK___, ___SINGLE_BACKTICK___Observers___SINGLE_BACKTICK___, or ___SINGLE_BACKTICK___Domain___SINGLE_BACKTICK___ and module roots. Note each one. You will confirm how it is used in Step 2.