Files
holocron/plugins/lint/skills/vale-run/references/troubleshooting.md
Defame1297 149d564f6a fix(lint): make the Vale gate actually gate, drop VagueQualifier
Round-3 review of PR #85 found the "enforcing" pre-commit hook enforced
nothing. Vale's exit code keys on error-level alerts alone: five of the
six rules were level: warning, so they exited 0, and pre-commit hides
output from a passing hook — the alerts were invisible and blocked
nothing. ADR-0013 rejected a report-only trial tier and then shipped one
by accident.

Flatten every rule to level: error. Vale's own exit code is then correct,
so the hook entry drops to a bare vale-wrap.sh call and the graded
error->FAIL / warning->SUGGESTION mapping disappears from both audit
skills: every alert is a FAIL, in the gate and the audit alike. No
ignorable tier, matching shellcheck, the test suite and
conventional-pre-commit.

Delete Kyberforge.VagueQualifier. Measured against the 41 skill/agent
files as they stood before the rule ever ran: 2 hits. One marginal
("very different" -> "fundamentally different"), one an unfixable false
positive — caveman/SKILL.md quotes "of course" as an example of filler,
a mention not a use — which forced the only Vale suppression comments in
the repo. Those four lines go with it; two of them were dead anyway,
suppressing a frontmatter-scoped rule on a body line. Held-out prose (273
files) fired 15 times, 9 inside out-of-scope research examples and the
rest one word in two idioms in a single doc. SentenceOpenerThereIs
survives: 22 held-out hits, both in-corpus hits clean rewrites, zero
suppressions.

Widen .vale.ini's globs to [**/SKILL.md], [**/agents/*.md] and
[**/*.agent.md]. The plugins/*/-prefixed globs scoped nothing — Vale's *
crosses /, so they already matched docs/research/examples/**/agents/*.md
and assets/templates/SKILL.md, the two paths CONTEXT.md claimed they
excluded. Scoping is and was the hook's files: regex. The old globs also
hid a silent false negative: a skill outside plugins/ matched no section,
so Vale reported 0 files and exited 0, which both audits read as clean.
They now treat a 0-file run as NOT RUN and fall back to full judgment.

Also:
- vale-wrap.sh resolves relative --config values and file arguments
  against the caller's cwd, as vale does, instead of the repo root, which
  hard-errored from a subdirectory and silently skipped flattening for
  file args that did not resolve from the root. Absolute paths inside the
  cwd are relativized so reports cite resolvable paths, not scratch ones.
- vale-run's exit-code model was documented backwards ("exits non-zero
  whenever it finds an alert at or above MinAlertLevel") and would have
  led anyone following it to build a gate that passes everything. Its
  Markdown suppression syntax was MDX-only and does not suppress in .md;
  corrected in the skill and its troubleshooting reference, with
  backtick/fence exemption documented as the first resort.
- skill-size-check.sh fails only above 500 lines, agreeing with
  skill-audit's validate.sh <= 500 pass.
- ADR-0013 and CONTEXT.md amended to match, recording why graded
  severities cannot gate.

Verified: 9 test scripts / 15 vale-wrap cases pass; vale-audit-prefilter,
skill-size-check and shellcheck pass --all-files; check-manifests and
claude plugin validate --strict clean. New tests fail against the old
script (3 of them) and pass against the new one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MCQ648fLSFXPHGZdQ8gn58
2026-08-08 20:42:15 +00:00

3.2 KiB

source_keys
source_keys
context7-websites-vale-sh

Vale troubleshooting reference

Inline suppression syntax by format

Markdown uses HTML comments — the MDX {/* */} form does not suppress anything 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

Targets one rule and specific known-exception strings, then re-enables — the preferred fix for a recurring false positive on a specific term, since it keeps the rule active everywhere else:

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 */}

Ignoring words in spell check

The spelling check accepts an ignore list of external plain-text files, so 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 or incorrect results (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

Only error-level alerts make Vale exit non-zero; warning and suggestion alerts are printed but exit 0. If a CI job fails solely because of 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. If the alerts are warnings or suggestions, Vale did not fail the job — look elsewhere.

pre-commit integration

Vale ships a pre-commit hook definition. A typical setup runs vale sync once (with pass_filenames: false) plus the actual lint pass with CI-appropriate flags:

repos:
  - repo: https://github.com/errata-ai/vale
    rev: 16d3a7f
    hooks:
      - id: vale
        name: vale sync
        pass_filenames: false
        args: [sync]
      - id: vale
        args: [--output=line, --minAlertLevel=error]

If the project has documented a wrapper script for a known Vale scope/escaping limitation (see the Gotchas section of SKILL.md), point the second hook's entry: at that wrapper instead of at bare vale, even though the hook's repo/rev/id still come from the upstream definition above — only the invocation target changes:

      - id: vale
        entry: <path-to-project-wrapper>
        args: [--output=line, --minAlertLevel=error]

Using the upstream hook's bare vale entry in a project that has such a wrapper reintroduces exactly the bug the wrapper exists to fix.

CI output for machine parsing

$ vale --output=JSON README.md

Use --output=JSON when a CI step needs to parse results programmatically rather than read the default CLI-formatted output.