From 0c1eb9ecba66e238d7e240c9f3002cf217497914 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 31 Jul 2026 09:45:35 +0200 Subject: [PATCH] ADR-0004: ratify AM-4a and AM-4b (maintainer decision) Discharges the open item T07 raised. Values unchanged at 250,000 and 350,000; what was missing was a reviewed decision behind them, since they had been set by the implementer in the commit that measured them and that also changed the feature gating being measured. The ADR supplies the argument T07's test requires -- why the targets bind on FUTURE work rather than merely passing present work: AM-4a leaves 3,750 lines of headroom (1.5%), about one small crate, so any new shipped-runtime dependency breaches it almost immediately. That is intended: the shipped runtime should be effectively frozen. AM-4b leaves 32,979 lines (10.4%), deliberately looser -- dev tooling should absorb one moderate dependency without a spec change, not two. Both are ceilings on a quantity that only grows by choice. Nothing drifts across them; only adding a dependency does. Falsification condition stated: if a later pass raises AM-4a to accommodate a dependency it wants, that is the failure the ceiling exists to catch, and the answer is an ADR arguing for the dependency. First ADR written under the correction/retarget test; sets the shape. Co-Authored-By: Claude Opus 5 --- decisions/ADR-0004-am4-ratification.md | 88 +++++++++++++++++++++++++ history/260731-inner-loop-rule-audit.md | 12 ++-- specs/GameKernel.md | 5 +- 3 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 decisions/ADR-0004-am4-ratification.md diff --git a/decisions/ADR-0004-am4-ratification.md b/decisions/ADR-0004-am4-ratification.md new file mode 100644 index 0000000..1223b9a --- /dev/null +++ b/decisions/ADR-0004-am4-ratification.md @@ -0,0 +1,88 @@ +# ADR-0004: ratify AM-4a and AM-4b + +status: accepted +date: 2026-07-31 +decided by: maintainer (Bernd Worsch), 2026-07-31 +tier: S (structural S — ratifies an existing target, creates no capability; chaos d4=3) +supersedes: nothing; discharges the open item raised by CB-WP-0003 T07 +references: [GameKernel.md](../specs/GameKernel.md) §4, +[InnerLoop.md](../specs/InnerLoop.md) §Step 4 (correction vs retarget), +`history/260731-inner-loop-rule-audit.md` + +## Why this ADR exists + +CB-WP-0003 T07 added a mechanical test separating a **correction** (the +instrument disproved the target; the implementation did not change) from a +**retarget** (the same commit moved both the target and the code it +measures). AM-4a/AM-4b failed that test: they were set at 250,000 and +350,000 in commit `4be6e02`, by the implementer, after seeing the measured +246,250 — and that commit also changed the feature gating the metric +measures. + +The reasoning was recorded at the time and is defensible. The *structure* +was not, and the audit flagged both targets as unratified: `make +dep-weight` has been enforcing thresholds no reviewed decision stood +behind. + +## Decision + +**AM-4a (≤ 250,000 lines, shipped runtime) and AM-4b (≤ 350,000 lines, +dev toolchain) are ratified as written.** No values change. + +## The old target, and why it was abandoned + +AM-4 originally read **≤ 20 transitive crates**, set against +boardgame.io's 120 npm packages. Retired for two measured reasons: + +1. **Unreachable without undoing this spec's own contracts.** K5 (seeded + ChaCha) and K7 (SHA-256) cost 12 crates between them. The measured + ladder showed nothing reached 20 except reimplementing one of those + primitives — trading an audited cryptographic implementation for a + scoreboard number. +2. **Crate count does not compare across ecosystems.** Rust splits crates + far more finely than npm, so the original 33-vs-120 comparison + flattered us while the ≤20 target punished us, for the same reason. + +## The measurement that motivated the change + +At the time of the retarget, `make dep-weight`: + +| configuration | crates | third-party LOC | +|---|---|---| +| shipped-runtime (`--no-default-features`) | 23 | **246,250** | +| dev-toolchain (default features) | 29 | **317,021** | +| own source | — | 3,443 | + +## Why these targets bind on future work rather than merely passing present work + +This is the question T07 requires an ADR to answer, and it is the reason +ratification is defensible rather than a rubber stamp. + +- **AM-4a leaves 3,750 lines of headroom — 1.5%.** That is roughly one + small crate. Any dependency added to the shipped runtime breaches it + almost immediately, which is the intended behaviour: the shipped runtime + is meant to be effectively frozen, and the target enforces that a new + runtime dependency is a decision someone must argue for, not a default. +- **AM-4b leaves 32,979 lines — 10.4%.** Deliberately looser. The dev + toolchain is where scenario YAML, benchmarking, and future tooling land, + and it does not ship to a player. It should be able to absorb one + moderate dependency without a spec change, and not two. +- **Both are ceilings on a quantity that only grows by choice.** Nothing + drifts a project across these thresholds; only adding a dependency does. + A target that can only be breached deliberately is a target that binds. + +**What would falsify this ratification:** if a future pass finds itself +raising AM-4a to accommodate a dependency it wanted, that is the failure +mode the ceiling exists to catch, and the answer is a new ADR arguing for +the dependency — not a quiet retarget. + +## Consequences + +- The open item in `history/260731-inner-loop-rule-audit.md` is discharged. +- `make dep-weight` continues to fail the build on breach, now backed by a + reviewed decision. +- AM-4c (own source per 100k third-party lines) remains **reported, not + targeted**, and is unaffected. +- Precedent: this is the first ADR written under the correction/retarget + test. Future retargets follow this shape — old target, the measurement, + and an argument about *future* binding rather than present passing. diff --git a/history/260731-inner-loop-rule-audit.md b/history/260731-inner-loop-rule-audit.md index 13999eb..cc9f56c 100644 --- a/history/260731-inner-loop-rule-audit.md +++ b/history/260731-inner-loop-rule-audit.md @@ -136,12 +136,12 @@ evidence files. ## Open items raised by this audit -- **AM-4a / AM-4b are unratified retargets.** Measured at 246,250 and set - at 250,000 in the same commit, by the implementer, with the - implementation changing in that commit too — a retarget under the test - added to InnerLoop §Step 4 by T07, not a correction. They must be - ratified by ADR or changed. Until then `make dep-weight` is enforcing a - target no reviewed decision stands behind. +- ~~**AM-4a / AM-4b are unratified retargets.**~~ **Discharged + 2026-07-31** by [ADR-0004](../decisions/ADR-0004-am4-ratification.md), + ratified by the maintainer. Values unchanged; the ADR supplies the + future-binding argument the test requires (AM-4a leaves 1.5% headroom, + AM-4b 10.4%, and both measure a quantity that only grows by deliberate + choice). ## Class coverage — where the gaps are diff --git a/specs/GameKernel.md b/specs/GameKernel.md index dad7634..9ba10ef 100644 --- a/specs/GameKernel.md +++ b/specs/GameKernel.md @@ -135,7 +135,10 @@ Command (actor-tagged intent) ## 4. Acceptance metrics -**On AM-4's retarget (2026-07-31).** AM-4 originally read "≤20 +**On AM-4's retarget (2026-07-31).** *Ratified by +[ADR-0004](../decisions/ADR-0004-am4-ratification.md) on 2026-07-31; the +headroom argument for why these ceilings bind on future work lives there.* + AM-4 originally read "≤20 transitive crates", set against boardgame.io's 120 npm packages. That target was retired for two measured reasons. First, it was unreachable without undoing this spec's own contracts: K5 (seeded ChaCha) and K7