* fix(#724): block convergence on actionable review findings * merge: integrate clean next (#936 inline) onto author tip + re-apply cursor fixes (Mode field, REVIEWS.md extraction) and review hardening (#724) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -934,7 +934,7 @@ Planner prompt:
|
||||
- {PATTERNS_PATH} (Pattern Map — analog files and code excerpts, if exists)
|
||||
- {verification_path} (Verification Gaps - if --gaps)
|
||||
- {uat_path} (UAT Gaps - if --gaps)
|
||||
- {reviews_path} (Cross-AI Review Feedback - if --reviews)
|
||||
- {reviews_path} (Cross-AI Review Feedback - if --reviews; actionable findings must be incorporated or explicitly deferred/rejected in PLAN.md)
|
||||
- {UI_SPEC_PATH} (UI Design Contract — visual/interaction specs, if exists)
|
||||
- {SPIKE_FINDINGS_PATH} (Spike Findings — validated patterns, constraints, landmines from experiments, if exists)
|
||||
- {SKETCH_FINDINGS_PATH} (Sketch Findings — validated design decisions, CSS patterns, visual direction, if exists)
|
||||
@@ -955,6 +955,16 @@ ${API_SURFACE_PATH ? `
|
||||
` : ''}
|
||||
${AGENT_SKILLS_PLANNER}
|
||||
|
||||
<review_incorporation_contract>
|
||||
**If Mode is reviews:** REVIEWS.md is feedback input, not a hidden execution contract. /gsd:execute-phase primarily consumes PLAN.md plus the normal phase context, so every current actionable review finding must become visible in the relevant PLAN.md before planning can pass.
|
||||
|
||||
For each current actionable finding in REVIEWS.md, the planner MUST either:
|
||||
- incorporate it into a PLAN.md task, `<action>`, `<acceptance_criteria>`, `<verify>`, `must_haves`, threat model, or artifact list; or
|
||||
- explicitly document a deferral/rejection rationale in the relevant PLAN.md so the executor and reviewer can see the decision.
|
||||
|
||||
Historical findings already incorporated, explicitly deferred/rejected in PLAN.md, or marked fully resolved do not require new plan changes.
|
||||
</review_incorporation_contract>
|
||||
|
||||
**Phase requirement IDs (every ID MUST appear in a plan's `requirements` field):** {phase_req_ids}
|
||||
|
||||
**Project instructions:** Read ./CLAUDE.md if exists — follow project-specific guidelines
|
||||
@@ -1273,6 +1283,7 @@ Checker prompt:
|
||||
<verification_context>
|
||||
**Phase:** {phase_number}
|
||||
**Phase Goal:** {goal from ROADMAP}
|
||||
**Mode:** {standard | gap_closure | reviews}
|
||||
|
||||
<files_to_read>
|
||||
- {PHASE_DIR}/*-PLAN.md (Plans to verify)
|
||||
@@ -1280,10 +1291,17 @@ Checker prompt:
|
||||
- {requirements_path} (Requirements)
|
||||
- {context_path} (USER DECISIONS from /gsd:discuss-phase)
|
||||
- {research_path} (Technical Research — includes Validation Architecture)
|
||||
- {reviews_path} (Cross-AI Review Feedback - if --reviews; verify actionable findings are represented in PLAN.md)
|
||||
</files_to_read>
|
||||
|
||||
${AGENT_SKILLS_CHECKER}
|
||||
|
||||
<review_incorporation_verification>
|
||||
**If Mode is reviews:** Read REVIEWS.md and verify each current actionable review finding is visible in executable PLAN.md content or explicitly deferred/rejected in the relevant PLAN.md. A finding remains actionable if it requires a concrete plan task, `<action>`, `<acceptance_criteria>`, `<verify>`, `must_haves`, threat-model item, stale-path correction, or execution contract change before /gsd:execute-phase runs.
|
||||
|
||||
If an actionable finding remains only in REVIEWS.md and would be invisible to /gsd:execute-phase, return `## ISSUES FOUND`. Use WARNING by default; use BLOCKER when the missing incorporation can prevent the phase goal, create unsafe execution, or invalidate verification.
|
||||
</review_incorporation_verification>
|
||||
|
||||
**Phase requirement IDs (MUST ALL be covered):** {phase_req_ids}
|
||||
|
||||
**Project instructions:** Read ./CLAUDE.md if exists — verify plans honor project guidelines
|
||||
|
||||
@@ -3,7 +3,7 @@ Cross-AI plan convergence loop — automates the manual chain:
|
||||
gsd-plan-phase N → gsd-review N --codex → gsd-plan-phase N --reviews → gsd-review N --codex → ...
|
||||
Plan-phase runs inline (bare Skill at depth 0) so it can spawn gsd-planner/gsd-plan-checker at depth 1.
|
||||
Review runs inside an isolated Agent (leaf skill — Bash only, no sub-agents needed).
|
||||
Orchestrator only does: init, loop control, parse CYCLE_SUMMARY for HIGH count, stall detection, escalation.
|
||||
Orchestrator only does: init, loop control, parse CYCLE_SUMMARY for HIGH and actionable non-HIGH counts, stall detection, escalation.
|
||||
</purpose>
|
||||
|
||||
<required_reading>
|
||||
@@ -122,7 +122,7 @@ Initialize loop variables:
|
||||
|
||||
```text
|
||||
cycle = 0
|
||||
prev_high_count = Infinity
|
||||
prev_unresolved_count = Infinity
|
||||
```
|
||||
|
||||
### 5a. Review (Spawn Agent)
|
||||
@@ -143,9 +143,10 @@ Complete the full review workflow. Do NOT return until REVIEWS.md is committed.
|
||||
IMPORTANT — CYCLE_SUMMARY contract (required):
|
||||
Your final response MUST include a machine-readable line of exactly this form:
|
||||
|
||||
CYCLE_SUMMARY: current_high=<N>
|
||||
CYCLE_SUMMARY: current_high=<N> current_actionable=<M>
|
||||
|
||||
Where <N> is the integer count of HIGH-severity concerns that REMAIN UNRESOLVED in this cycle's findings.
|
||||
Where <M> is the integer count of actionable MEDIUM/LOW concerns that REMAIN UNRESOLVED because the latest PLAN.md files do not yet incorporate them or explicitly defer/reject them.
|
||||
|
||||
Counting rules:
|
||||
INCLUDE in the count:
|
||||
@@ -157,16 +158,23 @@ Counting rules:
|
||||
- FULLY RESOLVED HIGHs: concern addressed with verification complete (closed ticket, verification log, or reviewer sign-off)
|
||||
- HIGH mentions in retrospective/summary tables comparing cycles
|
||||
- Quoted excerpts from prior reviews referencing past HIGH items
|
||||
- MEDIUM/LOW concerns that are already incorporated into a PLAN.md task, action, acceptance_criteria, verify command, must_haves item, threat model, artifact list, or explicit deferral/rejection rationale
|
||||
|
||||
Definitions:
|
||||
PARTIALLY RESOLVED — concern acknowledged and mitigation is in progress but not yet verified/completed (e.g., open ticket exists but fix not landed).
|
||||
FULLY RESOLVED — concern addressed with verification complete (closed ticket, verification log, or explicit reviewer sign-off confirming closure).
|
||||
ACTIONABLE — a non-HIGH review finding that would be invisible to /gsd:execute-phase unless it is incorporated into PLAN.md or explicitly deferred/rejected in PLAN.md.
|
||||
|
||||
Your final response MUST also include this section immediately after the CYCLE_SUMMARY line:
|
||||
|
||||
## Current HIGH Concerns
|
||||
[List each unresolved HIGH with a brief description, one per bullet]
|
||||
[If none: write exactly 'None.']",
|
||||
[If none: write exactly 'None.']
|
||||
|
||||
## Current Actionable Non-HIGH Concerns
|
||||
[List each unresolved actionable MEDIUM/LOW with a brief description and the PLAN.md change still needed, one per bullet]
|
||||
[If none: write exactly 'None.']
|
||||
These two sections MUST be the final content of your response, in this exact order, with no additional "## " headings after them (the source-grounding "Verification coverage" block is appended to REVIEWS.md, not to this return message).",
|
||||
mode="auto"
|
||||
)
|
||||
```
|
||||
@@ -194,35 +202,49 @@ REVIEWS_FILE=$(ls ${phase_dir}/${padded_phase}-REVIEWS.md 2>/dev/null)
|
||||
|
||||
If REVIEWS_FILE is empty: Error — review agent did not produce REVIEWS.md. Exit.
|
||||
|
||||
### 5b. Extract HIGH Count from CYCLE_SUMMARY Contract
|
||||
### 5b. Extract unresolved counts from CYCLE_SUMMARY Contract
|
||||
|
||||
**Do NOT grep REVIEWS.md for HIGH count.** REVIEWS.md accumulates history across cycles — resolved HIGHs from prior cycles remain in the file as audit trail, inflating a raw grep count and causing false stall detection.
|
||||
**Do NOT grep REVIEWS.md for HIGH or actionable counts.** REVIEWS.md accumulates history across cycles — resolved findings from prior cycles remain in the file as audit trail, inflating a raw grep count and causing false stall detection.
|
||||
|
||||
Parse HIGH_COUNT from the review agent's return message via the CYCLE_SUMMARY contract:
|
||||
Parse HIGH_COUNT and ACTIONABLE_COUNT from the review agent's return message via the CYCLE_SUMMARY contract:
|
||||
|
||||
```bash
|
||||
# Extract the integer from "CYCLE_SUMMARY: current_high=N" in the agent's return message
|
||||
HIGH_COUNT=$(echo "$REVIEW_AGENT_RETURN" | grep -oE 'CYCLE_SUMMARY:\s*current_high=[0-9]+' | head -1 | grep -oE '[0-9]+$')
|
||||
# Extract integers from "CYCLE_SUMMARY: current_high=N current_actionable=M" in the agent's return message
|
||||
SUMMARY_LINE=$(echo "$REVIEW_AGENT_RETURN" | grep -oE 'CYCLE_SUMMARY:.*' | head -1)
|
||||
HIGH_COUNT=$(echo "$SUMMARY_LINE" | grep -oE 'current_high=[0-9]+' | head -1 | grep -oE '[0-9]+$')
|
||||
ACTIONABLE_COUNT=$(echo "$SUMMARY_LINE" | grep -oE 'current_actionable=[0-9]+' | head -1 | grep -oE '[0-9]+$')
|
||||
|
||||
if [ -z "$HIGH_COUNT" ]; then
|
||||
# Distinguish malformed contract from completely absent contract
|
||||
if echo "$REVIEW_AGENT_RETURN" | grep -q 'CYCLE_SUMMARY:'; then
|
||||
echo "CYCLE_SUMMARY present but current_high is malformed — expected integer, got non-numeric value. Retry or switch reviewer."
|
||||
else
|
||||
echo "Review agent did not honor the CYCLE_SUMMARY contract — cannot determine HIGH count. Retry or switch reviewer."
|
||||
fi
|
||||
if [ -z "$SUMMARY_LINE" ]; then
|
||||
echo "Review agent did not honor the CYCLE_SUMMARY contract — cannot determine unresolved review counts. Retry or switch reviewer."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$HIGH_COUNT" ]; then
|
||||
echo "CYCLE_SUMMARY present but current_high is missing or malformed — expected integer, got non-numeric or absent value. Retry or switch reviewer."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$ACTIONABLE_COUNT" ]; then
|
||||
echo "CYCLE_SUMMARY present but current_actionable is missing or malformed — expected integer, got non-numeric or absent value. Retry or switch reviewer."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
UNRESOLVED_COUNT=$((HIGH_COUNT + ACTIONABLE_COUNT))
|
||||
|
||||
# Extract the ## Current HIGH Concerns section from the agent's return message
|
||||
HIGH_LINES=$(echo "$REVIEW_AGENT_RETURN" | awk '/^## Current HIGH Concerns/{found=1; next} found && /^##/{exit} found{print}')
|
||||
ACTIONABLE_LINES=$(echo "$REVIEW_AGENT_RETURN" | awk '/^## Current Actionable Non-HIGH Concerns/{found=1; next} found && /^##/{exit} found{print}')
|
||||
|
||||
if [ "${HIGH_COUNT}" -gt 0 ] && [ -z "${HIGH_LINES}" ]; then
|
||||
echo "⚠ Review agent's CYCLE_SUMMARY reports ${HIGH_COUNT} HIGHs but did not provide ## Current HIGH Concerns section — continuing with incomplete escalation details."
|
||||
fi
|
||||
|
||||
if [ "${ACTIONABLE_COUNT}" -gt 0 ] && [ -z "${ACTIONABLE_LINES}" ]; then
|
||||
echo "⚠ Review agent's CYCLE_SUMMARY reports ${ACTIONABLE_COUNT} actionable non-HIGH concerns but did not provide ## Current Actionable Non-HIGH Concerns section — continuing with incomplete escalation details."
|
||||
fi
|
||||
```
|
||||
|
||||
**If HIGH_COUNT == 0 (converged):**
|
||||
**If HIGH_COUNT == 0 and ACTIONABLE_COUNT == 0 (converged):**
|
||||
|
||||
```bash
|
||||
gsd_run state planned-phase --phase "${PHASE}" --name "${phase_name}" --plans "${PLAN_COUNT}"
|
||||
@@ -236,6 +258,7 @@ Display:
|
||||
|
||||
Phase {phase_number} converged in {cycle} cycle(s).
|
||||
No HIGH concerns remaining.
|
||||
No actionable MEDIUM/LOW review findings remain outside PLAN.md.
|
||||
|
||||
REVIEWS.md: {REVIEWS_FILE}
|
||||
Next: /gsd:execute-phase {PHASE}
|
||||
@@ -243,16 +266,16 @@ Display:
|
||||
|
||||
Exit — convergence achieved.
|
||||
|
||||
**If HIGH_COUNT > 0:** Continue to 5c.
|
||||
**If HIGH_COUNT > 0 or ACTIONABLE_COUNT > 0:** Continue to 5c.
|
||||
|
||||
### 5c. Stall Detection + Escalation Check
|
||||
|
||||
Display: `◆ Cycle {cycle}/{MAX_CYCLES} — {HIGH_COUNT} HIGH concerns found`
|
||||
Display: `◆ Cycle {cycle}/{MAX_CYCLES} — {HIGH_COUNT} HIGH, {ACTIONABLE_COUNT} actionable non-HIGH review concerns found`
|
||||
|
||||
**Stall detection:** If `HIGH_COUNT >= prev_high_count`:
|
||||
**Stall detection:** If `UNRESOLVED_COUNT >= prev_unresolved_count`:
|
||||
```text
|
||||
⚠ Convergence stalled — HIGH concern count not decreasing
|
||||
({HIGH_COUNT} HIGH concerns, previous cycle had {prev_high_count})
|
||||
⚠ Convergence stalled — unresolved review concern count not decreasing
|
||||
({UNRESOLVED_COUNT} unresolved concerns, previous cycle had {prev_unresolved_count})
|
||||
```
|
||||
|
||||
**Max cycles check:** If `cycle >= MAX_CYCLES`:
|
||||
@@ -260,13 +283,15 @@ Display: `◆ Cycle {cycle}/{MAX_CYCLES} — {HIGH_COUNT} HIGH concerns found`
|
||||
If `TEXT_MODE` is true, present as plain-text numbered list:
|
||||
```text
|
||||
Plan convergence did not complete after {MAX_CYCLES} cycles.
|
||||
{HIGH_COUNT} HIGH concerns remain:
|
||||
{HIGH_COUNT} HIGH concerns and {ACTIONABLE_COUNT} actionable non-HIGH concerns remain:
|
||||
|
||||
{HIGH_LINES}
|
||||
|
||||
{ACTIONABLE_LINES}
|
||||
|
||||
How would you like to proceed?
|
||||
|
||||
1. Proceed anyway — Accept plans with remaining HIGH concerns and move to execution
|
||||
1. Proceed anyway — Accept plans with remaining review concerns and move to execution
|
||||
2. Manual review — Stop here, review REVIEWS.md and address concerns manually
|
||||
|
||||
Enter number:
|
||||
@@ -276,11 +301,11 @@ Otherwise use AskUserQuestion:
|
||||
```js
|
||||
AskUserQuestion([
|
||||
{
|
||||
question: "Plan convergence did not complete after {MAX_CYCLES} cycles. {HIGH_COUNT} HIGH concerns remain:\n\n{HIGH_LINES}\n\nHow would you like to proceed?",
|
||||
question: "Plan convergence did not complete after {MAX_CYCLES} cycles. {HIGH_COUNT} HIGH concerns and {ACTIONABLE_COUNT} actionable non-HIGH concerns remain:\n\n{HIGH_LINES}\n\n{ACTIONABLE_LINES}\n\nHow would you like to proceed?",
|
||||
header: "Convergence",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: "Proceed anyway", description: "Accept plans with remaining HIGH concerns and move to execution" },
|
||||
{ label: "Proceed anyway", description: "Accept plans with remaining review concerns and move to execution" },
|
||||
{ label: "Manual review", description: "Stop here — review REVIEWS.md and address concerns manually" }
|
||||
]
|
||||
}
|
||||
@@ -301,7 +326,7 @@ Exit workflow.
|
||||
|
||||
**If under max cycles:**
|
||||
|
||||
Update `prev_high_count = HIGH_COUNT`.
|
||||
Update `prev_unresolved_count = UNRESOLVED_COUNT`.
|
||||
|
||||
Display: `◆ Replanning inline with review feedback... (plan-phase runs here in the orchestrator — no output until replanning is complete, ~1–5 min; expected, not a freeze)`
|
||||
|
||||
@@ -309,7 +334,7 @@ Display: `◆ Replanning inline with review feedback... (plan-phase runs here in
|
||||
Skill(skill="gsd-plan-phase", args="{PHASE} --reviews --skip-research {GSD_WS}")
|
||||
```
|
||||
|
||||
Run plan-phase **inline** (do NOT wrap it in Agent()). Same rationale as step 4: the convergence orchestrator runs at depth 0 with Agent available, so inline plan-phase can spawn gsd-planner and gsd-plan-checker at depth 1. Wrapping in Agent() pushes plan-phase to depth 1 where the Agent tool is absent — the replan loop can never produce a revised plan when HIGHs are found. This is the root cause of bug #936. Wait until plan-phase completes (outputs '## PLANNING COMPLETE') and updated PLAN.md files are committed before continuing.
|
||||
Run plan-phase **inline** (do NOT wrap it in Agent()). Same rationale as step 4: the convergence orchestrator runs at depth 0 with Agent available, so inline plan-phase can spawn gsd-planner and gsd-plan-checker at depth 1. Wrapping in Agent() pushes plan-phase to depth 1 where the Agent tool is absent — the replan loop can never produce a revised plan when HIGHs are found. This is the root cause of bug #936. Actionable MEDIUM/LOW findings must be incorporated into executable PLAN.md content or explicitly deferred/rejected in the relevant PLAN.md before convergence can complete. Wait until plan-phase completes (outputs '## PLANNING COMPLETE') and updated PLAN.md files are committed before continuing.
|
||||
|
||||
After plan-phase completes → go back to **step 5a** (review again).
|
||||
|
||||
@@ -320,13 +345,15 @@ After plan-phase completes → go back to **step 5a** (review again).
|
||||
- [ ] Initial planning via inline Skill("gsd-plan-phase") if no plans exist — NOT wrapped in Agent() (bug #936: depth-1 Agent has no Agent tool)
|
||||
- [ ] Review via Agent → Skill("gsd-review") — isolated Agent is correct; gsd-review is a Bash leaf with no sub-agent spawns; {GSD_WS} forwarded
|
||||
- [ ] Replan via inline Skill("gsd-plan-phase --reviews") — NOT wrapped in Agent(); inline lets plan-phase spawn gsd-planner/gsd-plan-checker at depth 1
|
||||
- [ ] Orchestrator only does: init, config gate, loop control, parse CYCLE_SUMMARY for HIGH count, stall detection, escalation
|
||||
- [ ] HIGH count extracted from review agent's CYCLE_SUMMARY return message (not by grepping REVIEWS.md)
|
||||
- [ ] Review agent prompt defines CYCLE_SUMMARY: current_high=<N> contract with PARTIALLY/FULLY RESOLVED definitions
|
||||
- [ ] Orchestrator only does: init, config gate, loop control, parse CYCLE_SUMMARY for HIGH and actionable non-HIGH counts, stall detection, escalation
|
||||
- [ ] HIGH and actionable non-HIGH counts extracted from review agent's CYCLE_SUMMARY return message (not by grepping REVIEWS.md)
|
||||
- [ ] Review agent prompt defines CYCLE_SUMMARY: current_high=<N> current_actionable=<M> contract with PARTIALLY/FULLY RESOLVED/ACTIONABLE definitions
|
||||
- [ ] Abort with clear error if CYCLE_SUMMARY is absent; distinguish malformed from absent
|
||||
- [ ] Warn if HIGH_COUNT > 0 but ## Current HIGH Concerns section is absent from return message
|
||||
- [ ] Abort with clear error if current_actionable is absent or malformed
|
||||
- [ ] Warn if ACTIONABLE_COUNT > 0 but ## Current Actionable Non-HIGH Concerns section is absent from return message
|
||||
- [ ] The review Agent fully completes gsd-review before returning (plan-phase runs inline — no Agent wrap)
|
||||
- [ ] Loop exits on: no HIGH concerns (converged) OR max cycles (escalation)
|
||||
- [ ] Stall detection reported when HIGH count not decreasing
|
||||
- [ ] Loop exits on: no HIGH concerns and no actionable non-HIGH concerns (converged) OR max cycles (escalation)
|
||||
- [ ] Stall detection reported when total unresolved review concern count is not decreasing
|
||||
- [ ] STATE.md updated on convergence completion
|
||||
</success_criteria>
|
||||
|
||||
Reference in New Issue
Block a user