@alexeiled/pi-plan-exec2.1.0
Turn a Markdown execution plan into an isolated, resumable Pi run - durable controller state, one writer, deliberate recovery
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
pi-plan-exec
Turn a Markdown execution plan into an isolated, resumable Pi run.
pi-plan-exec solves the control problem of long-running AI implementation.
A capable agent can lose context, repeat work, skip verification, or start a
second writer after a restart. This extension moves task order, automatic
recovery, worktree checks, commit acceptance, and provider reconciliation out of
prompt prose into durable controller state.
The controller keeps polling and reconciles durable operations after a restart.
The default subagent backend uses the strict runtime contract on POSIX hosts
with the prerequisites and limits documented below.
It executes ready checked-list tasks in a Git checkout you choose, then runs the required review and fix stages with fresh Pi subagents or an explicitly selected review backend. A worker saying “done” is not enough: the plan’s checked items, accepted commit, required checks, and a clean worktree with no uncommitted or untracked non-ignored files are the implementation record.
The default backend targets unmodified
pi-subagents@0.76.1; no upstream patch, Bridge, pi-tasks or cc-thingz is required. Unknown launch or retirement evidence remains fenced. See runtime contracts.
Local bootstrap and required-check batches run through plan-exec's owned POSIX process-group runner, with unbounded user-stoppable lifetime and durable writer-exit retirement proof. Detached descendants that leave the process group are best-effort, matching the released runtime.
What it does
- Keeps one writer per execution lane.
/execcan create an isolated Git worktree, work in place, or use an explicitly selected existing worktree. Existing-worktree runs keep that worktree and branch, and move the interactive Pi session there. - Executes plans deterministically. It selects the next dependency-ready task, starts a fresh worker, and verifies completion from a committed plan candidate.
- Recovers deliberately. A reload reattaches a matching run owned by the
returning session.
/exec resumetakes over a run whose owning session is proven dead, and reconciles its existing operation before continuing it. Compare-and-set records, operation IDs, controller locks, and leases avoid intentionally starting another writer or losing a pause or cancellation. - Requires a valid candidate before completion. A task is accepted only after its committed plan checkboxes, ancestry, frozen required checks, and a clean worktree with no uncommitted or untracked non-ignored files are verified. The default review is one required subagent reviewer; blocking findings remain unmet and schedule recovery.
- Schedules dependencies and preserves partial work. Omitted
dependsOnmetadata keeps legacy sequential order.dependsOn: []declares an independent task. A failed partial task stays in its lane while an eligible independent task can use a clean lane from the last accepted commit. Completed lane work is promoted back to the original output branch by a guarded fast-forward after required review and verification.
Install and run
Requires Pi ^1.0.4 (1.0.4 or later in the 1.x series).
The development baseline is Pi 1.0.4 and pi-subagents@0.76.1. Install them as independent Pi
packages; no Git dependency or allow-git=all setting is required:
pi install -l npm:pi-subagents@0.76.1
pi install -l /absolute/path/to/pi-plan-exec
The default review backend is one required readonly plan-exec-reviewer, registered
through public native runtime-agent events, with an empty
fallback list (none). Fusion 0.9.3 is the tested baseline; that stack does
not satisfy this extension's strict review ownership contract. Compatibility
requires advertised lifetime, durable lookup and process-tree proof capabilities;
a newer version alone does not establish support. Revmux's required lifecycle
support is still in an unmerged PR. Use these backends only with a verified
runtime contract; see runtime contracts.
Task summaries come from run.tasks; Fleet is advisory. No task-store package is used.
The development checkout and CI use npm 12.0.2.
Pi supplies its SDK, TUI and TypeBox modules. This extension declares the SDK
as a tested ^1.0.4 peer and TUI/TypeBox as "*" peers, never private runtime
dependencies. pi-subagents is an optional versioned peer for its runtime APIs. If startup reports “Host-provided
extension packages must be declared in peerDependencies”, check the
package.json path in the warning: another installed extension can cause it.
Update or fix that package's declarations; do not suppress the warning or add
private SDK copies here. See the historical upstream audit for
the pre-cutover investigation; current requirements are in the runtime contracts.
Before cutover, quiesce existing executors and keep a consistent registry/journal
backup. Restart Pi after package upgrades; do not run old and new controllers
against the same registry. /reload is for local source/config changes.
Downgrade is unsafe while native records or artifacts remain, including terminal
history. Older code can accept those records and delete their artifacts. Use the
read-only rollback preflight; never delete
evidence merely to make that check pass.
Legacy records are read-only data, not another backend. Already-bound native IDs
need no journal. Unbound records can explicitly import a consistent offline
schema-7 snapshot:
/exec resume <full-run-id> --legacy-journal /absolute/path/to/offline.sqlite
Import preserves the original request/digest and cannot authorize replay, erase stop intent or revive abandoned runs. Never copy only the main file of a live WAL database. No default live journal is opened or migrated.
New model operations use one keyed native workflow and unique run-owned output.
Requested maxTurns settings are recorded but unsupported by native RPC 0.76.1.
Unbounded workflow mode does not remove native child defaults. Bounded timeout is
passed to both root and child; observed limits and retirement remain evidence,
not assumptions. Typed review must match the exact commit; missing reports fail.
From an interactive session in a Git repository, start a goal or run a plan:
/reload
/goal Fix the failing tests
/goal Add a greeting endpoint --check "npm test"
/exec docs/plans/20260713-add-greeting.md
/exec --worktree ../project-feature docs/plans/20260713-add-greeting.md
/goal <goal text> pursues a goal autonomously in place on the current branch
and needs no plan file or checkbox list. It requires a clean worktree and at
least one required check, auto-detected from the project or supplied with
--check "<command>". The controller runs one worker turn per iteration through
the same owned runtime, registry, leases, stop fences, and recovery as /exec:
the worker inspects the state, chooses and executes the next useful action, and
commits. An ordinary turn summary is an intermediate answer and the controller
schedules the next turn automatically. A completion claim only starts
verification: the required checks, then the configured review and final
verification, must pass on the committed work. Deleting test files or adding
skip/only markers pauses completion for confirmation; three turns without
progress pause the goal with a recorded reason, and a blocker pauses it until
/goal resume <run-id>. /goal status, /goal pause, /goal cancel, and
/goal help manage the run.
Progress without the noise
Pi shows a two-line progress strip: plan title, state, accepted task count and current action. Green means healthy running or complete. Amber means waiting, uncertain or stopping. Failures are red; paused runs are muted. Cancelled runs are not displayed. Text and symbols carry the same meaning without color. In-flight runs are shown as amber snapshots unless this session's local controller owns and polls them. Snapshots retain the saved execution label. A snapshot is not a claim that the worker is healthy or still running. An observed operation pause is amber, not green Working. If one task waits on a prerequisite while another runs, the strip shows both work and the wait.
Both commands use the same controls:
| Control | Meaning |
|---|---|
status [run-id] |
Inspect progress and recovery evidence |
resume [run-id] |
Continue paused or stuck work |
pause [run-id] |
Pause and keep for later |
cancel [run-id] |
End the run and dismiss its UI permanently |
hide |
Toggle the strip and footer without stopping work |
help |
Show the short command list |
For example, /goal cancel or /exec cancel.
/goal stop also cancels finally. Use /goal pause when you want to resume later. Cancellation hides the run
immediately, including after reload or in another session. Saved work stays.
It does not mean successful completion or prove worker exit: the controller
keeps the ownership record while it safely stops tracked work. No clear or
cleanup command is needed to dismiss a cancelled run.
hide preferences survive reload in the active session branch. Compatibility
controls ui on|off, show [run-id], and clear [run-id] remain accepted by
both commands. They cannot restore a cancelled run.
See live Pi screenshots and checks.
Advanced recovery and compatibility controls
Use /exec help advanced for the full command reference.
/exec statusnever interrupts or restarts a run. It may idempotently repair advisory Fleet visibility and task summaries fromrun.json. With no run ID it lists every run, groups the ones that claim a worker by the evidence for that claim, reports any missing package with its install command, and ends every row in one next command. Add a full run ID for one run in detail, or--allto include terminal runs older than a day./exec resumecontinues or recovers anything stuck. It takes the lease over from a session proven dead, reconciles the existing operation when its worker is provably gone and then continues it, and asks before retrying a task blocked outside the run or rebinding the execution branch after external work moved the worktree. It never launches on partial evidence: a run whose worker cannot be proven gone is reported, not reconciled. A model or provider failure is retried with the model this Pi session is signed in to and does not consume an implementation retry;--model currentor--model provider/modelis an advanced override for that one replacement child and never pins later workers. When a child pauses for a supervisor reply, the live controller preserves and polls that workflow, then continues automatically after the reply. After a restart, resume consumes its durable result or reattaches the same operation; it does not launch a duplicate. Missing native correlation, a missing async directory, and legacy absence are inconclusive; only a matching owned-tree terminal proof, an authoritative local never-started fence permits recovery to launch again./exec recover-isolated <full-run-id> <absolute-new-checkout>previews an explicitly different recovery contract for local implementation tasks.--applyasks for confirmation, preserves the same logical run, quarantines the old operation/tree, and prepares an independent repository from the verified accepted commit. It does not prove the old worker stopped or import unaccepted edits. Activation leaves the run paused; continue from the new checkout with ordinary/exec resume. No shared Git metadata, object alternates, or old push remote is retained. This is not a security sandbox; refuse external-side-effect tasks. Quarantined trees remain reserved and prevent record cleanup./exec pause [run-id]stops the current attempt and keeps it resumable./exec cancel [run-id]requests final cancellation and dismisses the UI. The compatibility namestophas the same meaning for plans and goals. The record stayscancel_pendinguntil worker retirement is proven./exec stop <full-run-id> --forcepermanently ends controller management, including unresolved legacy launches. It dismisses the run across sessions and restarts, revokes new work and result acceptance, and attempts cancellation of the exact tracked operation. It does not claim an unknown worker died. A live foreign controller refuses the command: use its owning session. Eligible registry artifacts are removed after a durable backup; unknown operations/local commands/quarantined checkouts retain their ownership record and reservation. Worktrees, branches, progress files and provider journals are never deleted. See force-stop recovery./exec cancel <full-run-id> --forceis also accepted./exec cleanupretires run records. It previews by default and deletes nothing;--applyremoves the registry entry — never the worktree, branch, or progress file — for terminal runs that finished more than 7 days ago.failedruns are excluded, because their record is what/exec resumeneeds.
After Pi starts or reloads, the native controller restores unfinished runs when
their lease is claimable and reattaches durable operations by ID. The strip
shows current state; /exec status holds detailed evidence. Cancellation intent
wins over an old task state: the strip disappears immediately while worker
retirement continues in the background. Abandoned
runs are hidden from the default list; inspect them by ID or with status --all.
Native control distinguishes stop intent from delivery. Neither is exit proof. Advisory Fleet visibility cannot gate
recovery. Statistics are deterministic usage/task bookkeeping by default;
statsEnabled: true opts into an additional report child.
A worker that reports <<<RALPHEX:TASK_FAILED>>> with incomplete checkboxes
keeps the run in automatic recovery with its blocker reason. The controller
schedules another evidence-gathering attempt with backoff; diagnostic status
failure counters do not become a terminal retry cap or a second writer. The
worktree, accepted commits, and completed tasks are preserved; a successful
workflow transport result does not mean the task succeeded.
When the worker supplies an observed Prerequisite: value of credentials,
permission, missing_executable, or runtime together with Evidence:,
the task enters waiting_external and receives an automatic wake. Generic
blocker wording does not create that classification.
Task dependencies control eligibility, while plan-exec still runs one child at
a time per controller and keeps one writer per lane. When a provider operation
may still exist, plan-exec keeps its recorded operation ID and reconciles it
before any retry. If an optional review or statistics stage
cannot recover, /exec skip <full-run-id> --reason <text> stops the tracked
child before recording an explicit waiver and advancing. Required review and
final verification cannot be skipped; implementation and archival never can.
The run finishes as completed_with_findings.
The installed exec-plan skill is also available as /skill:exec-plan for the
plan format, the recovery rules, and the retired names and flags a scripted agent
uses instead of a prompt.
The Guide defines the accepted
heading-based formats and checkbox rules. Omit the path to select an eligible
Markdown plan below docs/plans/.
Runtime model
flowchart LR
plan["Markdown plan"] --> controller["durable controller"]
controller --> native["public native RPC: keyed main workflow"]
native --> worker["fresh worker / readonly reviewer"]
worker --> worktree["Git worktree"]
worktree --> checks["plan checkboxes"]
checks --> controller
controller --> lanes["accepted baseline + task lanes"]
lanes --> worktree
controller --> fusion["selected Fusion or Revmux review backend"]
fusion --> controller
controller --> result["completed or completed_with_findings"]
pi-plan-exec owns plan-specific control flow. Existing Pi packages retain
ownership of subagent execution, task UI, and multi-model review.
Read next
- Guide — requirements, executable-plan format, commands, lifecycle, recovery, and safety limits.
- Architecture — component ownership, state, RPC contracts, stages, and trust boundaries.
- Development — local verification and release process.
- Changelog — release history and compatibility changes.
- Historical design record — the original design before autonomous recovery.