epic-story-resume
Pick up one already in-progress story from an epic and continue it. Use when a fresh session needs to resume ongoing work on a specific story.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Pick up one already in-progress story from an epic and continue it. Use when a fresh session needs to resume ongoing work on a specific story.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Open, attach, or refresh optional GitHub PR delivery metadata/evidence for one OpenSpec story. Does not change story Status.
Archive a locally completed OpenSpec change workspace after pre-flight checks (review approved, tasks done, PR merged or explicitly waived). Thin wrapper over /opsx:archive.
Absorb structured review/tool, PR, or reviewer feedback into an OpenSpec initiative by routing it to story edits, review rework, story candidates, or initiative-level decisions. Use when feedback needs to be incorporated without bloating or drifting stories.
Interview-driven OpenSpec initiative planning — creates openspec/initiatives/<slug>/initiative.md with goal, context, story candidates, decisions, constraints, and external resources. Use when starting a new body of work that needs an OpenSpec-backed initiative before any change workspaces can be drafted.
Inspect the current or selected OpenSpec initiative, change, or spec state and recommend the single next workflow action with concise reasoning. Use when you need lightweight lifecycle routing before choosing a planning, implementation, PR, feedback, or archive command.
Claim one ready, unclaimed story from an OpenSpec initiative and execute it end-to-end, leaving a clean handoff. Use when starting a fresh session on a new story in an OpenSpec change workspace.
| name | epic-story-resume |
| description | Pick up one already in-progress story from an epic and continue it. Use when a fresh session needs to resume ongoing work on a specific story. |
| disable-model-invocation | true |
| argument-hint | <epic-name> [story-number-or-spec-file] |
| allowed-tools | Read Edit Write Grep Glob Bash |
Continue exactly one already-ongoing story, following the existing handoff / review guidance, and leave the coordination docs in a state the next fresh session can trust.
Argument: $ARGUMENTS — <epic_name> [<story_number_or_spec_file>] [WORKTREE="<basename>=<path>"].... The epic name is required. The story selector is optional; when omitted and there is exactly one in-progress step, it is selected automatically. WORKTREE= is an optional, repeatable opt-in that overrides the preflight's default decision per target repo. Two forms are accepted: WORKTREE="<basename>=<path>" (multi form, repeatable, preferred) and legacy WORKTREE="<path>" (valid only when the story has exactly one target repo; the path is applied to that sole repo). Mixing the two forms in a single invocation is an error. When WORKTREE= is absent, the preflight reads any - Worktrees: list recorded in the story's ## Active Claim, falling back to a legacy - Worktree: singular bullet for stories claimed before the multi-worktree format.
Do not claim a new step. Do not rediscover or redefine the epic from scratch.
🔄 IN PROGRESS, 🟣 IN REVIEW, or ⛔ BLOCKED$ARGUMENTS:
<epic-name>: required, the first positional token<story>: optional, the second positional token (story number or spec file)WORKTREE="<value>" occurrences (parsed in ## Worktree preflight step 3 into <explicit_worktree_map> and/or <legacy_worktree>)<workspace_root> = <cwd> and resolve <epic> = <workspace_root>/agent_coordination/epics/<epic-name>. <workspace_root> and <epic> are never re-anchored; coordination files always live here.<epic> does not exist, stop and report the exact missing path.<workspace_root>):
AGENTS.md for the repo you will touch<epic>/MASTER.mdIf <story> was provided:
<epic>/MASTER.md as the only lookup tableStep value equals the selectorStep, try to match exactly one row whose Spec value equals the selectorStep and Spec values from MASTER.mdStep lookup and Spec lookup both match but point to different rows, stop and report the ambiguitySpec value<epic>/, stop and report the exact missing path🔄 IN PROGRESS or 🔵 IN PR with PR changes requested, stop and report the actual statusPlan column and Plan is not 🟢 PLAN APPROVED, stop before implementation work and report: "planning contract is not approved (<plan lane>); run /epic-story-plan-converge <epic> <story> before /epic-story-resume."If <story> was not provided:
MASTER.md marked 🔄 IN PROGRESS🔵 IN PR only if the PR is currently requesting code changes (check the step file's ## PR Tracking section PR status field; changes_requested is a resumable signal)Plan column exists and is not 🟢 PLAN APPROVED; list them separately with /epic-story-plan-converge <epic> <story> as the next action/epic-story-claim insteadAfter the step is resolved, read:
MASTER.md## Active Claim## Progress Log## Session Handoff## Review Log## PR Tracking (only present on steps that went through /epic-story-pr)If the step is 🔵 IN PR and the PR is requesting code changes, treat the PR review comments as the authoritative CTA for this continuation and move the step back to 🔄 IN PROGRESS for the duration of the session.
After reading the story file's ## Active Claim, build <project_root_map> for this continuation session: reuse worktrees the original claim recorded, recreate stale ones, and fall back to on-the-fly creation for legacy stories that predate the multi-worktree format.
Invariant: <workspace_root> = <cwd>, always. All reads and writes under agent_coordination/... anchor at <workspace_root> unconditionally, regardless of any worktrees built below. Worktrees only redirect writes to projects/<name>/... paths and git -C commands for the corresponding sub-repo.
Read Worktrees: from ## Active Claim. Parse the story file for a - Worktrees: bullet under ## Active Claim. For each child bullet of the form - <basename>: <path>, record <recorded_worktree_map>[<basename>] = <path> (normalized absolute). If no - Worktrees: bullet exists, <recorded_worktree_map> is empty.
Back-compat read for legacy single-form. If <recorded_worktree_map> is empty, look for a legacy - Worktree: <path> (singular) bullet. If present, set <recorded_worktree_map>[basename(<path>)] = <path> and note the session is in back-compat mode (the next claim refresh in step 9 will rewrite it as a - Worktrees: list).
Parse explicit WORKTREE= arguments into <explicit_worktree_map>. Collect every WORKTREE="<value>" occurrence from $ARGUMENTS. For each value:
=, split on the FIRST = into <basename> and <path>. Normalize <path> to an absolute path and record as <explicit_worktree_map>[<basename>] = <path>.<legacy_worktree> (normalized absolute path).Validation:
WORKTREE= with =, some without) is an error: abort with "mix of WORKTREE=\"path\" and WORKTREE=\"basename=path\" forms is not allowed; use one or the other".<legacy_worktree> is set, defer its application until <target_repos> is computed in step 5; it is only valid when exactly one <target_repo> is discovered.Compute <story-slug>. Strip the .md extension from the resolved step's spec file. Example: story-03-bootstrap-and-docs-rewrite.md → story-03-bootstrap-and-docs-rewrite.
Compute <target_repos>:
<recorded_worktree_map> is non-empty, build <target_repos> from its basenames: for each <basename>, resolve to <workspace_root>/projects/<basename> if <workspace_root>/projects/<basename>/.git exists, or to <workspace_root> if <basename> matches basename(<workspace_root>) AND <workspace_root> is itself a git repo. If a recorded basename resolves to neither, warn "recorded worktree for <basename> cannot be matched to any repo on disk" and retain it for downstream verification anyway./epic-story-claim (Worktree preflight steps 2–3): parse ## Scope of the step file for projects/[A-Za-z0-9_-]+/ tokens, intersect with real <workspace_root>/projects/<name>/.git repos, and additionally include <workspace_root> if it is itself a git repo.If <legacy_worktree> is set (from step 3), it is now applied: <explicit_worktree_map>[basename(<sole_target_repo>)] = <legacy_worktree> if <target_repos> has exactly one element, otherwise abort with "WORKTREE=\"<path>\" requires exactly one target repo; found N (basenames: ...). Pass WORKTREE=\"<basename>=<path>\" form to specify which repo".
No targets. If <target_repos> is empty, set <project_root_map> = {} and skip to step 10. The continuation will only touch <workspace_root>/agent_coordination/....
Per-repo decision. Initialize <project_root_map> = {} and <pending_prompt> = []. For each <target_repo> in <target_repos>, iterating in sorted order by basename:
<repo-basename> = basename <target_repo>.<default-path> = $HOME/add-worktrees/<repo-basename>-<epic-name>-<story-slug>.Branch on the four cases:
(a) Explicit override present (<explicit_worktree_map>[<repo-basename>] is set): <wt-path> = explicit path. Mark for create-or-reattach in step 9 regardless of dirtiness.
(b) Recorded entry present (<recorded_worktree_map>[<repo-basename>] is set, no explicit override): verify it via git -C <target_repo> worktree list --porcelain. If a worktree <recorded path> line exists AND the recorded path exists on disk, reuse: <project_root_map>[<repo-basename>] = recorded path. Skip step 8 for this repo. If the recorded entry is stale (path missing or unregistered), prompt the operator once for this repo:
Recorded worktree for `<repo-basename>`: <recorded path> is missing or not registered.
Recreate?
Default path: <default-path> (recorded: <recorded path>)
Reply: `default`, `recorded`, a new path, or `no`.
On no: <project_root_map>[<repo-basename>] = <target_repo> (main tree), warn "proceeding on dirty main tree for <repo-basename>" if the repo is dirty, otherwise no warning. On default: <wt-path> = <default-path>, mark for create-or-reattach in step 9. On recorded: <wt-path> = recorded path, mark for create-or-reattach in step 9. On a path: <wt-path> = normalized absolute, mark for create-or-reattach in step 9.
(c) Neither recorded nor explicit, <target_repo> is clean: <project_root_map>[<repo-basename>] = <target_repo> (main tree). Done for this repo.
(d) Neither recorded nor explicit, <target_repo> is dirty: append (<repo-basename>, <target_repo>, <default-path>, <porcelain output>) to <pending_prompt> — decision deferred to the batched prompt.
Batched operator prompt for case-(d) entries. If <pending_prompt> is non-empty, show ONE combined message (identical shape and parsing rules to /epic-story-claim step 7):
These target repos have uncommitted changes:
<repo-basename-1>:
<indented porcelain output, capped at ~5 lines with "...and N more" suffix if truncated>
Default worktree path: <default-path-1>
<repo-basename-2>:
<indented porcelain output...>
Default worktree path: <default-path-2>
Reply with one of:
- `default` or `all` — create worktrees at all default paths
- `no` — proceed on dirty main trees for all listed repos (NOT recommended)
- one line per repo: `<repo-basename>: default | no | <path>`
Parse the reply identically to /epic-story-claim step 7 (single token default/all/no, or multi-line <repo-basename>: ... form). On malformed input, re-prompt once with a clearer hint; on a second malformed reply, abort with "couldn't parse reply after two attempts; re-run /epic-story-resume". After parsing, for each pending repo: either set <project_root_map>[<repo-basename>] = <target_repo> (main tree mode) and warn, or resolve <wt-path> and mark for create-or-reattach in step 9.
Create or reattach worktrees for every repo marked in step 7 (cases a/b-stale-recreated) or step 8, iterating in sorted basename order:
mkdir -p "$(dirname <wt-path>)"/epic-story-claim): git -C <target_repo> worktree add <wt-path> <epic-name>/<story-slug><epic-name>/<story-slug> does not exist in <target_repo>, fall back to create: git -C <target_repo> worktree add -b <epic-name>/<story-slug> <wt-path>.<project_root_map>[<repo-basename>] = <wt-path>.Re-read the story's current state per worktree. For every <basename> in <project_root_map> whose value is a worktree, re-read any branch-local files that the resume needs from that worktree path. Coordination files (<epic>/MASTER.md, the step file, dependency step files) are NOT re-read from worktrees — they remain anchored at <workspace_root>/agent_coordination/... unconditionally. Subsequent "Resume intent" prioritization operates on the workspace-anchored copies.
Stale-recorded-entries warning. If <recorded_worktree_map> had basenames that did not resolve to any real repo in step 5, retain those entries in the upcoming ## Active Claim refresh so they are not silently dropped, and warn: "recorded worktree for <basename> could not be resolved to any repo on disk — retained in next claim refresh for manual review".
Conditional <workspace_root> sanity check. Run this check ONLY if ALL of the following are true:
<workspace_root> is itself a git repo,<workspace_root> is in <target_repos>,<project_root_map>[basename(<workspace_root>)] is a worktree (not <workspace_root> itself).Then, if the original git -C <workspace_root> status --porcelain output mentioned files under agent_coordination/, warn: "pending changes to agent_coordination/ on <workspace_root> main will NOT be in any worktree — commit them on main and rerun, or proceed knowing they are stranded". Do NOT run this check against sub-repo worktrees; sub-repos do not contain agent_coordination/ at all.
Done. <project_root_map> is set. All downstream resolution uses these rules:
<epic>/MASTER.md, step files, and anything under agent_coordination/... → read/write at <workspace_root>/agent_coordination/... unconditionally.projects/<name>/foo/bar → if <project_root_map> has <name>, route to <project_root_map>[<name>]/foo/bar; else route to <workspace_root>/projects/<name>/foo/bar.<name>: git -C <project_root_map>[<name>] ... (or git -C <workspace_root>/projects/<name> ... if <name> is not in the map).<epic>/MASTER.mdWhen launched by a converger, you may receive Shared Research Board from parent orchestration session before the slash command. This is the only allowed cross-session context beyond neutral operational notes. Use it as sourced orientation only. The converger owns keeping it relevant; you only decide whether the needed fact is present in the provided board. If present, verify it with direct reads/search against the cited anchors before it affects implementation, proof updates, or coordination write-back instead of rerunning expensive research. If a provided entry does not verify, report a board-refresh signal with exact anchors; do not decide how to curate the board. If absent, follow this skill's normal research rules. Ignore any board item that lacks an exact source anchor such as path:line, symbol, command/output excerpt, or tool/query/path.
Treat this as continuation work, not a new claim.
Use the latest concrete guidance in this order:
Review Log entry with blocking findings or a concrete next actionSession HandoffProgress Log milestonePurpose / Actors / Scenarios / Behavior Examples / AcceptanceIf these conflict, prefer the higher source in the list above and record the conflict in the progress log.
Unresolved-review heuristic: After identifying the newest request_changes Review Log entry, scan later Progress Log bullets for any that reference that finding's timestamp or Next action. A bullet like Picked up existing in-progress step and resumed work from the latest review CTA (TIMESTAMP) with a timestamp after the review log entry signals a session that attempted resolution — check its remaining bullets to confirm. If no later progress bullet addresses the finding, it is still open.
Proof-matrix editing: Each markdown table row is a single pipe-delimited line. Use grep -n '| A[0-9]' <story-file> to locate exact line numbers, then edit with the full line as oldString.
Before deep implementation work:
## Active Claim section:## Active Claim
- Claimed at: <UTC ISO timestamp>
- Claimed by: $RUNTIME_NAME continuation session
- Model: $MODEL (the exact model name used for this resume)
- Scope: <one sentence for this pickup chunk>
- Worktrees:
- <repo-basename>: <absolute-worktree-path>
- <repo-basename>: <absolute-worktree-path>
- Main-tree targets: <repo-basename>, <repo-basename>
- Primary write surfaces: <paths>
The - Worktrees: parent bullet must reflect the current <project_root_map>: list one child entry per repo whose value is an actual worktree (not the main tree). If the preflight reused recorded worktrees, keep their paths as-is; if it recreated stale entries at new locations, update those paths; if it added new entries (because the operator passed WORKTREE= for a previously-unrecorded repo or the scope expanded), include them. If <project_root_map> has no worktree entries, omit the - Worktrees: bullet entirely. Never delete a worktree entry that other sessions depend on for reattachment unless step 11 of the preflight explicitly retained it for manual review (in which case keep it). If the preflight read the story in back-compat mode (legacy singular - Worktree: bullet), this refresh rewrites it as the new - Worktrees: list — that is the one place legacy stories are migrated forward.
The - Main-tree targets: bullet lists every repo basename from <project_root_map> whose value is the repo's own main tree (i.e. NOT a worktree). This tells /epic-story-review that these repos were intentionally written to directly — their dirtiness at review time is the implementation itself. Omit when there are no main-tree target repos. If the previous claim had a - Main-tree targets: bullet, refresh it to reflect the current <project_root_map>.
## Progress Log:- <UTC ISO timestamp> Picked up existing in-progress step and resumed work from the latest handoff/review CTA.
Active Claim section.MASTER.md plus the selected step file as the source of truthBefore the first patch in this session:
## Actors, normative ## Scenarios / Behavior Examples linked with exactly one Covers: A<n>, ## Verification, especially ### Test Architecture Plan, ## Critical Files, and ## Discovery Notes.A<n> id, every named variant/mode/branch/fallback/error/example, and every normative S<n> Covers: A<n> case. Check latest handoff/review feedback against this map so continuation work does not leave sibling variants or linked scenario cases untested. Orientation-only scenarios remain context only.TAP-* row's acceptance slice, layer/scope, owning suite/file, boundary, assertions/observability, fixture/data strategy, CI lane/command, fallback plan, and split/merge rationale. Continue the smallest credible red seam while preserving planned test organization./epic-story-plan-converge or /epic-feedback. Do not silently replan inside resume.MASTER.md minimally and note it in the step file## Verification and record why in ## Progress Log before continuing.## Progress Log, set or ask to set the Plan lane to 🟠 PLAN CHANGES REQUESTED when available, and route the story to /epic-feedback or /epic-story-plan-converge. Do not perform replanning inside /epic-story-resume.## Progress Log before proceeding. Name the reason, the alternative proof seam, and the verification path you will use instead.## Progress Log using the docs/epic-conventions.md shape. Use fix-now only for enabling cleanup directly required to make this story correct, testable, reviewable, or safely maintainable; include Scope Justification. Use split-story, defer-explicitly, or block for debt that is non-enabling, too large, too non-local, or proof-blocking.🟣 IN REVIEW, run a reviewer-mindset self-check over every activated risk lens: compare risky choices with existing repo idioms; check async paths for blocking sync calls; check external/OS/API operations for sibling failure modes such as not-found, permission denied, timeout/cancellation, already-complete, unsupported, and partial failure; verify tests assert observable behavior rather than private choreography unless the mechanic is contractual; verify sensitive names/comments do not overstate identity, ownership, lifecycle, or safety invariants; and confirm every review finding or discovered risk has disposition, fix proof, and regression/side-effect verification.⛔ BLOCKEDAppend concise timestamped bullets under ## Progress Log after meaningful milestones. Examples:
MASTER.mdDo not wait until the end to record progress.
Avoid touching files outside the selected step's primary write surfaces unless required. Record any boundary crossing in the progress log.
At the end of the session:
## Session Handoff
- Status: done | blocked | in progress | in review
- What changed: <short bullets>
- Files touched: <paths>
- Red-first path: <focused seam + red/green outcome, or explicit exception + alternative proof path>
- Tests run: <commands/results or not run>
- Acceptance proof coverage: <all acceptance ids and named variants covered | gaps/exclusions listed>
- Risk-lens self-check: <activated lenses checked, exclusions, or none material>
- Finding closure: <review/feedback findings fixed with proof and regression check, or none>
- Remaining work: <short bullets>
- Unresolved Debt Friction: <split-story / defer-explicitly / block / unfinished fix-now entries, or none>
- Blockers / risks: <short bullets>
- Exact next step: <one concrete recommendation>
Before transitioning to ✅ DONE, offer to check in worktree changes. For each worktree in ## Active Claim -> - Worktrees:, run git -C <path> status --porcelain. If dirty, propose git -C <path> add -A && git -C <path> commit -m "<epic-name>/<story-slug>: <worksummary>" and execute on operator confirmation. If all worktrees are clean, skip.
Update MASTER.md status using this lifecycle:
🔄 IN PROGRESS — implementation or requested-change work still underway🟣 IN REVIEW — outstanding implementation work complete, focused seam green or exception recorded, ready for a fresh review pass🔵 IN PR (optional) — local review passed, PR awaiting GitHub review + merge. Do not set this status from /epic-story-resume; use /epic-story-pr to record PR metadata.✅ DONE — only if a real review pass completes and passes in this session AND any PR stage is merged⛔ BLOCKED — external blocker prevents completion or reviewDefault rule:
🔄 IN PROGRESS🟣 IN REVIEW✅ DONE if no PR stage is needed, or hand off to /epic-story-pr which transitions to 🔵 IN PR🔵 IN PR step that is requesting changes, move to 🔄 IN PROGRESS while working, then back to 🔵 IN PR via /epic-story-pr once the new push is ready for another review round🟣 IN REVIEW🔄 IN PROGRESSIf the epic's MASTER.md Legend does not list 🔵 IN PR, add it after the 🟣 IN REVIEW line:
- `🔵 IN PR` — local review passed, PR opened, awaiting GitHub review + merge
State:
## Research Events with reused board entries, board-refresh signals, and newly sourced research; for reused entries, name the board entry plus the direct-read/search anchors used to verify it; for board-refresh signals, name the board entry or absent needed fact plus anchors proving the miss or replacement fact; for new research, include exact anchors; use - None. when no research was used or produced