Summary
The create-vale-rule recipe leads an author straight into a rule that is green on verify, green on test, and catches zero real violations — because in markdown Vale skips code spans and fenced blocks by default, and a rule about a shell command is a rule about text that is almost always inside one.
What happened
Authoring docs-npx-cli (flag pnpm dlx @taskless/cli, prefer npx @taskless/cli) by following the recipe:
- Wrote the
substitution rule and fixtures per the worked examples. verify ok, test ok.
check against the real repository: zero findings, despite two READMEs containing the exact string — both inside ```bash blocks.
- Probed with a fixture holding the same command in three forms. Measured, with no
scope: inline code not flagged, fenced block not flagged, plain prose flagged.
scope: raw, scope: code, and scope: text each alone still missed at least one form. Only scope: [raw, code, text] caught all three — and then the two real violations surfaced.
Why the recipe does not prevent this
It does say "URLs and code spans are not prose" under the markup notes, which is accurate. But:
- It is framed as a false-positive protection ("your rule won't fire on
`Github/docs`"), not as the false-negative it becomes when the rule's whole subject is a command.
- None of the nine worked rules is about a command, a flag, or a package name, so there is no example to copy for the case.
- The step-1 table routes "preferring one term over another" to
substitution with no scope guidance, and scope is introduced later as a way to narrow, never to widen into code.
- The fixture advice ("the
pass/ fixture must contain the same phrase outside that place") catches over-firing. Nothing prompts the author to put the phrase in a code span in fail/, which is what would have caught this.
The result is a rule that passes every local gate and is inert.
Suggested change
Add a worked rule for the command/identifier case — the one where a multi-scope value is required:
extends: substitution
message: "Use '%s' instead of '%s'"
level: error
scope: [raw, code, text]
swap:
'pnpm dlx @taskless/cli': npx @taskless/cli
With the "goes wrong" line the other nine have: omitting the scope. Measured, the rule then passes its fixtures and reports nothing on a real repository, because every command in a README is in a code span or a fenced block.
Worth pairing with a fixture instruction: when a rule is about something that normally appears in code, the fail/ document must contain it inline, fenced, and in prose. That is the check that would have caught this before it shipped.
🤖 Generated with Claude Code
https://claude.ai/code/session_017cEN93Acyp4zBwP3oDnyy1
Summary
The
create-vale-rulerecipe leads an author straight into a rule that is green onverify, green ontest, and catches zero real violations — because in markdown Vale skips code spans and fenced blocks by default, and a rule about a shell command is a rule about text that is almost always inside one.What happened
Authoring
docs-npx-cli(flagpnpm dlx @taskless/cli, prefernpx @taskless/cli) by following the recipe:substitutionrule and fixtures per the worked examples.verifyok,testok.checkagainst the real repository: zero findings, despite two READMEs containing the exact string — both inside```bashblocks.scope: inline code not flagged, fenced block not flagged, plain prose flagged.scope: raw,scope: code, andscope: texteach alone still missed at least one form. Onlyscope: [raw, code, text]caught all three — and then the two real violations surfaced.Why the recipe does not prevent this
It does say "URLs and code spans are not prose" under the markup notes, which is accurate. But:
`Github/docs`"), not as the false-negative it becomes when the rule's whole subject is a command.substitutionwith no scope guidance, andscopeis introduced later as a way to narrow, never to widen into code.pass/fixture must contain the same phrase outside that place") catches over-firing. Nothing prompts the author to put the phrase in a code span infail/, which is what would have caught this.The result is a rule that passes every local gate and is inert.
Suggested change
Add a worked rule for the command/identifier case — the one where a multi-scope value is required:
With the "goes wrong" line the other nine have: omitting the scope. Measured, the rule then passes its fixtures and reports nothing on a real repository, because every command in a README is in a code span or a fenced block.
Worth pairing with a fixture instruction: when a rule is about something that normally appears in code, the
fail/document must contain it inline, fenced, and in prose. That is the check that would have caught this before it shipped.🤖 Generated with Claude Code
https://claude.ai/code/session_017cEN93Acyp4zBwP3oDnyy1