# Work Orders — Long-Haul Implementation on a 35B-Class Model

**Origin:** Root-cause review of the `myactuator` ESP32/PlatformIO session (35B `ornith-vision`)
plus a 2026-literature sweep of surprising remedies. See companion analysis in
`docs/context-management-medium-models-proposal.md` and
`docs/duplicate-calls-root-cause-analysis.md`.

## Implementation status (Ralph loop + live wiring, 2026-07-04)

All 8 core modules implemented, unit-tested, and wired into `agenticRunner.ts` via a single
fault-tolerant integration bundle (`packages/orchestrator/src/longhaul-integration.ts`,
`LongHaulComponents`). Full monorepo `pnpm -r build` exits 0 (cli, apps/api, apps/worker included).

| WO | Module | Tests | Live in `agenticRunner` |
|----|--------|-------|--------------------------|
| WO-1 | `execution/src/boundary-verifier.ts` | 12 ✅ | **glue live**; compiler-runner dormant (needs repo profile — fires only when a runner is supplied) |
| WO-2 | `orchestrator/src/coherence-gate.ts` | 8 ✅ | **LIVE** — scans full-file writes to boundary files; regenerate guidance via `runtimeSystemGuidance` |
| WO-3 | `orchestrator/src/convergence-breaker.ts` | 9 ✅ | **LIVE** — wired into `focusSupervisor`; cross-session ledger at `.omnius/convergence-ledger.json` (gated on `disablePersistentMemory`) |
| WO-4 | `memory/src/context-folding.ts` | 5 ✅ | bundle instantiated; active-window rewrite dormant (needs context-frame-builder integration) |
| WO-5 | `memory/src/compaction-policy.ts` | 9 ✅ | decision/validate/SNR available via bundle; SNR already computed in the context dump; compaction firing unchanged (advisory) |
| WO-6 | `orchestrator/src/spec-gate.ts` | 8 ✅ | functions live; dormant until a planner supplies a `LockedContract` |
| WO-7 | `execution/src/harness-plan.ts` | 8 ✅ | plan+guard live; execution gated on the sandbox + security review |
| WO-8 | `execution/src/adaptive-edit-strategy.ts` | 7 ✅ | **LIVE** — tracks edit failures per file at the tool seam; rewrite guidance via `runtimeSystemGuidance` |
| WO-9 | `orchestrator/src/focusSupervisor.ts` (family-key normalization) | 17 ✅ | **LIVE** — generic action-identity canonicalizer collapses command-string/path/error variants so WO-3 actually escalates; `resolve()` on success. Found + fixed from live monitoring. |

**Cross-cutting genericity invariant:** every triage component is **toolchain-agnostic** and validated
across ecosystems — never tuned to a specific project or command (that would be reward-hacking the
demo, not hardening the harness). WO-1 parses gcc/clang **and** tsc; WO-2 scans C/C++ **and** TS;
WO-8 keys on file path (tool-neutral); WO-9's normalizer keys on shell *grammar* only, proven on
npm/cargo/pytest/make/go with pio as just one row.

**74 new unit tests, all green** (66 module + 8 integration-bundle). Wiring is additive and
try/catch-guarded so a long-haul component can never throw into the agentic loop; when
`disablePersistentMemory` is set, the convergence ledger stays in-memory (test-isolated).

**LIVE now** (behavior changes in the loop): WO-3 (convergence escalation past `forced_replan`),
WO-8 (edit→rewrite guidance), WO-2 (coherence→regenerate guidance on full-file writes).
**Dormant-by-necessity** (infra not present): WO-1 compiler runner, WO-4 active-window rewrite,
WO-6 locked contract, WO-7 execution. These are instantiated and one dependency away from firing;
each is documented above. Runtime behavior (as opposed to type/unit correctness) needs live-model
validation — the loop cannot be exercised end-to-end without a backend.

## The failure signature these work orders attack

Observed in `~/Documents/Projects/myactuator/.omnius` telemetry:

| Signal | Value | Contract that fixes it |
|---|---|---|
| Successful builds, ever | **0** (9 FAILED markers) | WO-1, WO-2 |
| Duplicate-call dedup events | **15,342** | WO-3 |
| Lifetime tool failures | **15,505** | WO-3, WO-8 |
| `forced_replan` never escalating past itself | ∞ loop | WO-3 |
| Context frame @ 82k tokens, `signalToNoiseRatio: null` | bloat | WO-4, WO-5 |
| `file_edit` hash-mismatch retried 8× identically | thrash | WO-8 |
| Cross-file type drift (3× `MotorConfig`) | incoherent base | WO-1, WO-2, WO-6 |
| `z212/MCP2515` hallucinated package | ungrounded | WO-1, WO-7 |

The convergence-cliff literature (Yang et al., EMNLP 2025: rounds 1–2 capture ~75% of
reachable improvement; 96.5% of refinement sequences resolve in ≤3 iterations; skill loops
plateau by round 5) says a trajectory that has not converged in ~3 rounds essentially never
will — it needs a *different* trajectory, not more iterations. Every work order below is built
so the harness can detect "not converging" and switch strategy instead of brute-forcing.

---

## Verified integration map (anchors)

| Package | File | Role |
|---|---|---|
| orchestrator | `src/agenticRunner.ts` (33k LOC — **do not enlarge**; wire, don't grow) | main turn loop; calls supervisor, ledger, compaction, context dump |
| orchestrator | `src/focusSupervisor.ts` (1212 LOC) | failure-family counting → `forced_replan` directives |
| orchestrator | `src/dedup-gate.ts` | cross-turn duplicate-call gate |
| orchestrator | `src/completionLedger.ts`, `src/completion-evidence-gate.ts` | completion evidence |
| orchestrator | `src/resolution-memory.ts` | cross-session failure→fix learning |
| orchestrator | `src/contextWindowDump.ts` | telemetry frame dumps |
| memory | `src/compaction.ts` (155 LOC), `src/context-window.ts` (336 LOC) | context management |
| execution | `src/typecheckRunner.ts`, `src/buildRunner.ts`, `src/linterRunner.ts` | verifier primitives (already exist!) |
| execution | `src/tool-executor.ts`, `src/tools/file-edit.ts` (671 LOC), `src/tools/batch-edit.ts` | tool dispatch + edits |
| execution | `src/model-broker.ts` | model tier selection |
| backend-vllm | `src/routing.ts` | request→backend routing |

Persistence convention: session-scoped JSON under the project `.omnius/` dir, matching the
existing `error-patterns.json` / `resolution-memory.json` / handoffs pattern.

---

## WO-1 — In-Loop Structural Verifier (verify *during* generation, not after)

**Insight:** Decoding-Time Verification (arXiv 2605.17626) — interleave the compiler/type-checker
at structural boundaries; "early errors corrupt the autoregressive context." Qwen3-4B
72.3%→82.0% (C→Rust) with in-loop verification.

**Root-cause tie:** `pal.cpp` was written whole against an imagined `MotorConfig`/`Command`
shape; the mismatch was only discovered after 300+ lines, then patched forever.

**Anchors:** new `packages/execution/src/boundary-verifier.ts`; reuses `typecheckRunner.ts`,
`buildRunner.ts`, `linterRunner.ts`. Integration point: `tool-executor.ts` post-write hook +
`agenticRunner.ts` turn epilogue.

**Design:** after any file-mutating tool that touches a "structural boundary" (a header/interface
file, a new function/struct/class), synchronously run the cheapest applicable verifier for that
language (tsc/clang/pio check) scoped to the changed unit. Emit a `BoundaryVerdict {ok, diagnostics[],
scope}` that the turn epilogue attaches to the frame. On failure, the next turn is gated with the
exact diagnostics as authoritative evidence and forbidden from proceeding to unrelated files.

**Acceptance (measurable):**
- After editing a header, a signature-mismatch is reported within the same turn (not N turns later).
- `boundary-verifier` unit tests: given a fixture with a header/impl drift, verdict.ok === false and
  diagnostics name the drifted symbol.
- Regression harness: replaying the myactuator `pal.cpp` edit produces a boundary block before the
  next unrelated file edit.

**Telemetry:** `boundaryVerifier: { runs, blocked, avgMs }` in the context dump.

**Depends on:** none. **Status:** SPEC (verifier primitives already exist → medium effort).

---

## WO-2 — Contract-Coherence Regime Switch (patch ⇄ regenerate)

**Insight:** Patch repair beats regeneration *when invariants hold*; below a coherence floor you
must regenerate the type layer wholesale (Solvita 2605.15301; Beyond-Accuracy 2511.11012). myactuator
was below the floor (3× `MotorConfig`) so every patch was whack-a-mole.

**Anchors:** new `packages/orchestrator/src/coherence-gate.ts`. Consumes WO-1 verifier diagnostics +
a lightweight structural scan (duplicate type/symbol defs, header/impl signature-match ratio).
Integration point: `agenticRunner.ts` before choosing edit strategy; emits a new
`FocusRequiredNextAction: "regenerate_from_spec"` (enum widened here).

**Design:** compute `coherenceScore ∈ [0,1]` from: (a) duplicate top-level symbol definitions,
(b) fraction of impl methods whose signature matches a declaration, (c) unresolved-symbol density.
Below `regenThreshold` (default 0.6) the gate forces a **full-file / whole-module regeneration from
the locked contract (WO-6)** and forbids incremental `file_edit` on the incoherent unit until it
compiles once. Above threshold, patch mode as today.

**Acceptance:** unit test on a 3×-duplicate-typedef fixture → score < 0.6 → verdict `regenerate`;
a coherent fixture → `patch`. Integration: myactuator `types.h` replay → `regenerate`.

**Depends on:** WO-1 (diagnostics), WO-6 (locked contract as regeneration source). **Status:** SPEC.

---

## WO-3 — Convergence Circuit-Breaker (the hard cliff) — **IMPLEMENTED THIS PASS**

**Insight:** Rounds 1–2 = ~75% of reachable improvement; ≤3 iterations resolves 96.5%; plateau by
round 5 (Yang et al. EMNLP 2025; EvoSkills 2604.01687; Practical Limits 2605.01471). More iterations
on the same trajectory ≈ zero marginal value.

**Root-cause tie:** `focusSupervisor` escalates to `forced_replan` at family-count ≥ 2 but **never
escalates further**, and its `failureFamilies` map is **session-local** — a resumed session re-earns
the count from zero. The myactuator `pio run` family repeated across 5 sessions with no global
"abandon this trajectory."

**Anchors:** new `packages/orchestrator/src/convergence-breaker.ts` (+ test); minimal additive hook in
`focusSupervisor.ts observeToolResult`; exported from `src/index.ts`. Cross-session store:
`.omnius/convergence-ledger.json` (matches `error-patterns.json` convention).

**Design:** pure `ConvergenceBreaker` observes the same failure-family key focusSupervisor already
computes. `totalRounds = sessionCount + priorSessionCarry(family)`. A *productive mutation* since the
last failure decays the carry (progress resets the cliff). Tiers by `totalRounds`:
`healthy < 2 ≤ converging_warn < 3 ≤ stalled < 5 ≤ abandon`. `stalled` → directive to **stop
patching, regenerate the incoherent layer** (`run_verification`/replan); `abandon` → escalate
focusSupervisor to `terminal_incomplete` + `report_incomplete` with a regeneration instruction,
instead of emitting `forced_replan` forever. Cross-session carry is loaded on construction and
persisted on each trip so a resumed session trips immediately.

**Acceptance (measurable):**
- Same family observed 5× (across a simulated session boundary) → verdict `abandon`, tripped === true.
- A productive mutation between failures decays the count (no false abandon).
- focusSupervisor with a breaker injected escalates to `terminal_incomplete` on abandon; **without** a
  breaker, behavior is byte-identical to today (existing `focusSupervisor.test.ts` stays green).
- Cross-session: store round-trips the carry; a fresh breaker seeded from the store trips on round 1.

**Telemetry:** `convergence: { family, totalRounds, tier }` in the context dump + a
`.omnius/convergence-ledger.json` audit trail.

**Depends on:** none. **Status:** ✅ IMPLEMENTED (module + unit tests + additive focusSupervisor hook).

---

## WO-4 — Context-Folding (10× smaller active context)

**Insight:** Context-Folding (arXiv 2510.11967) — branch into a subtask sub-trajectory, then *fold*
it to a one-line outcome; active context up to 10× smaller, beats summarization.

**Root-cause tie:** a single 380 KB myactuator frame contained "duplicate" ×276, "error" ×423 —
finished-subtask noise crowding out the live type contract.

**Anchors:** new `packages/memory/src/context-folding.ts`; integrates with `compaction.ts` +
`context-window.ts`; frame assembly in `agenticRunner.ts` (`upsertContextFrame`).

**Design:** a `FoldableSegment` boundary opened when the agent starts a named subtask (e.g. "make
cem_driver.cpp compile") and closed on its boundary-verifier success (WO-1). On close, replace the
segment's turns with `folded: { subtask, outcome, artifacts[], verifier: pass }`. Folded segments are
excluded from the active window but retained on disk for audit and re-expansion.

**Acceptance:** a run that folds 3 completed subtasks shows active-window tokens drop ≥5× vs unfolded;
folded outcomes remain queryable. **Depends on:** WO-1 (fold trigger). **Status:** SPEC.

---

## WO-5 — Decision-Based Compaction + Validation

**Insight:** Self-Compacting agents (arXiv 2606.23525) — model fires compaction by rubric (fire when
subtask resolved/converging, **hold when mid-derivation/stuck**), +18.1 pts at 30–70% lower cost.
Slipstream (2605.08580) — trajectory-grounded validation that compaction didn't drop architectural
decisions.

**Root-cause tie:** myactuator compaction fired on a token threshold and `signalToNoiseRatio` was
`null` (never computed); the locked type contract was at risk each compaction.

**Anchors:** extend `packages/memory/src/compaction.ts` with a `shouldCompact(rubric)` decision fn;
new `packages/memory/src/compaction-validator.ts` (Slipstream check); pin the locked contract into the
system-prompt region so it survives every compaction. Integration: `agenticRunner.ts` compaction gate
(currently threshold-only at `compactionThreshold`/`compactionPercent`).

**Design:** replace pure-threshold firing with `threshold AND rubric`: hold if a boundary-verifier is
mid-run or the last N turns are a single unresolved derivation; fire when the last subtask verified or
the trajectory is converging. Post-compaction, the validator asserts every pinned invariant (locked
contract symbols, open bugs, next-action) still appears; if not, it rolls back and keeps the pre-compaction frame.

**Acceptance:** compute and emit `signalToNoiseRatio` (no longer null); validator blocks a compaction
that drops a pinned symbol in a fixture. **Depends on:** WO-6 (what to pin). **Status:** SPEC.

---

## WO-6 — Strong-Planner / Weak-Executor + Spec-as-Executable-Gate

**Insight:** Scaffolding out-levers model size ("Sonnet+plan > Opus+vibe"); planner-executor with a
strong planner and cheap executor + re-plan on failure; SDD specs *execute as validation gates*.

**Root-cause tie:** the 35B decided the type architecture across 40 files; the excellent
`contracts/` docs were never enforced as gates → definitions diverged file-by-file.

**Anchors:** new `packages/orchestrator/src/plan-executor.ts` + `src/spec-gate.ts`; model tiering via
`execution/src/model-broker.ts` + `backend-vllm/src/routing.ts`. Integration: `agenticRunner.ts` run
setup (a plan phase precedes the execute loop).

**Design:** a one-time plan phase (larger tier via broker, or the current session) emits a locked
**type/interface contract** (structs, signatures, file manifest) derived from the project's spec docs.
The executor loop (35B) fills one manifest unit at a time; every unit must pass its `spec-gate`
(declared symbols present, signatures match the contract) — a hard gate, not advice. Re-plan triggers
on WO-3 `stalled`.

**Acceptance:** spec-gate rejects a unit whose emitted `MotorConfig` diverges from the contract;
the locked contract is the single source WO-2 regenerates from. **Depends on:** WO-2, WO-3.
**Status:** SPEC.

---

## WO-7 — Code-as-Harness (env manipulation via code, fewer brittle tool-args)

**Insight:** Code-as-Agent-Harness (arXiv 2605.18747) — the agent manipulates its environment by
writing code rather than emitting brittle structured tool calls.

**Root-cause tie:** a large share of the 15,505 failures were malformed tool arguments
(obsolete metadata envelopes, a `ce_m_driver.h` typo, hash mismatches).

**Anchors:** new `packages/execution/src/tools/harness-exec.ts` (sandboxed, allow-listed); reuses the
existing `code-sandbox.ts` tool. Integration: register in the tool registry; route multi-step file/env
ops through a single code cell.

**Design:** expose a constrained code channel (fs + shell within the project root, no network) so a
batch of edits/reads/moves is one verified code cell with real error messages, instead of a dozen
brittle `file_edit` calls each subject to the hash/`old_string` contract.

**Acceptance:** a 5-file rename that today needs 5 hash-guarded edits completes as one code cell with a
single pass/fail. **Depends on:** existing `code-sandbox.ts`. **Status:** SPEC (security review required
per `browser-control-safety`/`token-security` conventions).

---

## WO-8 — Adaptive Edit Strategy (HarnessBridge-lite: auto-switch edit→rewrite)

**Insight:** HarnessBridge (arXiv 2606.12882) — a learnable controller for the harness↔model
interface. The harness should *adapt* rather than let a weak model bang on a brittle primitive.

**Root-cause tie:** `file_edit expected_hash=…` rejected and retried **8× identically**; 965
`file_edit:not_found`.

**Anchors:** new `packages/execution/src/adaptive-edit-strategy.ts` (+ test); minimal hook in
`tool-executor.ts` / `tools/file-edit.ts`.

**Design:** per-file counter of consecutive `file_edit` failures (hash-mismatch / old_string-not-found
/ not_found). After `switchThreshold` (default 2) failures on a file, the strategy recommends
switching that file to a **full-file rewrite** (`file_write`) seeded with the current file contents,
and the executor surfaces that as the required recovery. Counter resets on a successful mutation.

**Acceptance:** 2 hash-mismatch failures on one file → strategy returns `mode: "rewrite"` with the
current contents as the base; a success resets the counter; unit tests cover mismatch, not-found, and
reset. **Depends on:** none. **Status:** SPEC (small, self-contained — next after WO-3).

---

## WO-9 — Convergence Family Normalization & Correctness (from live monitoring)

**Origin:** Live 35B run on `myactuator` (2026-07-04, turn 14–16). WO-3 was confirmed firing —
`.omnius/convergence-ledger.json` was created and tracking the `pio run` failure — **but the breaker
never escalated** because the model re-ran the same logical action with trivially different command
strings, so the ledger fragmented into 3 families each stuck at `rounds=1`:

```
rounds=1  shell:cd firmware/esp32 && pio run 2>&1 | tail -100 :tool_failed
rounds=1  shell:cd firmware/esp32 && pio run 2>&1              :tool_failed
rounds=1  shell:cd /home/roko/.../firmware/esp32 && pio run    :tool_failed
```

None reaches `stalled`(3)/`abandon`(5). The 35B slips the guard by varying the command — the same
evasion behind the original 15k-thrash. (Positive: context stayed ~1.2–1.4k tokens, no bloat.)

### Root cause (two fragmentation axes) — anchors

1. **Command-string axis.** `actionFamily(toolName, args)` in
   `packages/orchestrator/src/focusSupervisor.ts` keys a shell family on the raw command:
   ```ts
   if (toolName === "shell") {
     const command = args?.["command"] ?? args?.["cmd"] ?? "";
     return `${toolName}:${compactTarget(String(command ?? "") || "no-command", 120)}`;
   }
   ```
   `compactTarget()` only collapses whitespace + truncates — no semantic normalization. So
   `pio run`, `pio run 2>&1`, and `pio run | tail -100` are three families.

2. **Error-class axis.** `failureFamilyKey()` = `` `${actionFamily(...)}:${errorClass}` ``. The
   breaker is fed this (`family`, with errorClass) at `focusSupervisor.ts` ~line 662. A command that
   fails with a different `errorClass` each attempt fragments a second way. Convergence should track
   *"stuck repeating this action,"* independent of which error each attempt throws.

3. **No `resolve()` on success.** The breaker never clears a family when the underlying work
   succeeds (the `resolve()` API exists in `convergence-breaker.ts` but is unwired). A family that
   accumulates rounds then finally passes could still carry stale rounds and falsely trip later.

### Genericity & anti-reward-hacking guardrails (PRIMARY constraint)

The `pio run` case is the *symptom that surfaced the gap*, **not** the thing to fix. The normalizer
MUST be a generic **action-identity canonicalizer** that reduces any semantically-equivalent shell
invocation to the same key across **any** toolchain — never a PlatformIO/`pio`-aware special case.
Tuning to the demo command would be reward-hacking (making this run look good instead of making the
harness robust) and is explicitly forbidden.

Rules:

1. **No tool-name allow-lists / no project-specific patterns.** The normalizer never matches `pio`,
   `platformio`, `firmware/esp32`, or any literal from this repo. It operates only on *shell
   grammar* (pipes, redirections, path syntax, whitespace) — decoration that is semantically neutral
   for *every* command.
2. **Strip only meaning-preserving decoration.** Remove trailing display filters (`| tail`, `| head`,
   `| less`, `| cat`, `| grep` used for viewing), stream redirections (`2>&1`, `>/dev/null`,
   `2>/dev/null`), and normalize absolute↔relative path *form* (via the run's cwd, not a hard-coded
   root). Never remove flags/arguments that change *what the command does*.
3. **Conservative — prefer false-split over false-merge.** Collapsing two genuinely different
   commands into one family causes *premature abandonment* of distinct work — worse than leaving
   them split. When a token's semantic effect is uncertain, keep it. `npm test` and
   `npm test -- --grep auth` must stay **distinct**; `cargo build -e x` and `cargo build -e y` must
   stay **distinct**.
4. **Validated across ecosystems, not one.** Correctness is demonstrated on npm, cargo, pytest, make,
   go, and generic shell — with `pio` as merely one of several rows — so the rules cannot silently
   overfit. The same discipline applies to the other triage components (WO-1 parses gcc/clang **and**
   tsc; WO-2 scans C/C++ **and** TS; WO-8 keys on file path, tool-agnostic).

### Design

- **9a — Generic action-identity canonicalizer** for family keying. New
  `normalizeShellForFamily(cmd, cwd?)`: collapse whitespace (reuse the pattern from
  `packages/execution/src/tools/shell.ts:899 normalizeCommand`), strip trailing *display* pipelines
  and stream redirections, and canonicalize path *form* against the run's cwd (relative↔absolute) —
  all grammar-level, tool-agnostic. Semantically-meaningful arguments are preserved verbatim.
  Examples (each collapses to one family; none is pio-specific):
  `npm test 2>&1 | tail -50` ≡ `npm test`; `cargo build 2>&1` ≡ `cargo build`;
  `cd <abs>/svc && pytest -q | tee log` ≡ `cd svc && pytest -q | tee log` (only the `cd` path form
  is normalized; `-q` and the writing `tee` are preserved). Counter-examples that must **stay
  distinct:** `npm test` vs `npm run test:e2e`; `make` vs `make clean`; `go build ./a` vs
  `go build ./b`.
- **9b — Coarser convergence key.** Feed the breaker the normalized **action** family
  (`actionFamily(...)` alone, no `:errorClass`) rather than `failureFamilyKey`. Keeps the focus
  `failureFamilies` map as-is (error-specific); only the convergence trajectory is coarsened, so
  error-message churn on the same action doesn't fragment it either.
- **9c — Wire `resolve()` on verified success.** When a verification-like shell command succeeds,
  clear that action family's carry (generic: any command that previously failed and now succeeds).

### Full integration modification points (exact)

| # | File · anchor | Change |
|---|---------------|--------|
| 1 | `orchestrator/src/focusSupervisor.ts` · `actionFamily()` shell branch | wrap `command` in `normalizeShellForFamily(...)` before `compactTarget` |
| 2 | `orchestrator/src/focusSupervisor.ts` · new top-level helper near `actionFamily`/`compactTarget` | add `normalizeShellForFamily(cmd: string): string` (9a) |
| 3 | `orchestrator/src/focusSupervisor.ts` · breaker wiring (~L662) | change `family` → `convergenceFamily` where `const convergenceFamily = actionFamily(input.toolName, input.args)` (9b) |
| 4 | `orchestrator/src/focusSupervisor.ts` · `observeToolResult` shell-success branch (`if (input.toolName === "shell" && input.success)`) | add `this.convergenceBreaker?.resolve(actionFamily(input.toolName, input.args))` (9c) |
| 5 | `orchestrator/src/convergence-breaker.ts` | no change required (keys on `obs.family`); optionally accept a `normalizeFamily` fn for defense-in-depth |
| 6 | `orchestrator/tests/focusSupervisor.test.ts:1104` | update the `forbiddenActionFamilies` expected string if the normalized shell family differs (**test modification point**) |
| 7 | `orchestrator/tests/*` (new) | add: `normalizeShellForFamily` collapses the 3 pio variants; breaker escalates `stalled`→`abandon` after 3/5 *varied* pio-run failures; `resolve()` clears on success |
| 8 | `orchestrator/src/longhaul-integration.test.ts` (new case) | end-to-end: 3 varied `pio run` failures through a `FocusSupervisor` → terminal escalation |

### Acceptance (measurable — proven generic, parameterized over ecosystems)

- **Genericity table** (drives a parameterized test — pio is one row of many): for each
  `{ base, variants[] }` below, all variants collapse to one family:
  | base | variants that must MERGE |
  |------|--------------------------|
  | `npm test` | `npm test 2>&1`, `npm test \| tail -50` |
  | `cargo build` | `cargo build 2>&1 \| head`, `cargo build 2>/dev/null` |
  | `cd firmware && pio run` (path FORM only) | `cd <abs>/firmware && pio run 2>&1`, `cd <abs>/firmware && pio run \| tail` |
  | `pytest -q` | `pytest -q 2>&1`, `pytest -q \| tail -80` |
  | `make` | `make 2>/dev/null`, `cd <abs> && make` |
  | `go test ./...` | `go test ./... 2>&1 \| tail` |
  | `pio run` | `pio run 2>&1`, `cd <abs>/firmware/esp32 && pio run \| tail -100` |
- **Non-merge table** (must stay DISTINCT — proves conservatism): `npm test` ≠ `npm run test:e2e`;
  `make` ≠ `make clean`; `go build ./a` ≠ `go build ./b`; `cargo build -e x` ≠ `cargo build -e y`.
- For any base, three *varied* failures → one family, `rounds` 3 → `stalled`; a 5th → `abandon` →
  `focusSupervisor` state `terminal_incomplete` (validated with a non-pio base, e.g. `npm test`).
- A successful verification command clears the family (`resolve()`), so a later unrelated failure
  starts at round 1.
- `focusSupervisor.test.ts` updated and green; full orchestrator suite has no new regressions;
  `pnpm -r build` exits 0.

### Peripheral gaps folded in / noted

- **WO-8 edit families** key on file path (`adaptive-edit-strategy.ts`) — stable, low fragmentation
  risk; verify `batch_edit`/`file_patch` path extraction is consistent (`realMutationPaths[0]`).
- **WO-1 boundary compiler runner** remains dormant (needs a repo profile / runner) — separate,
  already tracked in the status table.

**Status:** ✅ IMPLEMENTED + LIVE-WIRED. `normalizeShellForFamily()` +
`actionFamily(…, cwd)` + coarse convergence key (`convergenceFamilyCounts`) + `resolve()` on shell
success, all in `focusSupervisor.ts`; cwd threaded from `agenticRunner`. 17 new WO-9 tests
(cross-ecosystem merge/non-merge, path-form, escalation on varied commands, resolve) + updated the
one focusSupervisor test that encoded the old pager-evasion behavior. Found during live monitoring;
fixes the 5-families-at-rounds-1 fragmentation.

## Root refinement — progress = verification delta, not edit activity (from live monitoring + literature)

**Observed live (post-WO-9):** the breaker never escalated the myactuator *edit* loop — the model
edited ~1000× without ever compiling, and WO-3/WO-9's progress-decay treated every mutation as
"advancing," so a *futile* edit loop looked like progress forever.

**Literature confirms this is the crux.** *Coherence Collapse* (arXiv 2603.24631): agents reach/near
correct code then degrade it; the fix is quality-tracked verification, not edit counting. RLCSF /
Lanser-CLI (arXiv 2510.22907) and PyTy: "coding agents fail when text-level guesses outrun program
facts" — progress must be measured by the **compiler/verification signal**, not by edits.

**Root fix (implemented):** the convergence breaker's decay is now driven by a **verification signal
delta** — `failureSignal` (a generic error count) must *drop* across repetitions to count as progress;
editing that doesn't reduce errors no longer decays the cliff, so a futile loop escalates to
`stalled`/`abandon` → regenerate. Crucially this needs **no separate compiler run** — the signal is
extracted from the failing action's *own output* (`failureProgressSignal()` in `focusSupervisor.ts`),
which the model already produces when it runs the build/test. Generic: counts `error:`/`error TS`/
`error[`/`N failed`/`FAIL` across gcc/clang/tsc/cargo/pytest/go with no tool literals; falls back to
the mutation heuristic when no signal is present (legacy behavior preserved).

- `convergence-breaker.ts`: `ConvergenceObservation.failureSignal`; decay iff signal dropped; `resolve()` clears signal history.
- `focusSupervisor.ts`: `failureProgressSignal(output)` extractor; passed as `failureSignal` in the breaker call.
- 11 tests (cross-toolchain extraction, stagnant→escalate, dropping→hold, signal-over-mutation authority, worsening→escalate fastest, focus-integration futile-vs-progressing build loops).

This is the highest-ROI change for the *edit-without-convergence* frontier: WO-1 (a dedicated
compiler run) is now optional for this signal, though still valuable for injecting the *named*
diagnostic into the next edit (PyTy pattern) and for WO-2's coherence regenerate decision.

## Mainline wiring — final status (after investigating the existing runner infra)

Investigating the mainline (research-before-decision) changed the answer for two WOs: their
intent is **already implemented** by existing omnius machinery, so wiring my modules would be
redundant duplication (and risk the tuned compaction path). Honest outcome:

| WO | Status | Evidence |
|----|--------|----------|
| WO-1 | ✅ **LIVE-WIRED** | `diagnosticGuidance()` at the tool seam — named drifted symbols from the model's own compiler output (PyTy). New capability. |
| WO-2 | ✅ LIVE | coherence scan → regenerate guidance on full-file writes |
| WO-3 | ✅ LIVE | convergence breaker → focusSupervisor (validated live: republish escalated to `stalled`) |
| WO-6 | ✅ **LIVE-WIRED** | locked contract from *coherent* units + spec-gate at the boundary seam — gives the breaker's "regenerate from the locked contract" a real target. New capability. |
| WO-8 | ✅ LIVE | adaptive edit→rewrite guidance |
| WO-9 + root fix | ✅ LIVE | family normalization + diagnostic-delta progress (validated live) |
| **WO-4** | ⚠️ **already covered** | The fold-to-one-line-that-survives-compaction is already done by `TaskState.completedSteps` (pushed on every successful mutation/verify, agenticRunner ~20806) + `recent_completed=` re-injection (~2952/27943, "survives compaction"). My `ContextFolder` duplicates this. Not wired — redundant. The *non*-redundant part (window rewrite) is the layered compaction below. |
| **WO-5** | ⚠️ **already covered** | Compaction is a 3-layer tuned system: `compactMessages` (summarization) + `WO-CE-BOUNDARY` context-engine token-budget pruning + `microcompact` (idle Qwen pattern), with mode-collapse ROOT-FIX guards; SNR (`signalToNoise.ratio`) already computed in the dump (~3531). My `decideCompaction`/`validateCompaction` would be a redundant 4th layer that risks the tuned system. Not wired. |
| **WO-7** | 🔒 **security-gated** | Arbitrary sandboxed exec requires a security review per `browser-control-safety`/`token-security`. The `planHarnessBatch` builder (pure validation) is available; adding an exec tool is blocked on review — a rule, not a gap. |

Net: every WO that adds *new* capability the mainline lacked is now live (WO-1/2/3/6/8/9 + root fix).
WO-4 and WO-5 were built before the existing `completedSteps`/layered-compaction infra was known;
their intent is already met by that infra, so wiring my modules would be duplication. WO-7's exec is
security-gated. The remaining *real* build is WO-11 (compile-verify-fold isolated sub-agents on the
existing `subtask_call`/`sub_agent` recursion), now unblocked by WO-6's locked contract.

## Dependency-ordered build sequence

0. **WO-9** convergence family normalization — **do first**; without it WO-3 fragments on command
   variants and never escalates (found in live monitoring). Generic, zero deps, blocks further live runs.
1. **WO-3** convergence-breaker — *landed + live-wired* (unblocks the infinite loop; zero deps).
2. **WO-8** adaptive-edit — small, zero deps, kills the edit thrash.
3. **WO-1** boundary-verifier — reuses existing runners; foundation for WO-2/WO-4.
4. **WO-2** coherence-gate — needs WO-1 diagnostics.
5. **WO-6** planner/executor + spec-gate — needs WO-2 (regeneration source) + WO-3.
6. **WO-4** context-folding — needs WO-1 (fold trigger).
7. **WO-5** decision-compaction — needs WO-6 (what to pin).
8. **WO-7** code-as-harness — independent; gated on security review.

Each work order lands as a **new focused module** (≤300 LOC) with its own unit tests, wired into the
seam with a minimal additive hook, never enlarging `agenticRunner.ts`.
