fix(#2201): accept --phase N flag in the phase verb family (#2231)

* fix(#2201): accept --phase N flag in the phase verb family (complete, list-plans)

The phase family router treated the first positional (args[2]) as the phase
number, so `phase complete --phase 12` passed the literal '--phase' as the phase
→ 'Phase --phase not found'. The state family already accepted --phase N. Now
complete and list-plans accept --phase N (and --phase=N) as well as the bare
positional; unrecognized flags yield a usage error naming the accepted form.

Closes #2201

* docs(#2201): add changeset fragment

* docs(#2201): backfill PR number
This commit is contained in:
Tom Boucher
2026-07-12 23:47:47 -04:00
committed by GitHub
parent 19fa7364e0
commit 0278329c3a
2 changed files with 47 additions and 2 deletions

View File

@@ -0,0 +1,5 @@
---
type: Fixed
pr: 2231
---
**`phase complete --phase N` now works alongside the positional form** — the phase verb family treated the first positional as the phase number, so `--phase 12` was passed as the literal phase name and failed with 'Phase --phase not found'. The phase family now accepts the --phase flag consistently with the state family, and unrecognized flags yield a usage error. (#2201)

View File

@@ -163,7 +163,28 @@ function routePhaseCommand({ phase, args, cwd, raw, error }: RoutePhaseCommandOp
return { ok: true as const, data: null };
},
complete: (_ctx: Record<string, unknown>): { ok: true; data: null } => {
phase.cmdPhaseComplete(cwd, args[2], raw);
// #2201: accept --phase N as well as the positional form (the state
// family already accepts --phase). An unrecognized flag is a usage
// error, not "Phase --phase not found".
let phaseNum: string | null = null;
for (let i = 2; i < args.length; i++) {
if (args[i] === '--phase') {
phaseNum = args[++i];
if (!phaseNum || phaseNum.startsWith('--'))
return makeInvalidArgs('--phase', '--phase requires a value') as never;
} else if (args[i].startsWith('--phase=')) {
phaseNum = args[i].slice(8);
} else if (args[i] === '--raw') {
continue;
} else if (args[i].startsWith('--')) {
return makeInvalidArgs(args[i], `phase complete does not support ${args[i]}`) as never;
} else {
phaseNum = args[i];
}
}
if (!phaseNum)
return makeInvalidArgs('--phase', 'phase number required (positional or --phase N)') as never;
phase.cmdPhaseComplete(cwd, phaseNum, raw);
return { ok: true as const, data: null };
},
'uat-passed': (_ctx: Record<string, unknown>): { ok: true; data: null } => {
@@ -185,7 +206,26 @@ function routePhaseCommand({ phase, args, cwd, raw, error }: RoutePhaseCommandOp
},
// #1437 — list plan files for a phase
'list-plans': (_ctx: Record<string, unknown>): { ok: true; data: null } => {
phase.cmdPhaseListPlans(cwd, args[2], raw);
// #2201: accept --phase N as well as positional.
let phaseNum: string | null = null;
for (let i = 2; i < args.length; i++) {
if (args[i] === '--phase') {
phaseNum = args[++i];
if (!phaseNum || phaseNum.startsWith('--'))
return makeInvalidArgs('--phase', '--phase requires a value') as never;
} else if (args[i].startsWith('--phase=')) {
phaseNum = args[i].slice(8);
} else if (args[i] === '--raw') {
continue;
} else if (args[i].startsWith('--')) {
return makeInvalidArgs(args[i], `phase list-plans does not support ${args[i]}`) as never;
} else {
phaseNum = args[i];
}
}
if (!phaseNum)
return makeInvalidArgs('--phase', 'phase number required (positional or --phase N)') as never;
phase.cmdPhaseListPlans(cwd, phaseNum, raw);
return { ok: true as const, data: null };
},
},