From 562e8eb164fd440edc3a7ec2aa6ab9a7be454ece Mon Sep 17 00:00:00 2001 From: Iouri Goussev Date: Sat, 21 Mar 2026 14:04:13 -0400 Subject: [PATCH] fix: add @gsd/pi-tui to test module resolver in dist-redirect (#1811) --- .../extensions/gsd/tests/dist-redirect.mjs | 2 ++ .../integration-mixed-milestones.test.ts | 36 +++++++++++++++++-- src/tests/node-modules-symlink.test.ts | 6 ++-- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/resources/extensions/gsd/tests/dist-redirect.mjs b/src/resources/extensions/gsd/tests/dist-redirect.mjs index d6223356b..56e7d50c2 100644 --- a/src/resources/extensions/gsd/tests/dist-redirect.mjs +++ b/src/resources/extensions/gsd/tests/dist-redirect.mjs @@ -10,6 +10,8 @@ export function resolve(specifier, context, nextResolve) { specifier = new URL("packages/pi-ai/dist/index.js", ROOT).href; } else if (specifier === "@gsd/pi-agent-core") { specifier = new URL("packages/pi-agent-core/dist/index.js", ROOT).href; + } else if (specifier === "@gsd/pi-tui") { + specifier = new URL("packages/pi-tui/dist/index.js", ROOT).href; } // 2. Redirect packages/*/dist/ → packages/*/src/ with .js→.ts for strip-types else if (specifier.endsWith('.js') && (specifier.startsWith('./') || specifier.startsWith('../'))) { diff --git a/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts b/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts index ca12428c9..b5e2e8de1 100644 --- a/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +++ b/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts @@ -419,7 +419,7 @@ Built the legacy feature successfully. // Blocker: trying to dispatch M002-abc123/S02 when S01 is incomplete assertMatch( getPriorSliceCompletionBlocker(base, 'main', 'execute-task', 'M002-abc123/S02/T01') ?? '', - /dependency slice M002-abc123\/S01 is not complete/, + /M002-abc123\/S01 is not complete/, 'G5: blocks M002-abc123/S02 when S01 incomplete', ); @@ -478,9 +478,41 @@ Built the legacy feature successfully. // Check that S02 of M002-abc123 is still blocked by its own S01 assertMatch( getPriorSliceCompletionBlocker(base, 'main', 'execute-task', 'M002-abc123/S02/T01') ?? '', - /dependency slice M002-abc123\/S01 is not complete/, + /M002-abc123\/S01 is not complete/, 'G5: intra-milestone blocker still works in mixed-format context', ); + + // Positional path: S02 has no declared dependencies — blocked by positional ordering. + // Complete M002-abc123 so the guard reaches M003's intra-milestone check. + writeRoadmap(base, 'M002-abc123', `# M002-abc123: Second Feature + +**Vision:** Second + +## Slices +- [x] **S01: Done** \`risk:low\` \`depends:[]\` + > Completed +- [x] **S02: Done** \`risk:low\` \`depends:[S01]\` + > Completed +`); + writeRoadmap(base, 'M003-xyz789', `# M003-xyz789: Positional Test + +**Vision:** Positional + +## Slices +- [ ] **S01: Pending** \`risk:low\` \`depends:[]\` + > Not started +- [ ] **S02: Also Pending** \`risk:low\` \`depends:[]\` + > Not started +`); + run('git add .', base); + run('git commit -m add-m003', base); + clearPathCache(); + + assertMatch( + getPriorSliceCompletionBlocker(base, 'main', 'execute-task', 'M003-xyz789/S02/T01') ?? '', + /earlier slice M003-xyz789\/S01 is not complete/, + 'G5: positional path produces "earlier slice" message with new-format milestone ID', + ); } finally { cleanup(base); } diff --git a/src/tests/node-modules-symlink.test.ts b/src/tests/node-modules-symlink.test.ts index a3c13f4cb..4f2f2230e 100644 --- a/src/tests/node-modules-symlink.test.ts +++ b/src/tests/node-modules-symlink.test.ts @@ -1,6 +1,6 @@ import test from "node:test"; import assert from "node:assert/strict"; -import { existsSync, lstatSync, mkdirSync, mkdtempSync, readlinkSync, rmSync, symlinkSync } from "node:fs"; +import { existsSync, lstatSync, mkdirSync, mkdtempSync, readlinkSync, rmSync, symlinkSync, unlinkSync } from "node:fs"; import { join } from "node:path"; import { tmpdir } from "node:os"; @@ -69,7 +69,7 @@ test("initResources replaces a stale symlink with a correct one", async () => { const correctTarget = readlinkSync(nodeModulesPath); // Remove and replace with a stale symlink pointing to a non-existent path - rmSync(nodeModulesPath, { force: true }); + unlinkSync(nodeModulesPath); symlinkSync("/tmp/nonexistent-gsd-node-modules-" + Date.now(), nodeModulesPath); const staleTarget = readlinkSync(nodeModulesPath); @@ -98,7 +98,7 @@ test("initResources replaces symlink whose target was deleted", async () => { // Create a symlink that points to a path that doesn't exist // (simulates the case where npm upgrade moved the package location) - rmSync(nodeModulesPath, { force: true }); + unlinkSync(nodeModulesPath); const deadTarget = join(tmp, "old-install", "node_modules"); symlinkSync(deadTarget, nodeModulesPath);