{"type": "meta", "schema": "session-state/v1", "slug": "mega-plan-harness", "topic": "provider-agnostic plan-execution harness: shared shell core + standalone Node runner + DynWF driver", "created": "2026-06-27", "exec_mode": "ship", "scheduler": "dag-parallel", "seat": "codex", "land_mode": "merge-to-main", "base_branch": "main", "status_enum": ["BLOCKED", "PENDING", "WORKING", "WRITTEN", "REVIEWED", "COMMITTED"], "truth_rule": "this file is ground truth for INTENT; git is ground truth for DONE-NESS — reconcile statuses against git, never trust a COMMITTED line with no commit", "refresh_how": "native Read of THIS file — NEVER ctx_execute/ctx_search", "refresh_what": "meta + every goal/methodology/intent/direction record + all WORKING and BLOCKED tasks", "refresh_when": ["wave/phase boundary", "any task status change", "after a compaction system-reminder", "before calling advisor"], "update_rule": "on status change, rewrite that task's single line in place; append new tasks/session_memory as new lines", "report_rule": "at session end emit brief: done / blocked / deferred / canceled — NO next-action", "preflight": {"task_graph_hash": "480e3c841dba0890"}, "glue_model": "haiku", "codex_impl_model": "gpt-5.4", "codex_impl_effort": "low", "codex_review_model": "gpt-5.3-codex-spark", "codex_review_effort": "low"}
{"type":"goal","text":"Build mega-plan-harness Plan A: shared shell core (resolve-seat, wrappers incl codex, gates, journal) + standalone anthropic-less Node runner + DynWF driver + presets + tests. ~/.claude run-plan.js cutover AND its sonnet->haiku declassify are Plan B (separate run)."}
{"type":"methodology","text":"Contract-first per spec/ docs (WRAPPER-CONTRACT, PRESETS, FORK, schemas \u2014 single source of truth, never duplicate). Each shared-core unit = a CLI both planes invoke identically; control planes hold ONLY control flow. Test both branches (success + fail-closed) per unit. Vendor existing na.sh/ca.sh/cx.sh/risk-router.sh + the tested gate0 lib, adapt to contract."}
{"type":"intent","text":"Execution must run standalone outside Claude Code (droppable into opencode/codex), engine-agnostic + per-run configurable via presets. Anthropic only plans/launches. Standalone runner is the day-1 product; DynWF is an optional thin front-end sharing the same core."}
{"type":"direction","verbatim":"Fail-closed everywhere: unexpected state \u2192 error+detail, never guess/force. Env scoped to the subprocess, no leak to caller."}
{"type":"direction","verbatim":"Deterministic gates (gate0=tsc/lint/test, risk-router) are NOT preset seats \u2014 always run, never bound/omitted. Only model-bound seats (coder/reviewer/fixer) are bindable."}
{"type":"direction","verbatim":"No stubs/placeholders/workarounds in DELIVERABLE code \u2014 full functionality. A contract/spec that pins the seam is NOT a stub."}
{"type":"direction","verbatim":"Comments document WHAT is non-obvious about code, NEVER why-you-chose-it. Default zero comments."}
{"type":"direction","verbatim":"Standalone runner has ZERO Anthropic dependency and NO model anywhere in its loop; shared core is shell CLIs (DynWF script body cannot require a JS module)."}
{"type":"direction","verbatim":"Plan node vocabulary = seat + tier, NEVER an engine id (no task.executor). The preset maps tier->engine. The Anthropic planner pins tier at author time; no runtime classify model in either plane."}
{"type":"direction","verbatim":"Binding.model = the ENGINE model, pinned IDENTICALLY by both planes (runner passes it to spawn, does NOT ignore it \u2014 the ca.sh wrong-model regression). The only model that drifts is the DynWF dispatch agent's own model:'haiku', which lives in the ~10-line dispatch glue, never in the binding."}
{"type":"direction","verbatim":"haiku (DynWF dispatch agent) and tier:low->north (engine binding) are DIFFERENT layers \u2014 never conflate 'haiku' with the low-coder seat; that is a category error that misresolves bindings."}
{"type":"anchor","path":"docs/specs/2026-06-27-mega-plan-harness-design.md","what":"spec"}
{"type":"anchor","path":"docs/plans/2026-06-27-mega-plan-harness.md","what":"plan"}
{"type":"anchor","path":"spec/FORK.md","what":"fork contract (2 planes, shared core, journal schema)"}
{"type":"anchor","path":"spec/WRAPPER-CONTRACT.md","what":"uniform engine wrapper CLI + exit codes"}
{"type":"anchor","path":"spec/PRESETS.md","what":"resolution ladder + fallback"}
{"type":"deferred","text":"Optional anthropic-less pre-flight: invoke na.sh directly in a disposable repo (zero model, pure wrapper) to harvest real engine exit-code vocabulary and verify WRAPPER-CONTRACT 0/124/2/3 + 'any other nonzero' coverage before the runner consumes those codes.","reason":"contract-completeness validation, not a build dependency \u2014 run before/alongside wave 1 if desired"}
{"type":"task","id":"w1.p1.t1","wave":1,"phase":1,"seat":"coder","tier":"medium","desc":"Vendor wrappers to wrappers/: na.sh (verbatim, already contract-clean), ca.sh (adapt rc to emit 0/124/2/3 distinctly — currently set -e), codex.sh (vendor+adapt from ~/.claude/workflows/lib/cx.sh). Add wrappers/_contract-probe.sh <wrapper> asserting the fixed flag set + exit-code map against a mock engine. Each MUST satisfy WRAPPER-CONTRACT.md.","status":"COMMITTED","deps":[],"files":["wrappers/na.sh","wrappers/ca.sh","wrappers/codex.sh","wrappers/_contract-probe.sh"],"requires_decision":null,"blocker":null}
{"type":"task","id":"w1.p2.t1","wave":1,"phase":2,"seat":"coder","tier":"high","desc":"Build lib/resolve-seat.sh: --plan <jsonl> --runconfig <json> --node <id> -> stdout binding JSON exit 0; resolution ladder PRESETS.md rungs 1-3 (override->tiered->flat), rung 4 unresolvable -> exit 2 + stderr {ok:false,detail} fail-closed; MUST reject gate0/risk as non-seats (exit 2). Pure fn of (plan,runconfig,node). lib/test-resolve-seat.sh asserts every rung + gate-rejection + unknown/cyclic fail-closed (both branches), run-plan-lib.sh test pattern.","status":"COMMITTED","deps":[],"files":["lib/resolve-seat.sh","lib/test-resolve-seat.sh"],"requires_decision":null,"blocker":null}
{"type":"task","id":"w1.p3.t1","wave":1,"phase":3,"seat":"coder","tier":"medium","desc":"Build lib/journal.sh: append <jsonl> <record> (one line, never pretty), state <jsonl> <task> -> last state, reconcile <jsonl> <repoRoot> <branch> -> re-derive done-ness from git + downgrade phantom COMMITTED. runstate/v1 schema per FORK.md. lib/test-journal.sh both branches.","status":"COMMITTED","deps":[],"files":["lib/journal.sh","lib/test-journal.sh"],"requires_decision":null,"blocker":null}
{"type":"task","id":"w1.p4.t1","wave":1,"phase":4,"seat":"coder","tier":"medium","desc":"Build lib/gates.sh wrapping the EXISTING tested gate0 (vendor gate0_* funcs from ~/.claude/workflows/lib/run-plan-lib.sh; modes strict + baseline-ratchet, default strict) + vendor risk-router.sh to lib/. Deterministic, NEVER a seat; repo-agnostic check discovery, fail-closed if none. lib/test-gates.sh reusing the existing lib's tests as vendoring fidelity check.","status":"COMMITTED","deps":[],"files":["lib/gates.sh","lib/risk-router.sh","lib/test-gates.sh"],"requires_decision":null,"blocker":null,"lease_ts":1782646220}
{"type":"task","id":"w2.p1.t1","wave":2,"phase":1,"seat":"coder","tier":"medium","desc":"Author presets/anthropic-less.json + presets/codex.json (preset/v1), wrapper paths repo-relative wrappers/<x>.sh. Build presets/_validate.mjs (zero-dep) asserting every preset + example runconfig vs spec/{presets,runconfig}.schema.json AND every bound wrapper path resolves to an existing executable (no vapor).","status":"COMMITTED","deps":["w1.p1.t1"],"files":["presets/anthropic-less.json","presets/codex.json","presets/_validate.mjs"],"requires_decision":null,"blocker":null}
{"type":"task","id":"w2.p2.t1","wave":2,"phase":2,"seat":"coder","tier":"high","desc":"Build src/runner.js: harness run --plan --runconfig [--concurrency N] [--resume]. Control flow ONLY (FORK iron rule): parse->wave groups->bounded Promise pool; per task lease->resolve-seat->child_process.spawn(wrapper) passing binding.model->gate0 bounded retry-fix->risk->[review if seat bound]->commit; journal each transition; compute base/head shas itself; fail-closed halts (wrapper 2/3, gate-not-green-after-N, resolver error); fallback on 3/repeated-124 bounded 4 hops cycle-detected; --resume = journal.reconcile then advance to next APPLICABLE state. NO model anywhere. Imports lib/*.sh via child_process, never a JS port.","status":"COMMITTED","deps":["w1.p1.t1","w1.p2.t1","w1.p3.t1","w1.p4.t1"],"files":["src/runner.js","src/test/runner-transcript.test.js"],"requires_decision":"g-protected-src","blocker":null}
{"type":"task","id":"w2.p3.t1","wave":2,"phase":3,"seat":"coder","tier":"high","desc":"Build src/dynwf-driver.js: Workflow-script form of the SAME loop, allowed drift only (FORK.md). Plan via args injection (no FS); dispatch = agent(prompt,{model:'haiku',schema}) whose prompt shells out to resolve-seat.sh + the wrapper and transcribes rc (pure dispatch+transcribe, NEVER judgment); concurrency/resume via Workflow parallel/runId; journals SAME runstate/v1 at SAME per-task granularity; re-derive in-flight state from git+JSONL on compaction.","status":"COMMITTED","deps":["w1.p1.t1","w1.p2.t1","w1.p3.t1","w1.p4.t1"],"files":["src/dynwf-driver.js"],"requires_decision":"g-protected-src","blocker":null}
{"type":"task","id":"w3.p1.t1","wave":3,"phase":1,"seat":"coder","tier":"medium","desc":"Runner integration test: fixture plan + stub wrapper (echoes a diff) -> assert journal transitions leased->...->committed AND a fail-closed halt on stub exit 3.","status":"COMMITTED","deps":["w2.p1.t1","w2.p2.t1"],"files":["test/runner-integration.sh"],"requires_decision":null,"blocker":null}
{"type":"task","id":"w3.p2.t1","wave":3,"phase":2,"seat":"coder","tier":"medium","desc":"DynWF drift-guard dry-run: assert the DynWF driver shells the SAME resolve-seat.sh + wrapper paths as the runner (two planes MUST call identical core CLIs — the FORK delete-and-rebuild seam).","status":"COMMITTED","deps":["w2.p2.t1","w2.p3.t1"],"files":["test/dynwf-drift-guard.sh"],"requires_decision":null,"blocker":null}
{"type":"gated","id":"scan-1","category":"input","needs":"Source paths for na.sh and ca.sh vendoring","why":"Task desc mentioned ~/.claude/workflows/lib/ paths that do not exist","blast_radius":"w1.p1.t1 vendoring","options":["proceed","abort"],"status":"RESOLVED","answer":"proceed","resolved_by":"preflight-scan"}
{"type":"gated","id":"scan-2","category":"input","needs":"Source path for risk-router.sh","why":"Task desc gave no source path","blast_radius":"w1.p4.t1 gates.sh build","options":["proceed","abort"],"status":"RESOLVED","answer":"proceed","resolved_by":"preflight-scan"}
{"type":"gated","id":"scan-3","category":"architecture","needs":"codex.sh invocation shape","why":"Task says vendor+adapt from cx.sh but cx.sh has review|integrate mode interface, not WRAPPER-CONTRACT.md interface","blast_radius":"codex.sh interface mismatch breaks all codex-preset runs","options":["proceed","abort"],"status":"RESOLVED","answer":"proceed","resolved_by":"preflight-scan"}
{"type":"gated","id":"scan-4","category":"architecture","needs":"How codex.sh parses compound model strings like gpt-5.5-high","why":"codex exec takes separate -m <model> -c model_reasoning_effort=<effort>; presets pass gpt-5.5-high as --model","blast_radius":"wrong effort dispatched on every codex seat","options":["proceed","abort"],"status":"RESOLVED","answer":"proceed","resolved_by":"preflight-scan"}
{"type":"session_memory","key":"scan-1-resolution","text":"w1.p1.t1 vendoring paths: na.sh vendor from ~/.claude/skills/north-orchestrator/na.sh; ca.sh vendor from ~/.claude/skills/cursor-orchestrator/ca.sh. Task description paths (~/.claude/workflows/lib/) do not exist."}
{"type":"session_memory","key":"scan-2-resolution","text":"w1.p4.t1 risk-router.sh vendor from ~/.claude/skills/multi-orchestrator/risk-router.sh."}
{"type":"session_memory","key":"scan-3-resolution","text":"w1.p1.t1 codex.sh MUST implement WRAPPER-CONTRACT.md interface (--workspace --trust --task-slug [--model] [--timeout]). Borrow cx.sh patterns for timeout/stdin/test-seam discipline only. Do NOT copy cx.sh review|integrate CLI shape."}
{"type":"session_memory","key":"scan-4-resolution","text":"codex.sh model string parsing: split on last dash. gpt-5.5-high -> model=gpt-5.5 effort=high. Document <model>-<effort> convention in WRAPPER-CONTRACT.md. Unknown suffix -> exit 2."}
{"type":"gated","id":"g-protected-src","category":"policy","needs":"Allow Wave 2 source tasks to modify their declared src/ implementation and test files","why":"Harness protects src/; these tasks' declared deliverables are in src/.","blast_radius":"w2.p2.t1 and w2.p3.t1 only","options":["proceed","abort"],"status":"RESOLVED","answer":{"protectedPaths":["src/runner.js","src/test/runner-transcript.test.js","src/dynwf-driver.js"]},"resolved_by":"user"}
