fix(sdk): skip advance step when verification finds gaps#1454
fix(sdk): skip advance step when verification finds gaps#1454trek-e merged 2 commits intogsd-build:mainfrom
Conversation
Previously, the advance step ran unconditionally after verify, marking phases as complete in ROADMAP.md even when gaps_found. This caused subsequent auto runs to skip unfinished phases. Now checks if all verify steps passed before advancing. When verification fails, the phase remains incomplete so the next auto run re-attempts it.
jeremymcs
left a comment
There was a problem hiding this comment.
Validated review findings from local verification of commit 39d8688.
1) High: advance can still run when verification gaps persist
In sdk/src/phase-runner.ts:
- advance gate uses
verifyPassed = steps.every(... s.success)(around line 253) - but
runVerifyStep()still returnssuccess: truewhengaps_foundexhausts retries (around lines 911, 926, 932)
So persistent gaps can still pass the new gate and execute runAdvanceStep().
Recommended fix
Track explicit verify outcome and gate advance on outcome instead of s.success alone.
Example direction:
- add a verify-specific marker to
PhaseStepResult(e.g.verifyOutcome?: 'passed' | 'human_needed' | 'gaps_found') - in
runVerifyStep(), when retries are exhausted withgaps_found, returnsuccess: falseandverifyOutcome: 'gaps_found' - in
run(), gate advance withverifyOutcome !== 'gaps_found' - if you flip verify to
success: falseon exhausted gaps, ensureretryOnce('verify', ...)does not trigger an extra full verify cycle unintentionally
2) Medium: tests still encode old behavior, missing regression
In sdk/src/phase-runner.test.ts:
- tests around ~580 and ~662 still expect exhausted-gap verify to be
success: true - no regression test currently asserts “persistent gaps => no advance / no phaseComplete”
Recommended test additions
Add tests that assert:
- persistent
gaps_founddoes not appendPhaseStepType.Advance tools.phaseCompleteis not called in that case- verifier disabled path still advances (to preserve intended behavior)
These changes would align implementation with PR intent: "skip advance step when verification finds gaps".
|
@odmrs if you can update your PR with the findings. I"ll merge it. |
Address review findings from gsd-build#1454: 1. runVerifyStep now returns success:false when gaps persist after exhausting retries (was always returning success:true) 2. human_needed + callback accept correctly sets outcome to passed 3. retryOnce skips retry for verification outcomes (gaps_found, human_needed) which have their own internal retry logic 4. Updated 3 existing tests to expect success:false on exhausted gaps 5. Added 3 regression tests: - persistent gaps_found does NOT append Advance step - persistent gaps_found does NOT call phaseComplete - verifier disabled still advances normally
|
Thanks for the thorough review! Updated the PR with your findings — verify now properly returns success:false on exhausted gaps, and added the 3 regression tests you suggested. Will be more careful with these edge cases on future PRs. Mind taking another look? |
Address review findings from gsd-build#1454: 1. runVerifyStep now returns success:false when gaps persist after exhausting retries (was always returning success:true) 2. human_needed + callback accept correctly sets outcome to passed 3. retryOnce skips retry for verification outcomes (gaps_found, human_needed) which have their own internal retry logic 4. Updated 3 existing tests to expect success:false on exhausted gaps 5. Added 3 regression tests: - persistent gaps_found does NOT append Advance step - persistent gaps_found does NOT call phaseComplete - verifier disabled still advances normally
trek-e
left a comment
There was a problem hiding this comment.
Adversarial Review: fix(sdk): skip advance step when verification finds gaps
Verdict: APPROVE (after addressing review feedback from jeremymcs)
The author has addressed all findings from the previous CHANGES_REQUESTED review by jeremymcs. Verifying the amendments:
Review finding 1 (High): advance can still run when verification gaps persist
Original issue: runVerifyStep() returned success: true even when gaps_found exhausted retries, so the advance gate (steps.every(s.success)) would pass.
Fix verified in commit 4bf9789:
runVerifyStep()now returnssuccess: falsewhen outcome is notpassed(line:const verifySuccess = outcome === 'passed')- Error field set to
verification_${outcome}for traceability retryOncenow short-circuits onverification_*errors to avoid re-triggering verify's internal retry logic- The advance gate
verifyPassed = steps.every(s => s.step !== PhaseStepType.Verify || s.success)now correctly blocks advance when verify returnssuccess: false
Review finding 2 (Medium): tests encode old behavior, missing regression tests
Fix verified in commit 4bf9789:
- Three existing tests updated from
expect(verifyStep!.success).toBe(true)toexpect(verifyStep!.success).toBe(false)for exhausted-gap scenarios - Three new regression tests added:
- "persistent gaps_found does NOT append Advance step" -- asserts
stepTypesdoes not containPhaseStepType.Advance - "persistent gaps_found does NOT call phaseComplete" -- asserts
tools.phaseCompletenot called - "verifier disabled still advances normally" -- asserts advance still works when verifier is skipped
- "persistent gaps_found does NOT append Advance step" -- asserts
All three tests are well-structured and directly assert the behaviors recommended in the review.
Additional changes (from earlier commits)
- Step-skip optimization for auto_advance resume mode (skips research/plan if artifacts exist)
- Phase success determination based on verify outcome rather than all-step history
Note: These additional changes overlap with PR #1443 (same author). Whichever PR merges first, the other will need a rebase. Both PRs should coordinate to avoid duplicate work.
No security issues, no prompt injection. The fix addresses a real $15+ waste scenario described in the PR.
Problem
The
advancestep inPhaseRunner.run()executes unconditionally afterverify, marking phases as[x](complete) in ROADMAP.md even when verification returnsgaps_found. On subsequentautoruns, the SDK sees[x]and skips the phase entirely.Impact observed: In a 6-phase project, phases 2 and 3 were marked "Complete" with zero lines of code written. ~$15 spent on research/plan/verify cycles that produced nothing because the SDK kept advancing past unfinished phases.
Fix
phase-runner.tsnow checks if all verify steps passed before running advance:When verification fails, the phase remains
[ ]so the nextautorun re-attempts it.Open question
Should the milestone runner continue to the next phase when a phase fails verification?
Currently it stops on first
success: false(index.tsline ~197). Possible behaviors:autoafter fixingworkflow.on_verify_fail: "stop" | "retry"Happy to implement whichever approach you prefer.
Test plan
npm run test:unit— 675 tests passing, zero breakagenpm run build— zero errorsgaps_foundstay[ ]in ROADMAP