--- name: docs-drift-guard description: Blocks calling a code change "done" when it renamed, added, removed, or changed a public name, flag, command, default value, count, config key, or behavior but left the docs (README, CHANGELOG, docs/, examples, --help text, code comments/docstrings) still referencing the old surface. Best used reactively after code changes a public name, flag, command, default value, count, config key, or behavior. Use when the user says "rename", "change the flag", "update the API", "add a command", "bump the version", or after any change to a user-facing surface. DO NOT USE for pure internal refactors with no public surface, or for verifying tests (test-code quality is out of proofguard's scope; a test-quality-guard is in `deferred/`, not yet shipped); this guard checks that DOCS match the code after a change. --- # docs-drift-guard "Docs are part of done." A change that renames a flag, adds a command, or flips a default is not finished the moment the code compiles — it is finished when every doc that describes the old surface has been found and updated to describe the new one. This guard blocks the completion claim until that grep has actually been run. The failure mode this guard targets is AI-slop documentation: grammatically perfect JSDoc/README prose that describes what the model *thinks* the code does — inferred from the function/flag/command *name* — rather than what it actually does after the rename. A renamed flag silently drifts from its own docs because nothing forced the two to be checked against each other. ## When to use — three modes - **Guard-pass (default).** Right before saying a change is "done" that touched a public name, flag, command, default value, count, config key, or behavior: diff the public surface, grep the whole repo for every OLD token, and update or explicitly list every doc file that still references it. This is the mode that fires on "rename", "change the flag", "update the API", "add a command", "bump the version," or any commit/PR that touches a user-facing surface. - **Live.** While actively making the rename/add/remove: update the doc reference in the same edit pass as the code change, rather than batching "fix the docs" as an afterthought at the end. If you touch `cli.js` to rename a flag, touch the README's flag table in the same turn. - **Review.** When asked "did the docs get updated?" / "is this in sync?": audit as a critic — grep for the old token across the whole repo, list every remaining hit with file and line, and do not silently patch them unless asked to fix what you find. ## What this guard blocks 1. **Rename/remove/add a public token → grep the WHOLE repo for the OLD token, update every doc that references it.** A "public token" is a CLI flag, subcommand name, exported function/class name, environment variable, config key, default value, or a documented count. When one of these changes, grep the entire repo (not just the file you edited) for the old literal string and check every hit: `README`, `CHANGELOG`, `docs/`, `examples/`, `--help`/usage text, and code comments/docstrings. Fixing the code and leaving the README's flag table saying the old name is not done — it is a half-finished rename. See `references/stale-token-grep.md` for the exact grep commands. 2. **A new/removed/renamed feature updates its describing doc IN THE SAME change.** If the README (or a `docs/` page) lists available commands, flags, or config keys, adding/removing one without touching that list in the same diff is a drift bug the moment it merges, not a follow-up task. 3. **Never invent doc content you did not verify.** Do not write a new example, a new "supports X" claim, or a new usage snippet describing behavior you did not actually read from the code or run. A doc update that "sounds right" but was never checked against the real implementation is the same failure this guard exists to catch, just introduced fresh instead of left stale. 4. **Update counts and version strings the change invalidates.** "Supports 5 commands," "3 config options," a hardcoded version number in an example, or a "supports N flags" sentence must be recomputed, not left at its pre-change value, whenever the change adds/removes an item from the set being counted. 5. **Report doc files touched vs. doc files still stale.** Every guard-pass ends with two explicit lists: the doc files that were updated, and any doc file that still references the old surface and was NOT updated (with a stated reason — out of scope, needs a human call, etc.). "I updated the docs" without naming which files, and confirming no old-token hits remain elsewhere, is not evidence. ## Procedure (guard-pass mode) 1. **Diff the public surface.** Identify exactly what changed: a flag name, a command name, a function/env/config name, a default value, a count, or a described behavior. If nothing on this list changed (pure internal refactor, private/unexported symbol, no behavior change visible to a caller), this guard has nothing to do — say so and stop (see the control fixture in `tests/kill-tests/docs-drift-guard/control.md`). 2. **Grep the whole repo for the OLD token**, not just the directory you were editing. Use the commands in `references/stale-token-grep.md` — case-sensitive, whole-repo, including `README*`, `CHANGELOG*`, `docs/**`, `examples/**`, and any `--help`/usage string literal in the source. 3. **Classify every hit.** For each file that still contains the old token: is it (a) a doc that describes the changed surface and must be updated, (b) a historical/point-in-time record (an old changelog entry, an ADR, a dated example) that should stay as written, or (c) genuinely unrelated (the string coincidentally matches something else)? Use `references/doc-surface-map.md` to know which doc artifacts a given kind of change typically touches, so you're not guessing file-by-file. 4. **Update category (a) hits in this same change.** Edit the README table, the `--help` string, the example file, the docstring — whatever references the old surface as current/live documentation. Do not defer this to "a follow-up docs pass." 5. **Do not invent.** For anything you add or reword, confirm it matches the actual current code (read it or run it) before writing it down — never phrase a new doc claim from the symbol name alone. 6. **Recompute any invalidated count/version string** touched by the change (item 4 above). 7. **Compose the two lists** — doc files updated, and doc files that still reference the old surface and were deliberately left (with why) — before claiming the change is done. 8. **Emit the guard footer** (see Output) as the last line of the response. ## Output Emit this verbatim as the last line of the response where this guard fires or is checked: ``` proofguard:docs-drift-guard — · Triggered: · Fixed: · Verified: · Remaining gap: ``` - `PASS` — either no public surface changed (nothing for this guard to do), or a public surface changed and the whole-repo grep for the old token came back clean after doc updates were applied. - `FIX-REQUIRED` — a public surface changed and at least one doc file still references the old token/behavior/count and has not yet been updated in this response. - `WAIVED(reason)` — a stale doc reference was found and the user explicitly accepted leaving it for a later pass, with a stated reason (e.g. a point-in-time historical record that must stay as written). ## References - `references/doc-surface-map.md` — for each kind of change (CLI flag, command, env var, config key, default value, public function, count or version string), which doc artifacts typically reference it and must be checked. - `references/stale-token-grep.md` — exact, cross-platform commands for grepping the repo for an old token, what counts as a doc artifact to check, and the "don't invent docs" rule in detail. ## What this guard does NOT do It does not write net-new tutorials or explanatory docs from scratch, does not judge documentation prose quality or style, and does not verify that the build/tests actually pass (that's `evidence-before-done`). It does not grade whether a test is a *good* test (test-code quality is out of proofguard's scope; a test-quality-guard is in `deferred/`, not yet shipped), whether the diff is scoped tightly (`clean-diff-guard`), or whether a dependency is real (`dep-verify-guard`). This guard has exactly one job: after a public-surface change, keep the *existing* docs in sync with the *changed* code — no more, no less.