Imported from chris59/emergent-claude-plugin (
skills/start-story/SKILL.md). Install upstream withnpx skills add chris59/emergent-claude-plugin --skill start-story. Copyright stays with the author.
Start Story
Prepare an ADO story for development with full governance: validate readiness, assign, estimate, activate, create a branch, research, plan, implement, and verify acceptance criteria.
Arguments
The user provides a story ID after /start-story, with optional flags:
910or#910— the ADO work item ID (required)--spec <path>— path to a specification/reference doc to load during planning (optional)--panel— force the multi-agent planning judge-panel (Step 5c) on, regardless of points--no-panel— force it off (single-planner path) even for large stories--deep-review— use the multi-agent fan-out + adversarial-verify self-review at Gate 3.5c
Examples:
/start-story 1051/start-story 1051 --spec .claude/data-ingestion/sap-extracts-specification.md/start-story 1051 --panel
Instructions
Follow these steps in order. Use Bash for all az and git commands.
Step 0: Load Project Configuration
Before any other step, read the convention files from .claude/ and extract configuration values.
See tools/emergent-claude-plugin/skills/shared-preamble.md for the full instructions.
Required — read .claude/project.env.md and extract:
- ADO_ORG: Organization URL (e.g.,
https://dev.azure.com/MyOrg) - ADO_PROJECT: Project name (e.g.,
My Project) - ADO_PROJECT_ENCODED: URL-encoded project name (replace spaces with
%20) - ADO_REPO_ID: Repository GUID
- BRANCH_USERNAME: Username for branch naming (e.g.,
chrisa)
Configure az defaults immediately:
az devops configure --defaults organization={ADO_ORG} project="{ADO_PROJECT}"
If project.env.md does not exist, STOP and tell the user:
Project configuration not found. Run /emergent-dev:init-project to set up
.claude/project.env.md with your ADO, database, and Azure configuration.
Recommended — read .claude/project.architecture.md if it exists and extract:
- SOLUTION: Solution file path (e.g.,
MyApp.slnf) - BUILD_CMD: Build command (default:
dotnet build {SOLUTION} -c Release) - TEST_CMD: Test command (default:
dotnet test {SOLUTION} -c Release --no-build) - FORMAT_CMD: Format command (default:
dotnet format whitespace {SOLUTION})
If not found, auto-detect solution: ls *.slnf *.sln 2>/dev/null | head -1
Optional — read .claude/project.testing.md if it exists and extract:
- SCSS_CMD: SCSS compilation command (skip the SCSS step if not defined)
- DB_BUILD_CMD: Database build command (skip the DB build step if not defined)
Optional — read .claude/project.team.md if it exists and extract:
- MERGE_STRATEGY: PR merge strategy (default:
rebase— linear history; "Rebase and fast-forward") - SPLIT_THRESHOLD: Story point splitting threshold (default:
13) - POINT_SCALE: Fibonacci point scale (default:
1, 2, 3, 5, 8, 10)
Step 1: Parse & Fetch Story
- Parse the argument string:
- Strip any leading
#from the story ID to get the numeric ID - If
--spec <path>is present, save the path for use in Step 5 - Note
--panel/--no-panel(planning judge-panel override) and--deep-review(Gate 3.5c multi-agent self-review) for use in Step 5c and Step 6 step 3.5c respectively
- Strip any leading
- Fetch the story:
az boards work-item show --id {id} --output json - Extract and display to the user:
- Title (
fields.System.Title) - State (
fields.System.State) - Assigned To (
fields.System.AssignedTo.displayName/.uniqueName) - Story Points (
fields.Microsoft.VSTS.Scheduling.StoryPoints) - Description (
fields.System.Description) — strip HTML tags for display - Acceptance Criteria (
fields.Microsoft.VSTS.Common.AcceptanceCriteria) — strip HTML - Parent (
fields.System.Parent) — if present, fetch parent title too
- Title (
Step 2: Story Readiness Gate (Gate 1)
Run a structured readiness assessment before any work begins. Display results as a checklist to the user.
2a. Hierarchy Validation
Verify the story is connected to a business goal:
- The story MUST have a Parent (Feature). Extract
fields.System.Parentfrom Step 1. - If parent exists, fetch the parent work item and check that IT has a parent (Epic):
Extract the Feature title and its parent Epic ID/title.az boards work-item show --id {parentId} --output json - Display the hierarchy chain:
Story #{id} → Feature #{parentId} ({parentTitle}) → Epic #{epicId} ({epicTitle})
If no parent Feature: WARN — display: "⚠️ Hierarchy: Story has no parent Feature — this work has no documented business justification. Link to a Feature or explain why this is standalone."
Use AskUserQuestion to ask the user to either provide the Feature ID to link, or confirm this is intentional orphaned work.
If Feature has no parent Epic: WARN (less severe) — display: "⚠️ Feature #{parentId} has no parent Epic — acceptable for infrastructure work, flag for product stories."
2b. Acceptance Criteria Validation
-
AC must exist: If acceptance criteria is empty, BLOCK — use AskUserQuestion:
"This story has no acceptance criteria. What does 'done' look like? Please provide testable pass/fail criteria."- If user provides AC, update the story in ADO:
az boards work-item update --id {id} --fields "Microsoft.VSTS.Common.AcceptanceCriteria={userResponse}"
- If user provides AC, update the story in ADO:
-
AC quality check: Scan the acceptance criteria text for vague/ambiguous terms:
Vague Term Flag "improve" ⚠️ Vague — improve how? What metric? "optimize" ⚠️ Vague — optimize what? Target value? "clean up" ⚠️ Vague — what specific changes? "as needed" ⚠️ Ambiguous — specify exact conditions "etc." ⚠️ Ambiguous — enumerate all cases "appropriate" ⚠️ Ambiguous — define the criteria "better" ⚠️ Vague — better by what measure? "handle errors" ⚠️ Vague — what errors? What response? "flexible" ⚠️ Vague — what extension points? "robust" ⚠️ Vague — what failure modes? If any vague terms found: WARN — list them and ask user to clarify or confirm intent. Do NOT block.
-
AC testability check: Each AC should be a pass/fail statement. Flag ACs that are purely descriptive (no measurable outcome). Example:
- Good: "Files are processed in chronological order based on YYYYMMDD-HHMMSS timestamp"
- Bad: "The system should handle files appropriately"
2c. Scope Validation
- If story points are already set and ≥ {SPLIT_THRESHOLD}: WARN —
"⚠️ Scope: {points} points is very large. Consider whether this covers genuinely independent capabilities that could be split. Stories up to 10 points are fine if cohesive." - If story points are not yet set, this will be addressed in Step 3.
2d. Dependency Check
Check for linked predecessor work items that might block this story:
# Fetch work item relations
az boards work-item show --id {id} --output json --query "relations[?contains(attributes.name, 'Predecessor') || contains(rel, 'Predecessor')]"
If predecessors exist, check each one's state. If any predecessor is NOT in Dev Complete, Closed, or Resolved:
WARN — "⚠️ Dependencies: Predecessor #{predId} ({predTitle}) is in state '{predState}' — may block this work."
2e. Business Context Check
Scan the description for a "why" statement. The description should explain the business need, not just the technical change.
Heuristic: If the description contains ONLY technical terms (file names, class names, SQL, code patterns) with no mention of users, stakeholders, business process, or client request — WARN:
"⚠️ Business Context: Description appears purely technical with no stated business reason. Who benefits from this and why?"
2f. Readiness Summary
Display the full assessment:
Story #{id} Readiness Assessment:
{✅|⚠️|❌} Hierarchy: {chain or warning}
{✅|⚠️|❌} Acceptance Criteria: {count} ACs defined {+ any vague term warnings}
{✅|⚠️} Scope: {points} points
{✅|⚠️} Dependencies: {status}
{✅|⚠️} Business Context: {status}
If any items are ❌ (BLOCK), resolve them before proceeding. If items are ⚠️ (WARN), the user may acknowledge and continue — use AskUserQuestion with options: "Acknowledged — proceed" / "Let me fix these first".
2g. Record Readiness Telemetry
Append ONE line to .claude/process-metrics.jsonl (create if missing) capturing the readiness gate
outcome, so /emergent-dev:process-report can correlate start-time signals with end-state rework.
Fire-and-forget — never block on it.
{"event":"start","storyId":{id},"points":{points|null},
"acCount":{n},"acWarnings":{n},"hierarchyOk":{true|false},
"depsBlocking":{n},"ts":"{ISO-8601}"}
Stamp ts from date -u +%Y-%m-%dT%H:%M:%SZ; append with >> (don't clobber). A later panel field is
added by Step 5c if the planning judge-panel runs.
Step 3: ADO Updates
Only update fields that need changing:
-
Assign to me (if not already assigned to me):
# Get my identity az ad signed-in-user show --query userPrincipalName -o tsv # Assign az boards work-item update --id {id} --assigned-to "{email}" -
Story points (if missing/null):
- Analyze the story scope (description + acceptance criteria + parent context)
- Suggest a point value from the {POINT_SCALE} scale with brief reasoning
- Use AskUserQuestion to let the user confirm or override
- Apply:
az boards work-item update --id {id} --fields "Microsoft.VSTS.Scheduling.StoryPoints={points}"
-
State → Active (conditional):
Current State Action NewMove to ActiveActiveSkip — already active Unapproved / Future,Future PhaseWarn user — may need approval first, ask before changing Closed,Dev Complete,Resolved,In QAWarn user — this re-opens finished work, ask before changing BlockedWarn user — investigate blocker first az boards work-item update --id {id} --state "Active"
Step 4: Git Prep — the worktree (MANDATORY)
Every story gets its own git worktree. Do not ask, and never branch inside the main checkout.
There is no main-checkout mode and no --no-worktree escape hatch: if a user asks for one, say so
in one line and carry on into the worktree.
Why this is not optional here:
- The main checkout carries the developer's own uncommitted work, and other Claude sessions run in
it at the same time.
git checkoutthere moves files under someone else's editor, and a latergit addcan sweep up changes that were never yours. - Git refuses to clean up around a held branch — deleting a merged branch fails while the main checkout is sitting on it.
- Two stories in two worktrees have separate
bin/objand separate branches. Two stories in one checkout have a stash — which is what the old version of this step used to do.
4a. Check what the main checkout is holding
bash .claude/skills/start-story/scripts/story-worktree.sh check
Prints KEY=value lines only. This is a report, not a decision — the worktree gets created
either way. Two lines earn their keep: REASON names what would have been disturbed had the story
branched in place, and STALE_WORKTREES surfaces abandoned worktrees on every pickup. Report
OTHER_SESSIONS=unknown as unknown — never as zero.
4b. Create the worktree
Branch name is unchanged: feature/{BRANCH_USERNAME}/{id}-{slug} (slug = lowercase title, spaces →
hyphens, non-alphanumerics stripped, ~50 chars). Example: story #910 "Add Wish List Balance" →
feature/chrisa/910-add-wish-list-balance.
bash .claude/skills/start-story/scripts/story-worktree.sh create "feature/{BRANCH_USERNAME}/{id}-{slug}"
The directory is named from the branch's last segment and sits BESIDE the main checkout:
../wt-{id}-{slug}. The script branches from origin/develop, seeds the gitignored files a working
checkout needs (all of .claude/'s config, .mcp.json, and the three local DB config files), and
repoints AZURE_CONFIG_DIR at the main checkout so the worktree shares the one az login.
Read WORKTREE_PATH out of the output. If it prints REUSED=yes, the story was already started —
that is fine, carry on in the existing worktree.
4c. Move the session into it
EnterWorktree({ path: "<WORKTREE_PATH>" })
Use the path parameter only. Never EnterWorktree's name parameter: it branches from
origin/<default-branch>, which is origin/main here, and this project bases every feature branch
on develop.
Verify before the first edit:
git rev-parse --show-toplevel # must be the worktree, not the main checkout
git branch --show-current # must be the story branch
4d. What is shared, and the one thing to watch
The worktree isolates code only. Deliberately shared with the main checkout:
| Shared | Consequence |
|---|---|
.claude/.azure (az login) |
One login serves every worktree. Nothing to do. |
.claude/allocation-pipeline reference workbooks |
Reach them at the main checkout path in .claude/CLAUDE.local.md → ALLOCATION_REFERENCE_DIR. |
The local SQL database HondaAIM |
Not cloned per worktree. Two worktrees that both deploy a DACPAC hit the same database. Run schema/DACPAC stories ONE AT A TIME; check reports other live worktrees so that is a visible choice, not a surprise. |
| The git stash stack | Never use bare git stash / git stash pop. Prefer a WIP commit. |
Step 5: Research, Specification & Planning (Gates 2 & 3)
This step has three sub-phases that MUST be executed in order: Load Context → Research/Spec → Plan. The depth of each phase scales with story complexity (story points).
5a. Load Context
Before planning, load all available context in this priority order:
-
Explicit spec file (
--specflag): If the user provided--spec <path>, read that file with the Read tool. This is the primary planning reference and should be treated as authoritative context for this story. -
Description-referenced spec: If the story description contains a reference to a spec file (look for patterns like
Full spec:,Reference:,See:, or.claude/paths followed by.md), read that file too. This catches specs that were linked when the story was created. -
Related
.claude/documentation: Based on the story title and tags, check for relevant documentation in the.claude/directory. Look for subdirectories whose names match keywords from the story title or tags, and read anyREADME.md, notes, or specification files found there.
Display a brief summary of loaded context to the user:
Loaded context:
- .claude/data-ingestion/sap-extracts-specification.md (SAP extract specs — 550 lines)
5b. Research & Specification (Gate 2)
Purpose: Understand the problem before designing a solution. Prevent "jump to code" syndrome.
The research depth depends on story size:
| Story Points | Research Depth |
|---|---|
| 1-2 | Brief: Read the directly-affected files, understand the change. No written spec needed. |
| 3-5 | Standard: Use Explore subagents to investigate the codebase area. Produce a brief spec (see below). |
| 8+ | Deep: Full exploration + architecture impact assessment. Written spec required. |
For stories > 3 points (or any story where the approach is unclear), produce a specification:
-
Use Explore subagents to investigate the relevant codebase area. Do NOT start planning yet.
-
Write a brief spec covering:
- Current behavior: What exists today in the affected area
- Desired behavior: What should change (map directly to ACs)
- Boundaries: What should NOT change (explicit scope limits)
- Edge cases & risks: What could go wrong
- Affected layers: Which architecture layers are touched (Domain, Application, Infrastructure, Web, Database)
-
Save the spec to
.claude/specs/story-{id}.mdfor audit trail. -
Present the spec to the user for confirmation before proceeding to planning. Use AskUserQuestion: "I've completed research and produced a spec. Please review the spec above. Is this understanding correct?" with options "Yes, proceed to planning" / "No, let me clarify"
For stories > 8 points, additionally assess architecture impact:
- Does this touch authentication or authorization?
- Does this modify database schema?
- Does this change public API contracts?
- Are there cross-cutting concerns (logging, validation, error handling)?
- Should this be reviewed by a second person?
Display the impact assessment and flag high-risk areas.
5c. Create Plan (Gate 3)
Every story gets a plan. The depth varies by size:
| Story Points | Plan Depth |
|---|---|
| 1-2 | Inline plan: "I'll modify X file to change Y behavior. 2-3 files affected." Present to user for quick confirmation. |
| 3-5 | Written plan in plan file via EnterPlanMode: files to modify, approach, risks, verification steps. |
| 8+ | Multi-agent judge-panel (see below) → synthesized written plan + architecture review + explicit approval. |
Judge-panel planning (≥8 pts, or any size with --panel; skipped with --no-panel).
Large stories have a wide solution space where a single planner can anchor on the first viable approach.
Instead, generate several independent plans, score them, and synthesize the best — the "stress-test from
every angle before you commit" pattern. This is a Workflow (opt-in by the points threshold / flag, so it
never auto-fans-out on small work):
- Fan out 3 planners, each the
planneragent with a distinct lens (vary the prompt by lens):- risk-first — what breaks, what's irreversible, what's the migration/rollback story
- MVP-first — smallest change that satisfies every AC, defer the rest
- fidelity-first — match existing patterns/conventions exactly, minimize architectural novelty Pass each the story, ACs, loaded context (5a), and spec (5b). Use structured output so each returns a comparable plan object (approach summary, files, AC-coverage map, risks, est. complexity).
- Judge pass — score each plan on AC-coverage, risk, and simplicity (a scoring agent, or inline if only 3). Identify the strongest plus the best ideas from the runners-up.
- Synthesize ONE plan — a final
plannerinvocation that produces the single authoritative plan, grafting the best of each lens. Cite which lens each major decision came from.
Output is still one .claude/specs/story-{id}.md in the format below, so Step 6 (implementation) is
unchanged. Present the synthesized plan via EnterPlanMode for approval. Record "panel":true (and
the winning lens) on the start-story telemetry line from Step 2g.
If the Workflow tool isn't available, fall back to running the 3 lenses as sequential planner
subagents and synthesizing inline — same output, less parallelism.
Every plan MUST include (regardless of size, and regardless of whether the panel produced it):
- Files to create/modify (with line references to existing code where applicable)
- AC-to-implementation mapping: A table showing which implementation step satisfies which acceptance criterion:
| AC | Implementation | Verification | |----|----------------|-------------| | AC1: Extension-agnostic discovery | Modify FindDatFile() in SapDatFileImporter.cs | Manual test with extensionless file | | AC2: MFT patterns | Add to SapDatasetRegistry.cs | Unit test | - Scope boundary: What is explicitly OUT of scope for this story
- Verification plan: How each AC will be verified (test command, manual check, etc.)
Use EnterPlanMode for stories ≥ 3 points (including the judge-panel's synthesized plan for ≥8 pts). For 1-2 point stories, present the inline plan and use AskUserQuestion for quick approval.
Step 6: Post-Implementation — Format, Build, Test, Commit, Push, PR
After the implementation is complete:
-
Format: Run
{FORMAT_CMD}— auto-fixes whitespace/spacing violations. Stage any changes it made:git add -u. -
Build: Run
{BUILD_CMD}.- If it fails, fix compile errors (missing files, type mismatches, etc.) and re-run.
- Common cause: a new source file is untracked — add it with
git add <path>.
-
Test: Run
{TEST_CMD}.- If tests fail, fix them before proceeding.
3.5. ⛔ MANDATORY PRE-PR VERIFICATION GATE (Gate 4) — DO NOT SKIP:
Before committing, pushing, or creating a PR, you MUST complete ALL of the following:
a. AC Verification Checklist: Map every acceptance criterion to what was implemented. Present as a checklist:
Acceptance Criteria Verification:
✅ AC1: {AC text} — {what was implemented and where}
✅ AC2: {AC text} — {what was implemented and where}
⚠️ AC3: {AC text} — {implemented but lacks test coverage}
❌ AC4: {AC text} — {not yet implemented}
If ANY AC is ❌, it must be implemented before proceeding. If any AC is ⚠️, flag it and ask user if partial coverage is acceptable.
b. Scope Creep Detection: List every file modified and map each to an AC:
Files Modified → AC Mapping:
SapDatasetRegistry.cs → AC1, AC2
MftFileNameParser.cs (NEW) → AC3
SapLoaderHostedService.cs → AC4, AC5
⚠️ README.md → No AC (scope creep candidate)
Any file that doesn't map to an AC is a scope creep candidate. Ask the user: "These files were modified but don't map to any AC. Keep or revert?"
c. Self-Review: Review the diff in a clean context — the reviewer has no confirmation bias since it didn't write the code. Two modes:
- Standard (default): spawn one reviewer subagent over all changes vs develop, focused on architecture compliance, security, correctness, and whether the changes match the stated ACs.
- Deep (
--deep-review, or auto-suggest it when the diff exceeds ~15 files): run the fan-out-by-dimension + adversarial-verify recipe in therevieweragent's "Deep Review Mode" (§9) — best done as aWorkflow. Only findings that survive the refute pass are surfaced.
Address any Critical or Major findings before proceeding.
d. User Approval: After presenting the AC checklist, scope map, and self-review results:
- Present a specific test plan (what to navigate to, what to click, what to verify)
- Use AskUserQuestion to ask: "Build and tests pass. AC verification and self-review complete. Have you tested locally and approved the changes?" with options "Yes, approved — commit and push" / "No, I found issues"
- DO NOT PROCEED to step 4 until the user selects "Yes, approved". If they report issues, fix them first.
- This gate exists to avoid wasting CI cycles. Get local approval first, then commit/push/PR.
-
Commit with a descriptive message explaining the "why", ending with the
Co-Authored-Bytrailer. (The pre-commit hook re-runs format and stages any remaining changes automatically.) -
Stamp review:
bash .claude/hooks/stamp-review.sh(must be a separate command BEFORE push). -
Push:
git push -u origin {branch}(separate command AFTER stamp). (The pre-push hook runs build + tests again as a final gate before allowing the push.) -
Create PR (Gate 5 — Merge Readiness): Use
az repos pr createtargetingdevelop, linking the work item with--work-items {id}.The PR description MUST include business context from the Feature/Epic hierarchy (fetched in Gate 1). Use this structured format (via HEREDOC):
## Summary [One-sentence description linking to business value] ## Motivation [The 'why' — reference the parent Feature/Epic and the business need it addresses. Example: "Part of Feature #706 (SFTP Setup & Connectivity) under Epic #XXX. Client requested standardized naming conventions for nightly extracts."] ## Implementation Details * [Bulleted list of key technical changes] * [Mention patterns, libraries, or architectural decisions] ## Acceptance Criteria Verification | AC | Status | Implementation | |----|--------|---------------| | AC1: {text} | ✅ | {file and approach} | | AC2: {text} | ✅ | {file and approach} | ## Testing & Verification 1. [How to test — specific steps or commands] 2. [Include build/test results] ## Related Resources * [ADO Story #NNN]({ADO_ORG}/{ADO_PROJECT_ENCODED}/_workitems/edit/NNN) * Parent: [Feature #NNN]({ADO_ORG}/{ADO_PROJECT_ENCODED}/_workitems/edit/NNN) 🤖 Generated with [Claude Code](https://claude.com/claude-code)⚠️ MANDATORY after PR creation — check for merge conflicts immediately via
mcp__azure-devops__repo_get_pull_request_by_id(repositoryId: {ADO_REPO_ID},pullRequestId: {prId}) — readmergeStatus. (Clean JSON, no cp1252/curl encoding issues.)- If
mergeStatusisconflicts: rebase, stamp, force-push, then re-check until clean:git fetch origin develop git rebase origin/develop bash .claude/hooks/stamp-review.sh git push --force-with-lease - If
mergeStatusisqueued: wait 5s and re-check (ADO is still computing the merge). - Only proceed to auto-complete and build polling when
mergeStatusissucceeded.
- If
-
Set auto-complete once AI review is clean. The user already approved the changes locally at step 3.5, so once the AI code review passes (0 Critical, 0 Major), set auto-complete immediately. No additional user gate is needed here.
Step 6a: AI Code Review Gate
After the PR is created, the CI build will run and include an AI code review. You must wait for this to pass before proceeding to Step 7.
⚠️ CRITICAL — DO NOT set auto-complete until the AI review is clean (0 Critical AND 0 Major). Setting auto-complete too early causes the PR to merge and delete the branch while you're still fixing issues. This creates orphan branches with no PR and wastes time. The correct flow is: create PR → poll build + review → fix all issues → push fixes → poll again → set auto-complete once review is clean. (User already approved locally at step 3.5, so no additional user gate is needed.)
Merge Gate
The AI code review blocks merge when:
- Any Critical issues are found, OR
- More than 5 Major issues are found (i.e., ≤5 Major is OK — but ALL Major issues must still be fixed before setting auto-complete)
Polling Loop
🚨 POLL VIA MCP TOOLS + ScheduleWakeup — NEVER curl/az-rest/python poll loops.
curl ... | python/az rest ... | pythonpoll loops are BROKEN on Windows: cp1252 mangles the JSON, python gets empty stdin, the loop's completion check NEVER fires, and you wait silently forever until the human notices the build/review finished. That is a failure of your core job here: shepherd the PR all the way to done (auto-complete set, work item closed) without the human having to tell you it's ready.Reliable path:
- Merge status / PR detail:
mcp__azure-devops__repo_get_pull_request_by_id— readmergeStatus(succeeded= no conflicts).- Build status:
mcp__azure-devops__pipelines_get_buildswithbranchName: "refs/pull/{prId}/merge", thenpipelines_get_build_status.status: 2= completed; checkresult.- AI review:
mcp__azure-devops__repo_list_pull_request_threads— find the comment whosecontentcontainsAI Code Review; parse#### Critical Issues/#### Major Issues.- Wait by re-scheduling yourself with
ScheduleWakeup(~150s while a build runs), NOT a bash sleep loop orrun_in_backgroundpoll (which silently hangs on the broken pipeline). Each wakeup re-invokes you to re-check via the MCP tools. Keep going until done or you need a human decision.
Execute the gate with these MCP calls (re-invoked across ScheduleWakeup wakeups — no bash loops):
-
Check for merge conflicts first —
mcp__azure-devops__repo_get_pull_request_by_id(repositoryId: {ADO_REPO_ID},pullRequestId: {prId}). ReadmergeStatus.- If
conflicts: rebase, stamp, force-push, then re-check before polling for the build:git fetch origin develop git rebase origin/develop bash .claude/hooks/stamp-review.sh git push --force-with-lease - If
succeededorqueued: proceed to build polling.
- If
-
Wait for the build to complete —
mcp__azure-devops__pipelines_get_buildswithbranchName: "refs/pull/{prId}/merge", thenmcp__azure-devops__pipelines_get_build_statusonce you have the build id.status: 1= in progress,2= completed; readresultfor success/failure. Drive the wait withScheduleWakeup(~150s while a build is actively running), NOT a bash sleep loop orrun_in_backgroundpoll — each wakeup re-invokes you to re-check via these MCP tools.If no build appears after several checks: the PR-policy build may not have auto-triggered (can happen when a branch is re-pushed after a previous PR on the same branch was squash-merged). Queue it with
mcp__azure-devops__pipelines_run_pipeline(branch: "refs/heads/{branchName}"), then poll that run by id. -
Poll for the AI review thread —
mcp__azure-devops__repo_list_pull_request_threads(repositoryId: {ADO_REPO_ID},project: {ADO_PROJECT}). Find the thread whose commentcontentcontainsAI Code Review(author is the build service; it's a summary thread with nothreadContext/filePath). If multiple reviews exist from fix iterations, always use the one with the latestpublishedDate.ADO commentType gotcha:
commentTypecomes back as a string ("text","system"), NOT an integer — do NOT filter bycommentType == 1. Always match oncontentcontainingAI Code Review,#### Critical, or#### Major. Only conclude the review was skipped after several wakeups with no thread found — do NOT give up after a single check. -
Parse the findings from the review content:
- Count findings under
#### Critical Issues— each- **[line is one finding - Count findings under
#### Major Issues— each- **[line is one finding - Count findings under
#### Minor Issues— informational only, do not block
- Count findings under
-
Evaluate:
- FAIL (any Critical OR >5 Major): Enter the fix loop (see below).
- PASS (0 Critical AND ≤5 Major): Still fix all Major issues before proceeding. The merge gate allows ≤5 Major, but ALL Major issues must be fixed or logged as false positives — do NOT skip them. Fix real issues in code, log false positives in
.claude/ai-review-findings.md. After fixing, push and poll for a new clean review. Once the latest review shows 0 Critical AND 0 Major (or all remaining are logged as false positives), set auto-complete immediately — the user already approved locally at step 3.5.
Fix Loop (when review fails)
For each Critical and Major finding, triage into one of three categories:
| Category | Action |
|---|---|
| Real issue | Fix it in the code. These are genuine bugs, missing validation, or security concerns. |
| False positive | The reviewer misunderstands the architecture, conventions, or design intent. Do NOT change code — instead, log it. |
| Questionable | Borderline finding. Could go either way. If fixing is low-effort, fix it. Otherwise, log it. |
For real issues: Fix them in the code, commit, stamp review, push.
For false positives and questionable findings: Log them in .claude/ai-review-findings.md for threshold tuning. Append entries in this format:
## {date} — PR #{prId} — Story #{storyId}
### False Positives
- **[File:Line]** {Finding summary} — **Why FP**: {1-2 sentence explanation of why this is not a real issue}
### Questionable
- **[File:Line]** {Finding summary} — **Notes**: {Why this is borderline and what you decided}
Create the file if it doesn't exist. This log helps the team tune the AI review thresholds over time.
After fixing and logging:
git addchanged files and commit with message describing the fixes- Update the PR description — append a
## Review Fixessection (or update existing) summarizing what was fixed and why:
Use### Iteration N **Issues addressed:** - **[Major]** {summary of fix and why} - **[Minor]** {summary — or "logged as false positive"}az repos pr update --id {prId} --description "..."to replace the full description with the appended section. bash .claude/hooks/stamp-review.sh(separate command)- Check for merge conflicts BEFORE pushing —
developmay have moved while you were working:git fetch origin develop && git rebase origin/develop bash .claude/hooks/stamp-review.sh # re-stamp after rebase git push(orgit push --force-with-leaseif a rebase was needed)- Verify the PR has no conflicts before polling —
mcp__azure-devops__repo_get_pull_request_by_id(repositoryId: {ADO_REPO_ID},pullRequestId: {prId}), readmergeStatus. If stillconflicts, repeat the rebase + force-push loop. - Loop back to the polling step and wait for the new build
Max iterations: 5 fix-push cycles. If still failing after 5 attempts, stop and report to the user:
- List the remaining findings
- Explain which ones keep recurring and why
- Ask the user how to proceed (force merge, adjust approach, or abandon)
Build Failure (non-review)
If the build fails for reasons OTHER than AI review, triage the failure type and fix locally before re-pushing:
| Failure type | Local fix |
|---|---|
| Format violation | {FORMAT_CMD} → git add -u |
| Compile error / missing file | Fix or add the missing file: git add <path> |
| Test failure | Run {TEST_CMD} locally, read output, fix failing tests |
| SCSS compilation | Run {SCSS_CMD} (if defined in project.testing.md) |
| Database build | Run {DB_BUILD_CMD} (if defined in project.testing.md) |
Fix loop:
- Run the failing check locally to get the full error output
- Fix the issue in the code
- Re-run
{FORMAT_CMD}+git add -u - Re-run
{BUILD_CMD}— confirm clean - Re-run
{TEST_CMD}— confirm passing - If defined: re-run
{SCSS_CMD}and{DB_BUILD_CMD}as applicable git addchanged files and commitbash .claude/hooks/stamp-review.sh(separate command)git push(separate command) — pre-push hook verifies build + tests pass again- Loop back to the CI polling step
The AI review only runs if the build and tests succeed, so these must be resolved first.
Step 7: Verification & Close
Determine the verification path based on the story type:
Path A: Test-only stories (tag contains test-gap)
For stories tagged test-gap, the tests themselves ARE the verification. No manual user verification is needed.
Auto-close criteria — all must be true before closing:
{BUILD_CMD}— 0 errors, 0 warnings{TEST_CMD}— all tests pass (including the new ones)- PR has been created and linked to the story
If all three pass, proceed directly to closing the work item (skip AskUserQuestion):
az boards work-item update --id {id} --state "Closed" --discussion "$(cat <<'HTMLEOF'
<h3>Implementation Complete — PR #{prId}</h3>
<p><strong>What was done</strong>: {summary — e.g., "Added N unit tests covering X failure modes for Y handler"}</p>
<p><strong>Verification</strong>: All tests pass, build clean.</p>
<p><strong>Test count</strong>: {N} new tests, {total} total suite</p>
HTMLEOF
)"
Path B: Infrastructure / pipeline / tooling stories (CI-verified)
For stories where the changes are to CI/CD pipelines, build scripts, analyzer config,
architecture tests, .editorconfig, build props, tooling scripts, or other developer
infrastructure — the CI pipeline itself verifies the changes. No manual UI verification
is needed.
Indicators (any of these):
- Changed files are under
.azure-pipelines/,tools/, or.claude/ - Changed files are build props,
.editorconfig,*.props,*.targets - Story is tagged
enterprise-practicesor is a pure infrastructure task - Story title references "CI", "pipeline", "analyzer", "formatting", "coverage", "build"
Auto-close criteria — all must be true before closing:
{BUILD_CMD}— 0 errors, 0 warnings- PR has been created and linked to the story
- Python/YAML syntax valid (if pipeline scripts were changed)
If all pass, proceed directly to closing the work item (skip AskUserQuestion):
az boards work-item update --id {id} --state "Dev Complete" --discussion "$(cat <<'HTMLEOF'
<h3>Implementation Complete — PR #{prId}</h3>
<p><strong>What was done</strong>: {summary of infrastructure/pipeline changes}</p>
<p><strong>Verification</strong>: Build clean, pipeline config validated, PR created.</p>
<p><strong>Note</strong>: CI pipeline will validate these changes when the PR build runs.</p>
HTMLEOF
)"
Path C: All other stories and bugs (user already approved locally)
The user already verified the feature locally at Step 6, step 3.5 (the mandatory approval gate before commit/push). No additional user gate is needed here — proceed directly to auto-complete and close.
-
Set auto-complete on the PR and close the work item:
Set auto-complete ({MERGE_STRATEGY} merge + delete branch) via
mcp__azure-devops__repo_update_pull_request(repositoryId: {ADO_REPO_ID},pullRequestId: {prId}): setautoCompleteSetByto your own identity (resolve viamcp__azure-devops__core_get_identity_idsif you don't already have it) andcompletionOptionsto{mergeStrategy: "{MERGE_STRATEGY}", deleteSourceBranch: true}. Use MCP, not a curl/python pipe.Close the work item:
-
For Bugs: Set state to
Closedwith a formatted HTML discussion comment:<h3>Fix Verified — PR #{prId}</h3> <p><strong>Root Cause</strong>: [1-2 sentence explanation]</p> <p><strong>Fix</strong>: [what was changed and why]</p> <p><strong>Verified</strong>: [brief confirmation of what was tested]</p> -
For User Stories: Set state to
Dev Completewith a formatted HTML discussion comment that includes AC verification:<h3>Implementation Complete — PR #{prId}</h3> <p><strong>What was done</strong>: [summary of implementation]</p> <p><strong>Business Context</strong>: [reference parent Feature/Epic and why this was needed]</p> <h4>Acceptance Criteria Verification</h4> <table><tr><th>AC</th><th>Status</th><th>Implementation</th></tr> <tr><td>AC1: {text}</td><td>✅</td><td>{how it was implemented}</td></tr> <tr><td>AC2: {text}</td><td>✅</td><td>{how it was implemented}</td></tr> </table> <p><strong>Verified</strong>: [brief confirmation of what was tested]</p> <p><strong>Follow-up</strong>: [any stories created for deferred scope, or "None"]</p>
az boards work-item update --id {id} --state "Closed" --discussion "{html}" # Bugs az boards work-item update --id {id} --state "Dev Complete" --discussion "{html}" # Stories -
Step 8: Cleanup — Return to develop and delete local branch
After the work item is closed (regardless of path A/B/C), clean up the local branch:
-
Verify the PR merged —
mcp__azure-devops__repo_get_pull_request_by_id(repositoryId: {ADO_REPO_ID},pullRequestId: {prId}); the PR is merged whenstatusiscompleted.- If not yet completed: the PR may still be pending auto-complete — skip the branch delete and note it to the user.
- If
merged: proceed.
-
Switch to develop and pull latest:
git checkout develop git pull origin develop -
Delete the local feature branch (use
-dnot-D— safe delete only):git branch -d feature/{BRANCH_USERNAME}/{id}-{slug}- If it warns "not fully merged" but the PR is confirmed completed above, use
-Dinstead ({MERGE_STRATEGY} merge means git doesn't know the branch is merged). - If there were multiple branches (e.g., a
-review-fixesbranch), delete all of them.
- If it warns "not fully merged" but the PR is confirmed completed above, use
-
Confirm to the user:
"Switched to develop, pulled latest, and deleted local branch feature/{BRANCH_USERNAME}/{id}-{slug}."
Requirements
azCLI installed and authenticated (az login)- Git credentials configured for the ADO remote
.claude/project.env.mdpopulated (run/emergent-dev:init-projectif missing)