Pin context manifests in durable model commands

Merged
VA
4d ago
+2593-385

Problem

Durable model commands previously relied on a live context binding. Queueing with manifest A and reopening with B could change the request before dispatch or conflict during reconciliation.

Design

  • Require the exact manifest FileRef in ModelTaskCommand: volume, path, immutable version, content digest and byte length. Missing and null references fail decoding. Dispatch and replay load that retained file through the task's authorized volume reader.
  • GraphCoder's real prompt publisher retains the selected manifest reference before durable admission. Remove its startup-bound live pipeline. LocalHarness publishes one content-addressed default manifest per effective catalog under its existing inputs read grant, and retains that reference in every prompt. Explicit LocalHarness context selection takes a manifest FileRef.
  • Keep AGENTS.md, CLAUDE.md and selected skill bodies at pinned file/generation references. Hook/MCP configuration source references are authenticated without exposing configuration bytes as prompt text.
  • Carry registry ownership through manifest binding and into NativeStockExecutor. Unique registries retain their maps and keys. Native registry copies remain funded by the original worker ledger.
  • Carry original IO through selected-skill workspace opening, generation selection, pinning, body/metadata reads, decoding and reference construction. An explicit generation avoids observing an unrelated current head. Metadata reads use the remaining original read allowance.

Decisions

  • Every durable model command derives context and model-visible tools from its required manifest. Delete the ambient pipeline fallback rather than retaining a second recovery representation. Tool executors must still match the retained definitions; manifests convey no authority.
  • Use existing immutable files and ContentPublisher operations. No additional store, transport, journal, polling or client recovery state.
  • Preserve the signed main merge, including #686. No allowance increases. The worker's original ledger covers admission, execution, reopening, reconciliation and settlement. Later passive journal inspection is a separate bounded query; its regression verifies its own custody and that the settled worker receipt remains unchanged.
  • Retain all 256 workflow property cases and the effective shrinking budget. Share immutable schema setup, use fresh stream/volume state per case, and join independent scoped workers with an asserted total case count.

Deletions

Delete FilesystemTaskCommands::with_context_manifest, ModelBinding.tools and ModelBinding.context, the live pipeline argument to durable with_model, LocalHarnessConfig::context, and GraphCoder's startup-bound manifest stage. Repoint all callers, including browser and workflow fixtures. Delete the redundant native registry copy, per-entry temporary tree allocations, and the timing/polling interruption fixture replaced by a scripted provider notification.

Net +2,208 lines (+2,593/-385), including +804 lines updating the standalone fuzz lockfile to the already-selected native closure; net +1,404 excluding the lockfile. This review follow-up is +237 lines (+513/-276).

Tests run

Native closure, with defaults: filesystem-local,native-execution,terminal,mcp-http,test-support (includes hooks, mcp-stdio and mcp-http).

  • Final Windows lb.ps1 cargo check -p acyclic-harness --lib --tests: passed, 17.72s build after the local slot queue.
  • Final bb1 no-run build: --lib, --bin graphcoder, --test task-workflow and --test context-discovery; 116.87s. Run the resulting binaries directly: 33/33 focused tests passed. Longest suite 1.609s; manifest workflow/native/skill-budget suite 0.409s; GraphCoder production submission/recovery regression 0.202s; registry ownership property 0.083s.
  • GraphCoder regression queues A through prompt_command and queue, discards the session and retained references, reopens with B, and verifies A reaches the model. Also crash after dispatch and reconcile without generating again. Scripted dispatch notification replaces polling and real-time delays.
  • Admission-to-recovery regressions edit/delete actual AGENTS.md, CLAUDE.md, SKILL.md, hook settings and MCP config, replace the current manifest, discard the runtime and in-memory manifest references, then assert original context and replay without resend.
  • Shrinking properties cover complete command identity round trips, rejection of missing/null manifest references, source and skill path bounds, catalog uniqueness, original skill-read allowance/cancellation, and registry storage identity. The ownership detector rejects a deliberately cloned registry through the same binding path.
  • Final bb1 browser/WASM library check with browser: passed, 56.69s.
  • Pinned nightly debug ASan context_manifest fuzz target, including checked-in pinned/missing/null command and configuration seeds: 1,000 runs passed in 1.518s (debug build 114.782s)..
  • No production synchronization changes. Caller search, rustfmt, LF/NUL/file-size audits and git diff --check passed.