# Vale - Prose Linting for Docs and Vaults
Vale output from an editor or agent hook depends on the checkout, the config, and the path form. Treat advisory findings as unverified until you re-run the authoritative linter. On an Obsidian vault, Vale fails first on malformed frontmatter and person names. Fix the YAML parse and the vocabulary before you touch prose.
## Key points
- Vale per-path config sections match relative paths only. A hook that passes absolute paths checks nothing and reports zero alerts. Zero alerts mean a silent skip, not clean prose. Globs prefixed with `**/` match both path forms. A later section with rules `NO` overrides an earlier match. Use it to scope directories out.
- Vale findings depend on the checkout the hook runs from. Vocabulary entries that exist only on a branch produce pre-merge noise on shared files. The noise clears at merge. Verify from the feature worktree before you chase it on the main branch.
- A cached advisory report can predate a config change. One blocker report of 346 findings predated a vault-local config that arrived through a pull. A direct `vale` run on the same file exited clean. After any config change, re-run the linter directly before you act on a cached report.
- Advisory tooling misclassifies files. One layer read a GNU Makefile as a shell script, parsed JSON5 as strict JSON, and ran an edit-hook formatter with default flags against the repository's explicit style flags. The formatter reformatted whole files.
- Before you reformat a lint-flagged file, verify the flagged lines are byte-identical on the base branch. Check which linter the repository actually gates on. One zero-config linter run produced 80-column failures from defaults the repository never adopted. That repository gated on actionlint.
- A fast new language server may not integrate with the advisory layer. It advertises pull diagnostics, answers the first pull with `null`, and publishes semantic context seconds after a warm spawn. That delay passes the advisory layer's wait window, and the config has no wait-strategy knob. Request-response navigation stays unaffected.
- When you register a custom LSP server, set `args: []` explicitly. An unset `args` defaults to `--stdio`. Some servers reject that flag.
- Spelling blockers caused by person names are a vocabulary problem, not a prose problem. Use the vocabulary mechanism: `Vale.Terms = false`, a `Vocab` directory, and token ignores for wikilinks. A one-row edit reported 346 spelling blockers that were all colleague surnames. Editing the flagged prose would corrupt the names.
- Malformed frontmatter breaks Vale on a whole vault before linting starts. Content after a closing quote in a scalar, and a nested double quote inside a quoted scalar, both fail parsing. Fix the parse first. The fix unmasks vocabulary gaps the parse error hid: 30 legitimate technical terms appeared only after the YAML fix.
- To prove that a docs edit adds no new prose findings, run `vale --output=line` on the base branch and the working branch, then compare. One comparison showed 16 findings on each side and none on changed lines.
## How to apply
1. Test a Vale config with absolute paths: `vale --output line "$PWD/<file>"`. Editor hooks resolve files absolutely, and a relative-only glob silently checks nothing.
2. Prefix per-path globs with `**/` to match both path forms.
3. After a config change, or a pull that brings one in, run `vale` directly on the exact file. Do not act on cached blocker counts.
4. Fix frontmatter parse errors before any prose work.
5. Route person names and wikilinks through the vocabulary mechanism. Do not edit the flagged prose.
6. Verify that flagged lines are byte-identical on the base branch before reformatting. Confirm the repository's real linter gate.
7. To prove a docs edit is prose-clean, compare `vale --output=line` output between base branch and working branch.
8. Set `args: []` when you register a custom LSP server.
## Observations
- [vale] Vale per-path sections match relative paths only. An absolute path skips the check silently. #vale (source: agent sessions, 2026-11)
- [tooling] Vocabulary entries that exist only on a branch produce pre-merge hook noise on shared files. #vale (source: agent sessions, 2026-10)
- [tooling] A cached advisory report can predate the config change that invalidates it. #linting (source: agent sessions, 2026-09)
- [tooling] Advisory tooling misclassifies files and runs formatters with default flags. #linting (source: agent sessions, 2026-09)
- [linting] Verify flagged lines on the base branch before reformatting. Confirm the repo's real linter gate. #linting (source: agent sessions, 2026-09)
- [lsp] A fast language server can answer the first diagnostics pull with `null` and miss the advisory layer's wait window. #lsp (source: agent sessions, 2026-09)
- [lsp] Set `args: []` when you register a custom LSP server. #lsp (source: agent sessions, 2026-09)
- [vale] Spelling blockers on person names are a vocabulary problem. #vale (source: agent sessions, 2026-09)
- [yaml] Malformed frontmatter breaks Vale vault-wide before linting starts. #vale (source: agent sessions, 2026-09)
- [testing] Compare `vale --output=line` on both branches to prove an edit adds no findings. #vale (source: agent sessions, 2026-11)
## Relations
- relates_to [[resources/patterns/Verify Claims Against Primary Sources]] (advisory findings need the authoritative run)
- relates_to [[resources/documentation/Go/Go - Lint and Vulnerability Tooling]] (same discipline for code linters)
- relates_to [[resources/documentation/CI - Failure Triage and Silent Non-Runs]] (zero output can mean a silent skip)
## Sources
Personal agent-session notes, September 2026 to November 2026