This guide is for whoever decides what the standard is. A rule is a section of the English standard, imported into the analyzer and translated from there. Nothing is copied into a project, so a rule written today is the rule every connected assistant reads tomorrow, with nobody updating anything on their side.
1. Write the rule in English
The standards live in docs/coding-standards/en/, one file per standard. Add your rule as a heading under ## Rules, in the file it belongs to.
Write three things:
- A name short enough to read in a finding, because that is where it appears.
- What it checks, in one or two sentences, stated as an instruction.
- Why it exists. A rule with no reason cannot be argued with, so it gets worked around instead of followed.
Then show the wrong code and the correct code, in that order. Most of a rule's usefulness to a reader is in that example.
When the automated check is narrower than the wording — it reports one shape of the mistake and not another — say so inside the rule. A reader who knows what the check covers stops expecting the rest to be caught for them.
2. Mark a section that is not a rule
A standard also holds sections a reader needs and no check can ever run: a chapter introduction, a restatement of a rule written elsewhere, a note about what not to report. Mark those with a comment and the import leaves them out:
<!-- not-a-rule -->
The section stays in the standard and stays on the public page. It simply never becomes a rule with a verdict attached to it.
3. Import it
php artisan get:analyzers
The import reads every standard and syncs the rules against it: what was created, what changed, and what no longer exists in the Markdown and was therefore removed.
To see that list without writing anything:
php artisan get:analyzers --dry-run
4. Give it a check, or accept that it is read and not run
A rule is analysed only when a deterministic check can decide it from the file in front of it. The import reports the rest as waiting for a rule class: they stay published and readable, and they never produce a finding.
That is a real state and not a failure. Some rules can be proven from one file and some cannot, and the four that never can are in What the analyzer cannot check.
What is never acceptable is reporting a rule read by a person as an analyzer pass. They are different things and are reported as different things.
5. Try the check against real files
Before a new or changed check reaches anyone, see what it would have said about files the analyzer has already judged. In the admin panel, open Rule automation lab in the side menu (/admin/rule_automation_lab). It lists only rules that are linked to a check class that exists; Automation type narrows them to the classes with process(), with preprocess(), or with both, and Rule type and Rule pick the one to try.
The page shows the class linked to the rule, the rule's text, and how often the rule has run, passed and failed so far. Under Real examples it picks up to twenty different files from the history, balanced between runs that passed and runs that failed and spread across time. Test examples runs the current class over each of them and puts its verdict beside the one recorded at the time: Original status, Test status, and Match — Yes when they agree, No when they do not, and Not applicable when the class did not decide. Open a file to compare the original response with the replay, and to see what preprocess() kept of it.
A No is worth reading before you ship the check: either the old verdict was wrong, or the new class is. Nothing is saved by the test, so run it as often as you change the class.
6. Translate it
php artisan standards:translate
Every translated rule carries a fingerprint of the English it came from, so a run only translates what is new or what has changed since the last one. Narrow it to a single standard with --type="Laravel Models", translate everything again with --force, or see what would happen with --dry-run.
Then verify the result:
php artisan standards:check
It lists every rule that is missing, outdated, or left over from an English rule that no longer exists. It compares fingerprints instead of asking a model, so it costs nothing and can run on every commit.
7. Correcting a translation
Rewording the Spanish so it reads like it was written rather than translated is welcome. Changing what it states is not: the two languages are one rule, and a reader has no way to tell which version is true when they disagree.
When the content itself has to change, change the English and translate again. The source moves first, always. A rule corrected by hand is reported by the check. The next translation keeps it as long as its English has not changed; it is replaced only when the English moves or when you translate again with --force, and the command then names every hand correction it replaced.
8. Sweep what already exists
A new rule almost always finds something in code written before it. Run it over everything before you announce it:
php artisan validate:project --rule="Meaningful Scopes"
That walks the project it runs in and reports the files the rule touches, with --all to list the passing ones too and --fresh to evaluate every rule again instead of reusing a stored verdict. In another project the sweep belongs to your assistant: point it at the area the rule covers and have it check each file, as described in Analyse a file.
9. Changing a rule that already exists
The same path, in the same order: edit the English, import, translate, check. The fingerprint marks the translation as outdated the moment the English moves, so nothing depends on you remembering which rules you touched.
A rule that fires on correct code, or stays silent on code it should catch, is a defect in the rule rather than something for each project to work around. Fix it at the source and every project gets the corrected rule on its next call.
