| name | phased-implement |
|---|---|
| description | Coordinator skill that runs a multi-phase implementation across workmux worktrees. Each phase invokes /implement in its own worktree; the coordinator handles dispatch ordering (sequential, parallel, DAG), merge sequencing, and failure isolation. Composes /implement, /merge, workmux, and consult-llm. |
| allowed-tools | Bash, Read, Write, Glob, Grep |
| disable-model-invocation | true |
You are a coordinator. You never edit source files yourself. You write a master plan, spawn workmux worktree agents that each run /implement for one phase, and merge their work back via /merge in deterministic topological order.
Load the consult-llm skill before any CLI call. Follow its invocation contract (quoted heredoc, __CONSULT_LLM_END__ terminator, timeout: 600000, thread-id capture). The coordinator skill (workmux) is also a useful reference for spawn/wait/capture/send patterns.
Arguments: $ARGUMENTS
Modes:
- Free-form task — the coordinator generates the master plan via
consult-llm --task plan. --plan <path>— skip generation; load an existing phased plan from<path>.
Coordinator-level flags (apply ONLY to master-plan generation, not forwarded to per-phase /implement):
--consult-first— gather independent reviewer proposals before drafting the master plan (mirrorsimplementskill's Phase 2A).--no-review— skip plan review (Phase 1.b).--<selector>(e.g.--gemini,--openai) — reviewer selection, repeatable. Default: all available selectors fromconsult-llm models.
Per-phase flags — declared in the plan's YAML implement_flags: list. The coordinator never injects flags into a phase.
Other flags:
--integration-branch <name>— branch to merge into. Default: current branch at coordinator startup.
Strip flags from arguments to get the task description.
- Coordinator never writes source. All implementation happens inside spawned worktree agents via
/implement. workmux done≠ success. A phase is successful only when its agent has written a result sentinel reportingstatus=success. See "Phase result sentinel" below.- Merges are serialized. At most one
/mergein flight globally. /mergeis invoked with--keepso the coordinator can verify success before destroying the worktree. Coordinator runsworkmux remove <handle>after verification.- Dependents only spawn when all predecessors are
merged. No exceptions. - No tight polling. All waits use
workmux waitwith explicit timeouts. - Failure halts dependents. No auto-retry. Failed/blocked worktrees are preserved for inspection.
- YAML reasoning is native. The coordinator (you, the LLM) reads
plan.md's YAML block semantically. Do not writeawk/grepparsers for it. Use Bash only forgit,workmux,consult-llm.
START_HEAD=$(git rev-parse HEAD)
# Honor --integration-branch <name> if provided; otherwise use current branch.
INTEGRATION_BRANCH="${INTEGRATION_BRANCH_FLAG:-$(git symbolic-ref --short HEAD)}"
# Verify the branch exists.
git rev-parse --verify "$INTEGRATION_BRANCH" >/dev/null
git status --shortHalt conditions:
- Working tree shows uncommitted changes outside
history/— user must clean or stash. INTEGRATION_BRANCHresolves to a detached HEAD or does not exist — abort.- No
--planwas provided ANDconsult-llm modelsresolves no selectors — abort. (Master-plan generation requires at least one model regardless of--no-review.)
Pick a topic slug from the task description. Create the control-plane directory:
TODAY=$(date +%F)
PLAN_DIR="history/${TODAY}-phased-${TOPIC}"
mkdir -p "$PLAN_DIR/prompts" "$PLAN_DIR/captures"Initialize manifest.md (uncommitted; coordinator-local state):
# phased-implement manifest — <topic>
- integration_branch: <name>
- start_head: <sha>
- coordinator_started: <iso8601>
| id | status | handle | branch | started | ended | commit | notes |
| -- | ------ | ------ | ------ | ------- | ----- | ------ | ----- |Status enum: pending | ready | working | done-unverified | merging | merged | failed | blocked.
If --plan <path> was provided: copy the file to $PLAN_DIR/plan.md. Skip 1.b.
Otherwise generate via consult-llm. With --consult-first, mirror implement Phase 2A: write a context bundle, consult all selectors with --task plan, capture the group thread_id, write proposals + ADR, then synthesize. Without --consult-first, do a single consult-llm --task plan call.
The generated plan must be a markdown file with a fenced YAML block defining the phase DAG (schema below). Write it to $PLAN_DIR/plan.md.
Review must not reuse the planner's thread. Drop -t, pass the plan as -f, run multiple selectors in parallel: consult-llm --task review -m <r1> -m <r2> -f $PLAN_DIR/plan.md.
Use the review structure from implement Phase 3 (Spec Check / Premortem / Plan Findings). Apply must-fix changes, append a Feedback Ledger to plan.md. Single round only.
history/ is gitignored and shared across worktrees (symlinked into each new worktree by the workmux setup). The plan, manifest, prompts, and captures all live there and are visible to spawned worktree agents directly via the same path. Do not commit any of these files. Coordinator and phase agents read/write the shared history/<plan-dir>/ tree directly.
plan.md must contain exactly one fenced YAML block of this shape near the top:
phases:
- id: <kebab-case-id> # required, unique
description: <one sentence> # required
depends_on: [] # required, list of phase ids (may be empty)
paths: # optional, file-scope hint passed to /implement
- "src/foo/**"
acceptance: # optional, excerpt copied verbatim into prompt
- "Given X, when Y, then Z"
implement_flags: # optional, default: []
- "--no-review"Hard constraints (the LLM coordinator must verify on read):
- Every
depends_onentry exists in thephaseslist. - No cycles.
- Every
idis unique and matches[a-z0-9-]+. implement_flagsstrings are passed verbatim to/implement. Do not inject--consult-firstautomatically; the master plan already absorbed planning cost.
If the YAML block is missing or malformed, halt with a clear error and ask the user to fix plan.md. Do not silently regenerate.
phases:
- id: api-contract
description: Define and lock the new public API surface for X.
depends_on: []
paths: ["src/api/**", "tests/api/**"]
- id: server-impl
description: Implement the server side of the new API.
depends_on: ["api-contract"]
paths: ["src/server/**", "tests/server/**"]
- id: client-impl
description: Implement the client side of the new API.
depends_on: ["api-contract"]
paths: ["src/client/**", "tests/client/**"]
- id: integration-test
description: End-to-end tests crossing client and server.
depends_on: ["server-impl", "client-impl"]
paths: ["tests/integration/**"]api-contract runs first. Then server-impl and client-impl run in parallel. After both merge, integration-test runs.
You hold the DAG in your reasoning context. Maintain manifest.md as the durable state record. After every transition, rewrite manifest.md (read, modify, write).
Loop:
-
Compute the ready set: phases whose status is
pendingand whose everydepends_onentry has statusmerged. -
If ready set is empty AND nothing is
working/merging: all done → Phase 4 (summary). -
For each phase in the ready set, write a prompt file (next section) and spawn:
workmux add "<phase-id>" -b --base "$INTEGRATION_BRANCH" -P "$PLAN_DIR/prompts/<phase-id>.md"
Mark the phase
workingin the manifest with the resulting handle and branch (workmux listwill show the branch). -
Confirm the spawn started:
workmux wait <handles...> --status working --timeout 120
On exit-code 1 (timeout), inspect
workmux statusfor each handle: a fast-completing phase may have skipped throughworkingstraight todone. Treatdoneas a valid post-spawn state and proceed to step 5; only markfailedif a handle is missing entirely or inwaiting. On exit-code 3, mark the missing handlefailedand proceed to halt logic. -
Recompute the live handle set before every wait: only handles whose manifest status is currently
workingbelong in the wait list. A handle that already moved todone-unverified,merging,merged, orfailedmust be excluded — otherwisewait --anyreturns immediately on its already-finished state and the loop spins.Wait for the next transition with bounded chunks. Use 5-minute (300s) chunks; on each timeout, inspect statuses to detect
waiting:workmux wait <all-working-handles> --any --timeout 300 rc=$? if [ $rc -eq 0 ]; then # Some handle became done. Check each. workmux status <all-working-handles> elif [ $rc -eq 1 ]; then # Timeout — inspect for stuck waiting agents. workmux status <all-working-handles> # If any handle is in `waiting` status, mark it `blocked` and halt dependents. # Otherwise loop back to Step 5. elif [ $rc -eq 3 ]; then # An agent exited unexpectedly. Mark the missing handle `failed`. fi
Treat
doneas unverified success: set status todone-unverifiedand proceed to phase verification (Phase 3). -
After verification updates one or more phases to
mergedorfailed, recompute the ready set. Loop to step 1.
Halt logic. When any phase becomes failed or blocked:
- Stop spawning new phases.
- Mark every transitive dependent of the failed phase as
blockedwithnotes: blocked-by:<id>. - Allow currently
workingphases that are NOT transitive dependents to finish; verify and merge them normally. - After the loop drains, jump to Phase 4 with a non-zero summary.
Each phase prompt instructs the agent to write, as the final action of /implement, a one-line result file:
<repo-root>/<plan-dir>/captures/<phase-id>.result
Format (single line, no surrounding whitespace):
PHASE_RESULT id=<phase-id> status=success|failed commit=<sha> validation=passed|failed
The agent writes status=success only if /implement Phase 7 reports validation passed and no blockers. Otherwise status=failed. The commit is the head of the worktree's branch (git rev-parse HEAD inside the worktree).
history/ is shared across worktrees, so the coordinator reads the sentinel directly from $PLAN_DIR/captures/<phase-id>.result after the handle reaches done. No commit needed.
Write this to $PLAN_DIR/prompts/<phase-id>.md before each spawn. Self-contained: assume the agent cannot see your context. Use relative paths (each worktree has its own root).
# Phased Implement — phase <phase-id>
You are an isolated worktree agent. The coordinator spawned you to implement
**only** this phase of a larger phased plan. Do not work on other phases. Do
not modify the master plan.
## Phase
- **id:** <phase-id>
- **description:** <description>
- **depends_on:** <comma-separated, or "none">
- **file scope (advisory):** <paths joined>
- **acceptance criteria:**
<verbatim excerpt from plan>
## Master plan
The master plan lives at `<plan-dir>/plan.md`. The `history/` directory is
gitignored and shared across worktrees, so this path is visible from your
worktree even though it is not part of your branch. Read it for cross-phase
context but do **not** modify it.
## What to do
1. Run `/implement <implement_flags...> <description>` to plan and implement
this phase. The /implement skill will write its own per-phase plan,
review it, implement it, run a red-team pass, and commit on success.
2. **Do not initiate `/merge` yourself.** After your work is committed and
the sentinel is written (step 3), wait. The coordinator will send you
`/merge --keep` as an explicit instruction once it has verified your
sentinel. When that command arrives in this session, run it — it is the
coordinator-managed merge step, not a user override. Do not ask for
confirmation; just run it.
3. As the very last step, write the phase result sentinel to the shared
`history/` tree (do NOT commit it — `history/` is gitignored):
```bash
COMMIT=$(git rev-parse HEAD)
STATUS=success # or "failed" if /implement reported blockers
VALIDATION=passed # or "failed" if validation failed
mkdir -p <plan-dir>/captures
echo "PHASE_RESULT id=<phase-id> status=$STATUS commit=$COMMIT validation=$VALIDATION" \
> <plan-dir>/captures/<phase-id>.result- Stay within the file scope above unless /implement's plan-drift halt is triggered (in which case follow /implement's protocol).
- Do not run
git push, do not modify other phases' files. - If you cannot complete the phase, write
status=failedin the sentinel and exit. The coordinator will halt dependent phases.
## Phase 3 — Per-phase verification and merge
When a handle transitions to `done`:
1. **Read the sentinel** directly from the shared `history/` tree:
```bash
cat "$PLAN_DIR/captures/<phase-id>.result"
If the file is missing or status=failed or validation=failed: mark phase failed, capture workmux capture <handle> -n 200 to $PLAN_DIR/captures/<phase-id>.tail, halt logic.
-
Capture the tail for the audit trail regardless:
workmux capture <handle> -n 200 > "$PLAN_DIR/captures/<phase-id>.tail"
-
Serialize merges. If another phase is currently
merging, wait for that one to finish first. -
Trigger merge with
--keep. Send the/mergeskill with--keepso the worktree survives for verification. Use chunked waits so a/mergethat drops into awaitingprompt on a rebase conflict is detected fast instead of hanging the full timeout:workmux send <handle> "/merge --keep" # Chunked wait: at most 600s total, 60s chunks, abort early on `waiting`. elapsed=0 while [ $elapsed -lt 600 ]; do workmux wait <handle> --timeout 60 rc=$? if [ $rc -eq 0 ]; then break; fi # On timeout, peek status — `waiting` means /merge stalled on a conflict. if workmux status <handle> | grep -q waiting; then rc=2; break; fi elapsed=$((elapsed + 60)) done # rc: 0 done, 1 timeout (overall), 2 stuck waiting, 3 agent exited.
On
rc != 0: markfailed, capture tail to<plan-dir>/captures/<phase-id>.merge.tail, halt. -
Verify ancestry against the worktree's POST-rebase tip.
/mergerunsgit rebase <base>before merging, which rewrites commit SHAs. The pre-rebase sha in the result sentinel is therefore not a stable ancestry token. Re-read the worktree's branch tip after/mergereturns:# The worktree still exists because we used --keep. POST_TIP=$(workmux run <handle> -- git rev-parse HEAD | tail -1) if git merge-base --is-ancestor "$POST_TIP" "$INTEGRATION_BRANCH"; then # Merged successfully. Record the post-rebase sha in the manifest. workmux remove <handle> # Update manifest: status=merged, commit=$POST_TIP, ended=<iso8601>. else # Merge silently failed or was skipped. # Mark phase failed; halt dependents. Do NOT remove the worktree. fi
The sentinel's pre-rebase sha is still useful for the audit trail (record it in
notes), but is never the ancestry-check input. -
Drift check. If
INTEGRATION_BRANCHadvanced by commits not authored by phased-implement (external commits during the run), record the drift in manifestnotesand continue. If a parallel sibling has produced conflicts, the next sibling's/merge --keepwill surface them; treat that as a normal failure.
After the dispatch loop drains (success or halt), print:
## phased-implement summary
**Plan:** <plan-dir>/plan.md
**Integration branch:** <name>
**Start HEAD:** <short-sha>
**End HEAD:** <short-sha>
| id | status | commit | notes |
| -- | ------ | ------ | ----- |
| <each phase> |
**Merged:** <count> / <total>
**Failed:** <list of ids>
**Blocked:** <list of ids with blocked-by>
**Artifacts:**
- manifest: <plan-dir>/manifest.md
- prompts: <plan-dir>/prompts/
- captures: <plan-dir>/captures/
**Next steps (if any failed/blocked):**
- Inspect captures/<id>.tail.
- Worktrees for failed/blocked phases are preserved (use `workmux list`).
- To retry: there is no automatic resume in v1. Inspect `manifest.md`, decide which phases need to be re-run, manually `workmux remove` the leftover failed worktrees, prune already-`merged` phases from `plan.md`, and re-invoke `/phased-implement --plan <plan-dir>/plan.md` on the trimmed plan.
- No
--continueresume. If the coordinator session dies mid-run, worktrees keep running. The user can inspectmanifest.mdand re-invoke manually; v1 does not auto-reconcile partial state. - Plan drift cross-phase. If a later phase discovers an earlier merged phase chose the wrong abstraction, the coordinator does not auto-replan. Halt and let the user re-plan.
- paths-scope leakage.
paths:is advisory. The coordinator does not rungit diff --name-onlyagainst allowed paths in v1; relies on/implement's plan-drift halt and red-team. - Base-branch drift. External commits on the integration branch during a run are tolerated but warned. Heavy drift can cause cascading rebase conflicts.
- History/ visibility assumption. This skill assumes
history/is gitignored and shared (symlinked) across worktrees by the workmux setup. If that is not true in a given repo, plan/manifest/sentinel/captures will not be visible to spawned agents. Verify withworkmuxconfiguration before running.
- Coordinator-only skill.
disable-model-invocation: truein frontmatter — invoke explicitly via/phased-implement. - Reads YAML semantically; never parses with shell tools.
- Spawns via
workmux add, communicates viaworkmux send, awaits viaworkmux wait, cleans viaworkmux remove. - Generates plans via
consult-llm(load that skill first). - Trusts
/implementfor actual implementation and/merge --keepfor branch integration; verifies both via the result sentinel (success/fail signal) and a post-rebase ancestry check using the worktree's branch tip read after/mergereturns.