From 6a067174ede7d9123915c7363da9564a900265ce Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 17:48:17 -0500 Subject: [PATCH 01/22] =?UTF-8?q?docs(remediation):=20bank=20D-9=20?= =?UTF-8?q?=E2=80=94=20comms=20path=20shell-interprets=20message=20bodies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit agent-send.sh -m with backticks executes them as command substitution: the recipient got a mangled body plus a shell error, and the send still reported success. Same class as the known pr-create.sh backtick bug — two tools in the comms path treating a message body as shell input. The failure mode is the mission's own pattern: silent corruption with a success receipt. Requirement on RM-40/RM-42: comms/v1 must carry payloads verbatim with no shell interpretation at any hop, with a byte-identical round-trip test (backticks, command substitution, quotes, newlines) registered under RM-02 including a must-fail control. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/TASKS.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index 58e68115..0d6f92a5 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -93,6 +93,25 @@ 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-9 — the comms path shell-interprets message bodies (injection-shaped, found by accident) + +Sending a status message with `agent-send.sh -m "...`backticks`..."` caused bash to **execute** the +backticked text as command substitution. The recipient received a mangled body plus a +`No such file or directory` error; the intended sentence never arrived. The message was reported as +delivered. + +This is the **same class** as the already-noted `pr-create.sh` backtick-quoting bug (M2 scratchpad): +**two tools in the comms path treat a message body as shell input.** A body that can execute on the +sender is a _correctness_ bug before it is ever a security one — and note the failure mode: the +send reported success while silently transmitting something other than what was written. Silent +corruption with a success receipt is precisely the pattern this mission exists to eliminate. + +**Requirement on RM-40 / RM-42 (comms/v1):** the envelope must carry its payload **verbatim**, and +the payload must not be subject to shell interpretation at **any** hop — sender, transport, or +adapter. Round-trip fidelity (send a body containing backticks, `$(…)`, quotes, and newlines; assert +byte-identical receipt) is a required registered test case under RM-02, including a must-fail control +proving the assertion can detect corruption. + ### D-8 — a PRE-REGISTERED acceptance check that was not runnable as written On PR #1025 the author (me) pre-registered AC2 with the fixture snippet `mkdir -p apps/*/venv/lib`. -- 2.54.0 From 31c3191305b2ed35b6f8bff191dcb1b1f3bd51d5 Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 17:50:26 -0500 Subject: [PATCH 02/22] docs(remediation): rolling-branch resume pointer + D-9 interim comms rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit KICKSTART resume now points at origin/remediation/state for the live board, per Mos's cadence ruling: every tick is pushed to the rolling branch immediately (durable per-tick, no per-tick main PR); main carries periodic snapshots only. Reading the board from main would silently yield a stale tick, so the step warns explicitly. D-9 hardened: comms/v1 must use file/stdin transport, never argv interpolation. Standing interim rule until then — agent-send -f for any body with special characters, never -m. Mandatory in every worker brief alongside the D-8 clause. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/KICKSTART.md | 11 ++++++++--- docs/remediation/TASKS.md | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/docs/remediation/KICKSTART.md b/docs/remediation/KICKSTART.md index fa4900f0..662a7557 100644 --- a/docs/remediation/KICKSTART.md +++ b/docs/remediation/KICKSTART.md @@ -7,10 +7,15 @@ mechanically until Build 3 (rotation) makes it automatic. ## On resume (do in order, before any orchestration action) -1. `cd /src/mosaic-stack` and confirm you are on the remediation working branch. +1. `cd /src/mosaic-stack`, then **`git fetch origin remediation/state`**. + ⚠ **The live board is on the rolling branch `remediation/state`, NOT on `main`.** `main` carries only + periodic snapshots, so reading the board from `main` will silently give you a STALE tick. Read the + live files at `origin/remediation/state` (e.g. `git show origin/remediation/state:docs/remediation/BOARD.md`), + or check that branch out. Every tick is pushed there immediately, so its HEAD is always the newest state. 2. Read `docs/remediation/MISSION.md` — the charter (goal, 4 builds, 15 decisions, sequencing, directives). -3. Read `docs/remediation/BOARD.md` — the LIVE state: current phase, in-flight tasks, fleet seat assignments, - gate status. This is your single source of in-flight truth (kept small). +3. Read `docs/remediation/BOARD.md` **at `origin/remediation/state`** — the LIVE state: current phase, + in-flight tasks, fleet seat assignments, gate status. Single source of in-flight truth (kept < 8 KB; + older entries roll to `BOARD-LEDGER.md` via `board-roll.sh`). 4. Read the discussion checkpoint for full rationale if needed: `../jarvis-brain/docs/scratchpads/postmortem/REMEDIATION-DISCUSSION-STATE.md` (or the jarvis-brain repo path). 5. **Residency attestation (fail-closed):** restate from the reloaded files — (a) the goal in one line, (b) the diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index 0d6f92a5..fa0b27ed 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -106,9 +106,14 @@ sender is a _correctness_ bug before it is ever a security one — and note the send reported success while silently transmitting something other than what was written. Silent corruption with a success receipt is precisely the pattern this mission exists to eliminate. -**Requirement on RM-40 / RM-42 (comms/v1):** the envelope must carry its payload **verbatim**, and -the payload must not be subject to shell interpretation at **any** hop — sender, transport, or -adapter. Round-trip fidelity (send a body containing backticks, `$(…)`, quotes, and newlines; assert +**Requirement on RM-40 / RM-42 (comms/v1), hardened by Mos.** The envelope must carry its payload +**verbatim** and must not be subject to shell interpretation at **any** hop — sender, transport, or +adapter. Concretely: **file/stdin transport, never argv interpolation.** + +**Standing interim rule, effective now (Mos).** Until the envelope lands, use `agent-send.sh -f +` for any message body containing special characters — **never `-m`**. Passing a file sidesteps +argv interpolation entirely. **This rule is mandatory in every worker brief this mission issues**, +alongside the D-8 "if a check is unrunnable, say so" clause. Round-trip fidelity (send a body containing backticks, `$(…)`, quotes, and newlines; assert byte-identical receipt) is a required registered test case under RM-02, including a must-fail control proving the assertion can detect corruption. -- 2.54.0 From 409bf23e6a235d6aec367b1ca4e686830160d22d Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 17:52:42 -0500 Subject: [PATCH 03/22] =?UTF-8?q?docs(remediation):=20bank=20D-10=20?= =?UTF-8?q?=E2=80=94=20the=20queue=20guard's=20failure=20modes=20are=20inv?= =?UTF-8?q?erted?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same required gate, both directions wrong: fails OPEN on state=unknown (5 meaningless greens this session, wrong branch too), and fails CLOSED on credential resolution, hard-blocking a worker's completed work. The identical command succeeded from that worker's own worktree in another shell, so the checkout was fine. A gate that waves through unchecked work and blocks ready work has its failure modes backwards. Availability failures must degrade to a loud, audited CANNOT_ASSERT; correctness failures must block. Also the Pi-brick shape: a gate whose unavailability prevents recovery from it. RM-03 extended to a third requirement: distinguish CANNOT_ASSERT from ASSERTED_NOT_READY, both registered with must-fail controls, neither exiting 0 silently. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/TASKS.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index fa0b27ed..c463f25b 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -93,6 +93,33 @@ 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-10 — the queue guard's failure modes are exactly backwards + +`ci-queue-wait.sh` — a **required** pre-push/pre-merge gate — was observed this session doing both of +these: + +- **Fails OPEN on an unknown result.** `state=unknown ⇒ exit 0`, five times, during real pushes and + real merges. It also evaluates `branch=main` rather than the branch being acted on. +- **Fails CLOSED on credential resolution.** In a worker seat it aborted with + `Gitea token not found`, hard-blocking a legitimate push of completed, tested work. The worker + correctly stopped (Constitution gate 8). The identical command run from that worker's _own worktree_ + in another shell succeeded, so the checkout and remote were fine — the difference was the worker's + process environment. + +**A gate that waves through work it never checked, and blocks work that is ready, has its failure +modes inverted.** Availability failures (cannot reach the provider, cannot resolve a credential) +should degrade to a loud, auditable _inability to assert_ — never to a hard stop on delivery, and +never to a silent pass. Correctness failures (unknown, malformed, terminal-failure) are what must +block. + +This is also the **Pi-brick shape** (P-RECOVERY-001): a gate whose own unavailability prevents the +work needed to recover from it. + +**Requirement on RM-03, extending its existing two defects:** the guard must distinguish +`CANNOT_ASSERT` (credential/transport/provider unavailable — loud, audited, does not silently pass and +does not permanently block) from `ASSERTED_NOT_READY` (a real non-green CI state — blocks). Both are +registered R-002 cases with must-fail controls; neither may exit 0 silently. + ### D-9 — the comms path shell-interprets message bodies (injection-shaped, found by accident) Sending a status message with `agent-send.sh -m "...`backticks`..."` caused bash to **execute** the -- 2.54.0 From 75dfe2fa75828e2ed28fac4c0839b217dd44ce22 Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 17:56:34 -0500 Subject: [PATCH 04/22] =?UTF-8?q?docs(remediation):=20bank=20D-11=20?= =?UTF-8?q?=E2=80=94=20identity=20drift=20+=20seat=20capability=20opacity?= =?UTF-8?q?=20at=20dispatch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RM-01's seat was briefed to export MOSAIC_GIT_IDENTITY; its commits are authored as the generic mosaic-coder fallback, so git history cannot say which seat did the work. P-WRAPPER-001 reproduced on our own delivery. Separately, nothing at dispatch time revealed the seat lacked a credential for the target provider — discovered only when it failed mid-task after ~$9 and 69% context. get_gitea_token behaved correctly by refusing to borrow another slot's token; the dispatch-time information simply did not exist. RM-50 gains per-seat capability declaration + pre-dispatch check; RM-04 gains identity-binding verified by an exit-asserting test rather than assumed from an export in a brief. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/TASKS.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index c463f25b..4a6248d8 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -93,6 +93,34 @@ 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-11 — seat identity did not survive into git, and seat capability is invisible at dispatch + +Two defects, one dispatch (RM-01 → `f10-coder`): + +**(a) Identity drift — P-WRAPPER-001, reproduced on our own delivery.** The brief instructed the seat +to `export MOSAIC_GIT_IDENTITY=f10-coder`. Its commits are authored +`mosaic-coder ` — the generic fallback. **You cannot tell from git history +which seat did this work.** Recorded, not rewritten: the drift is the evidence. + +**(b) Capability opacity.** Nothing at dispatch time revealed that `f10-coder` had no credential for +the target provider. Per-slot tokens live at `~/.config/mosaic/secrets/gitea-tokens/`; the seat holds +`gitea-usc-f10-coder` but not `gitea-mosaicstack-f10-coder`. This surfaced only when the seat failed +**mid-task, after ~$9 and 69% of its context.** The orchestrator (me) selected a seat without any way +to check it could act on the target repo — and there was no way to check. + +`get_gitea_token` behaved **correctly**: it refused to fall through and borrow another slot's token, +failing loud precisely to protect gate-16 attribution. The tooling was right; the _dispatch-time +information_ did not exist. + +**This is P-RECOVERY-001's "honest capability labeling" applied to seats rather than services.** A seat +should declare what it can actually do — which providers, which repos, which credentials — and that +declaration must be **checkable before dispatch**, not discovered by failure after the budget is spent. + +**Requirements:** RM-50 (roster ownership) gains per-seat capability declaration and a pre-dispatch +capability check; RM-04 (activation coherence) gains the identity-binding half — a seat's declared +identity must provably reach its commits, verified by an exit-asserting test, not assumed from an +`export` in a brief. + ### D-10 — the queue guard's failure modes are exactly backwards `ci-queue-wait.sh` — a **required** pre-push/pre-merge gate — was observed this session doing both of -- 2.54.0 From 2201c30284d5836c8f4284fa5d7171e8a7827c6b Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 17:59:06 -0500 Subject: [PATCH 05/22] =?UTF-8?q?docs(remediation):=20correct=20D-11(a)=20?= =?UTF-8?q?mechanism=20=E2=80=94=20token=20identity=20and=20commit=20autho?= =?UTF-8?q?rship=20are=20separate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per Mos. MOSAIC_GIT_IDENTITY resolves the TOKEN; commit author comes from git config user.name/user.email, a separate setting that fell back to the generic value. The export could never have fixed authorship — my worker brief instructed only the export, so the seat did what it was told and the commits were still mis-attributed. The error was in the brief before it was in the finding. Requirement is COHERENCE: token and authorship must agree; either half alone is drift. Belongs in seat setup, verified by an exit-asserting test that commits and asserts the author — not in prose a seat can follow correctly and still end up wrong. Capability check mechanized: capability IS token-file existence. Before dispatching seat X to provider Y, test gitea--.token exists. The token-file set is the authoritative capability registry. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/TASKS.md | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index 4a6248d8..b1ee3d93 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -97,10 +97,22 @@ is the class confirmed, not anecdote. Two defects, one dispatch (RM-01 → `f10-coder`): -**(a) Identity drift — P-WRAPPER-001, reproduced on our own delivery.** The brief instructed the seat -to `export MOSAIC_GIT_IDENTITY=f10-coder`. Its commits are authored -`mosaic-coder ` — the generic fallback. **You cannot tell from git history -which seat did this work.** Recorded, not rewritten: the drift is the evidence. +**(a) Identity drift — P-WRAPPER-001, reproduced on our own delivery.** The seat's commits are +authored `mosaic-coder ` — the generic fallback. **You cannot tell from +git history which seat did this work.** Recorded, not rewritten: the drift is the evidence. + +> **Mechanism, corrected (Mos).** My original framing here was wrong, and the error was in the brief +> before it was in the finding. `MOSAIC_GIT_IDENTITY` resolves the **token** (which per-slot credential +> the wrappers act with). The **commit author** comes from `git config user.name` / `user.email`, which +> is a **separate setting** — it fell back to the generic value because nothing set it. Exporting the +> identity could never have fixed authorship. **My worker brief instructed only the export, so the +> seat did exactly what it was told and the commits were still mis-attributed.** +> +> **The requirement is coherence: token and authorship must agree.** A seat acting with +> `gitea-mosaicstack-f10-coder` must also commit as `f10-coder `. +> Either half alone is identity drift — one produces the right credential with the wrong author, the +> other the reverse. That coherence _is_ P-WRAPPER-001, and it belongs in seat setup, not in prose +> instructions a seat may follow correctly and still end up wrong. **(b) Capability opacity.** Nothing at dispatch time revealed that `f10-coder` had no credential for the target provider. Per-slot tokens live at `~/.config/mosaic/secrets/gitea-tokens/`; the seat holds @@ -116,10 +128,18 @@ information_ did not exist. should declare what it can actually do — which providers, which repos, which credentials — and that declaration must be **checkable before dispatch**, not discovered by failure after the budget is spent. -**Requirements:** RM-50 (roster ownership) gains per-seat capability declaration and a pre-dispatch -capability check; RM-04 (activation coherence) gains the identity-binding half — a seat's declared -identity must provably reach its commits, verified by an exit-asserting test, not assumed from an -`export` in a brief. +**Requirements.** + +- **RM-04 (activation coherence)** gains the identity-binding half: seat setup must set **both** the + token identity **and** `git config user.name`/`user.email`, coherently. Verified by an + exit-asserting test that makes a commit and asserts its author — never assumed from an instruction + in a brief. +- **RM-50 (roster ownership)** gains per-seat capability declaration plus a **pre-dispatch capability + check**. Mos (who owns provisioning) confirms the check is mechanically trivial: **capability is + token-file existence.** Before dispatching seat `X` to provider `Y`, test that + `~/.config/mosaic/secrets/gitea-tokens/gitea--.token` exists; if absent, provision it or pick a + provisioned seat. **The token-file set is the authoritative capability registry.** A one-second check + would have replaced a mid-task failure that cost ~$9 and 69% of a seat's context. ### D-10 — the queue guard's failure modes are exactly backwards -- 2.54.0 From be10bdc8281f109daa41389a2688574bccb7e62a Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 18:01:55 -0500 Subject: [PATCH 06/22] =?UTF-8?q?docs(remediation):=20board=20tick=20?= =?UTF-8?q?=E2=80=94=202=20PRs=20merged,=20RM-01=20on=20rotated=20seat,=20?= =?UTF-8?q?dispatch=20doctrine?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Board now carries the pre-dispatch capability check (token-file existence), the token/authorship coherence rule, and the accreted worker-brief doctrine, so a compacted or fresh seat inherits them mechanically rather than by recall. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/BOARD-LEDGER.md | 10 ++++++++++ docs/remediation/BOARD.md | 34 ++++++++++++++++---------------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/docs/remediation/BOARD-LEDGER.md b/docs/remediation/BOARD-LEDGER.md index 9510ff92..7c9e1560 100644 --- a/docs/remediation/BOARD-LEDGER.md +++ b/docs/remediation/BOARD-LEDGER.md @@ -13,3 +13,13 @@ Correct for the CI container (runs as root), fatal for EVERY non-root local chec ### **D-2 / hygiene — husky `prepare` fails `EPERM` copying into root-owned `.husky/_/`.** Repo working tree has root-owned dirs (`.husky/`, repo root) under a non-root agent. Worked around with the intended `HUSKY=0` escape hatch (does NOT disable the existing pre-commit/pre-push hooks). + + + +### **D-5 / P-QUEUE-001 + P-CONFORMANCE-001 — KEYSTONE: an inert gate that erased its own evidence.** + +Merged PR #868 (`b79336a8`) shipped a file that FAILS `pnpm format:check` ⇒ the CI format gate did not block. An unrelated later PR (#872) then reformatted that file via its own `lint-staged`, so `main` went green again and nobody learned the gate had failed to fire. Verified blob-level under the repo's own config. **Detection must be per-merge-commit against that commit's own tree** — a "is main green today" check reports all-clear on this exact defect. Binding on RM-02/RM-55. Full chain in `TASKS.md` §1a. NOT quiet-patched, by Mos's ruling: patching the symptom destroys the signal. + +### **D-4 / P-LIFECYCLE + hygiene — a dispatched agent silently IGNORED an in-message context reset.** + +planner-sol was at 64.3%/372k; the brief asked it to reset first; it began work on dirty context anyway. Only an out-of-band `/new` driven by the orchestrator guaranteed clean state. Confirms the postmortem thesis: **instructions are not enforcement.** Reset must be a mechanical pre-dispatch step, not a request. diff --git a/docs/remediation/BOARD.md b/docs/remediation/BOARD.md index 8d4d9d58..4f5c14b6 100644 --- a/docs/remediation/BOARD.md +++ b/docs/remediation/BOARD.md @@ -1,6 +1,6 @@ # mos-remediation — LIVE BOARD (keep < 8 KB) -**Phase:** EXECUTING — first PR merged; RM-01 in flight; all 3 decisions ruled. +**Phase:** EXECUTING — 2 PRs merged; RM-01 in flight (rotated seat); 11 dogfood classes banked. **Updated:** 2026-07-31 (mos-remediation orchestrator; seat active on `mosaic-fleet`). ## Head @@ -16,14 +16,14 @@ ## In-flight -| Task | Owner | State | -| ------------------------------------------------- | --------------- | ------------------------------------------------------------------ | -| PR #1026 docs (mission record + backlog) | mos-remediation | OPEN, retargeted to main, rebased; diff verified docs-only | -| PR #1025 hygiene | — | **MERGED** 52414605; rev-974 APPROVE + CI #2158 8/8 terminal-green | -| DECISION-1 wire-in point (charter change) | Mos / Jason | ESCALATED — both planners reject the charter's target | -| DECISION-2 rollback artifact + availability trade | Jason | ESCALATED | -| DECISION-3 RM-03 vs parked PR #1023 ownership | Mos | ESCALATED | -| RM-01 reproducible checkout (unblocks everything) | unassigned | READY TO DISPATCH | +| Task | Owner | State | +| ----------------------------------- | ---------- | ------------------------------------------------------------------ | +| PR #1025 hygiene | — | **MERGED** 52414605 (rev-974 APPROVE + CI 8/8 terminal-green) | +| PR #1026 mission package | — | **MERGED** 01e966f3 (docs policy: CI-green, precedent #968/#863) | +| PR #1027 RM-01 | f10-coder | **DRAFT** — AC2/3/5/7/8 proven; AC1/AC4/AC6 open | +| RM-01 remainder: AC6 race, AC1, AC4 | f10-coder | IN FLIGHT on ROTATED seat (reset 0.0%, rehydrated from #1027 body) | +| RM-03 queue guard (3 defects) | — | **HOLD** — #1023 SUPERSEDED-PENDING-JASON | +| RM-02 gate registry (keystone) | unassigned | READY — explicitly NOT held by RM-03 | ## Fleet seats @@ -39,6 +39,14 @@ - Freeze: LIFTED for this workstream only. - Git identity: `MOSAIC_GIT_IDENTITY=mos-dt-0` INTERIM. Mos ruled gate-16 HOLDS (author≠reviewer is what gate-16 protects; rev-974 reviews, mos-dt-0 never self-reviews). Dedicated identity TRACKED, Mos provisions. +- Capability check (D-11b): before dispatching seat X to provider Y, verify + `~/.config/mosaic/secrets/gitea-tokens/gitea--.token` exists. Token-file set = authoritative + capability registry. Mos owns provisioning; escalate missing pairs to him. +- Seat identity (D-11a): token identity AND `git config user.name`/`user.email` must BOTH be set and + agree. Exporting `MOSAIC_GIT_IDENTITY` alone does NOT fix commit authorship. +- Standing worker-brief doctrine (accreted, mandatory in every brief): don't weaken a RED test to make + it pass; if a check is unrunnable as written SAY SO, never silently substitute; `agent-send -f` never + `-m`; heavy artifacts off shared `/tmp`. - Remote control: native `/remote-control` NOT wired in this runtime. Path is **Mos-relay** (Jason ↔ mos-claude via Discord ↔ mos-remediation via agent-send). Not a blocker. @@ -72,14 +80,6 @@ PR #1025 AC2's fixture `mkdir -p apps/*/venv/lib` creates a literal `apps/*/venv Running the required `ci-queue-wait.sh --purpose push` before pushing produced `state=unknown ... exit 0` — the exact defect at `ci-queue-wait.sh:282-288` that PR #1023 is parked on. It also evaluated `branch=main` rather than the branch being pushed. The mission's own required pre-push gate passed me on an indeterminate result. Third independent live instance of the class. -### **D-5 / P-QUEUE-001 + P-CONFORMANCE-001 — KEYSTONE: an inert gate that erased its own evidence.** - -Merged PR #868 (`b79336a8`) shipped a file that FAILS `pnpm format:check` ⇒ the CI format gate did not block. An unrelated later PR (#872) then reformatted that file via its own `lint-staged`, so `main` went green again and nobody learned the gate had failed to fire. Verified blob-level under the repo's own config. **Detection must be per-merge-commit against that commit's own tree** — a "is main green today" check reports all-clear on this exact defect. Binding on RM-02/RM-55. Full chain in `TASKS.md` §1a. NOT quiet-patched, by Mos's ruling: patching the symptom destroys the signal. - -### **D-4 / P-LIFECYCLE + hygiene — a dispatched agent silently IGNORED an in-message context reset.** - -planner-sol was at 64.3%/372k; the brief asked it to reset first; it began work on dirty context anyway. Only an out-of-band `/new` driven by the orchestrator guaranteed clean state. Confirms the postmortem thesis: **instructions are not enforcement.** Reset must be a mechanical pre-dispatch step, not a request. - ## Decisions log -- 2.54.0 From 0ffdcf14bd2a845cbd5832a58add6052cd74319e Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 18:03:29 -0500 Subject: [PATCH 07/22] =?UTF-8?q?docs(remediation):=20bank=20D-12=20?= =?UTF-8?q?=E2=80=94=20pr-create=20silently=20dropped=20--draft;=20I=20tru?= =?UTF-8?q?sted=20exit=200=20over=20observed=20state?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #1027 was created with -d because it carries partial unproven work. tea auth was stale, the wrapper fell back to the raw API which cannot set draft, warned on stderr, and exited 0. The PR sat open and mergeable for ~25 minutes, protected only by the word DRAFT in its title and body. I had reported it to the coordinator as a draft. Three failures: a fallback silently degrading a SAFETY flag (nuisance for --labels, dangerous for --draft); a correct warning nobody consumed; and my own failure to verify the flag took effect — I checked the PR existed, not that it had the property I required. That is written-unverified treated as verified, by me, on exactly the class of tool this mission exists to distrust. Fixed via the WIP: title prefix; draft:True verified after. RM-02 gains a must-fail control: a wrapper that cannot honour a safety-relevant argument must exit non-zero. RM-24 gains this as its canonical tri-state example. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/TASKS.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index b1ee3d93..54a436f0 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -93,6 +93,39 @@ 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-12 — a requested SAFETY flag was silently degraded, and I did not check + +I created PR #1027 with `pr-create.sh ... -d` (draft) because it carries **partial, unproven work**. +`tea` authentication was stale, so the wrapper fell back to its raw-API path — which cannot set draft — +and emitted: + +``` +Warning: API fallback applies title/body/head/base only; labels/milestone/draft require authenticated tea setup. +``` + +The PR was created **not-draft**. I read the success output, saw the PR number, and moved on. I then +reported to the coordinator that the PR was "opened as draft". **It was open, mergeable, and marked +ready for ~25 minutes**, protected only by the words "DRAFT" and "do not merge" in its title and body — +i.e. by prose a human might read, not by the platform control I asked for. Detected only because a +watcher polled `draft:` and the value disagreed with my belief. Corrected by setting the `WIP:` title +prefix (Gitea's draft mechanism); `draft: True` verified after. + +**Three distinct failures, and the third is mine:** + +1. **Silent degradation of a safety flag.** The fallback path dropped `--draft` and still exited 0. A + fallback that cannot honour a _safety_ argument must fail, not proceed — degrading `--labels` is a + nuisance; degrading `--draft` publishes unproven work as ready to merge. +2. **The warning went to stderr and nothing consumed it.** It was correct, specific, and ignored — a + warning nobody acts on is indistinguishable from no warning. +3. **I did not verify the flag took effect.** I checked that the PR existed, not that it had the + property I required. This is the mission's own thesis turned on me: **I trusted a success exit code + over an observed state**, on exactly the class of tool this mission exists to distrust. + +**Requirements.** RM-02: a wrapper that cannot honour a safety-relevant argument must exit non-zero — +registered with a must-fail control asserting `--draft` on a degraded path fails rather than proceeds. +RM-24 (tri-state write outcomes): this is precisely `written-unverified` being treated as `verified` — +the PR write succeeded, the _requested property_ was never confirmed, and no one looked. + ### D-11 — seat identity did not survive into git, and seat capability is invisible at dispatch Two defects, one dispatch (RM-01 → `f10-coder`): -- 2.54.0 From d1e7ba19caad1dedd876ade17395ee019515c6dd Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 18:06:18 -0500 Subject: [PATCH 08/22] docs(remediation): promote observe-the-property principle to charter; bank D-13 dual credential registries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Charter gains a first-class principle per Mos: no write is done until the requested PROPERTY is observed; a success exit code is not evidence. Success output is designed to be believed — that is why the inert-gate class exists and why the P-WRAPPER tri-state is not optional. Recorded with its provenance: the orchestrator committed this exact error (D-12), and three of the session's twelve instances were its own. D-13: diagnosing D-12 found two parallel credential registries that can disagree. gitea-mosaicstack-mos-dt-0.token EXISTS, but tea has no mosaicstack login for that identity — so raw-API paths work while tea-dependent wrapper paths silently degrade. tea is not stale; the login does not exist. Capability declared authoritative by the token-file set does not govern the tea path. RM-04 must reconcile the registries (or assert agreement at startup, with a must-fail control). RM-50's pre-dispatch check must verify capability for the path actually used. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/MISSION.md | 18 ++++++++++++++++++ docs/remediation/TASKS.md | 27 +++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/docs/remediation/MISSION.md b/docs/remediation/MISSION.md index 2065267d..682eda5e 100644 --- a/docs/remediation/MISSION.md +++ b/docs/remediation/MISSION.md @@ -10,6 +10,24 @@ Convert the 15 accepted postmortem remediation proposals into a working, **dogfo **North star:** anything with a deterministic right answer moves OUT of the LLM into a deterministic gate/program; the LLM handles only genuine judgment. +### First-class principle — observe the property, not the exit code + +> **No write is done until the requested PROPERTY is observed. A success exit code is not evidence.** +> +> **Success output is designed to be believed.** That is the whole reason the inert-gate class exists +> and why P-WRAPPER-001's tri-state (`verified` / `written-unverified` / `failed`) is not optional. The +> failure is not carelessness — a green is _engineered_ to be trusted, so trusting it is the default +> behaviour of a competent operator, not a lapse. +> +> Promoted to the charter by Mos (2026-07-31) after the orchestrator committed this exact error: a +> `--draft` flag was silently dropped by a wrapper fallback that still exited 0, and the PR was reported +> as a draft on the strength of the exit code rather than an observed `draft: true` (D-12). Twelve +> failure instances were banked in that session; **three of them were the orchestrator's own.** That +> ratio is the point — the mechanism must catch the mechanic too, or it is not a mechanism. +> +> Operationally: after any write, read back the property you required. Applies to gates, wrappers, PR +> flags, commit authorship, file installs, and message delivery alike. + ## Decision record (authoritative, immutable) - **15/15 proposals decided: 13 accept, 2 modify (P-AUTHORITY-001, P-INBOX-001), 0 reject.** diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index 54a436f0..09517924 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -93,6 +93,33 @@ 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-13 — two credential registries that can disagree (why the `--draft` fallback fired at all) + +Diagnosing D-12's root cause surfaced a distinct defect. There are **two parallel credential +registries**, and capability in one does not imply capability in the other: + +| registry | contents for identity `mos-dt-0` on `mosaicstack` | +| ------------------------------------------------------ | -------------------------------------------------------------------------------------------- | +| token files — `~/.config/mosaic/secrets/gitea-tokens/` | `gitea-mosaicstack-mos-dt-0.token` **EXISTS** | +| `tea login list` | **NO** `mosaicstack` login for `mos-dt-0` (only `mosaicstack-mos` and `mosaicstack-rev-974`) | + +So `get_gitea_token` succeeds and every raw-API path works, while every **tea-dependent** wrapper path +fails its login validation and silently degrades to the API fallback — which is exactly what dropped +`--draft`. **tea is not "stale"; the login simply does not exist for that identity.** + +This matters beyond one flag: capability was declared authoritative by the token-file set (D-11b), but +that registry does not govern the tea path. A seat can be _fully provisioned_ by the authoritative +registry and still lose functionality with no error — only a warning, and only on the degraded path. + +**Requirements.** RM-04 (activation coherence): the two registries must be reconciled — one source of +truth, or a startup check asserting they agree, with a must-fail control proving disagreement is +detected. RM-50: the pre-dispatch capability check must verify capability for the **path actually +used**, not merely token-file presence. + +**Confirmed working despite the gap** (so this is degradation, not outage): pushes, `pr-merge.sh`, +PR/issue creation via API fallback, comment posting, and all reads. Impact is confined to +tea-only features — `--draft`, `--labels`, `--milestone`. + ### D-12 — a requested SAFETY flag was silently degraded, and I did not check I created PR #1027 with `pr-create.sh ... -d` (draft) because it carries **partial, unproven work**. -- 2.54.0 From f13222b76bccae6007152374ed322c08e073a0f2 Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 18:07:16 -0500 Subject: [PATCH 09/22] docs(remediation): charter reflects DECISION-1 corrected wire-in target and current status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The charter's build-1 cell still named mosaic_orchestrator.py::run_single_task after DECISION-1 ruled against it. Leaving the charter contradicting the ruled decision would mislead any future reader who starts there — corrected in place with the rationale and provenance, rather than only in TASKS.md. Also: status PLANNING -> EXECUTING; scout TODO discharged (file is in-tree) with a note that its findings stand but its recommended wire-in point is superseded. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/MISSION.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/remediation/MISSION.md b/docs/remediation/MISSION.md index 682eda5e..bb823ad3 100644 --- a/docs/remediation/MISSION.md +++ b/docs/remediation/MISSION.md @@ -1,7 +1,7 @@ # Mosaic Stack Remediation — Mission Charter **Owner:** project orchestrator `mos-remediation` (Claude, launched in `/src/mosaic-stack`). -**Origin:** 2026-07-16..31 fleet lifecycle postmortem. **Status:** PLANNING (task decomposition). +**Origin:** 2026-07-16..31 fleet lifecycle postmortem. **Status:** EXECUTING (planning complete; RM-01 in flight). **HOLD lifted** for this workstream by Jason, 2026-07-31 — "begin full mosaic fleet operation on this." ## Goal @@ -34,17 +34,17 @@ gate/program; the LLM handles only genuine judgment. - Site + `annotations.json`: `jarvis-brain/docs/postmortem-spec/site/` (committed, origin/main). - Discussion checkpoint (rich rationale per proposal): `jarvis-brain/docs/scratchpads/postmortem/REMEDIATION-DISCUSSION-STATE.md`. - Postmortem report: mosaicstack/stack PR #107 (merged 88f4ee04). -- MACP wiring scout (verdict c=STRANDED): `/tmp/macp-wiring-investigation.md` (copy into this dir — see TODO). +- MACP wiring scout (verdict c=STRANDED): [`MACP-WIRING-SCOUT.md`](./MACP-WIRING-SCOUT.md) (copied into this dir; TODO discharged). Its findings are sound; its _recommended wire-in point_ is superseded by DECISION-1. ## The plan — 15 proposals collapse to 4 builds + hygiene -| Build | Absorbs | What it is | -| ------------------------------------------------------------ | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **1. One choke-point service** (mechanical enforcer) | MISSION, STATE, AUDIT, WRAPPER, QUEUE | Deterministic program every task/data mutation flows through. **Wire the stranded `@mosaicstack/macp`** in at `mosaic_orchestrator.py::run_single_task` — typed tasks, gate-runner, event ledger, credential binding, tri-state write outcomes. | -| **2. One durable spine + hot path** | (storage under everything) | **PG system-of-record + Redis hot queue** (transactional-outbox). Mission/tasks/state-claims/audit-ledger/comms-inbox all land here. | -| **3. Rotation lifecycle** (finish the Mission Control Plane) | LIFECYCLE, CONTRACT, GUIDE, RECOVERY | Coordinator daemon: contract-hash binding, compaction-detected → rotate-not-compact, checkpoint→fresh-session→rehydrate, broker-independent recovery. Deterministic, not an LLM. Reuse `packages/coord`; existing PRD at `docs/mission-control/`. | -| **4. Comms service** | AUTHORITY, INBOX (+ versioning roadmap) | Envelope (comms/v1) → sole-path service → PG/Redis → pluggable adapters (tmux→Matrix/Discord/Slack/Telegram). Version the protocol, not participants. | -| **+ Hygiene & proof** | FLEET, WORKFLOW, CONFORMANCE | One roster-owned socket/host + stale GC; allowlist auto-sync; the conformance harness that fault-injects the failure classes and proves builds 1–4 hold. | +| Build | Absorbs | What it is | +| ------------------------------------------------------------ | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **1. One choke-point service** (mechanical enforcer) | MISSION, STATE, AUDIT, WRAPPER, QUEUE | Deterministic program every task/data mutation flows through. **Wire the stranded `@mosaicstack/macp`** — typed tasks, gate-runner, event ledger, credential binding, tri-state write outcomes. ⚠ **Target CORRECTED 2026-07-31 (DECISION-1, Mos):** a new production Node `TaskExecutor` on the **live** dispatch path (`packages/mosaic` launch + `packages/coord`), which Coord/Forge/live-dispatch submit through. **NOT** `mosaic_orchestrator.py::run_single_task` — that controller is `"enabled": false` and references a dispatcher absent from this checkout; wiring it would strand the executor, reproducing this mission's own disease. The Python rail is **deleted**, not ported. Both planners reached this independently. | +| **2. One durable spine + hot path** | (storage under everything) | **PG system-of-record + Redis hot queue** (transactional-outbox). Mission/tasks/state-claims/audit-ledger/comms-inbox all land here. | +| **3. Rotation lifecycle** (finish the Mission Control Plane) | LIFECYCLE, CONTRACT, GUIDE, RECOVERY | Coordinator daemon: contract-hash binding, compaction-detected → rotate-not-compact, checkpoint→fresh-session→rehydrate, broker-independent recovery. Deterministic, not an LLM. Reuse `packages/coord`; existing PRD at `docs/mission-control/`. | +| **4. Comms service** | AUTHORITY, INBOX (+ versioning roadmap) | Envelope (comms/v1) → sole-path service → PG/Redis → pluggable adapters (tmux→Matrix/Discord/Slack/Telegram). Version the protocol, not participants. | +| **+ Hygiene & proof** | FLEET, WORKFLOW, CONFORMANCE | One roster-owned socket/host + stale GC; allowlist auto-sync; the conformance harness that fault-injects the failure classes and proves builds 1–4 hold. | ## The finding that sets the cost @@ -55,6 +55,7 @@ orphaned context loader, a fail-open bypass. **Work = wire + consolidate + retir ## Sequencing (skeleton — adversarial decomposition refines this) 1. **Spine + choke-point service** (builds 1+2) — foundation; unlocks MISSION/STATE/AUDIT/WRAPPER/QUEUE at one integration point. + (Per DECISION-1, a P0 phase of provable-gate + activation work precedes this; see `TASKS.md` §3.) 2. **Rotation daemon** (build 3) on that spine — the drift fix proper. 3. **Comms service** (build 4) — envelope → service → PG/Redis → adapters; retire direct-tmux. 4. **Hygiene + conformance** (build 5) — fleet convergence, allowlist sync, dogfood harness. -- 2.54.0 From 7f686aaf6d4bd5af2e9e06fa64b91b52bb053b64 Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 18:11:01 -0500 Subject: [PATCH 10/22] docs(remediation): bank D-14 decision-propagation requirement; record D-13 reconciliation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit D-14: DECISION-1 was ruled and applied to TASKS.md while MISSION.md — the charter a cold-starting seat reads first — kept the superseded wire-in target for hours, flagged CONTESTED on the board but never corrected in the source of truth. A resuming seat would have read the rejected target as authoritative. Caught by hand during an unrelated edit; nothing would have caught it otherwise. P-MISSION-001 turned on ourselves: a decision that lives in a ruling and a board note but not in the authoritative record has been AGREED, not MADE. Requirement: rulings must propagate mechanically — decisions as records, documents rendering rather than restating, and a must-fail check where duplication is unavoidable. Interim rule until the DB cutover: the same commit that records a ruling updates every document stating it. D-13 updated with Mos's reconciliation: 5 of 6 mosaicstack-provisioned seats have no tea login — systemic, not a one-off. Supersedes D-11(b): the token-file set is necessary but NOT sufficient; capability is per-path. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/TASKS.md | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index 09517924..91897ad5 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -93,6 +93,34 @@ 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-14 — a ruled decision did not propagate to the authoritative record + +DECISION-1 (the corrected choke-point wire-in target) was ruled by the coordinator and applied to +`TASKS.md`. **`MISSION.md` — the charter, the document a cold-starting seat reads first — kept the +superseded target for hours.** It was flagged `CONTESTED` in a board note, then the ruling landed and +nobody edited the charter. A seat resuming from the charter would have read the _rejected_ target as +authoritative and wired the choke point into a disabled rail — the precise failure the ruling existed +to prevent. + +Caught by hand, during an unrelated edit. Nothing would have caught it otherwise. + +**This is P-MISSION-001 turned on ourselves.** The mission's own thesis is that convention exists and +_enforcement_ is the gap: a decision that lives in a chat ruling and a board note, but not in the +source of truth, has not actually been made — it has been _agreed_. The two are different, and the +difference is exactly what this mission is about. + +**Requirement (not merely a fix).** A ruled decision must propagate **mechanically** to the +authoritative record; it must not depend on someone remembering to edit a second file. Concretely, once +mission state is DB-backed (RM-53 / the P-MISSION cutover): + +- a decision is a **record**, not prose duplicated across documents; +- documents _render_ decisions rather than restating them, so there is one place to be wrong; +- and where duplication is unavoidable, a check asserts the authoritative record and the derived + document agree — with a must-fail control proving divergence is detected. + +Until then, the interim rule: **the same commit that records a ruling updates every document that +states it.** Interim rules are exactly what the DB cutover exists to replace. + ### D-13 — two credential registries that can disagree (why the `--draft` fallback fired at all) Diagnosing D-12's root cause surfaced a distinct defect. There are **two parallel credential @@ -120,6 +148,27 @@ used**, not merely token-file presence. PR/issue creation via API fallback, comment posting, and all reads. Impact is confined to tea-only features — `--draft`, `--labels`, `--milestone`. +**Reconciliation run by Mos (the manual form of RM-04's assert-agreement, done once by hand).** For +`git.mosaicstack.dev`, the token-file registry holds **six** seats; `tea` holds logins for **two**: + +| state | seats | +| ------------------------------------------------ | -------------------------------------------------------- | +| token file present, **no** mosaicstack tea login | `f10-coder`, `jarvis`, `mos-admin`, `mos-dt-0`, `pepper` | +| token file present **and** tea login present | `rev-974` (only) | + +**Five of six provisioned seats are silently degraded on tea-only features.** This is _systemic_, not +a one-off — which is why the fix is registry reconciliation (RM-04) and not a per-seat mint. Minting +one seat would clear a symptom and leave the class live. + +Mos deliberately deferred the mint: it is not on RM-01's critical path, and additively editing shared +`tea` config underneath running work is a change he declined to make without cause. Full remediation — +mint the five missing logins **and** wire the startup must-fail assertion that _detects_ disagreement — +lands as RM-04 at a non-critical seam, or immediately if any seat needs a tea-only feature to progress. + +**Correction of record:** this supersedes D-11(b)'s claim that the token-file set is _the_ authoritative +capability registry. It is **necessary but not sufficient**. Capability is **per-path**: the token file +governs the raw-API path, the tea login governs the tea path, and the two can disagree silently. + ### D-12 — a requested SAFETY flag was silently degraded, and I did not check I created PR #1027 with `pr-create.sh ... -d` (draft) because it carries **partial, unproven work**. -- 2.54.0 From d0ad6e942b48f9cd51e366c0c4d3693c18345a7b Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 18:12:16 -0500 Subject: [PATCH 11/22] =?UTF-8?q?docs(remediation):=20propagate=20DECISION?= =?UTF-8?q?-2=20to=20charter=20=E2=80=94=20second=20un-propagated=20ruling?= =?UTF-8?q?,=20found=20by=20applying=20D-14?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Applied D-14's own interim rule immediately instead of waiting to be bitten again, and it caught a second instance within minutes: MISSION.md's standing directives still stated the DB hard-cutover with no mention of Mos's binding qualification that the spine must not be a single-point hard-stop (degraded mode + rollback artifact required). A seat reading the charter would have designed toward an availability posture the coordinator had explicitly rejected, with the superseded 'no DB means the fleet stops' recommendation nowhere contradicted. Two un-propagated rulings out of two that touched charter text. Without a mechanism, propagation failure is the default outcome, not an oversight — which is the argument for D-14 being a requirement rather than a discipline. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/MISSION.md | 5 +++++ docs/remediation/TASKS.md | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/docs/remediation/MISSION.md b/docs/remediation/MISSION.md index bb823ad3..f3b434f0 100644 --- a/docs/remediation/MISSION.md +++ b/docs/remediation/MISSION.md @@ -69,6 +69,11 @@ orphaned context loader, a fail-open bypass. **Work = wire + consolidate + retir (WRAPPER), auto-sync sweep (WORKFLOW), #1018 stale-consumed (INBOX). The fleet is its own test bed. - **Orchestration tracking → DB**, hard cutover ("rip off the bandaid"), NO flat-file interim. jarvis-brain PDA flat-files untouched. Current flat-file tracking runs as-is/unhardened until DB tracking is real, then one clean replace. + - ⚠ **QUALIFIED 2026-07-31 (DECISION-2, Mos):** the DB spine **must NOT be a single-point hard-stop.** + A broker-independent / degraded mode **and** a rehearsed rollback artifact are **design requirements** + (P-RECOVERY-001), binding now on RM-12, RM-13, RM-23, RM-36 and RM-53. This **supersedes** the earlier + orchestrator recommendation to pre-commit "no DB ⇒ the fleet stops" — that answer is _not_ on record. + Only the specific availability _target_ remains open, queued for Jason; it does **not** block current work. ## The 15 decisions (one-line; full rationale in the checkpoint) diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index 91897ad5..71989fa0 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -121,6 +121,18 @@ mission state is DB-backed (RM-53 / the P-MISSION cutover): Until then, the interim rule: **the same commit that records a ruling updates every document that states it.** Interim rules are exactly what the DB cutover exists to replace. +**The rule found a second instance within minutes of being written.** Auditing the charter against all +rulings to date (rather than waiting to be bitten again) surfaced that **DECISION-2 had also not +propagated**: `MISSION.md`'s standing directives still stated the DB hard-cutover with no mention of +Mos's binding qualification that _the spine must not be a single-point hard-stop_ (degraded mode + +rollback artifact required). A seat reading the charter would have designed toward an availability +posture the coordinator had explicitly rejected — and would have found the superseded +"no DB ⇒ the fleet stops" recommendation nowhere contradicted. Now corrected in place. + +**Two un-propagated rulings out of two rulings that touched charter text.** The propagation gap is not +an oversight that happened once; without a mechanism it is the _default outcome_. That is the argument +for making this a requirement rather than a discipline. + ### D-13 — two credential registries that can disagree (why the `--draft` fallback fired at all) Diagnosing D-12's root cause surfaced a distinct defect. There are **two parallel credential -- 2.54.0 From 3477e933dfc2e8909d042cc82001dec6438b5142 Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 18:32:27 -0500 Subject: [PATCH 12/22] =?UTF-8?q?docs(remediation):=20bank=20D-15=20?= =?UTF-8?q?=E2=80=94=20token=20scope=20is=20not=20repository=20permission?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit f10-coder holds gitea-mosaicstack-f10-coder.token with write:repository scope and was verified at mint by 'repo access returns 200'. It cannot push: collaborator lookup 404s and its own token reports push:false, pull:true. Capability has three independent layers — token file (raw-API auth), tea login (tea path), repository permission (actual write authority) — and satisfying two proves nothing about the third. Scope bounds what a token may ATTEMPT; repository permission decides what the user may DO. The charter principle failing on the check meant to confirm capability: a 200 on a READ was accepted as evidence of WRITE. written-unverified treated as verified, by both provisioner and orchestrator, one layer above D-12. RM-50's pre-dispatch check must assert effective permission for the intended operation (permissions.push == true as that seat), not token existence or a read returning 200. A capability check that cannot fail on a seat lacking write permission is itself an inert gate. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/TASKS.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index 71989fa0..e03c3414 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -93,6 +93,44 @@ 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-15 — token scope is not repository permission (a THIRD capability layer) + +`f10-coder` was provisioned with `gitea-mosaicstack-f10-coder.token`, scopes `write:repository` + +`write:issue`, and the mint was verified by "repo access returns 200". It then failed to push: + +``` +remote: error: User permission denied for writing. +remote: error: pre-receive hook declined +``` + +Verified objectively rather than inferred (per the charter principle): + +| probe | result | +| ------------------------------------------------------ | ------------------------------------------- | +| `GET /repos/mosaicstack/stack/collaborators/f10-coder` | **404** — not a collaborator | +| repo permissions as seen by **its own token** | `admin: false`, `push: false`, `pull: true` | + +**Capability has at least three independent layers, and satisfying two proves nothing about the third:** + +1. **Token file exists** → raw-API authentication works (D-11b). +2. **`tea` login exists** → tea-dependent wrapper paths work (D-13). +3. **Repository permission granted** (collaborator/team membership) → _writes_ are actually authorised. + +A token can carry `write:repository` scope and still be refused, because **scope bounds what a token +may attempt; repository permission decides what the user may do.** They are different systems. + +**This is the charter principle failing on the very check meant to confirm capability.** The mint was +validated by an HTTP 200 on a _read_. A 200 proves reachability; it does not prove the property that +was required, which was **write**. Both the provisioner and I accepted it — the same +`written-unverified` treated as `verified` as D-12, one layer up, on a check whose entire purpose was +verification. + +**Requirements.** RM-50's pre-dispatch capability check must probe the **effective permission for the +operation intended** — for push authority, assert `permissions.push == true` as that seat, not token +existence and not a 200 on a read. RM-04's registry reconciliation covers all three layers, with a +must-fail control for each. A capability check that cannot fail on a seat lacking write permission is +itself an inert gate. + ### D-14 — a ruled decision did not propagate to the authoritative record DECISION-1 (the corrected choke-point wire-in target) was ruled by the coordinator and applied to -- 2.54.0 From e233f196b56ae8f8793eba587cd9fc5f0b1575d6 Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 18:40:53 -0500 Subject: [PATCH 13/22] =?UTF-8?q?docs(remediation):=20bank=20D-16=20?= =?UTF-8?q?=E2=80=94=20local=20and=20CI=20test=20gates=20disagree=20by=20e?= =?UTF-8?q?nvironment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ran down Mos's flag. Both hypotheses were wrong: CI runs exactly 'pnpm test' (same command, path IS exercised) and is green, while this host exits 97 on an environment-dependent BASH_LINENO guard (#973) that aborts on bash 5.2.15 and not in CI's container. PR #1027 touches zero files under packages/mosaic, so the guard is genuinely pre-existing — f10-coder's report was accurate in every particular, and main is equally affected here. Not 'merges step around a red' but something worse in one respect: the local gate and the CI gate disagree about what passing means. No agent on this host can get a green pnpm test on any branch. A gate only CI can run cannot be a pre-push gate. Second defect found while establishing this: in the main checkout the same package fails differently (exit 1) because a test scans the working tree and picks up apps/coordinator/venv third-party site-packages. A test whose verdict depends on untracked files is not hermetic — same contamination source that broke format:check, one foreign tree breaking two independent gates. Coordinate with #1007/#1024 rather than opening a third lane. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/TASKS.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index e03c3414..20a65983 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -93,6 +93,44 @@ 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-16 — the local test gate and the CI test gate disagree by environment + +Mos flagged a shape worth chasing: if `pnpm test` exits non-zero on a _pre-existing_ guard, then either +`main` is red and merges step around it (the #868 shape again), or CI does not run that path. **Both +branches turned out wrong, and the truth is a third thing.** Established by running it, not by asking: + +CI runs **exactly** `pnpm test` (`.woodpecker/ci.yml`, `test` step) — the same command. So the path _is_ +exercised. Yet: + +| environment | result | +| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| CI container | `test` step **green** (#2158, #2167) | +| this host, clean worktree | **exit 97** — `WAKE-ASSERT INIT ABORT: BASH_LINENO convention violated on bash 5.2.15(1)-release … expected [3 4], probe reported [3 5] (#973)`, after `PASS=18 FAIL=0` | +| this host, main checkout | **exit 1** — a _different_, second defect (below) | + +The guard is **environment-dependent**: it aborts on this host's bash and not in CI's container. `git +diff origin/main...` confirms PR #1027 touches **zero** files under `packages/mosaic`, so the guard is +genuinely pre-existing and unrelated — **f10-coder's report was accurate in every particular**, and +`main` is equally affected on this host. + +**So it is not "merges step around a red" — it is worse in one specific way: the local gate and the CI +gate do not agree about what passing means.** No agent on this host can obtain a green `pnpm test` at +all, on any branch, including `main`. A gate an operator cannot run is a gate that only CI enforces, +and a gate only CI enforces cannot be a pre-push gate. This is the hermeticity/portability class +already live as #1007 (PR #1024). + +**Second, independent defect found while establishing the above.** In the main checkout the same +package fails differently — exit 1 — because a test **scans the working tree** and asserts on files it +finds, picking up `apps/coordinator/venv/**` (third-party `site-packages`: `pi = math.pi` in `rich`, +`setuptools`, `mypy`). **A test whose result depends on untracked files present in the tree is not +hermetic.** This is the _same_ contamination source that made `pnpm format:check` unpassable (D-1/D-7 +hygiene) — one untracked foreign tree silently breaking two independent gates. + +**Requirements.** RM-01/RM-04: a gate must produce the same verdict on a developer host and in CI, or +declare loudly that it cannot run here — never diverge silently. RM-02 registers both as cases: the +environment-divergence guard, and a hermeticity control asserting a suite's verdict is unchanged by the +presence of untracked directories. Coordinate with #1007/#1024 rather than opening a third lane. + ### D-15 — token scope is not repository permission (a THIRD capability layer) `f10-coder` was provisioned with `gitea-mosaicstack-f10-coder.token`, scopes `write:repository` + -- 2.54.0 From 4512312b9fa0b5c1401c2aac93498a9f17d16daa Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 18:43:25 -0500 Subject: [PATCH 14/22] =?UTF-8?q?docs(remediation):=20D-16=20ownership=20?= =?UTF-8?q?=E2=80=94=20#1024=20is=20Jason-pending;=20CI=20is=20the=20autho?= =?UTF-8?q?ritative=20gate=20for=20#1027?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Propagating Mos's ruling in the same commit that records it, per D-14's interim rule. The hermeticity fix IS PR #1024, which sits in Jason's parked delivery stack, so its disposition is his — marked SUPERSEDED-PENDING-JASON alongside #1023. D-16 strengthens urgency without transferring ownership; we do not open a third lane on a parked PR. Class sharpened: a pre-push gate an operator cannot run locally is a gate only CI enforces, so pointing .husky/pre-push at it misrepresents where the gate lives. Non-hermetic gates make every green host-dependent. #1027 proceeds on CI-green; the local exit-97 is a host-specific guard abort and is not a merge consideration. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/TASKS.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index 20a65983..c5472e27 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -131,6 +131,22 @@ declare loudly that it cannot run here — never diverge silently. RM-02 registe environment-divergence guard, and a hermeticity control asserting a suite's verdict is unchanged by the presence of untracked directories. Coordinate with #1007/#1024 rather than opening a third lane. +**Ownership (Mos, 2026-07-31).** The hermeticity fix **is** PR #1024, which sits in **Jason's parked +delivery stack** — so, like #1023, its disposition is Jason's. Marked `SUPERSEDED-PENDING-JASON` +alongside #1023. D-16 strengthens the urgency but does not transfer ownership: **we do not open a third +lane on a parked PR.** The one-line escalation for Jason: _two independent gates +(`format:check`, `pnpm test`) were broken by a single untracked directory, and a third +(`pnpm test`) disagrees between host and CI — non-hermetic gates make every green host-dependent._ + +**Sharpened statement of the class (Mos).** A pre-push gate an operator _cannot run locally_ is a gate +only CI enforces — so pointing `.husky/pre-push` at it **misrepresents where the gate lives**. Combined +with the shared root cause across two gates, the finding is: **non-hermetic gates make every green +host-dependent.** A gate that only appears to pass depending on which host runs it is this mission's +exact subject, one meta-level up. + +**#1027 disposition (Mos):** proceeds on **CI-green**. CI is the authoritative gate; the local exit-97 +is a known host-specific guard abort, irrelevant to the merge decision. + ### D-15 — token scope is not repository permission (a THIRD capability layer) `f10-coder` was provisioned with `gitea-mosaicstack-f10-coder.token`, scopes `write:repository` + -- 2.54.0 From ae4baf145d8cbe317fbf7e40f6eb094a6fbe291a Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 19:07:58 -0500 Subject: [PATCH 15/22] =?UTF-8?q?docs(remediation):=20bank=20D-17=20?= =?UTF-8?q?=E2=80=94=20pre-registration=20confers=20neither=20correctness?= =?UTF-8?q?=20nor=20coverage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rev-974 blocked PR #1027: AC2 was pre-registered and explicitly required rejecting symlinked generated state; the implementation accepts it (ln -s into .next, preflight exits 0 instead of 43) while the acceptance suite ran 21/21 green throughout. Confirmed independently: preflight.mjs:82-92 rejects symlinks on the SOURCE path, :28 merely skips symlinked dirs, and the generated-state path :141-163 checks uid but never isSymbolicLink(). The suite's only symlink cases cover the turbo binary and a source file. Sharpens D-8 rather than repeating it. D-8: pre-registration does not confer CORRECTNESS. D-17: it does not confer COVERAGE — a suite can be green with every criterion appearing satisfied while a criterion's actual requirement is untested. RM-02 third clause: the registry must bind each criterion to the specific case that exercises it and prove that case red before trusting its green. Mutation testing pointed at the criterion-to-case mapping, not just the gate. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/TASKS.md | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index c5472e27..c68ce93f 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -93,6 +93,47 @@ 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-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 +instance of the session's theme because it occurred **inside our own verification machinery**. + +**AC2** was pre-registered before any code was written, and explicitly required that **symlinked +generated state be rejected**. The implementation does not do it: + +```sh +ln -s /etc/hosts apps/web/.next/reviewer-symlink +pnpm preflight # → "checkout preflight passed", exit 0 + # → required: generated-state exit 43 +``` + +The acceptance suite was **21/21 green** throughout. Confirmed independently rather than relayed: +`scripts/preflight.mjs:82-92` rejects symlinks on the **source** path; `:28` merely _skips_ symlinked +directories rather than rejecting them; and the **generated-state** path at `:141-163` `lstat`s and +checks `uid` (ownership) but **never** calls `isSymbolicLink()`. The suite's only symlink cases +(`preflight.test.mjs:59`, `:115`) cover the turbo binary and a _source_ file. No generated-state case +exists anywhere. + +**So: criterion pre-registered, suite green, requirement unmet.** Nobody was careless — the coverage gap +is _invisible from a green_, which is the entire problem. + +**This sharpens D-8 rather than repeating it.** D-8 established that pre-registration does not confer +_correctness_ (a check can be wrong when written). D-17 establishes the adjacent failure: +**pre-registration does not confer _coverage_** — a suite can be green, and every registered criterion +can appear satisfied, while a criterion's actual requirement is untested. The two together mean a +registry of checks needs **two** properties, not one: each check must be _right_, and the set must +_actually exercise_ what it claims. + +**Requirement on RM-02 (third clause).** The registry must bind each acceptance criterion to the +**specific case that exercises it**, and prove that case red before trusting its green. A criterion with +no case that can fail for _that criterion's stated reason_ is unregistered in substance however it +appears in the manifest. This is mutation testing pointed at the **criterion-to-case mapping**, not +merely at the gate. + +**Credit where due:** the reviewer also declined to re-run AC8, stating plainly that the PR carried it +forward with no runnable command rather than silently substituting a different boundary test. That is +the D-8 clause working a second time, in the same review that produced D-17. + ### D-16 — the local test gate and the CI test gate disagree by environment Mos flagged a shape worth chasing: if `pnpm test` exits non-zero on a _pre-existing_ guard, then either -- 2.54.0 From 85bdbe33837142f2499e51f5da2224450958afd4 Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 19:11:52 -0500 Subject: [PATCH 16/22] =?UTF-8?q?docs(remediation):=20bank=20D-18=20?= =?UTF-8?q?=E2=80=94=20pre-registered=20criteria=20AC2=20and=20AC4=20were?= =?UTF-8?q?=20mutually=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 -- 2.54.0 From 3b191b6b34c635397e34c35f94ae111c5b5ba27b Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 19:14:06 -0500 Subject: [PATCH 17/22] docs(remediation): promote the three-mode taxonomy and the integrity-claim corollary to the charter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per Mos. Two first-class principles alongside observe-the-property: 1. Pre-registration prevents RETROFITTING and nothing else. A pre-registered check set can be WRONG (D-8), INCOMPLETE (D-17), or INTERNALLY INCONSISTENT (D-18). It confers neither correctness nor coverage nor consistency. All three modes were found on this mission's own first delivery, by the machinery applied to its own work. RM-02's four clauses are the enforceable form. 2. Never ship an integrity claim dressed as a property. A verification artifact writable by the actor whose behaviour it certifies certifies the attack. It must sit inside its integrity envelope, publish atomically, and carry a tamper negative control observed red. If it cannot be made tamper-evident, say so and reconsider — an honest 'this cannot be verified' is always available and always preferable to laundering foreign content as certified. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/MISSION.md | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/docs/remediation/MISSION.md b/docs/remediation/MISSION.md index f3b434f0..e0258a86 100644 --- a/docs/remediation/MISSION.md +++ b/docs/remediation/MISSION.md @@ -28,6 +28,44 @@ gate/program; the LLM handles only genuine judgment. > Operationally: after any write, read back the property you required. Applies to gates, wrappers, PR > flags, commit authorship, file installs, and message delivery alike. +### First-class principle — pre-registration prevents retrofitting, and nothing else + +> **A pre-registered check set can fail in three distinct ways:** +> +> | mode | the set is… | found as | +> | --------------------------- | ------------------------------------------------- | -------- | +> | **WRONG** | a check does not test what it claims | D-8 | +> | **INCOMPLETE** | green while a criterion's requirement is untested | D-17 | +> | **INTERNALLY INCONSISTENT** | two criteria cannot both hold | D-18 | +> +> **Pre-registration protects against exactly one thing: retrofitting a check to fit the implementation +> it is supposed to judge.** It confers neither correctness, nor coverage, nor consistency. "We +> pre-registered the checks" has been treated as though it settled the question — it settles one of +> three. +> +> Promoted to the charter by Mos (2026-07-31). All three modes were found on this mission's own **first +> delivery**, by the machinery applied to its own work — not by inspection, and not by looking for them. +> +> **Enforceable form — RM-02's four clauses.** The registry must establish that: (1) each check is +> **right** — proven red for its own stated reason before its green counts; (2) the set **covers** — +> every criterion bound to a case that actually exercises it; (3) no two criteria **conflict** — +> mutual unsatisfiability is a registry defect discoverable by construction; (4) when a criterion's +> meaning changes, the registry **retains original text, restatement, and reason**, so evolution stays +> auditable. A criterion with no case that can fail for its own reason is unregistered in substance, +> however it reads in the manifest. + +### Corollary — never ship an integrity claim dressed as a property + +> A verification artifact that can be forged by whoever it is meant to catch verifies nothing. If a +> manifest, marker, ledger, or receipt is writable by the same actor whose behaviour it certifies, it +> **certifies the attack.** Such an artifact must sit inside the integrity envelope it belongs to, +> publish atomically, and carry a **tamper negative-control observed red** — otherwise its integrity is +> a _claim_, not a _property_. +> +> **If it cannot be made tamper-evident, say so and reconsider the approach.** Laundering foreign +> content as certified is the only unacceptable outcome; an honest "this cannot be verified" is always +> available and always preferable. + ## Decision record (authoritative, immutable) - **15/15 proposals decided: 13 accept, 2 modify (P-AUTHORITY-001, P-INBOX-001), 0 reject.** -- 2.54.0 From f9435c2a03f6bcbabd91883458c1b1fee24578a7 Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 19:20:05 -0500 Subject: [PATCH 18/22] =?UTF-8?q?docs(remediation):=20bank=20D-19=20?= =?UTF-8?q?=E2=80=94=20an=20integrity=20property=20that=20cannot=20exist?= =?UTF-8?q?=20at=20its=20specified=20layer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implementing the D-18 manifest hit CWE-345: manifest and marker share one same-UID writable tree, so that actor can regenerate both and pass. No local construction fixes self-authentication without a key outside its authority. The seat escalated rather than calling it tamper-resistant — the charter corollary working on its first real test. Ruling: Option A, scope AC2 to accidental/independent/stale mutation, retain the design. The undefendable boundary is not the weak link (same-UID write already owns the source, the tests, preflight.mjs and .husky); AC2 exists for the D-5 staleness class, against which the design works; and a real anchor arrives with the choke-point executor and PG spine, which verify outside the worktree's authority. Acceptable only with honest labelling: threat model verbatim in code and PR, the words tamper-proof/tamper-evident/secure barred there, scope carried in AC2's restatement, residual risk named as backlog, all controls kept RED-first. Generalizable: when a property cannot exist at the layer it was specified, implement what the layer can guarantee, state the boundary precisely, and record where the real guarantee comes from. A known gap written down is acceptable; a gap implied fixed is not. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/TASKS.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index 1f7d5dd1..5d8d3c82 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -93,6 +93,45 @@ 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-19 — an integrity property that cannot exist at the layer it was specified + +Implementing D-18's manifest, the seat + a Codex security review reached **CWE-345**: the symlink +manifest and the source-hash marker both live in the **same same-UID writable generated tree**, so an +actor with that UID can plant a rogue link, regenerate _both_, retain the fingerprint, and pass. **No +local cryptographic construction fixes self-authentication** without a key outside that actor's +authority; relocating the marker changes the path, not the authority. + +The seat **escalated rather than describing self-authentication as tamper-resistant** — the explicit +failure mode the charter corollary demands. That is the corollary working, on its first real test. + +**Ruling — Option A: scope AC2 to accidental / independent / stale mutation; retain the design.** +Rationale, recorded so it can be challenged: + +1. **The undefendable boundary is not the weak link.** An actor with same-UID write can already edit the + source, the tests, `scripts/preflight.mjs` itself, and `.husky/*`. If they have that, _nothing_ in the + local checkout is trustworthy — hardening the manifest buys no real security while **implying + protection that does not exist**, which is worse than the gap. +2. **What AC2 is actually for.** These checks exist because a five-month-stale `.next` produced 19 + phantom `TS2307` errors indistinguishable from real ones (**D-5**). That is staleness, drift and + foreign residue — and against that class the design demonstrably works. +3. **A real trust anchor arrives later, from this mission's own architecture.** An anchor must live + outside the actor's authority; for a fleet running as one user that means a separate service — + precisely the **choke-point executor + PG spine** of Builds 1–2, which verify outside the worktree's + authority. Hand-rolling key distribution for a local preflight now would duplicate that work badly. +4. Option C (structural policy, no manifest) is strictly worse — it cannot detect a **removed** expected link. + +**Option A is acceptable only with honest labelling**, or it becomes the disease it is meant to cure: +the threat model stated verbatim in the code _and_ the PR ("does **not** defend against same-UID write; +no local construction can"), the words _tamper-proof / tamper-evident / secure_ barred from that +context, the scope carried in AC2's restatement, the residual risk named as a backlog item pointing at +the spine work, and every existing control kept RED-first. + +**The generalizable rule.** When a required property **cannot exist at the layer where it was +specified**, the honest moves are: implement what the layer _can_ guarantee, **state the boundary +precisely**, and record where the real guarantee will come from. **A known gap that is written down is +acceptable; a gap that is implied fixed is not.** Silence here would have shipped a verification +artifact that verifies nothing — with a green to prove it. + ### 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: -- 2.54.0 From 43f69bf1671dba4ccc489356bba9d08bbd6cfa84 Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 19:23:15 -0500 Subject: [PATCH 19/22] docs(remediation): promote D-19 to charter; bind residual risk to RM-59 as a tracked edge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per Mos, with his two additions. Charter gains a fourth first-class principle: when a property cannot exist at the layer that specified it, three honest moves are mandatory — implement what the layer can guarantee; state the boundary in BOTH directions (what it does not defend AND what it does, since either alone misleads); and record the real guarantee as a TRACKED DEPENDENCY, not prose. A written-down gap is acceptable engineering; an implied-fixed gap is the mission's core failure in a new costume. The residual risk is now RM-59 (depends_on RM-12, RM-21, RM-25) — a real backlog task owned by the choke-point executor and spine, which verify from outside the worktree's authority. Mos's point: 'record where the guarantee comes from' only holds if the record is a live dependency someone must close; a documented gap with no owner becomes a permanent gap that reads as intentional. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/MISSION.md | 25 +++++++++++++++++++++ docs/remediation/TASKS.md | 44 +++++++++++++++++++++++-------------- 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/docs/remediation/MISSION.md b/docs/remediation/MISSION.md index e0258a86..65df03a3 100644 --- a/docs/remediation/MISSION.md +++ b/docs/remediation/MISSION.md @@ -66,6 +66,31 @@ gate/program; the LLM handles only genuine judgment. > content as certified is the only unacceptable outcome; an honest "this cannot be verified" is always > available and always preferable. +### First-class principle — when a property cannot exist at the layer it was specified + +> Some required properties are **impossible at the layer that asked for them** — not hard, impossible. +> A local check cannot defend against an actor who can rewrite the check itself. When that happens, +> there are exactly three honest moves, and all three are mandatory: +> +> 1. **Implement what the layer _can_ guarantee.** Partial protection against the class it was actually +> born from is worth having. +> 2. **State the boundary precisely, in BOTH directions.** What it does _not_ defend, **and** beside it +> what it _does_. A reader who sees only the negative dismisses the check as worthless; one who sees +> only the positive over-trusts it. **Both together is the honest artifact** — either alone misleads. +> 3. **Record where the real guarantee will come from — as a TRACKED DEPENDENCY, not prose.** It must +> name a task that someone must close. _A documented gap with no owner becomes a permanent gap that +> reads as intentional._ +> +> **A written-down gap is acceptable engineering. An implied-fixed gap is this mission's core failure in +> a new costume** — a verification artifact that verifies nothing, with a green to prove it. +> +> Promoted to the charter by Mos (2026-07-31) from D-19. Origin: the RM-01 symlink manifest could not be +> made tamper-evident against a same-UID actor (CWE-345), because the manifest and its marker share one +> writable tree. The implementing seat **escalated rather than relabelling self-authentication as +> tamper-resistance** — the corollary above firing on its first real adversarial test, on the cheapest +> seat in the loop. Residual risk bound to **RM-59** (`depends_on: RM-12, RM-21, RM-25`), where the +> choke-point executor and spine verify from _outside_ the worktree's authority. + ## Decision record (authoritative, immutable) - **15/15 proposals decided: 13 accept, 2 modify (P-AUTHORITY-001, P-INBOX-001), 0 reject.** diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index 5d8d3c82..593df7d9 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -120,11 +120,22 @@ Rationale, recorded so it can be challenged: authority. Hand-rolling key distribution for a local preflight now would duplicate that work badly. 4. Option C (structural policy, no manifest) is strictly worse — it cannot detect a **removed** expected link. -**Option A is acceptable only with honest labelling**, or it becomes the disease it is meant to cure: -the threat model stated verbatim in the code _and_ the PR ("does **not** defend against same-UID write; -no local construction can"), the words _tamper-proof / tamper-evident / secure_ barred from that -context, the scope carried in AC2's restatement, the residual risk named as a backlog item pointing at -the spine work, and every existing control kept RED-first. +**Option A is acceptable only with honest labelling**, or it becomes the disease it is meant to cure. +Conditions (last two added/sharpened by Mos): + +- Threat model stated verbatim in the code **and** the PR; the words _tamper-proof / tamper-evident / + secure_ **barred** from that context; the scope carried in AC2's restatement; every control kept + RED-first including manifest-only tamper. +- **State the boundary in BOTH directions.** Not only what it does _not_ defend (same-UID write; no + local construction can) but, beside it, what it **does** defend: accidental / independent / stale / + foreign-residue mutation — the **D-5** class it was born from (the five-month `.next` and its 19 + phantom `TS2307`s). _A reader who sees only the negative dismisses the check as worthless; one who + sees only the positive over-trusts it. Both together is the honest artifact._ +- **The residual risk is a HARD TRACKED DEPENDENCY EDGE, not a comment.** It is **RM-59**, owned by the + choke-point executor + spine work (`depends_on: RM-12, RM-21, RM-25`), and the AC2 scope note must + cite that id. _"Record where the real guarantee comes from" only holds if the record is a live + dependency someone must close._ **A documented gap with no owner becomes a permanent gap that reads + as intentional.** **The generalizable rule.** When a required property **cannot exist at the layer where it was specified**, the honest moves are: implement what the layer _can_ guarantee, **state the boundary @@ -735,17 +746,18 @@ spread is itself information, and X1 says we calibrate on real merged PRs. ### P5 — Retirements, hygiene, conformance -| id | task | src | depends_on | est (S/O) | tier | -| ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | -------------------------- | ---------------- | ------ | -| RM-50 | One roster-owned socket/host; quarantine unmanaged; **deterministic reaper for stale sessions AND dead-session disk scratch** (D-7) | O+S+live | RM-04 | 14K / 150K | sonnet | -| RM-51 | Auto-sync **allowlist** (never auto-stage unknown paths) + worktree/lease isolation | O+S | RM-02 | 8K / 110K | sonnet | -| RM-52 | Retire the Python controller + duplicate MACP islands (3 → 1) | O+S | RM-26, RM-27, RM-25, RM-28 | 14K / 110K | codex | -| RM-53 | Flat-file orchestration → DB hard cutover, with rehearsed rollback artifact | O+S | RM-27, RM-30, RM-34, RM-29 | (in S-10) / 200K | opus | -| RM-54 | Fleet-wide inert-gate audit against the RM-02 registry | O | RM-02 | — / 120K | sonnet | -| RM-55 | **Conformance harness:** fault-inject the live failure classes on real artifacts | O+S | RM-35, RM-41, RM-53 | 18K / 260K | opus | -| RM-56 | Retirement proof: CI asserts all three retirements are complete **and stay complete** | O | RM-52, RM-45, RM-53 | — / 90K | codex | -| RM-57 | Operator cutover docs + activation proof; map all 15 decisions to evidence | S | RM-04, RM-36, RM-45, RM-55 | 6K / — | codex | -| RM-58 | **Mechanical pre-dispatch context reset** — the orchestrator resets a seat out-of-band and verifies it, rather than asking the agent to reset itself | mos-remediation (D-4) | RM-31, RM-50 | 8K | sonnet | +| id | task | src | depends_on | est (S/O) | tier | +| ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | -------------------------- | ---------------- | ------ | +| RM-50 | One roster-owned socket/host; quarantine unmanaged; **deterministic reaper for stale sessions AND dead-session disk scratch** (D-7) | O+S+live | RM-04 | 14K / 150K | sonnet | +| RM-51 | Auto-sync **allowlist** (never auto-stage unknown paths) + worktree/lease isolation | O+S | RM-02 | 8K / 110K | sonnet | +| RM-52 | Retire the Python controller + duplicate MACP islands (3 → 1) | O+S | RM-26, RM-27, RM-25, RM-28 | 14K / 110K | codex | +| RM-53 | Flat-file orchestration → DB hard cutover, with rehearsed rollback artifact | O+S | RM-27, RM-30, RM-34, RM-29 | (in S-10) / 200K | opus | +| RM-54 | Fleet-wide inert-gate audit against the RM-02 registry | O | RM-02 | — / 120K | sonnet | +| RM-55 | **Conformance harness:** fault-inject the live failure classes on real artifacts | O+S | RM-35, RM-41, RM-53 | 18K / 260K | opus | +| RM-56 | Retirement proof: CI asserts all three retirements are complete **and stay complete** | O | RM-52, RM-45, RM-53 | — / 90K | codex | +| RM-57 | Operator cutover docs + activation proof; map all 15 decisions to evidence | S | RM-04, RM-36, RM-45, RM-55 | 6K / — | codex | +| RM-59 | **Close the D-19 residual risk** — generated-state verification anchored **outside** the worktree's authority (executor/spine-side attestation), retiring the same-UID self-authentication gap | mos-remediation (D-19) | RM-12, RM-21, RM-25 | 20K | opus | +| RM-58 | **Mechanical pre-dispatch context reset** — the orchestrator resets a seat out-of-band and verifies it, rather than asking the agent to reset itself | mos-remediation (D-4) | RM-31, RM-50 | 8K | sonnet | **Critical path:** `RM-01 → RM-02 → RM-10 → RM-11 → RM-12 → RM-21 → RM-23 → RM-31 → RM-33 → RM-34 → RM-53 → RM-55`. -- 2.54.0 From 1e7a0701fd66f08599ebc8b4db3b79a29d2a4b38 Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 19:48:00 -0500 Subject: [PATCH 20/22] =?UTF-8?q?docs(remediation):=20fix=20D-18=20overcla?= =?UTF-8?q?im=20(D-20)=20=E2=80=94=20reviewer=20empirically=20disproved=20?= =?UTF-8?q?my=20own=20documentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rev-974 blocked #1027 a second time, and the defect was in this file, not the code. D-18's AC2 restatement omitted the accidental/independent scope D-19 made mandatory, and D-18 asserted the tampered-manifest control turns integrity 'from a claim into a property'. It does not and cannot — that sentence predated D-19 and was never revised when D-19 landed. rev-974 disproved it by experiment: a same-UID consistent manifest+marker rewrite passed preflight. Two banked findings firing on the orchestrator at once: the integrity-claim corollary (I wrote a claim in the voice of a property, in the document defining the rule against it), and D-14 propagation — I carried D-19's consequence forward into the charter and the delivery conditions but never back into the finding it superseded. Backwards propagation is the same defect as forwards and I did not audit for it. Corrected in place with the original wording quoted and the disproof recorded, not silently rewritten. RM-02 fifth clause: documentation asserting a security or integrity property is itself a claim requiring a negative control observed red. Prose is not exempt from the mission's evidentiary standard, and governing prose least of all. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/TASKS.md | 66 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index 593df7d9..fe5b035c 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -93,6 +93,48 @@ 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-20 — the orchestrator's own documentation overclaimed, and a reviewer disproved it empirically + +`rev-974` blocked PR #1027 a second time. **The defect was not in the code — it was in this file**, at +D-18's entry, written by the orchestrator. + +Two faults, both mine: + +1. **D-18's AC2 restatement omitted the scope clause** that D-19 later established as mandatory + ("within an accidental/independent-mutation threat model"). +2. **D-18 asserted that the tampered-manifest control turns integrity "from a claim into a property."** + It does not, and _cannot_. That sentence was written **before** D-19 proved the property impossible + at this layer, and was never revised when D-19 landed. + +**The reviewer did not merely read it — it disproved it.** It performed a **same-UID consistent +manifest + marker rewrite**, and **preflight passed**. My documented claim was falsified by experiment. +Code, README, scratchpad and PR body all stated both threat-model directions correctly; **this file was +the only place still overclaiming.** + +**This is two banked findings firing on the orchestrator at once:** + +- **The integrity-claim corollary** — I wrote an integrity _claim_ in the voice of an integrity + _property_, in the very document that defines the rule against doing so. +- **D-14 (propagation)** — D-19 superseded D-18's assertion. I propagated the consequence into the + charter and the delivery conditions, but **not back into D-18 itself.** A ruling that fails to + propagate _backwards_ into the finding it supersedes is the same defect as one that fails to + propagate forwards, and I did not audit for that direction. + +**Corrected in place**, with the original wording quoted and the empirical disproof recorded, rather +than silently rewritten — the same standard demanded of any restated criterion. + +**Requirement on RM-02 (fifth clause).** Documentation asserting a _security or integrity_ property is +itself a claim requiring a negative control. Where a document states "X is guaranteed", the registry +must hold a case that **fails if X is not guaranteed** — and that case must have been observed red. +**Prose is not exempt from the mission's own evidentiary standard**, and prose in the _governing_ +document least of all: it is the artifact most likely to be quoted as authority long after the code has +moved on. + +**Reviewer credit.** rev-974 was briefed that its highest-priority check was "confirm the PR claims no +more than it can deliver, and a softened or omitted boundary is a finding even though the code works." +It applied that instruction **to the orchestrator's own governing document** and produced an experiment +to settle it. That is the review standard this mission is trying to make ordinary. + ### D-19 — an integrity property that cannot exist at the layer it was specified Implementing D-18's manifest, the seat + a Codex security review reached **CWE-345**: the symlink @@ -173,16 +215,30 @@ still rejected as a symlink; descendants are rejected unless _exactly_ certified 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._ +**AC2 restated (recorded, not absorbed).** _Generated state must reject `.next` itself being a symlink +or non-directory, and must reject any descendant symlink not exactly certified by the build manifest — +added, removed, retargeted, or manifest-only-tampered all fail with exit 43 — **within an accidental / +independent-mutation threat model.**_ + +> ⚠ **This entry is superseded in part by [D-19](#d-19). Do not read D-18 standalone.** The scope clause +> above is load-bearing: the design **cannot** defend against a same-UID actor, which can rewrite the +> manifest and the marker consistently (CWE-345). D-18 was written **before** that impossibility was +> established. **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. +**manifest-only-tampered**, plus a positive control that the canonical build passes. + +> ⚠ **CORRECTED (D-20).** This paragraph originally ended: _"without it, integrity is a claim rather +> than a property."_ **That overclaimed**, by implying the control makes integrity a _property_. It does +> not, and cannot. The manifest-only-tamper control detects **independent** mutation of the manifest; +> it confers **no authenticity** against an actor who rewrites manifest _and_ marker together. +> `rev-974` disproved the original wording empirically — a same-UID consistent manifest+marker rewrite +> **passed preflight**. Integrity here remains a scoped **drift-detection** property, never an +> authenticity one. See D-19 and the charter principle on properties that cannot exist at their +> specified layer. **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 -- 2.54.0 From f5a0566198365dca0727b4bde47155b88f7d535c Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 19:50:36 -0500 Subject: [PATCH 21/22] =?UTF-8?q?docs(remediation):=20board=20=E2=80=94=20?= =?UTF-8?q?RM-01=20MERGED=20(f58b3699);=20RM-02=20keystone=20is=20next?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/BOARD.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/remediation/BOARD.md b/docs/remediation/BOARD.md index 4f5c14b6..88eb9003 100644 --- a/docs/remediation/BOARD.md +++ b/docs/remediation/BOARD.md @@ -1,6 +1,6 @@ # mos-remediation — LIVE BOARD (keep < 8 KB) -**Phase:** EXECUTING — 2 PRs merged; RM-01 in flight (rotated seat); 11 dogfood classes banked. +**Phase:** EXECUTING — P0 open. RM-01 MERGED; RM-02 (keystone gate registry) is next. **Updated:** 2026-07-31 (mos-remediation orchestrator; seat active on `mosaic-fleet`). ## Head @@ -16,14 +16,13 @@ ## In-flight -| Task | Owner | State | -| ----------------------------------- | ---------- | ------------------------------------------------------------------ | -| PR #1025 hygiene | — | **MERGED** 52414605 (rev-974 APPROVE + CI 8/8 terminal-green) | -| PR #1026 mission package | — | **MERGED** 01e966f3 (docs policy: CI-green, precedent #968/#863) | -| PR #1027 RM-01 | f10-coder | **DRAFT** — AC2/3/5/7/8 proven; AC1/AC4/AC6 open | -| RM-01 remainder: AC6 race, AC1, AC4 | f10-coder | IN FLIGHT on ROTATED seat (reset 0.0%, rehydrated from #1027 body) | -| RM-03 queue guard (3 defects) | — | **HOLD** — #1023 SUPERSEDED-PENDING-JASON | -| RM-02 gate registry (keystone) | unassigned | READY — explicitly NOT held by RM-03 | +| Task | Owner | State | +| ----------------------------------- | --------------- | ------------------------------------------------------------------------- | +| RM-01 reproducible checkout | — | **MERGED** `f58b3699` (PR #1027) — rev-974 APPROVE + CI #2172 8/8 green | +| RM-02 gate registry ★keystone | unassigned | **READY** — depends only on RM-01; not held by RM-03 | +| RM-03 queue guard (3 defects) | — | HOLD — #1023 SUPERSEDED-PENDING-JASON | +| RM-59 close D-19 residual risk | — | BLOCKED by RM-12/RM-21/RM-25 (spine + executor) — tracked edge, not prose | +| `remediation/state` snapshot → main | mos-remediation | opening at this mission seam | ## Fleet seats -- 2.54.0 From 8a795df0ce77f9b84230fd9de4ebf6bf74ae2f09 Mon Sep 17 00:00:00 2001 From: mos-dt-0 Date: Fri, 31 Jul 2026 19:53:36 -0500 Subject: [PATCH 22/22] =?UTF-8?q?docs(remediation):=20D-14=20amended=20by?= =?UTF-8?q?=20D-20=20=E2=80=94=20propagation=20is=20bidirectional?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both the orchestrator and the coordinator read D-14 as forward propagation only: a ruling reaches the documents stating the new rule. D-20 proved that insufficient — when D-19 superseded part of D-18, the consequence went forward into the charter and the delivery conditions but never backward into D-18, which kept asserting a withdrawn claim until a reviewer disproved it by experiment. A supersession must update BOTH the documents rendering the new rule AND the finding it retires, with the retired wording quoted rather than deleted. Interim rule updated accordingly. Applying D-14's own rule to D-14, in the same commit that records the amendment. Co-Authored-By: Claude Opus 5 (1M context) --- docs/remediation/TASKS.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/remediation/TASKS.md b/docs/remediation/TASKS.md index fe5b035c..6d737813 100644 --- a/docs/remediation/TASKS.md +++ b/docs/remediation/TASKS.md @@ -394,6 +394,15 @@ _enforcement_ is the gap: a decision that lives in a chat ruling and a board not source of truth, has not actually been made — it has been _agreed_. The two are different, and the difference is exactly what this mission is about. +> ⚠ **AMENDED by D-20 — propagation is BIDIRECTIONAL.** As first written, this requirement was read by +> both the orchestrator and the coordinator as _forward_ propagation only: a ruling reaches the +> documents that state the new rule. **D-20 proved that insufficient.** When D-19 superseded part of +> D-18, the consequence propagated forward into the charter and the delivery conditions but **never +> backward into D-18 itself**, which went on asserting a withdrawn claim — and a reviewer disproved it +> by experiment. **A supersession must update BOTH the documents that render the new rule AND the +> finding it retires, with the retired wording quoted rather than deleted.** Backward propagation is +> the same defect as forward; neither of us audited that direction until it bit. + **Requirement (not merely a fix).** A ruled decision must propagate **mechanically** to the authoritative record; it must not depend on someone remembering to edit a second file. Concretely, once mission state is DB-backed (RM-53 / the P-MISSION cutover): @@ -404,7 +413,7 @@ mission state is DB-backed (RM-53 / the P-MISSION cutover): document agree — with a must-fail control proving divergence is detected. Until then, the interim rule: **the same commit that records a ruling updates every document that -states it.** Interim rules are exactly what the DB cutover exists to replace. +states it — and every finding it supersedes.** Interim rules are exactly what the DB cutover exists to replace. **The rule found a second instance within minutes of being written.** Auditing the charter against all rulings to date (rather than waiting to be bitten again) surfaced that **DECISION-2 had also not -- 2.54.0