fix(vale-config): correct the missing-style failure mode

Gotcha 1 said a style in BasedOnStyles that is not built-in and not
already under StylesPath "finds nothing until vale sync fetches it — a
clean run is not proof anything linted". Reproduced against vale 3.15.2:
that case is a hard `E100 [loadStyles] style '<name>' does not exist on
StylesPath`, exit 2. Nothing is linted and nothing is silent.

Worse, the same commit deleted the Gotcha that was the actual diagnostic —
that Packages and BasedOnStyles are separate keys and a style lints only
once it is in both. So the surviving rule sent a reader staring at E100 to
run `vale sync`, which fetches only what Packages declares and reports
"Synced 0 package(s)" against a BasedOnStyles-only name. The remediation
loop did not terminate. Reproduced end to end.

The genuinely silent case is the reverse — declared in Packages and
synced, but absent from BasedOnStyles — and it is now the one labelled as
such. Testing also turned up that StylesPath must exist as a directory
even when Vale is the only style (E201, exit 2), which was documented
nowhere.

references/configuration-reference.md gains a seven-row resolution matrix,
each row backed by a fixture. Its Frontmatter Scopes section claimed
provenance from the vale.sh research corpus, which contains no frontmatter
material at all; it is house-verified and now says so under its own slug.

Issue #99's wave-3 comment recorded this defect as found and repaired. It
was not — the file was byte-identical to the commit that introduced it, so
nothing here was treated as already correct.

Refs #99
This commit is contained in:
2026-08-30 20:51:32 +00:00
parent d2da45f78c
commit ca744d5d6c
6 changed files with 58 additions and 10 deletions

View File

@@ -2,6 +2,7 @@
topic: configuration-reference
source_keys:
- context7-websites-vale-sh
- house-vale-3-15-2-repro
---
## Core Settings
@@ -68,7 +69,7 @@ Individual rule YAML files (under a style's directory) support these header fiel
The underlying functions a rule's `extends` field can reference: `existence`, `substitution`, `occurrence`, `repetition`, `consistency`, `conditional`, `capitalization`, `metric`, `spelling`, `sequence`, `script`.
## Built-in Style
## Style Resolution
Only *package* styles need fetching. A style whose YAML rule files are already committed under `StylesPath` lints immediately, with no `Packages` entry and no `vale sync`; the same is true of the built-in `Vale` style, which ships with the binary and contains four rules:
@@ -77,11 +78,23 @@ Only *package* styles need fetching. A style whose YAML rule files are already c
- `Vale.Avoid` — enforces the project's rejected vocabulary terms.
- `Vale.Repetition` — flags repeated words (e.g. "the the").
`Packages` (top-level, what `vale sync` downloads) and `BasedOnStyles` (per-glob, what activates) are separate keys: a style lints a file only once it is in both. Every row below reproduced against Vale 3.15.2 (slug `house-vale-3-15-2-repro`):
| Configuration | Result |
|---|---|
| `BasedOnStyles` names a style with no directory under `StylesPath`, not built-in | `E100 [loadStyles] Runtime error` — `style 'X' does not exist on StylesPath`, exit 2 |
| `StylesPath` directory itself absent, even with only `Vale` active | `E201 Invalid value` — `The path '...' does not exist`, exit 2 |
| `vale sync` with a name in `BasedOnStyles` but not `Packages` | `SUCCESS Synced 0 package(s)`, exit 0, nothing downloaded — the next lint repeats the `E100` |
| `vale sync` with the name added to `Packages` | package lands under `StylesPath`, exit 0; lint then loads it |
| Style in `Packages` and synced, but in no glob's `BasedOnStyles` | 0 findings, exit 0 — downloads, never lints, indistinguishable from a clean run |
| `BasedOnStyles` names an *empty* directory under `StylesPath` | 0 findings, exit 0 — loads and lints nothing; `vale sync` never produces this state |
| Built-in `Vale`, or a style's YAML committed under `StylesPath` | lints immediately, no `Packages` entry, no sync |
## Frontmatter Scopes
A rule scoped to `text.frontmatter.<key>` (e.g. `text.frontmatter.description`) matches reliably when that field's value is a single physical line, and breaks on most — not all — multi-line forms.
House-verified behaviour, not documented on vale.sh — reproduced locally against Vale 3.15.2 (slug `house-vale-3-15-2-repro`).
Confirmed against Vale 3.15.2, multi-line forms spanning 2+ lines:
A rule scoped to `text.frontmatter.<key>` (e.g. `text.frontmatter.description`) matches reliably when that field's value is a single physical line, and breaks on most — not all — multi-line forms. Multi-line forms spanning 2+ lines:
| Frontmatter value form | Result |
|---|---|