enhance(#3913): docs, and the guards come down (#3994)

ADR-3889 terminal phase. Generated docs/reference/exit-codes.md from the exit-code declaration with a --check drift arm; deleted the inert soft-error-exit-zero oracle; promoted untyped-success from SMELL to VIOLATION so it can fail a build; pruned all 5 smell-baseline entries.

Fixed inline: two mis-scoped oracles (routing-validity, value-hygiene), a second source behind the band table, unescaped declaration strings reaching Markdown, and a pre-existing Windows 8.3 short-name path-comparison defect.

Guard ledger corrected from a claimed net -4 to a measured net -1.

Closes #3913
This commit is contained in:
Tom Boucher
2026-08-28 13:10:20 -04:00
committed by GitHub
parent c3e667df34
commit 12f9d1d9a0
16 changed files with 1517 additions and 152 deletions

View File

@@ -273,6 +273,56 @@ and it is the property ADR-2980's declined Option 3 lacked.
`n/no-process-exit: 'off'` exemption block, and the duplicated `scripts/lib/cli-exit.cjs`;
**added** one rule (`local/require-registered-exit`) plus the registry's own `--check`. Net **−2**.
> **Amendment — 2026-08-28: the ledger above is superseded (#3913).**
>
> Three of its terms did not survive contact with the code, and the net it states was never
> achievable. It is left in place unedited so the drift is legible; the measured ledger is below.
>
> 1. **`scripts/lib/cli-exit.cjs` was not deleted.** Phase 0 changed it from a duplicated module
> into a *generated* one, so the line retires a copy that still exists. The epic body was
> corrected to net **−1** at the time; this ADR's line was not.
> 2. **"their four baseline entries" was five** — four `soft-error-exit-zero` and one
> `untyped-success`, counted directly off `tests/qa/smell-baseline.json`. Issue #3913 repeated
> the figure of four, and so did the first recon pass of this phase. This is the second
> documented count in this epic to drift, after [ADR-2980](2980-payload-carried-error-is-a-degraded-result.md)'s
> 60-versus-64 `output({error})` sites.
> 3. **Only one of the two oracles was retired.** `soft-error-exit-zero` is deleted: its condition
> is now *declared* by the exit contract (`output({error})` → `DEGRADED`, 0 under v1 and 80
> under v2), so an inert SMELL restating it is ledger inflation. `untyped-success` is **not**
> deleted — it asserts that a `KIND.PROSE` command exposes no typed surface, which has nothing
> to do with exit codes, and neither the registry nor `local/require-registered-exit` replaces
> it. The clause this ADR and #3913 both rely on — *"the registry and the ESLint rule enforce
> the same property by construction"* — is simply false for it. Rather than drop the property,
> it was **promoted from SMELL to VIOLATION**, so it can now fail a build, which it never could
> before (`runOracles`'s `get failed()` returns `violations` only).
>
> **Measured ledger for the epic as delivered:** −1 oracle (`soft-error-exit-zero`), −1
> `n/no-process-exit: 'off'` exemption block, +1 rule (`local/require-registered-exit`), +1 registry
> `--check`, +1 generated-docs `--check` (`docs/reference/exit-codes.md`). One further guard changed
> strength rather than count: `untyped-success` SMELL → VIOLATION. Two mis-scoped oracles were
> corrected in passing (`routing-validity`, `value-hygiene`) — see #3913.
>
> **Net −1 by count**, not −4.
>
> The −4 first written here counted the five pruned `smell-baseline.json` entries in the same units
> as oracles and lint rules. They are not guards — they are *acknowledgements* that a guard fired.
> Removing them strengthens the surface rather than removing anything from it, and folding them into
> the count inflates the negative by five. An ADR about honest accounting should not pad its own
> ledger, so the entries are recorded as what they are and excluded from the count.
>
> **Two limits on how strong this is, stated rather than implied:**
>
> - **`soft-error-exit-zero`'s condition is now declared, not enforced.** No oracle references
> `KIND.SOFT_ERROR` after its deletion, and the corpus still contains four soft-error steps that
> nothing observes. Under `v1` — the default — those sites still exit `0`. The condition is
> modelled in the contract and projects to `80` only under the opt-in `v2`. That is a deliberate
> trade, not an equivalent replacement, and "the registry enforces the same property" would be too
> strong a claim for it.
> - **`untyped-success` is promoted against a corpus that no longer exercises the case.** Its
> `KIND.PROSE` count reached 0 because the sole prose-producing step was changed to
> `smart-entry --json`. The promotion is real and the guard now fails a build — but what it
> currently guards is that no *new* prose-only step appears, not that an existing one is caught.
## Revisit if
- Domain allocations exceed roughly a dozen. That means the generic four are wrong, not that the