From 7b014e13fb0cea9344f0e66bb59f559d20087a5a Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Mon, 16 Mar 2026 15:25:58 -0400 Subject: [PATCH] fix: support fractional slice IDs (e.g. S03.5) in roadmap parser (#681) The roadmap parser regex used (\w+) to capture slice/task IDs, which only matches [a-zA-Z0-9_]. Fractional IDs like S03.5 (created by /gsd steer) contain a dot, causing the parser to skip the entire line. The dispatcher then jumps from S03 to S04, finds S04 blocked by the unparsed S03.5, and gives up with 'earlier slice is not complete'. Update the ID capture group to ([\w.]+) in both: - roadmap-slices.ts (primary roadmap parser) - files.ts (plan task parser, for consistency) This allows dots in slice/task IDs while preserving all existing behavior for standard IDs like S01, S02, T01, etc. Closes #681 --- src/resources/extensions/gsd/files.ts | 2 +- src/resources/extensions/gsd/roadmap-slices.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/resources/extensions/gsd/files.ts b/src/resources/extensions/gsd/files.ts index ef8391a00..0edbd87e8 100644 --- a/src/resources/extensions/gsd/files.ts +++ b/src/resources/extensions/gsd/files.ts @@ -436,7 +436,7 @@ function _parsePlanImpl(content: string): SlicePlan { let currentTask: TaskPlanEntry | null = null; for (const line of taskLines) { - const cbMatch = line.match(/^-\s+\[([ xX])\]\s+\*\*(\w+):\s+(.+?)\*\*\s*(.*)/); + const cbMatch = line.match(/^-\s+\[([ xX])\]\s+\*\*([\w.]+):\s+(.+?)\*\*\s*(.*)/); if (cbMatch) { if (currentTask) tasks.push(currentTask); diff --git a/src/resources/extensions/gsd/roadmap-slices.ts b/src/resources/extensions/gsd/roadmap-slices.ts index e03e9d72c..2da593198 100644 --- a/src/resources/extensions/gsd/roadmap-slices.ts +++ b/src/resources/extensions/gsd/roadmap-slices.ts @@ -19,7 +19,7 @@ export function parseRoadmapSlices(content: string): RoadmapSliceEntry[] { let currentSlice: RoadmapSliceEntry | null = null; for (const line of checkboxItems) { - const cbMatch = line.match(/^\s*-\s+\[([ xX])\]\s+\*\*(\w+):\s+(.+?)\*\*\s*(.*)/); + const cbMatch = line.match(/^\s*-\s+\[([ xX])\]\s+\*\*([\w.]+):\s+(.+?)\*\*\s*(.*)/); if (cbMatch) { if (currentSlice) slices.push(currentSlice);