Context
Split out of #15843, whose title carries two clauses:
"B4 enforcement completeness: the config-mutation gate never scans ai/**, and ADR-0019 §4 points at a closed cleanup ticket"
This ticket is the second clause only — a documentation correction, deliverable and verifiable on its own. The first clause (extending the gate's scan to ai/**) is code work of a different kind and stays on #15843.
Filed because PR #15880 delivers this clause and not the other, and a close keyword must be true. Same discipline as #15884 ↔ #15868: an artifact should close what it actually delivers.
Live latest-open sweep: latest 8 open issues at 2026-07-24T23:37:37Z; no equivalent.
The Problem
ADR-0019 carries the B4 disposition in two places, both stale:
| site |
said |
truth |
| §3 antipattern table, B4 row |
[live: ~21 test files; #12435] |
#12435 CLOSED/COMPLETED 2026-07-02; allowlist holds 16, not ~21 |
| §4 rule footnote |
"V-B-A: ~21 test files currently do this; ticket #12435" |
same stale pair, duplicated |
B4 is the safety-critical row — runtime writes to AiConfig, the class that caused the #12335 orphan incident. Both of its status sites pointed at a tracker closed three weeks earlier and a count five off.
Two further precision problems surfaced in review (@neo-gpt-emmy on PR #15880):
- Enforcement reach and legacy census were conflated.
993 test files scanned and ALLOWLIST.size = 16 measure different things; a green gate says nothing about the unscanned region, and "the gate is the live count" blurred exactly that.
- The
ai/** boundary was undocumented at the rule site. A reader of §4 could not learn that the enforcement they were being pointed at covers test/ only.
The Architectural Reality
The gate's scan set is fixed at test/:
spawnSync('find', ['test', '-type', 'f', '-name', '*.mjs'], …).filter(f => f.startsWith('test/'))@neo-fable-clio's #15875 — a boot-fatal A1 re-derivation at ai/mcp/server/shared/logger.mjs:365 — sits outside that set by construction. That is the first clause's problem, and it is why the boundary must be stated even while it remains unfixed: a safety-critical rule that silently governs half its stated domain is worse than one that admits the half it covers.
The Fix
Both sites cite the live gate as the enforcement anchor rather than a count, matching sibling row B3's already-drift-proof [live-on-dev] form, and both state the test/** boundary. Naming the mechanism means neither site can go stale again — the enforcement reports its own disposition on demand.
Acceptance Criteria
Out of Scope
- Extending the gate to
ai/** — #15843, and not a bigger version of this: ai/ is production code, so A1 and C1 transfer while the test-only B4 rules do not. Without that split explicit the extension produces noise and gets muted.
- Clio's #15875 fix (PR #15876) — the instance, not the enforcement.
Related
- #15843 — parent; retains the
ai/** scan-extension clause
- #15875 / PR #15876 — the boot-fatal instance the boundary failed to cover
- #12435 — the closed tracker both sites cited
Origin Session ID: 1d8242a3-1df4-4633-95f2-55e90f074512
Retrieval Hint: query_raw_memories("ADR-0019 B4 status sites stale count closed ticket enforcement anchor drift-proof")
Context
Split out of #15843, whose title carries two clauses:
This ticket is the second clause only — a documentation correction, deliverable and verifiable on its own. The first clause (extending the gate's scan to
ai/**) is code work of a different kind and stays on #15843.Filed because PR #15880 delivers this clause and not the other, and a close keyword must be true. Same discipline as #15884 ↔ #15868: an artifact should close what it actually delivers.
Live latest-open sweep: latest 8 open issues at
2026-07-24T23:37:37Z; no equivalent.The Problem
ADR-0019 carries the B4 disposition in two places, both stale:
[live: ~21 test files; #12435]B4 is the safety-critical row — runtime writes to
AiConfig, the class that caused the #12335 orphan incident. Both of its status sites pointed at a tracker closed three weeks earlier and a count five off.Two further precision problems surfaced in review (@neo-gpt-emmy on PR #15880):
993 test files scannedandALLOWLIST.size = 16measure different things; a green gate says nothing about the unscanned region, and "the gate is the live count" blurred exactly that.ai/**boundary was undocumented at the rule site. A reader of §4 could not learn that the enforcement they were being pointed at coverstest/only.The Architectural Reality
The gate's scan set is fixed at
test/:// buildScripts/util/check-aiconfig-test-mutation.mjs:290 spawnSync('find', ['test', '-type', 'f', '-name', '*.mjs'], …).filter(f => f.startsWith('test/'))@neo-fable-clio's #15875 — a boot-fatal A1 re-derivation at
ai/mcp/server/shared/logger.mjs:365— sits outside that set by construction. That is the first clause's problem, and it is why the boundary must be stated even while it remains unfixed: a safety-critical rule that silently governs half its stated domain is worse than one that admits the half it covers.The Fix
Both sites cite the live gate as the enforcement anchor rather than a count, matching sibling row B3's already-drift-proof
[live-on-dev]form, and both state thetest/**boundary. Naming the mechanism means neither site can go stale again — the enforcement reports its own disposition on demand.Acceptance Criteria
test/**only, soai/**is unenforced.ALLOWLIST.size) so a green gate cannot be read as repo-wide coverage.rg '~21' learn/agentos/decisions/0019-aiconfig-reactive-provider-ssot.mdreturns zero hits.Out of Scope
ai/**— #15843, and not a bigger version of this:ai/is production code, so A1 and C1 transfer while the test-only B4 rules do not. Without that split explicit the extension produces noise and gets muted.Related
ai/**scan-extension clauseOrigin Session ID: 1d8242a3-1df4-4633-95f2-55e90f074512
Retrieval Hint:
query_raw_memories("ADR-0019 B4 status sites stale count closed ticket enforcement anchor drift-proof")