Methodology
How rules were chosen
- Each lint rule reads the rules file text only. No agent is run and no repository is read; R006 is the exception and runs only in the GitHub App, where the repository is available.
- Each rule is run against a corpus of 755 public rules files in 7 formats. Its false-positive rate is measured by two judges; see Measured false-positive rates.
- Thresholds (line counts, word counts, ratios) are fixed constants in the rule code and apply to every file the same way.
Severities
| Severity | Cost per finding | Meaning | Rules |
|---|---|---|---|
| Error | −10 | The file is broken or unsafe as written: an instruction contradicts another, a secret is exposed, or markup swallows the rest of the file. | R003, R009, R012 |
| Warning | −4 | An instruction or structure the agent cannot act on reliably: vague or hedged wording, repetition, length, emphasis, empty sections, frontmatter Cursor ignores, references that do not exist. | R002, R004, R005, R006, R007, R008, R011, R015 |
| Info | −1 | Text that is not an instruction: rationale, persona, long prose, references to unnamed context. | R001, R010, R013, R014, R016 |
Every file starts at 100. Each finding costs points by severity: Error 10, Warning 4, Info 1. One rule costs at most 30. Total costs per severity are capped: Error 40, Warning 30, Info 10. The lowest possible score is 20. Grades: A ≥ 90, B ≥ 80, C ≥ 70, D ≥ 60, F below 60.
Why R001 penalises rationale prose
An agent follows an instruction. It doesn't need to agree with it. When a rule carries its reason, the agent has something to weigh the rule against, and sometimes it decides the reason no longer applies and "fixes" the constraint. I've watched that happen. The reason belongs in a commit message or a design note, where a human reads it; the rules file gets the rule.
Thresholds
Corpus hit rates are from the 755-file corpus with ruleset v4.
| Rule | Threshold | Corpus files flagged |
|---|---|---|
| R004 FileLength | More than 200 lines | 116 of 755 (15.4%) |
| R008 EmphasisInflation | More than 5 emphasis lines per 100 lines, at least 3 allowed | 16 of 755 (2.1%) |
| R013 ProseParagraph | A paragraph of more than 80 words | 52 of 755 (6.9%) |
Why these thresholds
R004, 200 lines
Rules files are read in full on every turn, so every line competes with the task for the agent's attention. Past about 200 lines, mine stopped being followed consistently, and the lines nobody follows are the ones that get stale first. The number is a judgment, not a measurement: it's where I noticed the drop. Split by concern if you need more.
R008, emphasis
If every third line is IMPORTANT, none of them is. Emphasis works by contrast. The limit is set so that a file can shout about the few things that matter and still have those lines stand out. A file written in RFC 2119 keywords is exempt because those words are a vocabulary there, not volume.
R013, paragraphs
An instruction in a paragraph is an instruction the agent has to find. Lists are scanned; prose is read, and reading is where things get skipped. Eighty words is roughly where a paragraph stops being one instruction with context and starts being several instructions hiding in each other.
Measured false-positive rates
- Corpus: 755 rules files from public GitHub repositories, fetched 2026-10-03: 150 CLAUDE.md, 150 AGENTS.md, 147 GEMINI.md, 126 Copilot instructions, 119 Cursor .mdc, 45 .cursorrules, 18 .windsurfrules. One file per repository per format.
- Sample: up to 30 findings per rule, at most 2 per file, spread across formats. Rules with fewer findings: all of them.
- Two judges: judge A, and judge B, a separate model without access to judge A's verdicts. A finding is a true positive when it is what the rule's summary describes, on text the rule applies to.
- R001, R002, R005, R007 and R013 apply to instructions only. Descriptive prose, pasted documentation and project descriptions are never true positives.
- Ruleset v4 rates are the ruleset v3 sample re-scored for the findings v4 still reports. Rules unchanged since ruleset v2 show their v2 measurement.
- Judge agreement at ruleset v4: 140 of 149 findings (94.0%), Cohen's kappa 0.84.
| Rule | Judge A | Judge B | Sample | Ruleset |
|---|---|---|---|---|
| R001 RationaleProse | 14 of 30 | 12 of 30 | 30 | v4 |
| R002 VagueVerbs | 11 of 30 | 12 of 30 | 30 | v4 |
| R003 ContradictoryModals | Not measured: no findings in the 755-file corpus. | |||
| R004 FileLength | 0 of 30 | 0 of 30 | 30 | v2 |
| R005 DuplicateLines | 1 of 6 | 1 of 6 | 6 | v4 |
| R006 MissingIdentifiers | Not measured per finding (App-only; judged per file in field note 1). | |||
| R007 HedgedInstructions | 4 of 30 | 6 of 30 | 30 | v4 |
| R008 EmphasisInflation | 1 of 16 | 5 of 16 | 16 | v4 |
| R009 SecretsInRulesFile | Not measured: no findings in the 755-file corpus. | |||
| R010 PersonaPreamble | 0 of 14 | 1 of 14 | 14 | v2 |
| R011 EmptySections | 0 of 7 | 0 of 7 | 7 | v4 |
| R012 UnclosedCodeFence | 0 of 1 | 0 of 1 | 1 | v2 |
| R013 ProseParagraph | 4 of 30 | 4 of 30 | 30 | v4 |
| R014 UnverifiableCrossReference | 0 of 2 | 0 of 2 | 2 | v2 |
| R015 FrontmatterFields | 0 of 10 | 0 of 10 | 10 | v2 |
| R016 ManualCursorRule | 0 of 7 | 0 of 7 | 7 | v2 |