* test(#4257): W002 harvest precision + workstream-scoped warning regression rows Tests-only RED commit: A-rows pin the command-mention/code-span harvest precision on statePhaseTokens, B-rows drive W002 under root and workstream scope (scope clause asserted, root grammar byte-identical), C-rows pin the additive workstream snapshot field. All fail on next; fix follows. * fix(#4257): harvest only prose phase references; W002 names its workstream scope Sub-defect (a): the statePhaseTokens harvest was the verbatim #3309 relocation of verify.cts's unanchored, markdown-blind scan ([Pp]hase\s+(TOKEN) over the raw file), so GSD's own command names (/gsd-execute-phase 5, bare or quoted) and any token inside a code span/fenced block were harvested as phase references and fired W002 on ledger rows. Now strips fenced blocks then inline spans via the canonical markdown-sectionizer seam (#2365 composition order) and matches with a left word boundary (?<![-\w]) so hyphen- or word-suffixed carriers are mentions, not references. Pinned tradeoff: a genuine reference written in backticks stops counting (a quoted literal is not a reference). Sub-defect (b): the valid set is workstream-scoped by construction (planningPaths under GSD_WORKSTREAM; per-workstream numbering is deliberate), but the message claimed 'only phases 1, 2 are declared' unqualified. New additive PlanningSnapshot.workstream field, sourced from planning-workspace's new resolveEnvWorkstream() — the ONE env discriminator planningDir itself applies — so the clause cannot disagree with the base the reads used. Root scope keeps the byte-identical message; the checker's scope is unchanged. * test(#4257): close the B2 quoted-literal code span (fixture typo) The B2 fixture wrote a single opening backtick — an unterminated span is literal text per CommonMark, so its content is prose and W002 correctly fired on it. The test's name, the A3 snapshot-level twin, and the B2 matrix row all intend a closed span; pre-fix this was indistinguishable because the unanchored harvest fired either way. * chore(#4257): changeset fragment (pr number to backfill) * chore(#4257): backfill PR number in changeset --------- Co-authored-by: sim <sim@local>
This commit is contained in:
@@ -125,9 +125,26 @@ const PLANNING_LOCK_RETRY_ERRNOS = new Set([
|
||||
// compatible with the structural type the store expects.
|
||||
type WorkstreamAdapterOpts = Record<string, unknown>;
|
||||
|
||||
/**
|
||||
* #4257: the ONE owner of the env workstream discriminator `planningDir`
|
||||
* itself applies when handed no `ws` argument. `planningPaths(cwd)` — and
|
||||
* therefore every workstream-scoped `PlanningSnapshot` read — resolves its
|
||||
* base through exactly this read, and the CLI bootstrap has already folded
|
||||
* the stored active-workstream pointer into the env by the time any
|
||||
* diagnostic runs (`resolveActiveWorkstream` → `applyResolvedWorkstreamEnv`,
|
||||
* `active-workstream-store.cjs`). Exposed so a consumer that needs to NAME
|
||||
* the scope those reads used (W002's warning message, via the snapshot's
|
||||
* `workstream` field) derives it from the same resolution point instead of
|
||||
* growing a second env read site that can drift (the #612 PR-2
|
||||
* two-readers-two-bases lesson).
|
||||
*/
|
||||
function resolveEnvWorkstream(): string | null {
|
||||
return process.env['GSD_WORKSTREAM'] ?? null;
|
||||
}
|
||||
|
||||
function planningDir(cwd: string, ws?: string | null, project?: string | null): string {
|
||||
if (project === undefined) project = process.env['GSD_PROJECT'] ?? null;
|
||||
if (ws === undefined) ws = process.env['GSD_WORKSTREAM'] ?? null;
|
||||
if (ws === undefined) ws = resolveEnvWorkstream();
|
||||
|
||||
// Reject path separators and traversal components in project/workstream names
|
||||
const BAD_SEGMENT = /[/\\]|\.\./;
|
||||
@@ -667,6 +684,7 @@ export = {
|
||||
createMemoryPointerAdapter,
|
||||
planningDir,
|
||||
planningRoot,
|
||||
resolveEnvWorkstream,
|
||||
resolvePhaseIdConvention,
|
||||
listAvailableWorkstreams,
|
||||
planningPaths,
|
||||
|
||||
Reference in New Issue
Block a user