fix: exempt docs/.style/ prose from Vale's own Coder rules (#27192)

## Problem

The repo-root `.vale.ini` lints all of `docs/**/*.md`, including the
style guide under `docs/.style/style-guide/`. The guide deliberately
contains the constructs the Coder rules ban:

- Don't examples in blockquotes and in the Don't column of Do/Don't
tables.
- Banned terms named in prose and headings (a rule about "Next steps"
must write "Next steps").

`Coder.BrandNames` already fired on the Brand names table's Don't column
(`Hashicorp`, `HASHICORP`), and each future `Coder.*` rule would fire on
its matching section's examples. Vale runs advisory, so these surface as
non-blocking annotations, exactly the standing backlog the README warns
against, and they break the documented "zero baseline findings"
doctrine.

## Change

Option B, narrowed after review to the style-guide subtree:

- `.vale.ini`: clear `BasedOnStyles` for `docs/.style/style-guide/**`
(the guide subpages only). The annotation demo and the rest of
`docs/.style/` stay linted; the demo keeps firing its `Coder.Demo*`
rules by inheriting `Coder` from `[*.md]`, with no re-include. Also
corrects the `error`-tier doctrine line to reflect advisory-only Vale.
- `docs/.style/README.md`: "What still runs" / "What does not run"
describe the narrowed exemption, and record that it holds only for paths
that resolve to `docs/.style/style-guide/...` (repo-root-relative), not
absolute or subdirectory-relative invocations.
- `docs/.style/style-guide/README.md`: exemption note scoped to
`docs/.style/style-guide/**`.
- `docs/.style/styles/Coder/BrandNames.yml`,
`docs/.style/styles/Coder/README.md`: fix the remaining dead
`style-guide.md` links (the `BrandNames.yml` one was a live 404 surfaced
in Vale annotations).

## Validation

- `make lint/prose` reports only the 3 intended `Coder.Demo*` findings
across the corpus; the guide's `BrandNames` findings are gone.
- `content-guidelines.md`, the landing `README.md`, and
`styles/Coder/README.md` are now linted and clean (0). Injecting a
miscased `Hashicorp` into `content-guidelines.md` fires
`Coder.BrandNames`; reverted.
- The guide subpages stay exempt (0); the annotation demo still fires
its 3 findings via `[*.md]`.
- Invocation-path behavior verified against
`docs/.style/style-guide/word-choice.md`: repo-root-relative `docs/...`
is exempt (0), while `docs/`-relative and absolute-path invocations
still fire 2 `Coder.BrandNames` errors.
- `markdownlint-cli2` clean on the changed READMEs.

## Decision log

Considered three options from the issue:

- **A. Surgical in-file suppression** (`vale off`/`vale on` comment
blocks, backticking banned terms). Rejected as primary: noisy in source,
repeated per example, bare-term headings still fire, and every new rule
can re-break the guide. It is path-independent, so it would have covered
the editor case noted in Option B's limitation.
- **B. Config-level subtree exemption** (chosen; narrowed to the guide
subtree after round-2 review). One place, zero source noise,
future-proof for the guide subpages.
- **Scope.** The clear applies to `docs/.style/style-guide/**` only.
Round-2 review (three reviewers converged, verified end-to-end) showed
the original directory-wide clear over-reached: `content-guidelines.md`
and the landing `README.md` are ordinary contributor prose that lints
clean today (`content-guidelines.md` uses `HashiCorp` correctly), so
they should stay linted. Narrowing to the guide subtree preserves the
exact 3-finding baseline, relints those two pages, removes the
last-match-wins ordering hazard, and drops the whole-package demo
re-include. The demo sits at the `.style/` root and keeps firing via
`[*.md]`.
- **Tradeoff.** The guide's own prose under `style-guide/` is no longer
auto-linted by Vale. Acceptable because the guide must contain banned
terms by design, one-sentence-per-line is enforced by markdownlint, and
human review covers the rest.
- **Limitation.** The exemption holds only for invocations whose path
resolves to `docs/.style/style-guide/...` (repo-root-relative
`docs/...`, what `make lint/prose` and CI pass). Absolute paths
(editors/LSP) and subdirectory-relative paths still flag the guide.
Recorded in `docs/.style/README.md`.
- **C. Restructure examples into fenced code blocks.** Rejected: changes
the guide's rendered format and doesn't cover Do/Don't tables or
headings.

## Notes

- `.vale.ini` is outside `docs/`, so this PR modifies repo-wide lint
config; the clear is scoped to `docs/.style/style-guide/` only.
- Linear: DOCS-543.

---
Opened via Coder Agents on behalf of @nickvigilante.
This commit is contained in:
Nick Vigilante
2026-07-18 13:41:27 -04:00
committed by GitHub
parent 36e36e2048
commit 4d4d2575e4
5 changed files with 52 additions and 14 deletions
+31 -8
View File
@@ -9,14 +9,14 @@ Nothing under this directory is published to
| Path | Purpose |
|-------------------------|---------------------------------------------------------------------|
| `content-guidelines.md` | Canonical content rules: what belongs in `docs/`, what doesn't, why |
| `style-guide.md` | Canonical prose style guide for `docs/` |
| `style-guide/` | Canonical prose style guide for `docs/` |
| `styles/Coder/` | Custom Vale rules specific to Coder (product voice, terms) |
See [`content-guidelines.md`](content-guidelines.md) for the canonical
rules on what content belongs in `docs/` and what should be routed
elsewhere (blog, changelog, Support KB, etc.).
See [`style-guide.md`](style-guide.md) for the prose style guide. The
See [`style-guide/`](style-guide/README.md) for the prose style guide. The
`styles/Coder/` directory holds the custom Vale rules that enforce parts
of the guide; Vale's `StylesPath` in the repo-root `.vale.ini` points at
`docs/.style/styles/`.
@@ -25,8 +25,10 @@ of the guide; Vale's `StylesPath` in the repo-root `.vale.ini` points at
The leading dot mirrors the `.github/`, `.vscode/`, and `.claude/`
convention already used in this repo for tooling-internal directories.
Vale and the structural Markdown linters still pick it up; coder.com's
docs site does not.
The structural Markdown linters and Vale still pick it up (except the style
guide's own prose under `style-guide/`, which is exempt); coder.com's docs
site does not. Refer to "What does not run against this directory" below for
that exemption.
## How exclusion from coder.com works
@@ -56,9 +58,12 @@ directory from the surgical-reindex payload on mixed commits.
`markdownlint-cli2 --fix $(find docs -name '*.md')`.
- `make fmt/markdown` (markdown-table-formatter) reflows tables here for
the same reason.
- Vale lints the entire `docs/**/*.md` set, including `docs/.style/style-guide/`.
Refer to the repo-root `.vale.ini` for the active configuration.
Run `make lint/prose` locally to reproduce.
- Vale (`make lint/prose`) lints everything here except the style guide's own
prose under `style-guide/`: the landing page, `content-guidelines.md`, the
annotation demo (whose `Coder.Demo*` rules are meant to fire), and the Coder
rule docs. Refer to the repo-root `.vale.ini` for the active configuration,
and to "What does not run against this directory" below for the one
exemption.
## What does not run against this directory
@@ -71,6 +76,22 @@ directory from the surgical-reindex payload on mixed commits.
so `.style`-only PRs produce no preview comment. The selection logic also
skips `.style` files when picking the preview target on mixed PRs. See
`.github/workflows/docs-preview.yaml`.
- Vale's `Coder` rules on the style guide's own prose under
`docs/.style/style-guide/`. The guide deliberately contains the constructs
the rules ban, such as Don't examples and banned terms named in headings and
prose, so the repo-root `.vale.ini` clears `BasedOnStyles` for
`docs/.style/style-guide/**`. Nothing else under `docs/.style/` is exempt:
the landing page, `content-guidelines.md`, the annotation demo, and the Coder
rule docs are all linted. Zero-baseline is therefore measured over `docs/`
excluding `docs/.style/style-guide/`.
The exemption applies only when the path resolves to
`docs/.style/style-guide/...` from the working directory, which is what
`make lint/prose` and CI pass (repo-root-relative `docs/...`). Other
invocation forms bypass the glob and still flag the guide's intentional
examples: absolute paths (what editors and LSP integrations pass) and
subdirectory-relative paths (for example `vale .style/style-guide/...` run
from `docs/`). Treat those in-editor and subdirectory findings on the guide
as expected.
## Editing the content guidelines
@@ -86,7 +107,9 @@ Follow-up PRs add each rule and the matching style-guide section together.
## Adding a Vale rule
Each rule in the repo-root `.vale.ini` ships clean: zero baseline
findings against the current `docs/` corpus.
findings against the current `docs/` corpus, excluding
`docs/.style/style-guide/`, which is exempt because the style guide
demonstrates the violations the rules ban.
The PR that adds a rule is the rule's complete unit:
1. **Cleanup commit**: fix every existing-content violation of the new
+2
View File
@@ -87,6 +87,8 @@ Severity is a deliberate per-rule choice from the three-tier ladder:
Use for soft guidance where the right fix is contextual.
The full doctrine, including the false-positive policy, lives in [`README.md`](../README.md).
This guide is itself exempt from the Coder rules: it demonstrates the violations those rules ban, so the repo-root `.vale.ini` clears `BasedOnStyles` for `docs/.style/style-guide/**`.
Zero baseline is measured over `docs/` excluding `docs/.style/style-guide/`.
Run `make lint/prose` to reproduce the baseline locally.
## Relationship to `docs/about/contributing/documentation.md`
+1 -1
View File
@@ -17,7 +17,7 @@
# unchanged; the `%s` token interpolates the matched (wrong) text.
extends: substitution
message: "Use '%s' instead of '%s' (brand-name casing)."
link: https://github.com/coder/coder/blob/main/docs/.style/style-guide.md#brand-names
link: https://github.com/coder/coder/blob/main/docs/.style/style-guide/word-choice.md#brand-names
level: error
ignorecase: false
nonword: false
+2 -2
View File
@@ -4,7 +4,7 @@ Custom Vale rules specific to Coder live here.
Each rule is a YAML file that Vale loads through the `BasedOnStyles = Coder` setting in the repo-root `.vale.ini`.
Active rules ship as YAML files in this directory.
See the matching sections in `docs/.style/style-guide.md` for the user-facing policy each rule enforces.
See the matching sections in `docs/.style/style-guide/` for the user-facing policy each rule enforces.
Follow-up PRs add rules incrementally.
Planned coverage:
@@ -28,7 +28,7 @@ Planned coverage:
- The rule is objectively correct (typo, brand-name casing, banned
substitution).
- The existing-content violation count for the rule reaches zero.
4. A follow-up PR adds a parity CI check that verifies every rule here has a matching section in `style-guide.md`.
4. A follow-up PR adds a parity CI check that verifies every rule here has a matching section in `style-guide/`.
Add the section in the same PR as the rule.
## Reference