feat(quick-dev): sync sprint-status.yaml on epic-story implementation (#2234)

* feat(quick-dev): sync sprint-status.yaml on epic-story implementation

When quick-dev infers the intent is an epic story, resolve the full
sprint-status key during step-01's previous-story-continuity sub-step,
then sync sprint-status.yaml at the two workflow boundaries code-review
already owns the trailing half of:

- step-03 start: flip the story to in-progress and lift the parent
  epic out of backlog if needed.
- step-05 end: flip the story to review. Code-review keeps ownership
  of review -> done.

Resolution uses exact numeric-segment equality on the {epic}-{story}
prefix (never string-prefix match), so 1-1 no longer collides with
1-10. Both sync blocks are idempotent so step-04 loopbacks do not
clobber human edits or bump last_updated without cause. Skips silently
when sprint-status.yaml is missing or the intent is not an epic story.

* feat(quick-dev): add sprint-status sync to one-shot route

Epic stories do get implemented via one-shot in practice. Add the same
in-progress / review sync pair that step-03 and step-05 already have,
with identical idempotency guards and skip-on-missing behavior.

* refactor(quick-dev): extract sprint-status sync into shared file

Replace inline sync blocks in step-03, step-05, and step-oneshot with
one-line callouts to sync-sprint-status.md. The shared file owns all
edge-case handling (idempotency, epic lift, missing file/key) and is
parameterized by {target_status}. Any future route picks it up with a
single Follow line.

* fix(quick-dev): resolve story_key on early-exit resume paths

Extract story-key resolution into a shared subsection referenced by
all early-exit paths and INSTRUCTIONS, ensuring sprint-status sync
works for resumed epic stories.

* refactor(quick-dev): tighten story-key resolution prompt

Remove mechanical details the LLM can infer; keep only the
collision-prevention constraint.
This commit is contained in:
Alex Verkhovsky 2026-04-10 10:03:53 -07:00 committed by GitHub
parent a0705af9be
commit 17da5ca8ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 57 additions and 13 deletions

View File

@ -1,6 +1,7 @@
--- ---
deferred_work_file: '{implementation_artifacts}/deferred-work.md' deferred_work_file: '{implementation_artifacts}/deferred-work.md'
spec_file: '' # set at runtime for both routes before leaving this step spec_file: '' # set at runtime for both routes before leaving this step
story_key: '' # set at runtime to the current story's full sprint-status key (e.g. 3-2-digest-delivery) when the intent is an epic story and sprint-status resolution succeeds
--- ---
# Step 1: Clarify and Route # Step 1: Clarify and Route
@ -20,7 +21,7 @@ Before listing artifacts or prompting the user, check whether you already know t
1. Explicit argument 1. Explicit argument
Did the user pass a specific file path, spec name, or clear instruction this message? Did the user pass a specific file path, spec name, or clear instruction this message?
- If it points to a file that matches the spec template (has `status` frontmatter with a recognized value: draft, ready-for-dev, in-progress, in-review, or done) → set `spec_file` and **EARLY EXIT** to the appropriate step (step-02 for draft, step-03 for ready/in-progress, step-04 for review). For `done`, ingest as context and proceed to INSTRUCTIONS — do not resume. - If it points to a file that matches the spec template (has `status` frontmatter with a recognized value: draft, ready-for-dev, in-progress, in-review, or done) → set `spec_file`. Before exiting, run **Story-key resolution** (below). Then **EARLY EXIT** to the appropriate step (step-02 for draft, step-03 for ready/in-progress, step-04 for review). For `done`, ingest as context and proceed to INSTRUCTIONS — do not resume.
- Anything else (intent files, external docs, plans, descriptions) → ingest it as starting intent and proceed to INSTRUCTIONS. Do not attempt to infer a workflow state from it. - Anything else (intent files, external docs, plans, descriptions) → ingest it as starting intent and proceed to INSTRUCTIONS. Do not attempt to infer a workflow state from it.
2. Recent conversation 2. Recent conversation
@ -29,13 +30,19 @@ Before listing artifacts or prompting the user, check whether you already know t
3. Otherwise — scan artifacts and ask 3. Otherwise — scan artifacts and ask
- Active specs (`draft`, `ready-for-dev`, `in-progress`, `in-review`) in `{implementation_artifacts}`? → List them and HALT. Ask user which to resume (or `[N]` for new). - Active specs (`draft`, `ready-for-dev`, `in-progress`, `in-review`) in `{implementation_artifacts}`? → List them and HALT. Ask user which to resume (or `[N]` for new).
- If `draft` selected: Set `spec_file`. **EARLY EXIT**`./step-02-plan.md` (resume planning from the draft) - If `draft` selected: Set `spec_file`. Run **Story-key resolution** (below). **EARLY EXIT**`./step-02-plan.md` (resume planning from the draft)
- If `ready-for-dev` or `in-progress` selected: Set `spec_file`. **EARLY EXIT**`./step-03-implement.md` - If `ready-for-dev` or `in-progress` selected: Set `spec_file`. Run **Story-key resolution** (below). **EARLY EXIT**`./step-03-implement.md`
- If `in-review` selected: Set `spec_file`. **EARLY EXIT**`./step-04-review.md` - If `in-review` selected: Set `spec_file`. Run **Story-key resolution** (below). **EARLY EXIT**`./step-04-review.md`
- Unformatted spec or intent file lacking `status` frontmatter? → Suggest treating its contents as the starting intent. Do NOT attempt to infer a state and resume it. - Unformatted spec or intent file lacking `status` frontmatter? → Suggest treating its contents as the starting intent. Do NOT attempt to infer a state and resume it.
Never ask extra questions if you already understand what the user intends. Never ask extra questions if you already understand what the user intends.
### Story-key resolution
This runs on ALL paths (early-exit and INSTRUCTIONS) whenever `spec_file` is set. Determine whether the spec is an epic story — use the spec's filename, frontmatter, and any loaded epics file to identify `{epic_num}` and `{story_num}`. If the spec is not an epic story, skip silently and leave `{story_key}` unset.
If the spec is an epic story and `{sprint_status}` exists: find the `development_status` key matching `{epic_num}-{story_num}` by exact numeric equality on the first two segments (so `1-1` never collides with `1-10`). Exactly one match → set `{story_key}` to that full key. Zero or multiple matches → leave `{story_key}` unset (warn on multiple).
## INSTRUCTIONS ## INSTRUCTIONS
1. Load context. 1. Load context.
@ -45,7 +52,7 @@ Never ask extra questions if you already understand what the user intends.
**A) Epic story path** — if the intent is clearly an epic story: **A) Epic story path** — if the intent is clearly an epic story:
1. Identify the epic number and (if present) the story number. If you can't identify an epic number, use path B. 1. Identify the epic number `{epic_num}` and (if present) the story number `{story_num}`. If you can't identify an epic number, use path B.
2. **Check for a valid cached epic context.** Look for `{implementation_artifacts}/epic-<N>-context.md` (where `<N>` is the epic number). A file is **valid** when it exists, is non-empty, starts with `# Epic <N> Context:` (with the correct epic number), and no file in `{planning_artifacts}` is newer. 2. **Check for a valid cached epic context.** Look for `{implementation_artifacts}/epic-<N>-context.md` (where `<N>` is the epic number). A file is **valid** when it exists, is non-empty, starts with `# Epic <N> Context:` (with the correct epic number), and no file in `{planning_artifacts}` is newer.
- **If valid:** load it as the primary planning context. Do not load raw planning docs (PRD, architecture, UX, etc.). Skip to step 5. - **If valid:** load it as the primary planning context. Do not load raw planning docs (PRD, architecture, UX, etc.). Skip to step 5.
@ -59,6 +66,8 @@ Never ask extra questions if you already understand what the user intends.
5. **Previous story continuity.** Regardless of which context source succeeded above, scan `{implementation_artifacts}` for specs from the same epic with `status: done` and a lower story number. Load the most recent one (highest story number below current). Extract its **Code Map**, **Design Notes**, **Spec Change Log**, and **task list** as continuity context for step-02 planning. If no `done` spec is found but an `in-review` spec exists for the same epic with a lower story number, note it to the user and ask whether to load it. 5. **Previous story continuity.** Regardless of which context source succeeded above, scan `{implementation_artifacts}` for specs from the same epic with `status: done` and a lower story number. Load the most recent one (highest story number below current). Extract its **Code Map**, **Design Notes**, **Spec Change Log**, and **task list** as continuity context for step-02 planning. If no `done` spec is found but an `in-review` spec exists for the same epic with a lower story number, note it to the user and ask whether to load it.
6. **Resolve `{story_key}`.** If not already set by an earlier early-exit path, run **Story-key resolution** (above) now.
**B) Freeform path** — if the intent is not an epic story: **B) Freeform path** — if the intent is not an epic story:
- Planning artifacts are the output of BMAD phases 1-3. Typical files include: - Planning artifacts are the output of BMAD phases 1-3. Typical files include:
- **PRD** (`*prd*`) — product requirements and success criteria - **PRD** (`*prd*`) — product requirements and success criteria

View File

@ -24,6 +24,8 @@ Capture `baseline_commit` (current HEAD, or `NO_VCS` if version control is unava
Change `{spec_file}` status to `in-progress` in the frontmatter before starting implementation. Change `{spec_file}` status to `in-progress` in the frontmatter before starting implementation.
Follow `./sync-sprint-status.md` with `{target_status}` = `in-progress`.
If `{spec_file}` has a non-empty `context:` list in its frontmatter, load those files before implementation begins. When handing to a sub-agent, include them in the sub-agent prompt so it has access to the referenced context. If `{spec_file}` has a non-empty `context:` list in its frontmatter, load those files before implementation begins. When handing to a sub-agent, include them in the sub-agent prompt so it has access to the referenced context.
Hand `{spec_file}` to a sub-agent/task and let it implement. If no sub-agents are available, implement directly. Hand `{spec_file}` to a sub-agent/task and let it implement. If no sub-agents are available, implement directly.

View File

@ -48,16 +48,25 @@ Format each stop as framing first, link on the next indented line:
When there is only one concern, omit the bold label — just list the stops directly. When there is only one concern, omit the bold label — just list the stops directly.
### Commit and Present ### Mark Spec Done
1. Change `{spec_file}` status to `done` in the frontmatter. Change `{spec_file}` status to `done` in the frontmatter.
2. If version control is available and the tree is dirty, create a local commit with a conventional message derived from the spec title.
3. Open the spec in the user's editor so they can click through the Suggested Review Order: Follow `./sync-sprint-status.md` with `{target_status}` = `review`.
### Commit and Open
1. If version control is available and the tree is dirty, create a local commit with a conventional message derived from the spec title.
2. Open the spec in the user's editor so they can click through the Suggested Review Order:
- Resolve two absolute paths: (1) the repository root (`git rev-parse --show-toplevel` — returns the worktree root when in a worktree, project root otherwise; if this fails, fall back to the current working directory), (2) `{spec_file}`. Run `code -r "{absolute-root}" "{absolute-spec-file}"` — the root first so VS Code opens in the right context, then the spec file. Always double-quote paths to handle spaces and special characters. - Resolve two absolute paths: (1) the repository root (`git rev-parse --show-toplevel` — returns the worktree root when in a worktree, project root otherwise; if this fails, fall back to the current working directory), (2) `{spec_file}`. Run `code -r "{absolute-root}" "{absolute-spec-file}"` — the root first so VS Code opens in the right context, then the spec file. Always double-quote paths to handle spaces and special characters.
- If `code` is not available (command fails), skip gracefully and tell the user the spec file path instead. - If `code` is not available (command fails), skip gracefully and tell the user the spec file path instead.
4. Display summary of your work to the user, including the commit hash if one was created. Any file paths shown in conversation/terminal output must use CWD-relative format (no leading `/`) with `:line` notation (e.g., `src/path/file.ts:42`) for terminal clickability — the goal is to make paths clickable in terminal emulators. Include:
- A note that the spec is open in their editor (or the file path if it couldn't be opened). Mention that `{spec_file}` now contains a Suggested Review Order. ### Display Summary
- **Navigation tip:** "Ctrl+click (Cmd+click on macOS) the links in the Suggested Review Order to jump to each stop."
- Offer to push and/or create a pull request. Display summary of your work to the user, including the commit hash if one was created. Any file paths shown in conversation/terminal output must use CWD-relative format (no leading `/`) with `:line` notation (e.g., `src/path/file.ts:42`) for terminal clickability — the goal is to make paths clickable in terminal emulators. Include:
- A note that the spec is open in their editor (or the file path if it couldn't be opened). Mention that `{spec_file}` now contains a Suggested Review Order.
- **Navigation tip:** "Ctrl+click (Cmd+click on macOS) the links in the Suggested Review Order to jump to each stop."
- Offer to push and/or create a pull request.
Workflow complete. Workflow complete.

View File

@ -13,6 +13,8 @@ deferred_work_file: '{implementation_artifacts}/deferred-work.md'
### Implement ### Implement
Follow `./sync-sprint-status.md` with `{target_status}` = `in-progress`.
Implement the clarified intent directly. Implement the clarified intent directly.
### Review ### Review
@ -39,6 +41,8 @@ Write `{spec_file}` using `./spec-template.md`. Fill only these sections — del
2. **Title and Intent**`# {title}` heading and `## Intent` with **Problem** and **Approach** lines. Reuse the summary you already generated for the terminal. 2. **Title and Intent**`# {title}` heading and `## Intent` with **Problem** and **Approach** lines. Reuse the summary you already generated for the terminal.
3. **Suggested Review Order** — append after Intent. Build using the same convention as `./step-05-present.md` § "Generate Suggested Review Order" (spec-file-relative links, concern-based ordering, ultra-concise framing). 3. **Suggested Review Order** — append after Intent. Build using the same convention as `./step-05-present.md` § "Generate Suggested Review Order" (spec-file-relative links, concern-based ordering, ultra-concise framing).
Follow `./sync-sprint-status.md` with `{target_status}` = `review`.
### Commit ### Commit
If version control is available and the tree is dirty, create a local commit with a conventional message derived from the intent. If VCS is unavailable, skip. If version control is available and the tree is dirty, create a local commit with a conventional message derived from the intent. If VCS is unavailable, skip.

View File

@ -0,0 +1,19 @@
# Sync Sprint Status
Shared sub-step for updating `sprint-status.yaml` during quick-dev. Called from any route (plan-code-review, one-shot, future routes) with a `{target_status}` parameter.
## Preconditions
Skip this entire file (return to caller) if ANY of:
- `{story_key}` is unset
- `{sprint_status}` does not exist on disk
## Instructions
1. Load the FULL `{sprint_status}` file.
2. Find the `development_status` entry matching `{story_key}`. If not found, warn the user once (`"{story_key} not found in sprint-status; skipping sprint sync"`) and return to caller.
3. **Idempotency check.** If `development_status[{story_key}]` is already at `{target_status}` or a later state (`review` is later than `in-progress`; `done` is later than both), return to caller — no write needed. Never regress a story's status.
4. Set `development_status[{story_key}]` to `{target_status}`.
5. **Epic lift (only when `{target_status}` = `in-progress`).** Derive the parent epic key as `epic-{N}` from the leading numeric segment of `{story_key}` (e.g., `3-2-digest-delivery``epic-3`). If that entry exists and is `backlog`, set it to `in-progress`. Leave it alone otherwise. Skip this sub-step entirely when `{target_status}` is not `in-progress`.
6. Refresh `last_updated` to the current date.
7. Save the file, preserving ALL comments and structure including STATUS DEFINITIONS and WORKFLOW NOTES.

View File

@ -65,6 +65,7 @@ Load and read full config from `{main_config}` and resolve:
- `project_name`, `planning_artifacts`, `implementation_artifacts`, `user_name` - `project_name`, `planning_artifacts`, `implementation_artifacts`, `user_name`
- `communication_language`, `document_output_language`, `user_skill_level` - `communication_language`, `document_output_language`, `user_skill_level`
- `date` as system-generated current datetime - `date` as system-generated current datetime
- `sprint_status` = `{implementation_artifacts}/sprint-status.yaml`
- `project_context` = `**/project-context.md` (load if exists) - `project_context` = `**/project-context.md` (load if exists)
- CLAUDE.md / memory files (load if exist) - CLAUDE.md / memory files (load if exist)