gsd-pi 2.70.0 → 2.70.1-dev.3591dcf
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/loader.js +4 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +150 -2
- package/dist/resources/extensions/gsd/auto-model-selection.js +33 -19
- package/dist/resources/extensions/gsd/auto-prompts.js +7 -3
- package/dist/resources/extensions/gsd/auto-start.js +25 -1
- package/dist/resources/extensions/gsd/auto.js +12 -8
- package/dist/resources/extensions/gsd/commands-handlers.js +22 -8
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +12 -0
- package/dist/resources/extensions/gsd/doctor-format.js +2 -0
- package/dist/resources/extensions/gsd/guided-flow.js +21 -10
- package/dist/resources/extensions/gsd/pre-execution-checks.js +5 -3
- package/dist/resources/extensions/gsd/validate-directory.js +30 -12
- package/dist/resources/extensions/gsd/workflow-mcp.js +11 -0
- package/dist/resources/extensions/slash-commands/audit.js +2 -1
- package/dist/resources/extensions/subagent/isolation.js +4 -2
- package/dist/update-check.d.ts +1 -0
- package/dist/update-check.js +30 -27
- package/dist/update-cmd.js +3 -11
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +4 -4
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
- package/dist/web/standalone/.next/server/chunks/63.js +3 -3
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-f1e30ab6bb269149.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/dist/web-mode.js +4 -0
- package/package.json +11 -11
- package/packages/mcp-server/dist/workflow-tools.d.ts +2 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +35 -3
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/import-candidates.test.ts +48 -0
- package/packages/mcp-server/src/workflow-tools.ts +34 -1
- package/packages/pi-agent-core/dist/agent.d.ts +8 -0
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +3 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/src/agent.test.ts +82 -0
- package/packages/pi-agent-core/src/agent.ts +12 -0
- package/packages/pi-coding-agent/dist/core/lsp/config.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/lsp/config.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/config.js +38 -15
- package/packages/pi-coding-agent/dist/core/lsp/config.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +10 -0
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +3 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/lsp/config.ts +43 -17
- package/packages/pi-coding-agent/src/core/sdk.ts +8 -0
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +7 -5
- package/pkg/package.json +1 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +227 -2
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +172 -0
- package/src/resources/extensions/gsd/auto-model-selection.ts +39 -25
- package/src/resources/extensions/gsd/auto-prompts.ts +7 -3
- package/src/resources/extensions/gsd/auto-start.ts +34 -1
- package/src/resources/extensions/gsd/auto.ts +12 -8
- package/src/resources/extensions/gsd/commands-handlers.ts +22 -7
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +14 -0
- package/src/resources/extensions/gsd/doctor-format.ts +1 -0
- package/src/resources/extensions/gsd/doctor-types.ts +1 -0
- package/src/resources/extensions/gsd/guided-flow.ts +24 -8
- package/src/resources/extensions/gsd/pre-execution-checks.ts +6 -3
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +207 -0
- package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +48 -1
- package/src/resources/extensions/gsd/tests/resource-loader-import-path.test.ts +8 -7
- package/src/resources/extensions/gsd/tests/validate-directory.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +87 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +25 -0
- package/src/resources/extensions/gsd/validate-directory.ts +33 -11
- package/src/resources/extensions/gsd/workflow-mcp.ts +15 -0
- package/src/resources/extensions/slash-commands/audit.ts +2 -1
- package/src/resources/extensions/subagent/isolation.ts +4 -3
- package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
- /package/dist/web/standalone/.next/static/{Nl6lg7zP5dNgNBV1107v1 → KdlODhIktLmeRKpLpHdKb}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{Nl6lg7zP5dNgNBV1107v1 → KdlODhIktLmeRKpLpHdKb}/_ssgManifest.js +0 -0
|
@@ -9,10 +9,11 @@ import { deriveState, isValidationTerminal } from "../state.ts";
|
|
|
9
9
|
import { resolveExpectedArtifactPath, diagnoseExpectedArtifact } from "../auto-artifact-paths.ts";
|
|
10
10
|
import { verifyExpectedArtifact, buildLoopRemediationSteps } from "../auto-recovery.ts";
|
|
11
11
|
import { resolveDispatch, type DispatchContext } from "../auto-dispatch.ts";
|
|
12
|
-
import { buildValidateMilestonePrompt } from "../auto-prompts.ts";
|
|
12
|
+
import { buildCompleteMilestonePrompt, buildValidateMilestonePrompt } from "../auto-prompts.ts";
|
|
13
13
|
import type { GSDState } from "../types.ts";
|
|
14
14
|
import { clearPathCache } from "../paths.ts";
|
|
15
15
|
import { clearParseCache } from "../files.ts";
|
|
16
|
+
import { closeDatabase, insertMilestone, insertSlice, openDatabase } from "../gsd-db.ts";
|
|
16
17
|
|
|
17
18
|
// ─── Helpers ──────────────────────────────────────────────────────────────
|
|
18
19
|
|
|
@@ -25,9 +26,15 @@ function makeTmpBase(): string {
|
|
|
25
26
|
function cleanup(base: string): void {
|
|
26
27
|
clearPathCache();
|
|
27
28
|
clearParseCache();
|
|
29
|
+
closeDatabase();
|
|
28
30
|
try { rmSync(base, { recursive: true, force: true }); } catch { /* */ }
|
|
29
31
|
}
|
|
30
32
|
|
|
33
|
+
function openTestDb(base: string): void {
|
|
34
|
+
const dbPath = join(base, ".gsd", "gsd.db");
|
|
35
|
+
assert.equal(openDatabase(dbPath), true, "test DB should open");
|
|
36
|
+
}
|
|
37
|
+
|
|
31
38
|
function writeRoadmap(base: string, mid: string, content: string): void {
|
|
32
39
|
const dir = join(base, ".gsd", "milestones", mid);
|
|
33
40
|
mkdirSync(dir, { recursive: true });
|
|
@@ -218,6 +225,85 @@ test("buildValidateMilestonePrompt inlines ASSESSMENT evidence instead of UAT sp
|
|
|
218
225
|
}
|
|
219
226
|
});
|
|
220
227
|
|
|
228
|
+
test("buildCompleteMilestonePrompt skips skipped slices from DB-backed summary inlining", async () => {
|
|
229
|
+
const base = makeTmpBase();
|
|
230
|
+
try {
|
|
231
|
+
writeRoadmap(base, "M001", `# M001: Test Milestone
|
|
232
|
+
|
|
233
|
+
## Vision
|
|
234
|
+
Test
|
|
235
|
+
|
|
236
|
+
## Success Criteria
|
|
237
|
+
- It works
|
|
238
|
+
|
|
239
|
+
## Slices
|
|
240
|
+
|
|
241
|
+
- [x] **S01: First slice** \`risk:low\` \`depends:[]\`
|
|
242
|
+
> Done
|
|
243
|
+
- [ ] **S02: Skipped slice** \`risk:low\` \`depends:[]\`
|
|
244
|
+
> Intentionally skipped
|
|
245
|
+
|
|
246
|
+
## Boundary Map
|
|
247
|
+
|
|
248
|
+
| From | To | Produces | Consumes |
|
|
249
|
+
|------|-----|----------|----------|
|
|
250
|
+
| S01 | terminal | output | nothing |
|
|
251
|
+
`);
|
|
252
|
+
openTestDb(base);
|
|
253
|
+
insertMilestone({ id: "M001", title: "Test Milestone", status: "active" });
|
|
254
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "First slice", status: "complete", depends: [], sequence: 1 });
|
|
255
|
+
insertSlice({ id: "S02", milestoneId: "M001", title: "Skipped slice", status: "skipped", depends: [], sequence: 2 });
|
|
256
|
+
writeSliceSummary(base, "M001", "S01", "# S01 Summary\nDelivered.");
|
|
257
|
+
|
|
258
|
+
const prompt = await buildCompleteMilestonePrompt("M001", "Test Milestone", base);
|
|
259
|
+
assert.match(prompt, /S01 Summary/i, "prompt should inline non-skipped slice summaries");
|
|
260
|
+
assert.doesNotMatch(prompt, /### S02 Summary/i, "prompt should not inline skipped slice summaries");
|
|
261
|
+
assert.doesNotMatch(prompt, /not found — file does not exist yet/i, "prompt should not emit skipped-slice missing-file placeholders");
|
|
262
|
+
} finally {
|
|
263
|
+
cleanup(base);
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
test("buildValidateMilestonePrompt skips skipped slices from DB-backed summary inlining", async () => {
|
|
268
|
+
const base = makeTmpBase();
|
|
269
|
+
try {
|
|
270
|
+
writeRoadmap(base, "M001", `# M001: Test Milestone
|
|
271
|
+
|
|
272
|
+
## Vision
|
|
273
|
+
Test
|
|
274
|
+
|
|
275
|
+
## Success Criteria
|
|
276
|
+
- It works
|
|
277
|
+
|
|
278
|
+
## Slices
|
|
279
|
+
|
|
280
|
+
- [x] **S01: First slice** \`risk:low\` \`depends:[]\`
|
|
281
|
+
> Done
|
|
282
|
+
- [ ] **S02: Skipped slice** \`risk:low\` \`depends:[]\`
|
|
283
|
+
> Intentionally skipped
|
|
284
|
+
|
|
285
|
+
## Boundary Map
|
|
286
|
+
|
|
287
|
+
| From | To | Produces | Consumes |
|
|
288
|
+
|------|-----|----------|----------|
|
|
289
|
+
| S01 | terminal | output | nothing |
|
|
290
|
+
`);
|
|
291
|
+
openTestDb(base);
|
|
292
|
+
insertMilestone({ id: "M001", title: "Test Milestone", status: "active" });
|
|
293
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "First slice", status: "complete", depends: [], sequence: 1 });
|
|
294
|
+
insertSlice({ id: "S02", milestoneId: "M001", title: "Skipped slice", status: "skipped", depends: [], sequence: 2 });
|
|
295
|
+
writeSliceSummary(base, "M001", "S01", "# S01 Summary\nDelivered.");
|
|
296
|
+
writeSliceAssessment(base, "M001", "S01", "---\nverdict: PASS\n---\n# Assessment\nEvidence captured.");
|
|
297
|
+
|
|
298
|
+
const prompt = await buildValidateMilestonePrompt("M001", "Test Milestone", base);
|
|
299
|
+
assert.match(prompt, /S01 Summary/i, "prompt should inline non-skipped slice summaries");
|
|
300
|
+
assert.doesNotMatch(prompt, /### S02 Summary/i, "prompt should not inline skipped slice summaries");
|
|
301
|
+
assert.doesNotMatch(prompt, /not found — file does not exist yet/i, "prompt should not emit skipped-slice missing-file placeholders");
|
|
302
|
+
} finally {
|
|
303
|
+
cleanup(base);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
|
|
221
307
|
// ─── Dispatch rule ────────────────────────────────────────────────────────
|
|
222
308
|
|
|
223
309
|
test("dispatch rule matches validating-milestone phase", async () => {
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
getWorkflowTransportSupportError,
|
|
14
14
|
getRequiredWorkflowToolsForAutoUnit,
|
|
15
15
|
getRequiredWorkflowToolsForGuidedUnit,
|
|
16
|
+
supportsStructuredQuestions,
|
|
16
17
|
usesWorkflowMcpTransport,
|
|
17
18
|
} from "../workflow-mcp.ts";
|
|
18
19
|
|
|
@@ -291,6 +292,30 @@ test("usesWorkflowMcpTransport matches local externalCli providers", () => {
|
|
|
291
292
|
assert.equal(usesWorkflowMcpTransport("oauth", "local://custom"), false);
|
|
292
293
|
});
|
|
293
294
|
|
|
295
|
+
test("supportsStructuredQuestions disables structured ask flow on workflow MCP transports", () => {
|
|
296
|
+
assert.equal(
|
|
297
|
+
supportsStructuredQuestions(["ask_user_questions"], {
|
|
298
|
+
authMode: "externalCli",
|
|
299
|
+
baseUrl: "local://claude-code",
|
|
300
|
+
}),
|
|
301
|
+
false,
|
|
302
|
+
);
|
|
303
|
+
assert.equal(
|
|
304
|
+
supportsStructuredQuestions(["ask_user_questions"], {
|
|
305
|
+
authMode: "oauth",
|
|
306
|
+
baseUrl: "https://api.anthropic.com",
|
|
307
|
+
}),
|
|
308
|
+
true,
|
|
309
|
+
);
|
|
310
|
+
assert.equal(
|
|
311
|
+
supportsStructuredQuestions([], {
|
|
312
|
+
authMode: "oauth",
|
|
313
|
+
baseUrl: "https://api.anthropic.com",
|
|
314
|
+
}),
|
|
315
|
+
false,
|
|
316
|
+
);
|
|
317
|
+
});
|
|
318
|
+
|
|
294
319
|
test("transport compatibility passes when required tools fit current MCP surface", () => {
|
|
295
320
|
const error = getWorkflowTransportSupportError(
|
|
296
321
|
"claude-code",
|
|
@@ -61,6 +61,33 @@ const WINDOWS_BLOCKED_PATHS = new Set([
|
|
|
61
61
|
"C:\\Program Files (x86)",
|
|
62
62
|
]);
|
|
63
63
|
|
|
64
|
+
const WINDOWS_BLOCKED_SUFFIXES = new Set([
|
|
65
|
+
"\\",
|
|
66
|
+
"\\windows",
|
|
67
|
+
"\\windows\\system32",
|
|
68
|
+
"\\program files",
|
|
69
|
+
"\\program files (x86)",
|
|
70
|
+
]);
|
|
71
|
+
|
|
72
|
+
function normalizePathForComparison(dirPath: string): string {
|
|
73
|
+
let normalized = dirPath.replace(/[/\\]+$/, "");
|
|
74
|
+
if (normalized === "") {
|
|
75
|
+
normalized = "/";
|
|
76
|
+
} else if (/^[A-Za-z]:$/.test(normalized)) {
|
|
77
|
+
normalized += "\\";
|
|
78
|
+
}
|
|
79
|
+
return platform() === "win32" ? normalized.toLowerCase() : normalized;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function isBlockedWindowsPath(normalized: string): boolean {
|
|
83
|
+
if (!/^[a-z]:\\/.test(normalized)) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const suffix = normalized.slice(2);
|
|
88
|
+
return WINDOWS_BLOCKED_SUFFIXES.has(suffix);
|
|
89
|
+
}
|
|
90
|
+
|
|
64
91
|
// ─── Core Validation ────────────────────────────────────────────────────────────
|
|
65
92
|
|
|
66
93
|
/**
|
|
@@ -84,16 +111,11 @@ export function validateDirectory(dirPath: string): DirectoryValidationResult {
|
|
|
84
111
|
|
|
85
112
|
// Normalize trailing slashes for consistent comparison.
|
|
86
113
|
// Special cases: "/" → "/" (not ""), "C:\" → "C:\" (not "C:")
|
|
87
|
-
|
|
88
|
-
if (normalized === "") {
|
|
89
|
-
normalized = "/";
|
|
90
|
-
} else if (/^[A-Za-z]:$/.test(normalized)) {
|
|
91
|
-
normalized = normalized + "\\";
|
|
92
|
-
}
|
|
114
|
+
const normalized = normalizePathForComparison(resolved);
|
|
93
115
|
|
|
94
116
|
// ── Check 1: Blocked system paths ──────────────────────────────────────
|
|
95
117
|
const blockedPaths = platform() === "win32" ? WINDOWS_BLOCKED_PATHS : UNIX_BLOCKED_PATHS;
|
|
96
|
-
if (blockedPaths.has(normalized)) {
|
|
118
|
+
if (platform() === "win32" ? isBlockedWindowsPath(normalized) : blockedPaths.has(normalized)) {
|
|
97
119
|
return {
|
|
98
120
|
safe: false,
|
|
99
121
|
severity: "blocked",
|
|
@@ -104,9 +126,9 @@ export function validateDirectory(dirPath: string): DirectoryValidationResult {
|
|
|
104
126
|
// ── Check 2: Home directory itself (not subdirs) ───────────────────────
|
|
105
127
|
let resolvedHome: string;
|
|
106
128
|
try {
|
|
107
|
-
resolvedHome = realpathSync(resolve(homedir()))
|
|
129
|
+
resolvedHome = normalizePathForComparison(realpathSync(resolve(homedir())));
|
|
108
130
|
} catch {
|
|
109
|
-
resolvedHome = resolve(homedir())
|
|
131
|
+
resolvedHome = normalizePathForComparison(resolve(homedir()));
|
|
110
132
|
}
|
|
111
133
|
|
|
112
134
|
if (normalized === resolvedHome) {
|
|
@@ -120,9 +142,9 @@ export function validateDirectory(dirPath: string): DirectoryValidationResult {
|
|
|
120
142
|
// ── Check 3: Temp directory root ───────────────────────────────────────
|
|
121
143
|
let resolvedTmp: string;
|
|
122
144
|
try {
|
|
123
|
-
resolvedTmp = realpathSync(resolve(tmpdir()))
|
|
145
|
+
resolvedTmp = normalizePathForComparison(realpathSync(resolve(tmpdir())));
|
|
124
146
|
} catch {
|
|
125
|
-
resolvedTmp = resolve(tmpdir())
|
|
147
|
+
resolvedTmp = normalizePathForComparison(resolve(tmpdir()));
|
|
126
148
|
}
|
|
127
149
|
|
|
128
150
|
if (normalized === resolvedTmp) {
|
|
@@ -348,6 +348,21 @@ export function usesWorkflowMcpTransport(
|
|
|
348
348
|
return authMode === "externalCli" && typeof baseUrl === "string" && baseUrl.startsWith("local://");
|
|
349
349
|
}
|
|
350
350
|
|
|
351
|
+
export function supportsStructuredQuestions(
|
|
352
|
+
activeTools: string[],
|
|
353
|
+
options: Pick<WorkflowCapabilityOptions, "authMode" | "baseUrl"> = {},
|
|
354
|
+
): boolean {
|
|
355
|
+
if (!activeTools.includes("ask_user_questions")) return false;
|
|
356
|
+
|
|
357
|
+
// Workflow MCP currently exposes ask_user_questions via MCP form elicitation.
|
|
358
|
+
// Local external CLI transports such as Claude Code can invoke the tool, but
|
|
359
|
+
// do not reliably complete that elicitation round-trip yet, so guided discuss
|
|
360
|
+
// prompts must fall back to plain-text questioning.
|
|
361
|
+
if (usesWorkflowMcpTransport(options.authMode, options.baseUrl)) return false;
|
|
362
|
+
|
|
363
|
+
return true;
|
|
364
|
+
}
|
|
365
|
+
|
|
351
366
|
export function getWorkflowTransportSupportError(
|
|
352
367
|
provider: string | undefined,
|
|
353
368
|
requiredTools: string[],
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ExtensionAPI, ExtensionCommandContext } from "@gsd/pi-coding-agent";
|
|
2
|
+
import { mkdirSync } from "node:fs";
|
|
2
3
|
|
|
3
4
|
export default function auditCommand(pi: ExtensionAPI) {
|
|
4
5
|
pi.registerCommand("audit", {
|
|
@@ -39,7 +40,7 @@ export default function auditCommand(pi: ExtensionAPI) {
|
|
|
39
40
|
|
|
40
41
|
// ── Step 3: Ensure the output directory exists ───────────────────────
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
mkdirSync(".gsd/audits", { recursive: true });
|
|
43
44
|
|
|
44
45
|
// ── Step 4: Send the audit prompt to the agent ───────────────────────
|
|
45
46
|
|
|
@@ -53,8 +53,10 @@ interface Baseline {
|
|
|
53
53
|
// Directory helpers
|
|
54
54
|
// ============================================================================
|
|
55
55
|
|
|
56
|
-
function encodeCwd(cwd: string): string {
|
|
57
|
-
|
|
56
|
+
export function encodeCwd(cwd: string): string {
|
|
57
|
+
// Encode the entire cwd so Windows drive letters, separators, and UNC
|
|
58
|
+
// prefixes cannot leak into the isolation path.
|
|
59
|
+
return Buffer.from(cwd, "utf8").toString("base64url");
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
const gsdHome = process.env.GSD_HOME || path.join(os.homedir(), ".gsd");
|
|
@@ -500,4 +502,3 @@ export function readIsolationMode(): IsolationMode {
|
|
|
500
502
|
return "none";
|
|
501
503
|
}
|
|
502
504
|
}
|
|
503
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[8974],{5214:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"workAsyncStorage",{enumerable:!0,get:function(){return r.workAsyncStorageInstance}});let r=n(17828)},15726:(e,t,n)=>{Promise.resolve().then(n.bind(n,66919))},17828:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"workAsyncStorageInstance",{enumerable:!0,get:function(){return r}});let r=(0,n(64054).createAsyncLocalStorage)()},21957:(e,t,n)=>{"use strict";function r({moduleIds:e}){return null}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"PreloadChunks",{enumerable:!0,get:function(){return r}}),n(95155),n(47650),n(5214),n(2451),n(53887)},37206:(e,t,n)=>{"use strict";n.d(t,{default:()=>u.a});var r=n(75707),u=n.n(r)},41112:(e,t,n)=>{"use strict";function r({reason:e,children:t}){return t}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"BailoutToCSR",{enumerable:!0,get:function(){return r}}),n(1980)},64054:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n={bindSnapshot:function(){return s},createAsyncLocalStorage:function(){return a},createSnapshot:function(){return i}};for(var r in n)Object.defineProperty(t,r,{enumerable:!0,get:n[r]});let u=Object.defineProperty(Error("Invariant: AsyncLocalStorage accessed in runtime where it is not available"),"__NEXT_ERROR_CODE",{value:"E504",enumerable:!1,configurable:!0});class l{disable(){throw u}getStore(){}run(){throw u}exit(){throw u}enterWith(){throw u}static bind(e){return e}}let o="u">typeof globalThis&&globalThis.AsyncLocalStorage;function a(){return o?new o:new l}function s(e){return o?o.bind(e):l.bind(e)}function i(){return o?o.snapshot():function(e,...t){return e(...t)}}},66919:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>l});var r=n(95155);let u=(0,n(37206).default)(()=>Promise.all([n.e(1838),n.e(6079),n.e(4986),n.e(2008),n.e(2826)]).then(n.bind(n,62826)).then(e=>e.GSDAppShell),{loadableGenerated:{webpack:()=>[62826]},ssr:!1,loading:()=>(0,r.jsx)("div",{className:"flex h-screen items-center justify-center bg-background text-sm text-muted-foreground",children:"Loading workspace…"})});function l(){return(0,r.jsx)(u,{})}},68635:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return s}});let r=n(95155),u=n(12115),l=n(41112);function o(e){return{default:e&&"default"in e?e.default:e}}n(21957);let a={loader:()=>Promise.resolve(o(()=>null)),loading:null,ssr:!0},s=function(e){let t={...a,...e},n=(0,u.lazy)(()=>t.loader().then(o)),s=t.loading;function i(e){let o=s?(0,r.jsx)(s,{isLoading:!0,pastDelay:!0,error:null}):null,a=!t.ssr||!!t.loading,i=a?u.Suspense:u.Fragment,c=t.ssr?(0,r.jsxs)(r.Fragment,{children:[null,(0,r.jsx)(n,{...e})]}):(0,r.jsx)(l.BailoutToCSR,{reason:"next/dynamic",children:(0,r.jsx)(n,{...e})});return(0,r.jsx)(i,{...a?{fallback:o}:{},children:c})}return i.displayName="LoadableComponent",i}},75707:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return u}});let r=n(73623)._(n(68635));function u(e,t){let n={};"function"==typeof e&&(n.loader=e);let u={...n,...t};return(0,r.default)({...u,modules:u.loadableGenerated?.modules})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=15726)),_N_E=e.O()}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[7358],{2852:(e,s,n)=>{Promise.resolve().then(n.t.bind(n,27123,23)),Promise.resolve().then(n.t.bind(n,61304,23)),Promise.resolve().then(n.t.bind(n,78616,23)),Promise.resolve().then(n.t.bind(n,64777,23)),Promise.resolve().then(n.t.bind(n,57121,23)),Promise.resolve().then(n.t.bind(n,74581,23)),Promise.resolve().then(n.t.bind(n,90484,23)),Promise.resolve().then(n.bind(n,86869))},19393:()=>{}},e=>{var s=s=>e(e.s=s);e.O(0,[8441,3794],()=>(s(83861),s(2852))),_N_E=e.O()}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[9337],{52560:(e,s,_)=>{Promise.resolve().then(_.t.bind(_,27123,23))}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=52560)),_N_E=e.O()}]);
|
|
File without changes
|
|
File without changes
|