# Remediation Backlog — Reconciled Execution Plan

**Owner:** `mos-remediation` (sole writer). Workers read; they never modify this file.
**Sources:** [`DECOMP-OPUS.md`](./DECOMP-OPUS.md) (robustness, 38 tasks / 8 dissents) and
[`DECOMP-SOL.md`](./DECOMP-SOL.md) (pragmatic, 25 tasks / 10 defers / 7 dissents), produced
**independently** — neither planner read the other. Charter: [`MISSION.md`](./MISSION.md).
**Status:** EXECUTING — all three blocking decisions RULED by Mos on 2026-07-31 (§5). **RM-01 is
dispatched.** RM-03 is held pending Jason's disposition of PR #1023; nothing else is blocked.

> **Provenance of the inputs (both clean).** `planner-opus` ran in a fresh session throughout.
> `planner-sol` initially began work at 64.3% dirty context despite a brief instructing it to reset;
> that run was **interrupted and discarded before it produced any output**, the seat was reset
> out-of-band to 0.0%, and the brief was re-dispatched. `DECOMP-SOL.md` is the product of the clean
> run only (it peaked at ~26% context). Both decompositions are therefore clean-context artifacts and
> are weighted equally here. The discarded dirty run is banked as dogfood seed D-4 and as task RM-58 —
> the failure it demonstrates is that _asking_ an agent to reset is not enforcement.

---

## 1. What the two planners agreed on without collusion

Independent convergence is the strongest signal available here, because neither planner could see the
other's file. Where both arrived at the same conclusion from opposite biases, I treat it as settled.

| #   | Convergent finding                                                                                                    | OPUS                | SOL            |
| --- | --------------------------------------------------------------------------------------------------------------------- | ------------------- | -------------- |
| C1  | **The charter's wire-in point is wrong.** Do NOT wire the choke point into `mosaic_orchestrator.py::run_single_task`. | D2 (headline)       | Dissent 1      |
| C2  | P0 hygiene/gate work must precede the spine, not follow it.                                                           | D1, phase P0        | G0, SOL-01/02  |
| C3  | No new deployable microservice; the executor is a library + the coord daemon.                                         | implicit throughout | Dissent 3      |
| C4  | Comms adapters beyond tmux are out of scope for this mission.                                                         | D7                  | DEFER 4/5/6    |
| C5  | The "100 rotations lossless" bar is a late conformance gate, not an early tax.                                        | D4                  | Dissent 7      |
| C6  | Redis is a derived hot path, never an authority; PG commits first.                                                    | R-013, R-054        | SOL-11, SOL-21 |
| C7  | Reuse `packages/coord`; do NOT revive the untracked `apps/coordinator` residue.                                       | R-042               | SOL-15 AC5     |

**C1 is the single most consequential output of this exercise.** The charter (`MISSION.md`) and my
kickoff instruction both name `mosaic_orchestrator.py::run_single_task:126-276` as the integration
point. Both planners independently rejected it on the same evidence: that controller is
`"enabled": false` (`.mosaic/orchestrator/config.json:2`) and references a dispatcher path
(`tools/macp/dispatcher/pi_runner.ts`) that does not exist in this checkout. Wiring the new choke
point into a disabled rail produces **a stranded executor — the identical built-but-unwired disease,
one layer up, that would look "done" in a PR.** The live paths are
`packages/mosaic/src/commands/launch.ts` and `packages/coord/src/runner.ts`.
This contradicted the charter and was escalated as DECISION-1 — **now RULED in the planners' favour by
Mos (§5)**. The corrected target is a new production Node `TaskExecutor` on the live dispatch path
(`packages/mosaic` launch + `packages/coord`) that Coord/Forge/live dispatch submit through; the
Python rail is deleted, not ported.

---

## 1a. ★ KEYSTONE DOGFOOD CASE — an inert gate that erased its own evidence

**A merged commit shipped past `pnpm format:check` — and then the evidence quietly erased itself.**

Verified chain (blob-level, under the repo's own prettier config, at the file's real path):

| commit                                                              | state of `packages/mosaic/framework/tools/orchestrator/README.md`             |
| ------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `b79336a8` — **merged PR #868**                                     | blob `3ee7f104` — **FAILS** `pnpm format:check`                               |
| `48fd1df2` — merged PR #872 (unrelated: ci-queue-wait 404 handling) | blob `3d3bb132` — passes; incidentally reformatted by that PR's `lint-staged` |
| current `origin/main` (`06e0d403`)                                  | passes — **the gate now looks green**                                         |

So: PR #868 merged a file that fails a required gate ⇒ **the CI format gate did not block it.** The
gate was inert for that merge. Then an unrelated later PR's pre-commit hook reformatted the file as a
side effect, so `main` went green again **without anyone ever learning the gate had failed to fire.**

> **Correction on record:** my first report to Mos said "format:check is RED on main _now_." That was
> true of the `main` my checkout was pinned to (`b79336a8`) and is **no longer true of current `main`**,
> which advanced mid-session. The inert-gate finding itself is unchanged and verified; only its
> present-tense framing was wrong. The hygiene PR therefore carries the `.prettierignore` fix only —
> the README needs no fix today.

### Third live instance, same class — the queue guard, hit by this orchestrator

Running the **mandated** pre-push guard during TASK-0:

```
$ ~/.config/mosaic/tools/git/ci-queue-wait.sh --purpose push
[ci-queue-wait] platform=gitea purpose=push branch=main sha=06e0d403…
[ci-queue-wait] state=unknown purpose=push branch=main
$ echo $?   →  0
```

**Two distinct defects in one tool**, both feeding RM-03:

1. **Wrong exit** — `state=unknown` ⇒ `exit 0`. The defect at `ci-queue-wait.sh:282-288` that OPUS
   documented and that PR #1023 is parked on. A required gate returned PASS on an indeterminate result.
2. **Wrong branch** — it evaluated `branch=main`, not the branch actually being pushed. Even a
   correctly-exiting guard would have been answering the wrong question.

**Standing doctrine (Mos):** until RM-03 lands, a green from this guard carries **zero information**
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
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.
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
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:

- **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
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-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
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
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
`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.

**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` +
`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
`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.

> ⚠ **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):

- 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 — 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
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
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`.

**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**.
`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`):

**(a) Identity drift — P-WRAPPER-001, reproduced on our own delivery.** The seat's commits are
authored `mosaic-coder <coder@fleet.mosaicstack.dev>` — 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 <f10-coder@fleet.mosaicstack.dev>`.
> 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
`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-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-<Y>-<X>.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

`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
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), 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
<file>` 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.

### 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`.
In bash, when no `venv` exists the glob is unmatched and passes through literally, creating a
directory named `apps/*/venv/lib` rather than one per workspace. The check as written did not test
what it claimed to test.

`rev-974` ran it **exactly as written**, observed the wrong behaviour, then re-ran the intended
assertion at an explicit path — **and said so in the review** rather than silently substituting a
working fixture and reporting PASS.

Two things this establishes:

1. **The instruction "do not adjust a check to fit the diff; if it is unrunnable, say so explicitly"
   worked.** A silent substitution here would have produced a green AC2 that proved nothing, on the
   exact task whose subject is gates that appear to work. The disclosure is what made the PASS
   meaningful.
2. **Pre-registration does not confer correctness.** A pre-registered check is protected from being
   retrofitted to the implementation; it is not protected from being _wrong when written_. This is a
   small instance of the mission's own class — an unverified gate — occurring inside the mechanism
   built to catch unverified gates.

**Requirement on RM-02 (non-negotiable, sharpened by Mos).** The registry must **self-verify** that
every registered case demonstrably **runs** and demonstrably **fails on a known-bad input**.
Presence in the registry is **not** evidence. **A check is not trusted until it has been shown to
fail.** This is mutation testing / negative control applied _at the registry level_ — meaning
**the conformance harness must itself be conformance-tested.** A registered case that cannot fail, or
cannot run, is exactly as inert as an unregistered one, and the registry check must detect that
itself rather than assume it.

**Requirement on RM-55.** The same recursion applies to the harness: it must be observed red before
its green is worth anything (OPUS R-063 AC1 already states this; D-8 is the empirical case for it).

**Second, equally load-bearing lesson — reviewer disclosure is what makes a review trustworthy.**
rev-974 could have silently swapped in a working fixture and reported `AC2 PASS`. Nothing in the
process would have caught it, and the resulting green would have certified nothing — on the very task
whose subject is gates that only appear to work. The brief's instruction — _"do not adjust a check to
fit the diff; if it is genuinely unrunnable as specified, say so explicitly and explain why rather
than silently substituting your own"_ — is therefore not boilerplate. It is the clause that makes a
PASS mean something, and it must appear in **every** reviewer brief this mission issues.

### D-7 — shared-tmpfs contention → cascading ENOSPC (live incident, 2026-07-31)

The shared 30 G `/tmp` hit **100% ENOSPC** mid-session. It broke tool calls in **two different seats**
(mine and Mos's) — a single full disk degrades every agent on the host at once. Recurring: prior
incidents 2026-06-18 and 2026-07-17.

Attribution matters, because the wrong owner cleans the wrong thing. Measured:

| path                                           | size      | last modified                | owner                                             |
| ---------------------------------------------- | --------- | ---------------------------- | ------------------------------------------------- |
| `…/-src-mosaic-stack/6d2faee6…` (this session) | **88 K**  | live                         | mos-remediation                                   |
| `…/-src-mosaic-stack/c743185d…`                | **3.6 G** | **2026-07-22** (9 days dead) | abandoned session, same project path              |
| `…/claude-1001/pnpm-store`                     | **1.6 G** | **2026-07-23** (8 days dead) | abandoned; the live store is correctly on `$HOME` |

So ~5.2 G — the bulk of the pressure — is **dead session scratch that nothing will ever read again**.
This is not a quota problem; it is **P-FLEET-001's stale-session GC, applied to disk instead of tmux
sessions.** The same missing capability (nothing owns reaping dead ephemeral state) produces both the
orphaned-session failure and this one. Reaping dead-session scratch belongs in RM-50 alongside stale
tmux-session GC.

**Added to RM-01 as acceptance criteria:** heavy build artifacts (node_modules, package stores, build
output) must land on the main disk in the worktree, never on the shared 30 G `/tmp`.

**Resolution, and the part that is actually the finding.** Mos verified the attribution independently
(mtimes, no process or `lsof` holding either path, no live session maps) and reaped both as lead
coordinator: `/tmp` went to 79%, 6.0 G free. But note _how_ it was resolved — **a human-authority seat
did it by hand, because the authority exists and the reaper does not.** That gap is the finding, not
the disk usage.

Two doctrine points fall out, both binding on RM-50:

1. **The fix is not "agents should tidy up."** Asking each seat to clean its own scratch is
   `instructions are not enforcement` (D-4) wearing a different hat. A deterministic reaper must own
   it — same conclusion the north star reaches for every other class in this mission.
2. **Refusing to unilaterally delete another session's scratch was correct, and the resolution is not
   "be braver about deleting."** An agent guessing that someone else's state is garbage is exactly the
   unreviewed destructive act the Constitution forbids. The resolution is that _ownership and liveness
   become mechanically decidable_, so reaping is a determination rather than a judgement call.

**Reaper requirements for RM-50:** liveness determined mechanically (process/`lsof`/session-map, not
mtime alone); an age threshold; a dry-run that reports what it would reap and why; and an audit event
per reap. Never a heuristic sweep — that would reintroduce the P-WORKFLOW-001 auto-sync failure in a
more destructive form.

**The self-erasure is the important part.** An inert gate that is masked by unrelated downstream
commits produces no lasting artifact, which is precisely why this class survives for months. Detection
cannot rely on "is `main` currently red" — it must be per-merge-commit.

This matters more than the one-line fix:

- It is the **P-QUEUE-001 / P-CONFORMANCE-001 class** ("gate-6 was inert fleet-wide"), reproduced in
  the repository this mission is remediating, discovered incidentally.
- It independently **validates OPUS premise A1** ("every gate is inert until proven otherwise") with
  live evidence rather than argument — which is why RM-02 is adopted as the keystone (§2, X2).
- The file fix rides in its own hygiene PR. **The inert gate itself is NOT quiet-patched.** Per Mos:
  it stays a first-class backlog item, because patching the symptom would destroy the signal.

**Binding requirement on RM-02 and RM-55:** the gate registry and the conformance harness must assert
**"every merged commit passed every required gate"** — evaluated **per merge commit, against that
commit's own tree**, not against current `main`. As the table above proves, a "is main green today"
check would have reported all-clear. A merged-commit-that-fails-a-required-gate is the exact detection
signal, and it must be a registered must-fail case. A gate that cannot prove it blocked something has
not been shown to work.

---

## 2. Where they genuinely disagree (not averaged — adjudicated)

| #   | Axis                                        | OPUS                                                       | SOL                                           | My ruling                                                                                                                                                                                                                                                                                                                                                                                                 |
| --- | ------------------------------------------- | ---------------------------------------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| X1  | **Total cost**                              | 38 tasks, ~5.3M tok                                        | 25 tasks, ~294K tok                           | **~18× apart.** Not reconcilable by splitting. They measure different things: SOL explicitly excludes orchestration/review/iteration overhead and assumes one remediation pass; OPUS prices the full loop. Adopt **SOL's scope** with **OPUS's rigor**, and treat SOL's G1 as a hard budget checkpoint (§4). Re-estimate empirically after the first three merged PRs rather than trusting either number. |
| X2  | **Gate registry (OPUS R-002)**              | Keystone; blocks all P2                                    | Absent; only a queue-guard fix                | **ADOPT OPUS.** Empirically validated in this very session: I found `pnpm format:check` red on `main` via merged PR #868 — a required gate that did not block. OPUS's premise A1 ("every gate is inert until proven otherwise") is not theoretical; it reproduced today, unprompted. Scope it tighter than 120K.                                                                                          |
| X3  | **Drizzle PG first-install defect (R-010)** | Hidden blocker; everything downstream depends on it        | Not mentioned                                 | **ADOPT OPUS.** `packages/db/src/migrate.ts:30-38` carries a TODO admitting postgres-tier first-install fails today. The spine has only ever been proven on PGlite. Every later migration silently depends on this. SOL missed it.                                                                                                                                                                        |
| X4  | **Rollback artifact for the hard cutover**  | D3: hard cutover needs a rehearsed rollback snapshot       | SOL-07: import-only, explicitly no dual-write | Both obey "no flat-file interim." OPUS wants a one-directional snapshot nothing reads as authority. I read that as compatible with the directive, but it is Jason's call → **DECISION-2** (§5).                                                                                                                                                                                                           |
| X5  | **Where the queue guard sits**              | P0, independent of spine                                   | SOL-02, also early                            | Agree it is P0. But ownership collides with **parked PR #1023** → **DECISION-3** (§5).                                                                                                                                                                                                                                                                                                                    |
| X6  | **Report-only rollout**                     | D5: only with a hard expiry, else withdraw                 | not raised                                    | **ADOPT OPUS.** A report-only gate is by definition inert; expiry is the mechanism that stops it becoming the new fail-open.                                                                                                                                                                                                                                                                              |
| X7  | **Availability trade (FC-7/FC-11)**         | D8: "no DB ⇒ fleet stops" must be pre-committed in writing | not raised                                    | Genuine availability regression, correctly identified. Needs Jason → folded into **DECISION-2**.                                                                                                                                                                                                                                                                                                          |

---

## 3. Reconciled DAG

Phases run in order; `⛔` marks a hard barrier. `src` shows lineage (`O`=opus, `S`=sol, `O+S`=both).
Estimates are given as a **range** (SOL low / OPUS high) rather than a fabricated midpoint — the
spread is itself information, and X1 says we calibrate on real merged PRs.

### P0 — Make gates provable, and stop the fleet re-bricking

⛔ _No gate-introducing task in any later phase may merge before RM-02._

| id              | task                                                                                                                                          | src      | depends_on   | est (S/O)        | tier   |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------ | ---------------- | ------ |
| RM-01           | Reproducible non-root checkout; gate fails on **code, not env**; heavy artifacts OFF shared `/tmp` (banks D-1/D-2/D-5/D-7)                    | O+S+live | —            | 6K / 60K         | codex  |
| RM-02           | **Gate registry + negative-control CI check** (anti-inert-gate harness) ★keystone                                                             | O        | RM-01        | — / 120K         | opus   |
| RM-03 ⏸**HOLD** | Queue-guard: **two** defects — (a) `unknown`/`no-status`/malformed ⇒ ≠0, (b) guard evaluates `branch=main` instead of the branch being pushed | O+S+live | RM-02        | 8K / 100K        | sonnet |
| RM-04           | Activation/version coherence; block launch on skew, fail SAFE; honest `doctor` labels                                                         | O+S      | RM-01        | (in S-01) / 140K | sonnet |
| RM-05           | Break-glass replaces the three silent `MOSAIC BYPASS` fail-opens                                                                              | O        | RM-04, RM-02 | — / 120K         | opus   |

> ⚠ **RM-05 must not merge before RM-04.** The bypasses exist because the lease-broker daemon was
> never _deployed_ on this host — removing the fail-open before deployment coherence is real
> re-creates the 2026-07-22 bricking incident. Hard edge, from OPUS.

### P1 — Durable spine (PG)

⛔ _No migration may merge before RM-10._

| id    | task                                                                                          | src | depends_on | est (S/O)  | tier   |
| ----- | --------------------------------------------------------------------------------------------- | --- | ---------- | ---------- | ------ |
| RM-10 | **Fix the Drizzle postgres-tier first-install defect** ★hidden blocker                        | O   | RM-01      | — / 90K    | sonnet |
| RM-11 | Orchestration spine schema (tasks, attempts, gate_results, hash-chained ledger, typed claims) | O+S | RM-10      | 12K / 160K | opus   |
| RM-12 | Spine client, fail-closed connection (no silent PGlite in prod)                               | O   | RM-11      | — / 80K    | sonnet |
| RM-13 | Atomic claims/transitions + transactional outbox + reconciliation sweeper                     | O+S | RM-12      | 12K / 140K | opus   |

### P2 — The single choke point

⛔ _RM-25 (no-second-path) lands in the same milestone as RM-20, or the choke point is optional._

| id    | task                                                                                           | src | depends_on          | est (S/O)        | tier   |
| ----- | ---------------------------------------------------------------------------------------------- | --- | ------------------- | ---------------- | ------ |
| RM-20 | Canonical MACP contract completion (Task/Result/Event/Claim/tri-state outcome)                 | S   | —                   | 8K / (in R-020)  | codex  |
| RM-21 | **Production `TaskExecutor`** backed by `@mosaicstack/macp` ★keystone                          | O+S | RM-12, RM-02, RM-20 | 16K / 220K       | opus   |
| RM-22 | Gate-runner hardening: `fail_on`, timeouts, **empty gate set = failure**                       | O   | RM-21               | — / 120K         | sonnet |
| RM-23 | Hash-chained MACPEvent ledger in PG + lifecycle EventType extension                            | O+S | RM-21, RM-11        | — / 160K         | opus   |
| RM-24 | Seat identity from `MOSAIC_AGENT_NAME` + **mandatory** tri-state write outcomes                | O+S | RM-21               | (in S-03) / 150K | opus   |
| RM-25 | **No-second-path gate:** terminal status writable only by the executor                         | O   | RM-21, RM-23        | — / 140K         | opus   |
| RM-26 | `packages/coord` submits through the executor (retire direct spawn)                            | O+S | RM-21               | 16K / 140K       | sonnet |
| RM-27 | `mosaic yolo/claude/codex/pi` launch path records typed Task + events                          | O   | RM-21, RM-23        | — / 160K         | sonnet |
| RM-28 | Delete the Forge stub executor (empty-gate-list "success"); Forge submits through the real one | O+S | RM-21               | 10K / 90K        | codex  |
| RM-29 | One-shot flat-file import + cutover readiness audit (dry-run, idempotent, no dual-write)       | S   | RM-13               | 8K / (in R-062)  | codex  |

> **★ G1 — FIRST DOGFOOD. Stop here and prove it.** One live fleet task travels
> PG claim → TaskExecutor → worker → gates → terminal PG result/event, with **no** flat-file state.
> Adopted from SOL wholesale. If G1 cannot carry a real task, **do not build Redis, rotation, comms,
> or conformance** — remediate instead. This is the budget escape hatch (§4).

### P3 — Rotation lifecycle (finish the Mission Control Plane)

| id    | task                                                                                         | src | depends_on   | est (S/O)        | tier   |
| ----- | -------------------------------------------------------------------------------------------- | --- | ------------ | ---------------- | ------ |
| RM-30 | Typed state claims (source/confidence/TTL) with HMAC integrity, fail-closed                  | O+S | RM-11, RM-21 | (in S-03) / 170K | opus   |
| RM-31 | Contract-hash binding; stale generation loses mutation authority **mechanically**            | O+S | RM-21, RM-30 | 12K / 180K       | opus   |
| RM-32 | Durable compaction/token sensor (per-runtime thresholds, PreCompact event)                   | O   | RM-23, RM-31 | — / 130K         | sonnet |
| RM-33 | Typed checkpoint writer (structured claims, never transcript) + digest                       | O+S | RM-30, RM-32 | 12K / 150K       | opus   |
| RM-34 | **Rotation daemon:** watch → checkpoint → revoke → kill → relaunch → rehydrate               | O+S | RM-33, RM-26 | 16K / 240K       | opus   |
| RM-35 | Rehydration attestation gate: refuse to act on an incomplete claim set                       | O   | RM-33        | — / 130K         | opus   |
| RM-36 | Broker-independent recovery; remove silent bypass; honest capability labels                  | S   | RM-34        | 12K / (in R-004) | sonnet |
| RM-37 | Delete `/compact and continue` from the persistent-seat path (**substitution**, not removal) | O+S | RM-34, RM-44 | (in S-16) / 60K  | codex  |

### P4 — Comms service

⛔ _RM-50 (one roster-owned socket per host) precedes identity-addressed delivery._

| id    | task                                                                         | src | depends_on   | est (S/O)        | tier   |
| ----- | ---------------------------------------------------------------------------- | --- | ------------ | ---------------- | ------ |
| RM-40 | `comms/v1` envelope + protocol-version negotiation, LOUD reject              | O+S | RM-11, RM-31 | 8K / 140K        | opus   |
| RM-41 | Comms service: PG state machine PENDING→RECEIVED→CONSUMED→DEAD-LETTER        | O+S | RM-40, RM-13 | 16K / 200K       | opus   |
| RM-42 | tmux transport as a **dumb adapter**; durable retry before cursor advance    | O+S | RM-41, RM-50 | (in S-19) / 160K | sonnet |
| RM-43 | Per-class coalescing + supersede (the stale-consumed-as-live fix)            | O+S | RM-41        | 12K / 130K       | sonnet |
| RM-44 | Redis Streams hot delivery + provenance guard (**Redis is never authority**) | O+S | RM-41, RM-13 | 12K / 170K       | opus   |
| RM-45 | Retire direct tmux sends; only the service may write a pane                  | O+S | RM-42, RM-43 | (in S-20) / 100K | codex  |

### 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-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`.

---

## 4. Execution discipline

- **Every row is one PR.** Author ≠ reviewer; `rev-974` is the mosaicstack reviewer identity.
- **Pre-registered, diff-blind acceptance checks are committed BEFORE the reviewer reads the diff.**
  Both decomps wrote their ACs in runnable `⇒0` / `⇒≠0` form specifically to make this possible.
- **Every gate-introducing task carries at least one registered must-fail negative control.** This is
  RM-02's whole purpose; a gate with no proven failure path manufactures evidence.
- **Cost tiers:** codex for mechanical/unambiguous, sonnet for normal feature work, opus reserved for
  security/integrity/cross-cutting-invariant tasks. SOL priced 0 opus tokens; OPUS priced 14 opus
  tasks. I am keeping opus only where the failure is _integrity_, not merely complexity.
- **G1 is the budget checkpoint.** If the first-dogfood slice overruns SOL's estimate by >3×, stop and
  re-plan rather than spending the remainder. X1 says neither estimate is trustworthy until calibrated.
- **Defer list adopted from SOL** (10 items): mission dashboard/TUI, PRD-to-board auto-decomposition,
  heuristic churn scoring, Discord/Slack/Telegram adapters, public MCP comms surface, protocol-v2
  negotiation, multi-region PG/Redis, event analytics UI.

---

## 5. Decisions — all three ruled by Mos, 2026-07-31

**DECISION-1 — the wire-in point. ✅ RULED: accept the planners (Mos, 2026-07-31).**
The charter's `mosaic_orchestrator.py::run_single_task` target is the **disabled Python controller
this mission retires**; wiring the new choke point into the rail we are deleting is wrong.

> **Corrected target (authoritative):** a **new production Node `TaskExecutor`** sitting on the
> **live dispatch path** — `packages/mosaic` launch + `packages/coord` — which Coord, Forge, and live
> dispatch all **submit through**. This is the MACP scout's _full_ recommendation ("replace the block
> **with** a Node executor **and** make Coord/Forge submit through it"), not a resurrection of the
> Python controller. RM-52 is therefore a **deletion** task, and Build 1's acceptance is measured on a
> live `mosaic yolo` invocation.

Mos ruled this resolvable from the already-accepted retire-the-Python-rail decision — his authority,
not a Jason escalation. RM-21/RM-26/RM-27/RM-52 all take the corrected target.

**DECISION-2 — rollback artifact + availability trade. ⏸ JASON-PENDING — NOT BLOCKING.**
The DB build is phases away, so this is queued for Jason's next session rather than escalated now.
**Binding requirement in the meantime (Mos, from P-RECOVERY-001):** the DB spine **must NOT be a
single-point hard-stop.** Design for a broker-independent / degraded mode **plus** a rollback
artifact. Jason finalises only the specific availability target. This reverses my earlier reading of
OPUS D8 ("the fallback is: the fleet stops") — that answer is **not** pre-committed; a degraded mode
is now a design requirement on RM-12, RM-13, RM-23, RM-36 and RM-53.

**DECISION-3 — RM-03 vs. parked PR #1023. ✅ RULED: HOLD RM-03 (Mos, 2026-07-31).**
Do **not** open a third gate-6 lane — that is the postmortem's own anti-pattern performed by the
remediation. PR #1023 sits in Jason's **parked delivery stack**; its disposition (close, or supersede
by RM-03) is Jason's at his next session.

- **PR #1023 → `SUPERSEDED-PENDING-JASON`.** RM-03 stays `HOLD`; when Jason rules, RM-03 proceeds as
  the single correct lane.
- **RM-02 and RM-55 proceed independently and are NOT held.** The per-merge-commit gate-assertion
  requirement is the _conformance_ capability, not the gate-6 fix itself — different scope, no
  ownership collision.

---

## 6. Status

| phase              | state                                                                                                        |
| ------------------ | ------------------------------------------------------------------------------------------------------------ |
| Decomposition      | DONE — both planners delivered independently                                                                 |
| Reconciliation     | DONE — this document                                                                                         |
| Blocking decisions | **RULED** — all 3 closed by Mos 2026-07-31 (§5); D-2's availability target is Jason-pending but non-blocking |
| Dispatch           | **RM-01 IN FLIGHT** — f10-coder (codex), worktree-isolated, AC1–AC8 pre-registered                           |
| Review             | PR #1025 with rev-974; ACs pre-registered 22:12:26Z before diff exposure                                     |
