Documentation-Sync Gates (tiered)
In one line: Documentation-sync is enforced the way code is — as fitness functions, tiered by what a machine can judge: objective checks block (fail-closed), judgment checks advise (fail-open).
Living documentation (§11) is a discipline, not a stage; v3.2 gives it teeth without the blanket-age-gate friction the earlier advisory hook deliberately avoided.
| Tier | Check | Mechanism |
|---|---|---|
| Blocking (fail-closed) | Link integrity | the rendered build (onBrokenLinks: throw) + a repo-level markdown link pass |
| Blocking (fail-closed) | ADR-register integrity | every ADR file has a register row (check-adr-register.sh) |
| Blocking (fail-closed) | Scoped code↔doc drift | a code path in the doc-pointers manifest (§11.4) changes without its mapped doc → block; clear with [skip-docs: <reason>], logged for the §2.8 census |
| Advisory (fail-open) | Blanket 30-day staleness | check-doc-staleness.sh warns; a blanket age-gate that blocks commits surprises contributors, so it advises (never shipped armed) |
| Advisory (fail-open) | Prose quality, Diátaxis classification | human judgment; tooling (vale, etc.) is Recommended, not Core |
The split is scope, not predicate: a scoped, code-change-triggered check blocks; a blanket, calendar-age check advises. Core blocking checks use plain scripts plus the existing build — zero new Core dependencies. The scoped code↔doc gate ships behind DOC_SYNC_BLOCKING until a dry-run over recent PRs shows a sub-10% false-positive rate (the §7 gate-admission cost/mechanism/retirement rule).
Why: enforcing every documentation concern as advisory is the weak form — subjectively-evaluated concerns end up sparsely evaluated. Tiering keeps the objective concerns honest (they block) while refusing to arm the one gate — blanket age — that trains bypass behavior.