From 85bdbe33837142f2499e51f5da2224450958afd4 Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 19:11:52 -0500 Subject: [PATCH] =?UTF-8?q?docs(remediation):=20bank=20D-18=20=E2=80=94=20?= =?UTF-8?q?pre-registered=20criteria=20AC2=20and=20AC4=20were=20mutually?= =?UTF-8?q?=20unsatisfiable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implementing D-17's fix surfaced a conflict between criteria, not within one. AC2 (reject symlinked generated state) cannot hold alongside AC4 (canonical build succeeds): verified independently that apps/web sets output:'standalone' and the built tree carries 42 legitimate pnpm symlinks under .next/standalone. Only building the tree reveals it. Completes the chain: a pre-registered check set can be WRONG (D-8), INCOMPLETE (D-17), or INTERNALLY INCONSISTENT (D-18). Ruling: build-certified symlink manifest — .next itself still rejected; descendants rejected unless exactly certified. Stronger than blanket rejection because it catches retargeting. AC2 restated and RECORDED with provenance rather than absorbed, since silently resolving a conflict between pre-registered criteria destroys the point of registering them. Hardening: the manifest is generated state, so a manifest writable by whoever plants a rogue symlink certifies the attack. Must be inside the integrity envelope, published atomically, with negative controls observed red first including manifest-tampered. RM-02 fourth clause: the registry must detect conflicts between criteria, and retain original text plus restatement plus reason when a criterion changes meaning. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/TASKS.md | 46 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index c68ce93f..1f7d5dd1 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -93,6 +93,52 @@ and must not be cited as merge evidence. Rely on reviewer clearance + real CI. Three independent live instances in a single session — format gate, agent context reset, queue guard — is the class confirmed, not anecdote. +### D-18 — two pre-registered criteria were mutually unsatisfiable, discoverable only at implementation + +Implementing D-17's fix surfaced a conflict **between** pre-registered criteria: + +- **AC2** (as written) — reject symlinked generated state. +- **AC4** — the canonical `pnpm -w build` succeeds and leaves no residue. + +Verified independently rather than taken on report: `apps/web/next.config.ts:4` sets +`output: 'standalone'`, and the built tree contains **42 legitimate pnpm dependency symlinks** under +`.next/standalone/node_modules`. A blanket descendant-symlink rejection makes the canonical build fail +its own preflight with exit 43. **AC2 read literally is unsatisfiable alongside AC4 under this +configuration**, and nothing short of building the tree would have revealed it. + +**Third distinct failure mode of a pre-registered check set**, completing the chain: + +| finding | a pre-registered check set can be… | +| ------- | ------------------------------------------------------------------ | +| D-8 | **wrong** — a check that does not test what it claims | +| D-17 | **incomplete** — green while a criterion's requirement is untested | +| D-18 | **internally inconsistent** — two criteria that cannot both hold | + +The implementing seat escalated instead of silently picking a winner. That matters: **quietly resolving +a conflict between pre-registered criteria destroys the point of pre-registering them** — the registration +exists so that changes of meaning are auditable rather than absorbed. + +**Resolution (orchestrator ruling).** Approved a **build-certified symlink manifest**: `.next` itself is +still rejected as a symlink; descendants are rejected unless _exactly_ certified by a manifest the build +publishes atomically. Strictly **stronger** than blanket rejection — it also catches a **retargeted** +symlink, which blanket rejection cannot distinguish from a legitimate one. + +**AC2 restated (recorded, not absorbed).** _Generated state must reject `.next` itself being a symlink, +and must reject any descendant symlink not exactly certified by the build manifest — added, removed, +retargeted, or manifest-tampered all fail with exit 43._ + +**Hardening required before this counts.** The manifest is itself generated state, so **a manifest +writable by whoever plants a rogue symlink certifies the attack** — that is the one way this design +fails. It must sit inside the same ownership/fingerprint envelope, published atomically via the existing +marker mechanism, with negative controls **observed red first** for: added, removed, retargeted, +**manifest-tampered**, plus a positive control that the canonical build passes. The tampered-manifest +control is non-negotiable; without it, integrity is a claim rather than a property. + +**Requirement on RM-02 (fourth clause).** The registry must detect **conflicts between registered +criteria**, not only wrongness and coverage. Two criteria that cannot simultaneously hold is a registry +defect discoverable by construction — and when a criterion is restated, the registry must retain the +original text, the restatement, and the reason, so the evolution stays auditable. + ### D-17 — a pre-registered criterion passed a green suite without being satisfied `rev-974` returned **CHANGES REQUESTED** on PR #1027 with one blocking finding, and it is the sharpest