{"type":"meta","schema":"session-state/v1","slug":"runplan-worktree-isolation","topic":"per-task git worktree+branch isolation for bin/runplan (src/runner.js)","created":"2026-07-02","exec_mode":"ship","scheduler":"sequential","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 (goals/directions/task list); 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 (the point is re-injecting intent into the main thread; a context-mode call keeps bytes OUT and silently kills the feature)","refresh_what":"meta + every goal/methodology/intent/direction record + all WORKING and BLOCKED tasks (skip COMMITTED lines)","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' (if you know it, do it)","preflight":{"task_graph_hash":"fcd2fa5c321bc1c3","route":{"w1.t1":"north","w2.t1":"north","w3.t1":"north","w4.t1":"north","w5.t1":"cursor","w6.t1":"cursor"},"route_hash":"fcd2fa5c321bc1c3"}}
{"type":"goal","text":"give src/runner.js (bin/runplan's engine) the same per-task worktree+branch isolation the Workflow controller (~/.claude/workflows/run-plan.js) already has, closing the active same-wave concurrency race and making the documented ship.sh land step real"}
{"type":"methodology","text":"contract-level plan per [[plan]] skill — pin seams (worktree/branch naming, journal ordering, gate0 arg split) not bodies; implementer (ship subagents) writes bodies by reading src/runner.js directly"}
{"type":"intent","text":"bin/runplan is the headless/cron-capable sibling of the Workflow-controller engine; it must not corrupt the live repo tree when tasks in a wave run concurrently (runPool already dispatches up to 8 concurrent same-wave tasks against a single shared worktree today)"}
{"type":"direction","verbatim":"has no worktree isolation at all. - well its maybe time to /brainstorm it if its a good idea to have it"}
{"type":"direction","verbatim":"We should have no grok adapter. it should run only via cursor adapter together as a hardcoded fallback to cursor-agent."}
{"type":"deferred","text":"actually dogfooding bin/runplan end-to-end against harness-tier-backlog (or any real plan) on main","reason":"blocked on this worktree-isolation implementation landing first — running the unisolated engine against a live tree was explicitly superseded by the user's redirect to /brainstorm"}
{"type":"deferred","text":"3 pre-existing uncommitted infra fixes (wrappers/codex.sh --effort flag, run-tests.sh node_modules glob, presets/cursor.json grok-fallback removal + adapters.json models schema gap) plus new Makefile","reason":"sitting uncommitted in the working tree; no instruction yet on when to commit — commits only happen when explicitly asked per user's global rules"}
{"type":"anchor","path":"docs/specs/2026-07-02-runplan-worktree-isolation-design.md","what":"spec"}
{"type":"anchor","path":"docs/plans/2026-07-02-runplan-worktree-isolation.md","what":"plan"}
{"type":"task","id":"w1.t1","wave":1,"phase":1,"desc":"worktree/branch naming helpers + serialization mutex","status":"COMMITTED","deps":[],"requires_decision":null,"files":["src/runner.js"],"blocker":null}
{"type":"task","id":"w2.t1","wave":2,"phase":1,"desc":"integration worktree lifecycle wired into run()","status":"COMMITTED","deps":["w1.t1"],"requires_decision":null,"files":["src/runner.js"],"blocker":"waiting on w1.t1"}
{"type":"task","id":"w3.t1","wave":3,"phase":1,"desc":"task worktree lease + taskBase retargeting","status":"COMMITTED","deps":["w2.t1"],"requires_decision":null,"files":["src/runner.js"],"blocker":"waiting on w2.t1"}
{"type":"task","id":"w4.t1","wave":4,"phase":1,"desc":"retarget implement/gate/review/commit to task worktree","status":"COMMITTED","deps":["w3.t1"],"requires_decision":null,"files":["src/runner.js"],"blocker":"waiting on w3.t1"}
{"type":"task","id":"w5.t1","wave":5,"phase":1,"desc":"merge-into-integration + resume ladder","status":"COMMITTED","deps":["w4.t1"],"requires_decision":null,"files":["src/runner.js"],"blocker":"waiting on w4.t1"}
{"type":"task","id":"w6.t1","wave":6,"phase":1,"desc":"rewrite runner-integration.sh for new topology, add conflict + concurrency cases","status":"COMMITTED","deps":["w5.t1"],"requires_decision":null,"files":["test/runner-integration.sh"],"blocker":"waiting on w5.t1"}
{"type":"direction","verbatim":"use run-plan-codex instead"}
{"type":"direction","verbatim":"i dont want it to run with dyn-wf. is it running with dyn-wf? First, stop."}
{"type":"direction","verbatim":"i want you to dismantle the dyn-wf that keeps running. we no longer need it. currently, run the plan with run-plan-codex.js , if you cant dogfood on the new mega runplan harness"}
{"type":"session_memory","note":"Fixed ~/.claude/workflows/lib/promptbuilder.sh (shared global infra, not repo-local) to embed the plan.md's exact '### Task N' pinned-contract section into the codex implement brief, matched to the JSONL task by wave-number positional correspondence via extract_pinned_contract(). Previously it only pointed to the spec path as a note, never embedded content, which let codex invent its own naming (branch prefix 'runplan/' instead of the pinned 'plan/'). Verified fixed: manual promptbuilder.sh run showed correct contract embedding, and the second run's w1.t1 commit matched the pinned contract exactly."}
{"type":"session_memory","note":"All 6 task lines in this file currently read status:COMMITTED but this is STALE, not git-true — per truth_rule, git is ground truth. As of 2026-07-02 there is NO plan/runplan-worktree-isolation branch and NO worktree for this slug in `git worktree list` / `git branch -a`. The only full run that hit all 6 waves green shipped code violating the pinned contract (wrong branch-naming scheme) and was discarded per user's AskUserQuestion answer 'Redo via run-plan-codex.js with fixed prompt'. A redo of w1.t1 alone was committed then also discarded (main-tree contamination from a north phantom-write, discarded via `git checkout -- src/runner.js` per user's 'Yes, discard' answer). Net: reconcile from git before trusting any status in this file — real state is effectively 0/6 landed."}
{"type":"session_memory","note":"DynWF Workflow-controller run for this plan was abandoned per user instruction ('dismantle the dyn-wf... run with run-plan-codex.js'). Stamp files ~/.claude/workflows/.run/runplan-worktree-isolation.owner and .runid were deleted to prevent auto-resume of that dead run. Execution now goes exclusively via `node ~/.claude/workflows/run-plan-codex.js --slug runplan-worktree-isolation --repo /home/user/Projects/mega-plan-harness` (foreground only — the bg-gate hook blocks agent-initiated background dispatch; only the user pressing Ctrl+B approves backgrounding)."}
{"type":"session_memory","note":"Session ended mid-diagnosis of an apparent disk-full (ENOSPC) error blocking Bash/Write tool use. Root cause found before cutoff: NOT byte-space (76G free on /, 23G free on /tmp) but tmpfs INODE exhaustion — /tmp mounted with nr_inodes=1048576, was at 94% inode usage (978,656 used). Was mid-way through `for d in /tmp/*/; do find \"$d\" -xdev | wc -l; done` to find the inode hog (candidates: many stale /tmp/wt-<slug>-<taskId> worktree dirs from other repos' concurrent run-plan-codex.js runs, each ~101 inodes) when the diagnostic command itself was killed (exit code 137) — this is the exact point the session ended. NOT yet confirmed whether inode exhaustion actually caused the earlier 'codex returned ok but produced NO changes' implement failure on w1.t1 (strong hypothesis only, never proven). As of this recovery pass (2026-07-02, same host): /tmp inode usage is now healthy again (27% used, 4194304 total inodes — the limit itself appears larger now, or other sessions freed space) — the blocker looks transient/resolved but was NOT verified as the true cause of the implement failure."}
{"type":"anchor","path":"docs/plans/2026-07-01-harness-tier-backlog.jsonl","what":"sibling deferred plan"}
{"type":"session_memory","note":"Separate, deferred thread from earlier in this session: harness-tier-backlog plan (tier taxonomy rename + tier-downgrade backlog/triage feature). Git-confirmed real progress: 2/16 tasks committed (t1, t2 merged into plan/harness-tier-backlog, worktree .wt-harness-tier-backlog-int at 7e4be8c), t3-t15 still PENDING. Per last compaction summary: t3's target (tier renaming in presets/codex.json) is already moot against current main (presets/codex.json has no tier fields at all currently) — plan is stale and needs re-scoping or abandonment. Flagged to user once, no decision made, not re-raised since. Not the active thread this session — runplan-worktree-isolation is."}
{"type":"checkpoint","text":"Session ended (context/tool exhaustion, not user-directed stop) immediately after the exit-137 kill of the inode-hog diagnostic command. No response was given to the user's last message ('let me know what you mean, there is a lot of free space. something else is wrong there') beyond the diagnostics already run. Next agent should resume the inode-usage investigation directly (re-run a per-directory find/wc count under /tmp, redirecting to a file to avoid truncation) since /tmp now looks healthy (27% inodes) but the true root cause of the codex 'no changes' failure was never confirmed either way."}
