MAX_WORDS=2900 was calibrated to the corpus median density and carried no
margin: at the densest observed 7.22 chars/word (~1.81 tokens/word) it permits
~5,240 tokens against the 5,000 it proxies for. 2770 holds the worst observed
density under the ceiling. The largest SKILL.md is 2,489 words, so the change
costs nothing today — 281 words of margin — and the header comment now argues
the new calibration rather than swapping the digits.
Both enforcement points move together, and a new test asserts they agree, since
a SKILL.md passing its own audit while the commit hook blocks it is the
disagreement this pair exists to prevent.
CONTEXT.md is deliberately left ungated: it is 2,816 words, and gating it would
block the build. Recorded here so the omission reads as a decision rather than
an oversight.
skill-audit's manual-fallback path listed only the line ceiling, so an agent
taking that path passed an oversized SKILL.md the hook then rejected. The word
ceiling is now named alongside it. agent-audit is deliberately unchanged: the
size hook scopes to SKILL.md only and agent-audit's validate.sh has no word
gate, so claiming it there would be false.
The Vale research doc still showed the MDX {/* vale off */} form under a
Markdown heading, contradicting CONTEXT.md and vale-run's troubleshooting
reference — that form suppresses nothing in plain .md. Fixed in both places it
appeared.
tests/run-tests.sh used mapfile (bash 4.0+) with unguarded array expansion,
though AGENTS.md tells contributors to run it and macOS ships bash 3.2. It now
collects via a while-read loop over process substitution and guards every
expansion. The newline-delimited find|sort pipeline is kept rather than -print0
with sort -z, whose BSD portability is the weaker link, and which matches
mapfile -t's previous behaviour exactly.
Refs: #85
ADR: 0013
2.4 KiB
topic, source_keys
| topic | source_keys | |
|---|---|---|
| troubleshooting |
|
Suppressing False Positives Inline
Vale supports inline markup comments to disable checks for a section of content. Syntax varies by format:
Markdown — HTML comments; the MDX {/* */} form suppresses nothing in a plain .md file:
<!-- vale off -->
This text will be ignored.
<!-- vale on -->
MDX:
{/* vale off */}
This text will be ignored.
{/* vale on */}
Org mode:
# vale off
This text will be ignored.
# vale on
Disabling a Specific Rule for Specific Matches
Rather than disabling all checks, target one rule and specific known-exception strings, then re-enable. Same per-format comment syntax as above — Markdown:
<!-- vale Style.Redundancy["ACT test","OTHER"] = NO -->
This is some text ACT test
<!-- vale Style.Redundancy["ACT test","OTHER"] = YES -->
MDX:
{/* vale Style.Redundancy["ACT test","OTHER"] = NO */}
This is some text ACT test
{/* vale Style.Redundancy["ACT test","OTHER"] = YES */}
This is the preferred fix for recurring false positives on specific terms — it keeps the rule active everywhere else instead of disabling it project-wide.
Ignoring Words in Spell Check
The spelling check accepts an ignore list of external plain-text files, so known project-specific terms don't need touching the dictionary:
extends: spelling
message: "Did you really mean '%s'?"
level: error
ignore:
- ignore1.txt
- ignore2.txt
Plain-Text Fallback
If a file's syntax-aware parsing produces noisy/incorrect results (e.g. an unsupported or malformed format), rerun with --ignore-syntax to treat it as plain text instead of relying on the format-specific parser.
CI Failing Unexpectedly
If a CI job fails solely because Vale returns a non-zero exit code on error-level alerts (not because the content is actually wrong for that pipeline stage), add --no-exit rather than suppressing the rule itself — this preserves the lint output while not gating the build on it. Raising MinAlertLevel is not an alternative: it only filters which alerts print, so an error-level alert still exits non-zero.
The mirror-image failure is a Vale gate that never fails. Only error-level alerts drive the exit code, so a warning- or suggestion-level rule prints its alert and still exits 0 — invisible in any CI stage that hides passing output. If a rule must block, give it level: error.