* fix(#411): restore gsd_run launcher in next.md (re-run sync after #406 regression) * fix(#411): update policy-160 route0 test to expect gsd_run canonical resolver Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -95,7 +95,7 @@ This catches the common failure mode where a session died mid-execution (hang, t
|
||||
|
||||
**Why Route 0 runs here (after Gates 1-3, before the prior-phase defer prompt):** This step is a hard invariant independent of `current_phase`'s value — it must run before any routing rule that reads `current_phase`. Gates 1-3 are cheap repo/state validity checks that must always run — skipping them on the resume path would risk advancing into a broken-state project. The prior-phase completeness-scan DEFER PROMPT, however, must NOT run in the default (no-flag) case when Route 0 is about to resume the phase automatically: that would force a double-decision (prompt first, then resume anyway), overriding the user's choice. Route 0 placed here means: default = resume silently (no defer prompt); `--no-resume` = skip Route 0 and fall through to the prior-phase defer prompt in `prior_phase_completeness`; `--force` = jump straight to `determine_next_action` at `safety_gates` (never reaches Route 0 or `prior_phase_completeness` at all).
|
||||
|
||||
Scan ALL phases in ROADMAP order (lowest-numbered to highest) for incomplete-execution state. Use `$GSD_SDK query roadmap.analyze` to get the phase list, then for each phase number `N` query `$GSD_SDK query find-phase <N>` JSON and inspect its `plans` and `summaries` arrays. A phase is **incomplete-execution** when `plans.length > summaries.length` (at least one PLAN.md has no matching SUMMARY.md).
|
||||
Scan ALL phases in ROADMAP order (lowest-numbered to highest) for incomplete-execution state. Use `gsd_run query roadmap.analyze` to get the phase list, then for each phase number `N` query `gsd_run query find-phase <N>` JSON and inspect its `plans` and `summaries` arrays. A phase is **incomplete-execution** when `plans.length > summaries.length` (at least one PLAN.md has no matching SUMMARY.md).
|
||||
|
||||
Stop at the first such phase. Record its phase number as `INCOMPLETE_PHASE`. This is the lowest-numbered phase that needs continued execution.
|
||||
|
||||
@@ -103,7 +103,7 @@ Illustrative bash:
|
||||
|
||||
```bash
|
||||
INCOMPLETE_PHASE=""
|
||||
ROADMAP_JSON=$($GSD_SDK query roadmap.analyze)
|
||||
ROADMAP_JSON=$(gsd_run query roadmap.analyze)
|
||||
if [ $? -ne 0 ] || [ -z "$ROADMAP_JSON" ]; then
|
||||
echo "⚠ WARNING: resume-incomplete-phase scan could not run (roadmap.analyze failed)." >&2
|
||||
echo " The incomplete-phase invariant (#160) could not be verified." >&2
|
||||
@@ -111,7 +111,7 @@ if [ $? -ne 0 ] || [ -z "$ROADMAP_JSON" ]; then
|
||||
# Fall through to prior_phase_completeness rather than silently skipping
|
||||
else
|
||||
for PHASE_NUM in $(echo "$ROADMAP_JSON" | jq -r '.phases[] | (.number // .phase_number // empty)'); do
|
||||
PHASE_JSON=$($GSD_SDK query find-phase "$PHASE_NUM")
|
||||
PHASE_JSON=$(gsd_run query find-phase "$PHASE_NUM")
|
||||
if [ $? -ne 0 ] || [ -z "$PHASE_JSON" ]; then
|
||||
echo "⚠ WARNING: Could not query phase $PHASE_NUM — skipping in resume scan." >&2
|
||||
continue
|
||||
@@ -143,7 +143,7 @@ Then invoke via SlashCommand. Do not continue to subsequent steps.
|
||||
**Prior-phase completeness scan (runs when `--no-resume` was passed and Route 0 was skipped, or when Route 0 found no incomplete-execution phases in the default case). NOT reached under `--force` — that flag jumps directly to `determine_next_action` at `safety_gates`.**
|
||||
|
||||
**Prior-phase completeness scan:**
|
||||
Scan all phases that precede the current phase in ROADMAP.md order for incomplete work. For each prior phase number `N`, use `$GSD_SDK query find-phase <N>` JSON (plans, summaries, incomplete_plans, etc.) to inspect that phase.
|
||||
Scan all phases that precede the current phase in ROADMAP.md order for incomplete work. For each prior phase number `N`, use `gsd_run query find-phase <N>` JSON (plans, summaries, incomplete_plans, etc.) to inspect that phase.
|
||||
|
||||
Detect three categories of incomplete work:
|
||||
1. **Plans without summaries** — a PLAN.md exists in a prior phase directory but no matching SUMMARY.md exists (execution started but not completed).
|
||||
@@ -291,7 +291,7 @@ Resume with: `/gsd:progress --next --auto` once resolved.
|
||||
- [ ] Default (no flag): Route 0 resumes incomplete phase silently, exits — user never sees the prior-phase defer prompt
|
||||
- [ ] `--no-resume`: Route 0 skipped, prior_phase_completeness defer prompt runs as before
|
||||
- [ ] `--force`: everything skipped (Gates, Route 0, prior_phase_completeness) → straight to `determine_next_action`
|
||||
- [ ] Scan uses `$GSD_SDK` (canonical resolver form); errors are surfaced rather than suppressed
|
||||
- [ ] Scan uses `gsd_run` (canonical resolver form); errors are surfaced rather than suppressed
|
||||
- [ ] Predicate is plans-without-summaries (`plans.length > summaries.length`) — consistent with `determine_next_action` Route 4
|
||||
- [ ] Next action correctly determined from routing rules
|
||||
- [ ] Command invoked immediately without user confirmation
|
||||
|
||||
@@ -241,21 +241,21 @@ describe('Route 0: resume_incomplete_phase invariant (#160)', () => {
|
||||
|
||||
// ── SHOULD-FIX 2: SDK form and fail-closed error surfacing ──
|
||||
|
||||
test('scan uses $GSD_SDK (canonical resolver form, not bare gsd-sdk)', () => {
|
||||
test('scan uses gsd_run (canonical resolver form, not bare gsd-sdk)', () => {
|
||||
const content = fs.readFileSync(nextMdPath, 'utf8');
|
||||
const route0Start = content.indexOf('name="resume_incomplete_phase"');
|
||||
const route0End = content.indexOf('</step>', route0Start);
|
||||
const route0Block = content.slice(route0Start, route0End);
|
||||
// Must use $GSD_SDK, not bare gsd-sdk
|
||||
// Must use gsd_run, not bare gsd-sdk
|
||||
assert.ok(
|
||||
route0Block.includes('$GSD_SDK'),
|
||||
'Route 0 scan must use $GSD_SDK (canonical resolver), not bare gsd-sdk'
|
||||
route0Block.includes('gsd_run'),
|
||||
'Route 0 scan must use gsd_run (canonical resolver), not bare gsd-sdk'
|
||||
);
|
||||
// Must NOT use bare gsd-sdk (without $)
|
||||
const bareGsdSdkPattern = /(?<!\$)gsd-sdk/;
|
||||
assert.ok(
|
||||
!bareGsdSdkPattern.test(route0Block),
|
||||
'Route 0 must not use bare gsd-sdk — use $GSD_SDK to match the file convention'
|
||||
'Route 0 must not use bare gsd-sdk — use gsd_run to match the file convention'
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user