diff --git a/.vale.ini b/.vale.ini index a7a618fad12a1..37643143f1c2c 100644 --- a/.vale.ini +++ b/.vale.ini @@ -1,90 +1,29 @@ # Vale configuration for Coder documentation. # -# Curated cherry-pick of Google's developer-docs style, write-good (wordiness), -# and a hand-picked subset of alex (inclusive-language). The choice of base -# styles and disabled rules is documented in DOCS-40 and reproducible via -# `make lint/prose`. +# Rule rollout doctrine. Every rule listed below ships clean: zero +# baseline findings across `docs/` at enable time. Severity is a +# deliberate per-rule choice: # -# Severity policy. Rules sit at a level that reflects two things -# together: false-positive rate against real Coder docs and the gravity of -# the rule. Low FPs plus high gravity argues for `error`; lower gravity or -# more judgment calls argue for `warning` or `suggestion`. v1 lands most -# rules at `warning` and the wordiness rules at `suggestion`. Promote a -# rule to `error` only when (a) its false-positive rate against real -# content is effectively zero and (b) the existing-content violation count -# for that rule is also zero. +# - `error` hard policy; CI blocks merge on violations. +# - `warning` strong guidance; surfaces annotations without +# failing CI. +# - `suggestion` soft guidance; surfaces `notice` annotations. # -# About Vale's exit code: Vale exits non-zero only when error-level alerts -# are found, regardless of `MinAlertLevel`. The Makefile invokes Vale with -# `--no-exit` to suppress that exit while the un-overridden Google -# error-level rules still produce a baseline error count. Real failures -# (bad config, missing files) still propagate. See -# DOCS-40 for the rollout plan. +# To add a rule, follow the per-rule PR template in +# docs/.style/README.md ("Adding a Vale rule"). Third-party rules +# from Google, alex, and write-good are not enabled by default; each +# returns via the same per-rule PR pattern after its corpus is clean. # -# The styles themselves live under docs/.style/styles/ after `vale sync`, -# which the Makefile target invokes once per .vale.ini change. They are -# gitignored to keep the repo lean. +# About Vale's exit code: Vale exits non-zero only when error-level +# alerts are found. Warning and suggestion annotate without +# affecting exit. Real runtime failures (bad config, missing files) +# propagate regardless of severity. +# +# The Coder rule package lives under docs/.style/styles/Coder/ and is +# the single source loaded by default. StylesPath = docs/.style/styles MinAlertLevel = suggestion -# Packages drives `vale sync`. Pin upstream tags here when reproducibility -# matters more than getting upstream fixes; the unpinned form pulls the -# latest release of each package on `vale sync`. -Packages = Google, alex, write-good - [*.md] -BasedOnStyles = Google, write-good, Coder - -# --- Google curation ------------------------------------------------------- -# Google.EmDash conflicts with our em-dash ban (see scripts/check_emdash.sh -# and DOCS-44). The repo-level ban covers Unicode U+2014/U+2013 plus the -# ` -- ` ASCII fallback; Google.EmDash would double-flag and use prose -# different from our policy. -Google.EmDash = NO - -# Google.Latin flags i.e. and e.g. for non-native readers. Coder docs assume -# a technical audience that reads these fluently; leaving the rule on -# produces noise without value. -Google.Latin = NO - -# Soften two high-volume Google rules. The signal-to-noise ratio is low -# at the default warning level. -Google.Parens = suggestion -Google.WordList = warning - -# Google.Spacing flags fully-qualified Go type names like -# `codersdk.WorkspaceAgent` as "should have one space." It produces ~4,500 -# errors against `docs/reference/api/schemas.md` alone (measured -# 2026-05-18) because codersdk type names match the pattern. The -# architectural decision for generated content is to fix the upstream -# Go generators (clidocgen, apidocgen, auditdocgen, metricsdocgen) -# rather than add Vale path exclusions; this disable buys time until -# those generator changes land. Re-enable then, ideally promoted to -# `error`. -Google.Spacing = NO - -# --- write-good curation --------------------------------------------------- -# Passive voice is contextually correct often enough that flagging every -# instance teaches nothing. E-Prime forbids forms of "to be" entirely, -# which is incompatible with normal technical writing. -write-good.Passive = NO -write-good.E-Prime = NO - -# Keep the three rules that catch real wordiness problems. Wordiness and -# ThereIs are judgment calls (suggestion); Weasel is sharper (warning). -write-good.TooWordy = suggestion -write-good.Weasel = warning -write-good.ThereIs = suggestion - -# --- alex curation --------------------------------------------------------- -# alex is loaded a la carte rather than via BasedOnStyles. ProfanityMaybe -# and ProfanityUnlikely fire on technical terms like `execute`, `kill`, -# `failed`, and `attack`; ProfanityLikely is much more conservative and -# safe to keep on. -alex.Ablist = warning -alex.Condescending = warning -alex.LGBTQ = warning -alex.ProfanityLikely = warning -alex.Race = warning -alex.Suicide = warning +BasedOnStyles = Coder diff --git a/docs/.style/README.md b/docs/.style/README.md index 7f7e40c9201a2..db03fefec441d 100644 --- a/docs/.style/README.md +++ b/docs/.style/README.md @@ -82,3 +82,59 @@ with another style or contributing doc in the repo, it governs. Open a PR against `docs/.style/style-guide.md`. 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. +The PR that adds a rule is the rule's complete unit: + +1. **Cleanup commit**: fix every existing-content violation of the new + rule so `make lint/prose` reports zero findings for it. + The cleanup ships in the same PR as the enable, ordered first. +2. **Enable commit**: add the rule to `.vale.ini` at its chosen + severity, write a corresponding section under + `docs/.style/style-guide.md`, and add the custom rule YAML under + `docs/.style/styles/Coder/` if applicable. + The rule's `message:` field points at the relevant `style-guide.md` + anchor. + +Severity is a deliberate per-rule choice: + +- `error` blocks merge. Use for hard policy where any violation is + wrong: brand-name casing, first-person pronouns we ban outright, + em-dash bans. +- `warning` surfaces an annotation without failing CI. Use for strong + guidance with legitimate human-judgment exceptions: terms that need + context (`disabled` as a technical state vs. ableist usage), + judgment-bound style preferences. +- `suggestion` surfaces a `notice` annotation. Use for soft guidance + where the right fix is contextual: noun-as-adjective patterns like + `desired state`, wordiness, optional sentence reshaping. + +The severity choice and the cleanup discipline are independent. A +rule landing at `warning` or `suggestion` still ships with zero +baseline findings; the rule's purpose is to catch new violations, not +to surface a backlog of existing ones. A rule that surfaces a standing +backlog teaches contributors to ignore the annotation channel, which +erodes trust in CI regardless of the severity at which the noise +arrives. + +PR title: `feat(docs/.style): enable `. + +False-positive policy: one confirmed false positive after enable, +either refine the rule or revert. +We do not maintain rules that occasionally cry wolf, regardless of +severity. + +If a policy is judgment-bound (passive voice, weasel words, +sentence-case headings on a corpus with many proper nouns), write a +Coder-authored rule with the precision the situation needs instead of +accepting an imprecise third-party rule at any severity. + +This applies equally to Coder-authored rules (under +`docs/.style/styles/Coder/`) and third-party rules from Google, alex, +and write-good. +Third-party rules are not loaded by default. +Each returns through the same per-rule PR pattern after its corpus is +clean.