* fix(#1140): implement state add-roadmap-evolution CJS handler `query state.add-roadmap-evolution` was unreachable: the CJS state router listed it in the `unsupported` map with a circular message ("...is SDK-only. Use: gsd-tools query state.add-roadmap-evolution ...") and no CJS handler existed after the SDK retirement (ADR-0174). Every `/gsd:phase insert` and `/gsd:phase --edit` run hit a dead end recording Roadmap Evolution. Re-implement `cmdStateAddRoadmapEvolution` in CJS (src/state.cts) and wire it into the state router; remove the now-stale `unsupported` entry. The handler appends a single-line bullet under `## Accumulated Context` → `### Roadmap Evolution` (creating the subsection/section if missing, deduping identical entries), scoping every lookup to the Accumulated Context body so a decoy heading in an unrelated section is never targeted, and flattening multiline notes to a single bullet. Section-boundary regexes mirror the sibling add-decision/add-blocker handlers and preserve following sections on CRLF input. Regression cases live in tests/state.test.cjs (per the no-new-bug-NNNN-files policy) and cover the literal issue repro plus the CLI/parser QA matrix (missing/empty/whitespace note, flag-shaped value, duplicate flags, hostile shell metacharacters, Unicode, decoy section, CRLF, missing STATE.md). Closes #1140 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(#1140): backfill changeset PR number (1148) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -40,6 +40,7 @@ interface StateModule {
|
||||
cmdStateUpdateProgress(cwd: string, raw: boolean): void;
|
||||
cmdStateAddDecision(cwd: string, opts: Record<string, string | null | undefined>, raw: boolean): void;
|
||||
cmdStateAddBlocker(cwd: string, opts: Record<string, string | null | undefined>, raw: boolean): void;
|
||||
cmdStateAddRoadmapEvolution(cwd: string, opts: Record<string, string | boolean | null | undefined>, raw: boolean): void;
|
||||
cmdStateResolveBlocker(cwd: string, text: string | null | undefined, raw: boolean): void;
|
||||
cmdStateRecordSession(cwd: string, opts: Record<string, string | null | undefined>, raw: boolean): void;
|
||||
cmdStateBeginPhase(cwd: string, phase: string | null | undefined, name: string | null | undefined, plans: number | null, raw: boolean): void;
|
||||
@@ -78,9 +79,10 @@ function routeStateCommand({ state, args, cwd, raw, error }: RouteStateCommandOp
|
||||
args,
|
||||
subcommands: ['load', 'complete-phase', ...STATE_SUBCOMMANDS.filter((s) => s !== 'load')],
|
||||
defaultSubcommand: 'load',
|
||||
unsupported: {
|
||||
'add-roadmap-evolution': 'state add-roadmap-evolution is SDK-only. Use: gsd-tools query state.add-roadmap-evolution ...',
|
||||
},
|
||||
// No SDK-only state subcommands remain: add-roadmap-evolution was the last
|
||||
// holdout after the SDK retirement (ADR-0174) and is now implemented in CJS
|
||||
// (handler below). See #1140.
|
||||
unsupported: {},
|
||||
error,
|
||||
cwd,
|
||||
raw,
|
||||
@@ -147,6 +149,17 @@ function routeStateCommand({ state, args, cwd, raw, error }: RouteStateCommandOp
|
||||
const a = parseNamedArgs(args, ['text', 'text-file']);
|
||||
state.cmdStateAddBlocker(cwd, { text: strArg(a, 'text'), text_file: strArg(a, 'text-file') }, raw);
|
||||
},
|
||||
'add-roadmap-evolution': () => {
|
||||
const a = parseNamedArgs(args, ['phase', 'action', 'after', 'note', 'note-file'], ['urgent']);
|
||||
state.cmdStateAddRoadmapEvolution(cwd, {
|
||||
phase: strArg(a, 'phase'),
|
||||
action: strArg(a, 'action'),
|
||||
after: strArg(a, 'after'),
|
||||
note: strArg(a, 'note'),
|
||||
note_file: strArg(a, 'note-file'),
|
||||
urgent: a['urgent'] === true,
|
||||
}, raw);
|
||||
},
|
||||
'resolve-blocker': () => state.cmdStateResolveBlocker(cwd, strArg(parseNamedArgs(args, ['text']), 'text'), raw),
|
||||
'record-session': () => {
|
||||
const a = parseNamedArgs(args, ['stopped-at', 'resume-file']);
|
||||
|
||||
Reference in New Issue
Block a user