# Modular Runtime Phase 4 — Automatic Long-Build Batch Canary 01

Date: 2026-08-01

Status: accepted automatic-wave slice; Phase 4 gate remains open

Execution time: 115.926 seconds

## Accepted outcome

`LongBuildModule` selected two ready cooperative nodes from one dependency-safe wave and invoked both through the existing `RecipeNodeExecutor` and `GraphWorkRunner` with integration deferred. The graph runner still owned packet registration, resource dispatch, durable attempts, real Luna transport, candidate inspection, retry policy, independent acceptance, lease release, and queue admission. No parallel runner, attempt table, scheduler, or integration authority was added.

Two real `gpt-5.6-luna` workers at `xhigh` reasoning started 37 milliseconds apart in isolated same-base worktrees. They overlapped for 99.724 seconds. While both were running, the existing integration queue contained zero jobs and zero claims. Only after both candidates were independently accepted did `LongBuildModule` claim the existing two-member epoch seam.

The trusted batch adapter created one deterministic union, ran both focused commands and the shared system command once, and moved Git authority once. The canary then forced interruption after that promotion but before the SQLite epoch receipt. A reopened `LongBuildModule` recovered the exact claimed epoch before considering any new node dispatch, reconstructed identical integration evidence, made zero planner or worker calls, atomically accepted both graph nodes, and wrote the milestone checkpoint from graph truth.

This accepts automatic long-build wave batching. It does not accept all of Phase 4.

## Exact live evidence

| Boundary | Result |
|---|---|
| Project | `live-long-build-batch-01` |
| Base | `12bebd53a5f9424f1a66919d298a2740f7c7e888` |
| Care-priority worker | PID 81478; 111.153 seconds; candidate `3507e4b488bff14d0b639e28c930c58771e568f1` |
| Person-summary worker | PID 81502; 99.724 seconds; candidate `5d410672ed419597e4d17d5ec991b8ff9b1065eb` |
| Process overlap | 99.724 seconds; starts separated by 37 ms |
| Queue during implementation | 0 total jobs; 0 claimed jobs |
| Module mode | both calls used `integration: defer` |
| Durable epoch | `ie-89ed1ebcb7b2d46583e62c21`; two exact graph-runner candidates |
| Union checks | `npm run test:priority`, shared `npm run test:system` once, `npm run test:person` |
| Union commit | `688921ecb975f5df763d7f1a1e95d39533a0fdd1` |
| Authority movement | one first-parent promotion |
| Forced reopen | after Git promotion, before SQLite terminal receipt |
| Resume | exact horizon, epoch, candidates, and receipt; zero model calls; one milestone checkpoint |

Evidence directory: [`evidence/MODULAR_RUNTIME_PHASE4_AUTO_BATCH_CANARY_01`](./evidence/MODULAR_RUNTIME_PHASE4_AUTO_BATCH_CANARY_01/)

`run-summary.json` SHA-256: `ae8f8b0326bda7f3ed2f515a6be70da21f8a05b9a98ec65390c3e8aa0b07bde3`.

## Measured speed result

The observed worker durations sum to 210.877 seconds. Their concurrent span was 111.153 seconds. On this exact automatic long-build wave, overlap removed 99.724 seconds from the implementation critical path: a 47.290% reduction and 1.897× measured worker-lane speedup.

This comparison is against serial execution of the same observed worker durations. It does not assume every workload is compatible or receives the same speedup. Planning, acceptance decisions, and authority promotion remain serialized where their contracts require it.

## What changed

The shared graph runner now has one narrow integration option:

- `complete` preserves the previous single-node path;
- `defer` stops only after the candidate is durably accepted and its integration job is waiting.

Backend and UI modules pass that option into the same graph runner. `RecipeNodeExecutor.prepareNode` selects the same admitted recipe module used by `runNode`; it does not implement its own planning or execution logic.

When a ready long-build wave contains a conservative cooperative pair with distinct logical write domains, `LongBuildModule` prepares both concurrently. It then asks the existing graph coordinator to claim a compatible epoch. The authoritative batch selector still rechecks exact graph lineage, dependency independence, packet claims, accepted attempts, job checks, and real changed-file disjointness before any union is admitted.

If no two-member wave is available, the old one-node execution and integration path runs unchanged. A deterministic regression proves this with batching configured but a worker cap of one.

## Recovery order

Every `advance` first reloads the durable horizon and graph. Before scheduling new work, it checks for an active or newly claimable compatible epoch. Therefore a reopen after promotion cannot accidentally plan, implement, inspect, accept, or integrate either node again. The replay path invokes only the idempotent trusted batch adapter and the existing atomic graph transition.

The accepted live sequence was:

1. seal one durable milestone horizon;
2. start both existing graph-module calls with integration deferred;
3. persist two independently accepted attempts and two waiting jobs;
4. claim one compatible epoch;
5. verify and promote one deterministic union;
6. interrupt before the SQLite receipt;
7. reopen the controller and recover the exact epoch;
8. replay identical Git evidence with zero model calls;
9. accept both nodes and checkpoint the milestone atomically from durable truth.

## Deterministic proof

Current tests additionally prove:

- deferring integration does not repeat implementation or candidate inspection when the same graph runner resumes normally;
- two automatic wave calls must both start before either synthetic worker can finish;
- neither deferred node may invoke the single integration adapter;
- the exact claimed epoch survives SQLite close/reopen;
- reopen calls neither the horizon planner nor either node executor;
- the shared batch receipt accepts both nodes and records one checkpoint commit;
- a one-node wave uses the original single integration path even when a batch adapter is configured.

## Evidence isolation note

The live automatic-wave fixture uses a deterministic one-milestone horizon so this canary isolates the new consumer wiring. A separate accepted Phase 4 canary already proves a real Sol/high horizon plan survives controller reopen, and the compatible-batch canary separately proves the batch authority boundary. This run proves those accepted seams are now connected to two real Luna/xhigh workers by `LongBuildModule` itself.

An earlier evidence attempt completed the runtime path but its test harness expected a human-authored node order instead of the graph's deterministic topological order. That run was discarded, produced no durable evidence directory, and prompted only an order-insensitive assertion correction. The accepted run above started from a fresh fixture and is the sole evidence represented by the recorded hash.

## Current-revision regression

Commands:

```text
pnpm --filter @orchestrator/modular-builder-core test
pnpm --filter @orchestrator/modular-builder-core build
pnpm --filter @orchestrator/modular-builder-core check:source
NO_COLOR=1 RUN_LIVE_CODEX=1 PHASE4_AUTO_BATCH_EVIDENCE_DIR=<absolute-evidence-path> pnpm --filter @orchestrator/modular-builder-core exec vitest run test/live-long-build-batch-canary.test.ts --reporter=verbose
```

Results:

- 208 deterministic tests pass across 40 active suites;
- 14 separately gated live tests remain excluded from the deterministic lane;
- TypeScript passes with no diagnostics;
- 58 runtime source files average 179 logical lines, with p50 142 and p90 409;
- the largest runtime source file is 494 logical lines;
- no runtime source file crosses the 500-line cohesion-review threshold;
- live automatic-wave canary: 1/1 in 115.926 seconds;
- two real Luna/xhigh calls, zero human checkpoints, and zero model calls after reopen.

## Exact boundary before the next slice

The long-build controller now consumes the accepted batch seam automatically while preserving the direct single-member path. Phase 4 remains open for four bounded pieces: compact accepted graph history without losing checkpoint lineage, renew the one-to-two-milestone horizon when its detailed window is exhausted, prove cache reuse without stale authority, and run one named combined system review across the resulting long build.

The next smallest slice is graph compaction: replace old accepted execution detail with a content-addressed milestone summary while retaining every active dependency, accepted version, integration head, checkpoint, failure needed for retry, and evidence hash. Compaction must be replay-safe and must not create another graph or state owner.
