gsd-pi 2.18.0 → 2.20.0
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/README.md +5 -1
- package/dist/cli.js +3 -3
- package/dist/onboarding.d.ts +3 -1
- package/dist/onboarding.js +77 -3
- package/dist/remote-questions-config.d.ts +1 -1
- package/dist/resources/extensions/google-search/index.ts +164 -47
- package/dist/resources/extensions/gsd/auto-dashboard.ts +14 -2
- package/dist/resources/extensions/gsd/auto-prompts.ts +148 -39
- package/dist/resources/extensions/gsd/auto-worktree.ts +93 -9
- package/dist/resources/extensions/gsd/auto.ts +690 -39
- package/dist/resources/extensions/gsd/captures.ts +384 -0
- package/dist/resources/extensions/gsd/commands.ts +654 -36
- package/dist/resources/extensions/gsd/complexity-classifier.ts +322 -0
- package/dist/resources/extensions/gsd/context-budget.ts +243 -0
- package/dist/resources/extensions/gsd/context-store.ts +195 -0
- package/dist/resources/extensions/gsd/dashboard-overlay.ts +51 -3
- package/dist/resources/extensions/gsd/db-writer.ts +341 -0
- package/dist/resources/extensions/gsd/debug-logger.ts +178 -0
- package/dist/resources/extensions/gsd/dispatch-guard.ts +0 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +54 -0
- package/dist/resources/extensions/gsd/doctor-proactive.ts +286 -0
- package/dist/resources/extensions/gsd/doctor.ts +283 -2
- package/dist/resources/extensions/gsd/export.ts +81 -2
- package/dist/resources/extensions/gsd/files.ts +39 -9
- package/dist/resources/extensions/gsd/git-service.ts +6 -0
- package/dist/resources/extensions/gsd/gsd-db.ts +752 -0
- package/dist/resources/extensions/gsd/guided-flow.ts +26 -1
- package/dist/resources/extensions/gsd/history.ts +0 -1
- package/dist/resources/extensions/gsd/index.ts +277 -1
- package/dist/resources/extensions/gsd/md-importer.ts +526 -0
- package/dist/resources/extensions/gsd/metrics.ts +84 -0
- package/dist/resources/extensions/gsd/model-cost-table.ts +65 -0
- package/dist/resources/extensions/gsd/model-router.ts +256 -0
- package/dist/resources/extensions/gsd/notifications.ts +0 -1
- package/dist/resources/extensions/gsd/post-unit-hooks.ts +72 -2
- package/dist/resources/extensions/gsd/preferences.ts +198 -150
- package/dist/resources/extensions/gsd/prompt-loader.ts +45 -9
- package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -5
- package/dist/resources/extensions/gsd/prompts/heal-skill.md +45 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +5 -1
- package/dist/resources/extensions/gsd/prompts/quick-task.md +48 -0
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -0
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +8 -0
- package/dist/resources/extensions/gsd/prompts/system.md +2 -1
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +62 -0
- package/dist/resources/extensions/gsd/quick.ts +156 -0
- package/dist/resources/extensions/gsd/skill-discovery.ts +5 -3
- package/dist/resources/extensions/gsd/skill-health.ts +417 -0
- package/dist/resources/extensions/gsd/skill-telemetry.ts +127 -0
- package/dist/resources/extensions/gsd/state.ts +30 -0
- package/dist/resources/extensions/gsd/templates/preferences.md +1 -0
- package/dist/resources/extensions/gsd/tests/captures.test.ts +438 -0
- package/dist/resources/extensions/gsd/tests/complexity-classifier.test.ts +181 -0
- package/dist/resources/extensions/gsd/tests/context-budget.test.ts +283 -0
- package/dist/resources/extensions/gsd/tests/context-compression.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/context-store.test.ts +462 -0
- package/dist/resources/extensions/gsd/tests/continue-here.test.ts +204 -0
- package/dist/resources/extensions/gsd/tests/dashboard-budget.test.ts +346 -0
- package/dist/resources/extensions/gsd/tests/db-writer.test.ts +602 -0
- package/dist/resources/extensions/gsd/tests/debug-logger.test.ts +185 -0
- package/dist/resources/extensions/gsd/tests/derive-state-db.test.ts +406 -0
- package/dist/resources/extensions/gsd/tests/dispatch-guard.test.ts +0 -1
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +22 -0
- package/dist/resources/extensions/gsd/tests/doctor-proactive.test.ts +244 -0
- package/dist/resources/extensions/gsd/tests/doctor-runtime.test.ts +303 -0
- package/dist/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +434 -0
- package/dist/resources/extensions/gsd/tests/gsd-db.test.ts +353 -0
- package/dist/resources/extensions/gsd/tests/gsd-inspect.test.ts +125 -0
- package/dist/resources/extensions/gsd/tests/gsd-tools.test.ts +326 -0
- package/dist/resources/extensions/gsd/tests/integration-edge.test.ts +228 -0
- package/dist/resources/extensions/gsd/tests/integration-lifecycle.test.ts +277 -0
- package/dist/resources/extensions/gsd/tests/md-importer.test.ts +411 -0
- package/dist/resources/extensions/gsd/tests/metrics.test.ts +197 -0
- package/dist/resources/extensions/gsd/tests/milestone-transition-worktree.test.ts +144 -0
- package/dist/resources/extensions/gsd/tests/model-cost-table.test.ts +69 -0
- package/dist/resources/extensions/gsd/tests/model-isolation.test.ts +99 -0
- package/dist/resources/extensions/gsd/tests/model-router.test.ts +167 -0
- package/dist/resources/extensions/gsd/tests/parsers.test.ts +40 -0
- package/dist/resources/extensions/gsd/tests/post-unit-hooks.test.ts +41 -1
- package/dist/resources/extensions/gsd/tests/preferences-git.test.ts +0 -1
- package/dist/resources/extensions/gsd/tests/preferences-hooks.test.ts +0 -1
- package/dist/resources/extensions/gsd/tests/preferences-mode.test.ts +110 -0
- package/dist/resources/extensions/gsd/tests/preferences-models.test.ts +0 -1
- package/dist/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +464 -0
- package/dist/resources/extensions/gsd/tests/prompt-db.test.ts +385 -0
- package/dist/resources/extensions/gsd/tests/remote-questions.test.ts +488 -1
- package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +17 -29
- package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +2 -8
- package/dist/resources/extensions/gsd/tests/routing-history.test.ts +215 -62
- package/dist/resources/extensions/gsd/tests/skill-lifecycle.test.ts +126 -0
- package/dist/resources/extensions/gsd/tests/stop-auto-remote.test.ts +31 -8
- package/dist/resources/extensions/gsd/tests/token-savings.test.ts +366 -0
- package/dist/resources/extensions/gsd/tests/triage-dispatch.test.ts +224 -0
- package/dist/resources/extensions/gsd/tests/triage-resolution.test.ts +215 -0
- package/dist/resources/extensions/gsd/tests/unit-runtime.test.ts +25 -1
- package/dist/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +145 -0
- package/dist/resources/extensions/gsd/tests/visualizer-data.test.ts +290 -0
- package/dist/resources/extensions/gsd/tests/visualizer-overlay.test.ts +120 -0
- package/dist/resources/extensions/gsd/tests/visualizer-views.test.ts +478 -0
- package/dist/resources/extensions/gsd/tests/worktree-db-integration.test.ts +205 -0
- package/dist/resources/extensions/gsd/tests/worktree-db.test.ts +442 -0
- package/dist/resources/extensions/gsd/tests/worktree-post-create-hook.test.ts +165 -0
- package/dist/resources/extensions/gsd/triage-resolution.ts +200 -0
- package/dist/resources/extensions/gsd/triage-ui.ts +175 -0
- package/dist/resources/extensions/gsd/types.ts +29 -0
- package/dist/resources/extensions/gsd/undo.ts +0 -1
- package/dist/resources/extensions/gsd/unit-runtime.ts +5 -1
- package/dist/resources/extensions/gsd/visualizer-data.ts +505 -0
- package/dist/resources/extensions/gsd/visualizer-overlay.ts +337 -0
- package/dist/resources/extensions/gsd/visualizer-views.ts +755 -0
- package/dist/resources/extensions/gsd/worktree-command.ts +18 -0
- package/dist/resources/extensions/gsd/worktree-manager.ts +11 -4
- package/dist/resources/extensions/remote-questions/config.ts +4 -2
- package/dist/resources/extensions/remote-questions/discord-adapter.ts +35 -4
- package/dist/resources/extensions/remote-questions/format.ts +166 -14
- package/dist/resources/extensions/remote-questions/manager.ts +14 -4
- package/dist/resources/extensions/remote-questions/remote-command.ts +100 -4
- package/dist/resources/extensions/remote-questions/slack-adapter.ts +58 -2
- package/dist/resources/extensions/remote-questions/telegram-adapter.ts +161 -0
- package/dist/resources/extensions/remote-questions/types.ts +2 -1
- package/dist/resources/extensions/ttsr/ttsr-manager.ts +26 -0
- package/dist/resources/extensions/voice/index.ts +4 -3
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +12 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.js +25 -0
- package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.js +106 -3
- package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lsp.md +6 -0
- package/packages/pi-coding-agent/dist/core/lsp/types.d.ts +35 -0
- package/packages/pi-coding-agent/dist/core/lsp/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/types.js +6 -0
- package/packages/pi-coding-agent/dist/core/lsp/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/utils.d.ts +3 -1
- package/packages/pi-coding-agent/dist/core/lsp/utils.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/utils.js +45 -0
- package/packages/pi-coding-agent/dist/core/lsp/utils.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +43 -11
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +7 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js +5 -0
- package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js +5 -0
- package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +13 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +6 -0
- package/packages/pi-coding-agent/src/core/lsp/client.ts +26 -0
- package/packages/pi-coding-agent/src/core/lsp/index.ts +157 -2
- package/packages/pi-coding-agent/src/core/lsp/lsp.md +6 -0
- package/packages/pi-coding-agent/src/core/lsp/types.ts +53 -0
- package/packages/pi-coding-agent/src/core/lsp/utils.ts +56 -0
- package/packages/pi-coding-agent/src/core/settings-manager.ts +41 -11
- package/packages/pi-coding-agent/src/core/system-prompt.ts +7 -1
- package/packages/pi-coding-agent/src/core/tools/edit.ts +3 -0
- package/packages/pi-coding-agent/src/core/tools/write.ts +3 -0
- package/src/resources/extensions/google-search/index.ts +164 -47
- package/src/resources/extensions/gsd/auto-dashboard.ts +14 -2
- package/src/resources/extensions/gsd/auto-prompts.ts +148 -39
- package/src/resources/extensions/gsd/auto-worktree.ts +93 -9
- package/src/resources/extensions/gsd/auto.ts +690 -39
- package/src/resources/extensions/gsd/captures.ts +384 -0
- package/src/resources/extensions/gsd/commands.ts +654 -36
- package/src/resources/extensions/gsd/complexity-classifier.ts +322 -0
- package/src/resources/extensions/gsd/context-budget.ts +243 -0
- package/src/resources/extensions/gsd/context-store.ts +195 -0
- package/src/resources/extensions/gsd/dashboard-overlay.ts +51 -3
- package/src/resources/extensions/gsd/db-writer.ts +341 -0
- package/src/resources/extensions/gsd/debug-logger.ts +178 -0
- package/src/resources/extensions/gsd/dispatch-guard.ts +0 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +54 -0
- package/src/resources/extensions/gsd/doctor-proactive.ts +286 -0
- package/src/resources/extensions/gsd/doctor.ts +283 -2
- package/src/resources/extensions/gsd/export.ts +81 -2
- package/src/resources/extensions/gsd/files.ts +39 -9
- package/src/resources/extensions/gsd/git-service.ts +6 -0
- package/src/resources/extensions/gsd/gsd-db.ts +752 -0
- package/src/resources/extensions/gsd/guided-flow.ts +26 -1
- package/src/resources/extensions/gsd/history.ts +0 -1
- package/src/resources/extensions/gsd/index.ts +277 -1
- package/src/resources/extensions/gsd/md-importer.ts +526 -0
- package/src/resources/extensions/gsd/metrics.ts +84 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +65 -0
- package/src/resources/extensions/gsd/model-router.ts +256 -0
- package/src/resources/extensions/gsd/notifications.ts +0 -1
- package/src/resources/extensions/gsd/post-unit-hooks.ts +72 -2
- package/src/resources/extensions/gsd/preferences.ts +198 -150
- package/src/resources/extensions/gsd/prompt-loader.ts +45 -9
- package/src/resources/extensions/gsd/prompts/execute-task.md +3 -5
- package/src/resources/extensions/gsd/prompts/heal-skill.md +45 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +5 -1
- package/src/resources/extensions/gsd/prompts/quick-task.md +48 -0
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -0
- package/src/resources/extensions/gsd/prompts/replan-slice.md +8 -0
- package/src/resources/extensions/gsd/prompts/system.md +2 -1
- package/src/resources/extensions/gsd/prompts/triage-captures.md +62 -0
- package/src/resources/extensions/gsd/quick.ts +156 -0
- package/src/resources/extensions/gsd/skill-discovery.ts +5 -3
- package/src/resources/extensions/gsd/skill-health.ts +417 -0
- package/src/resources/extensions/gsd/skill-telemetry.ts +127 -0
- package/src/resources/extensions/gsd/state.ts +30 -0
- package/src/resources/extensions/gsd/templates/preferences.md +1 -0
- package/src/resources/extensions/gsd/tests/captures.test.ts +438 -0
- package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +181 -0
- package/src/resources/extensions/gsd/tests/context-budget.test.ts +283 -0
- package/src/resources/extensions/gsd/tests/context-compression.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/context-store.test.ts +462 -0
- package/src/resources/extensions/gsd/tests/continue-here.test.ts +204 -0
- package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +346 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +602 -0
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +185 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +406 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/dist-redirect.mjs +22 -0
- package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +244 -0
- package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +434 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +353 -0
- package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +125 -0
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +326 -0
- package/src/resources/extensions/gsd/tests/integration-edge.test.ts +228 -0
- package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +277 -0
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +411 -0
- package/src/resources/extensions/gsd/tests/metrics.test.ts +197 -0
- package/src/resources/extensions/gsd/tests/milestone-transition-worktree.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/model-isolation.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/model-router.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/parsers.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +41 -1
- package/src/resources/extensions/gsd/tests/preferences-git.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/preferences-hooks.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/preferences-mode.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/preferences-models.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +464 -0
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +385 -0
- package/src/resources/extensions/gsd/tests/remote-questions.test.ts +488 -1
- package/src/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +17 -29
- package/src/resources/extensions/gsd/tests/resolve-ts.mjs +2 -8
- package/src/resources/extensions/gsd/tests/routing-history.test.ts +215 -62
- package/src/resources/extensions/gsd/tests/skill-lifecycle.test.ts +126 -0
- package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +31 -8
- package/src/resources/extensions/gsd/tests/token-savings.test.ts +366 -0
- package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +224 -0
- package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +215 -0
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +25 -1
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +290 -0
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +478 -0
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +205 -0
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +442 -0
- package/src/resources/extensions/gsd/tests/worktree-post-create-hook.test.ts +165 -0
- package/src/resources/extensions/gsd/triage-resolution.ts +200 -0
- package/src/resources/extensions/gsd/triage-ui.ts +175 -0
- package/src/resources/extensions/gsd/types.ts +29 -0
- package/src/resources/extensions/gsd/undo.ts +0 -1
- package/src/resources/extensions/gsd/unit-runtime.ts +5 -1
- package/src/resources/extensions/gsd/visualizer-data.ts +505 -0
- package/src/resources/extensions/gsd/visualizer-overlay.ts +337 -0
- package/src/resources/extensions/gsd/visualizer-views.ts +755 -0
- package/src/resources/extensions/gsd/worktree-command.ts +18 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +11 -4
- package/src/resources/extensions/remote-questions/config.ts +4 -2
- package/src/resources/extensions/remote-questions/discord-adapter.ts +35 -4
- package/src/resources/extensions/remote-questions/format.ts +166 -14
- package/src/resources/extensions/remote-questions/manager.ts +14 -4
- package/src/resources/extensions/remote-questions/remote-command.ts +100 -4
- package/src/resources/extensions/remote-questions/slack-adapter.ts +58 -2
- package/src/resources/extensions/remote-questions/telegram-adapter.ts +161 -0
- package/src/resources/extensions/remote-questions/types.ts +2 -1
- package/src/resources/extensions/ttsr/ttsr-manager.ts +26 -0
- package/src/resources/extensions/voice/index.ts +4 -3
|
@@ -214,7 +214,11 @@ export function findMilestoneIds(basePath: string): string[] {
|
|
|
214
214
|
// Apply custom queue order if available, else fall back to numeric sort
|
|
215
215
|
const customOrder = loadQueueOrder(basePath);
|
|
216
216
|
return sortByQueueOrder(ids, customOrder);
|
|
217
|
-
} catch {
|
|
217
|
+
} catch (err) {
|
|
218
|
+
// Log why milestone scanning failed — silent [] here causes infinite loops (#456)
|
|
219
|
+
if (existsSync(dir)) {
|
|
220
|
+
console.error(`[gsd] findMilestoneIds: .gsd/milestones/ exists but readdirSync failed — ${err instanceof Error ? err.message : String(err)}`);
|
|
221
|
+
}
|
|
218
222
|
return [];
|
|
219
223
|
}
|
|
220
224
|
}
|
|
@@ -1002,6 +1006,27 @@ export async function showSmartEntry(
|
|
|
1002
1006
|
}
|
|
1003
1007
|
|
|
1004
1008
|
const milestoneIds = findMilestoneIds(basePath);
|
|
1009
|
+
|
|
1010
|
+
// Sanity check (#456): if findMilestoneIds returns [] but the milestones
|
|
1011
|
+
// directory has contents, something went wrong (permissions, stale worktree
|
|
1012
|
+
// cwd, etc). Warn instead of silently starting a new-project flow.
|
|
1013
|
+
if (milestoneIds.length === 0) {
|
|
1014
|
+
const mDir = milestonesDir(basePath);
|
|
1015
|
+
if (existsSync(mDir)) {
|
|
1016
|
+
try {
|
|
1017
|
+
const entries = readdirSync(mDir);
|
|
1018
|
+
if (entries.length > 0) {
|
|
1019
|
+
ctx.ui.notify(
|
|
1020
|
+
`Milestone directory has ${entries.length} entries but none were recognized as milestones. ` +
|
|
1021
|
+
`This may indicate a corrupted state or wrong working directory. Run \`/gsd doctor\` to diagnose.`,
|
|
1022
|
+
"warning",
|
|
1023
|
+
);
|
|
1024
|
+
return;
|
|
1025
|
+
}
|
|
1026
|
+
} catch { /* directory exists but unreadable — fall through to normal flow */ }
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1005
1030
|
const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
|
|
1006
1031
|
const nextId = nextMilestoneId(milestoneIds, uniqueMilestoneIds);
|
|
1007
1032
|
const isFirst = milestoneIds.length === 0;
|
|
@@ -24,7 +24,9 @@ import type {
|
|
|
24
24
|
ExtensionContext,
|
|
25
25
|
} from "@gsd/pi-coding-agent";
|
|
26
26
|
import { createBashTool, createWriteTool, createReadTool, createEditTool, isToolCallEventType } from "@gsd/pi-coding-agent";
|
|
27
|
+
import { Type } from "@sinclair/typebox";
|
|
27
28
|
|
|
29
|
+
import { debugLog, debugTime } from "./debug-logger.js";
|
|
28
30
|
import { registerGSDCommand, loadToolApiKeys } from "./commands.js";
|
|
29
31
|
import { registerExitCommand } from "./exit-command.js";
|
|
30
32
|
import { registerWorktreeCommand, getWorktreeOriginalCwd, getActiveWorktreeName } from "./worktree-command.js";
|
|
@@ -53,10 +55,39 @@ import {
|
|
|
53
55
|
import { Key } from "@gsd/pi-tui";
|
|
54
56
|
import { join } from "node:path";
|
|
55
57
|
import { existsSync, readFileSync } from "node:fs";
|
|
58
|
+
import { homedir } from "node:os";
|
|
56
59
|
import { shortcutDesc } from "../shared/terminal.js";
|
|
57
60
|
import { Text } from "@gsd/pi-tui";
|
|
58
61
|
import { pauseAutoForProviderError } from "./provider-error-pause.js";
|
|
59
62
|
|
|
63
|
+
// ── Agent Instructions ────────────────────────────────────────────────────
|
|
64
|
+
// Lightweight "always follow" files injected into every GSD agent session.
|
|
65
|
+
// Global: ~/.gsd/agent-instructions.md Project: .gsd/agent-instructions.md
|
|
66
|
+
// Both are loaded and concatenated (global first, project appends).
|
|
67
|
+
|
|
68
|
+
function loadAgentInstructions(): string | null {
|
|
69
|
+
const parts: string[] = [];
|
|
70
|
+
|
|
71
|
+
const globalPath = join(homedir(), ".gsd", "agent-instructions.md");
|
|
72
|
+
if (existsSync(globalPath)) {
|
|
73
|
+
try {
|
|
74
|
+
const content = readFileSync(globalPath, "utf-8").trim();
|
|
75
|
+
if (content) parts.push(content);
|
|
76
|
+
} catch { /* non-fatal — skip unreadable file */ }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const projectPath = join(process.cwd(), ".gsd", "agent-instructions.md");
|
|
80
|
+
if (existsSync(projectPath)) {
|
|
81
|
+
try {
|
|
82
|
+
const content = readFileSync(projectPath, "utf-8").trim();
|
|
83
|
+
if (content) parts.push(content);
|
|
84
|
+
} catch { /* non-fatal — skip unreadable file */ }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (parts.length === 0) return null;
|
|
88
|
+
return parts.join("\n\n");
|
|
89
|
+
}
|
|
90
|
+
|
|
60
91
|
// ── Depth verification state ──────────────────────────────────────────────
|
|
61
92
|
let depthVerificationDone = false;
|
|
62
93
|
|
|
@@ -190,6 +221,235 @@ export default function (pi: ExtensionAPI) {
|
|
|
190
221
|
};
|
|
191
222
|
pi.registerTool(dynamicEdit as any);
|
|
192
223
|
|
|
224
|
+
// ── Structured LLM tools — DB-first write path (R014) ──────────────────
|
|
225
|
+
|
|
226
|
+
pi.registerTool({
|
|
227
|
+
name: "gsd_save_decision",
|
|
228
|
+
label: "Save Decision",
|
|
229
|
+
description:
|
|
230
|
+
"Record a project decision to the GSD database and regenerate DECISIONS.md. " +
|
|
231
|
+
"Decision IDs are auto-assigned — never provide an ID manually.",
|
|
232
|
+
promptSnippet: "Record a project decision to the GSD database (auto-assigns ID, regenerates DECISIONS.md)",
|
|
233
|
+
promptGuidelines: [
|
|
234
|
+
"Use gsd_save_decision when recording an architectural, pattern, library, or observability decision.",
|
|
235
|
+
"Decision IDs are auto-assigned (D001, D002, ...) — never guess or provide an ID.",
|
|
236
|
+
"All fields except revisable and when_context are required.",
|
|
237
|
+
"The tool writes to the DB and regenerates .gsd/DECISIONS.md automatically.",
|
|
238
|
+
],
|
|
239
|
+
parameters: Type.Object({
|
|
240
|
+
scope: Type.String({ description: "Scope of the decision (e.g. 'architecture', 'library', 'observability')" }),
|
|
241
|
+
decision: Type.String({ description: "What is being decided" }),
|
|
242
|
+
choice: Type.String({ description: "The choice made" }),
|
|
243
|
+
rationale: Type.String({ description: "Why this choice was made" }),
|
|
244
|
+
revisable: Type.Optional(Type.String({ description: "Whether this can be revisited (default: 'Yes')" })),
|
|
245
|
+
when_context: Type.Optional(Type.String({ description: "When/context for the decision (e.g. milestone ID)" })),
|
|
246
|
+
}),
|
|
247
|
+
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
248
|
+
// Check DB availability
|
|
249
|
+
let dbAvailable = false;
|
|
250
|
+
try {
|
|
251
|
+
const db = await import("./gsd-db.js");
|
|
252
|
+
dbAvailable = db.isDbAvailable();
|
|
253
|
+
} catch { /* dynamic import failed */ }
|
|
254
|
+
|
|
255
|
+
if (!dbAvailable) {
|
|
256
|
+
return {
|
|
257
|
+
content: [{ type: "text" as const, text: "Error: GSD database is not available. Cannot save decision." }],
|
|
258
|
+
isError: true,
|
|
259
|
+
details: { operation: "save_decision", error: "db_unavailable" },
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
try {
|
|
264
|
+
const { saveDecisionToDb } = await import("./db-writer.js");
|
|
265
|
+
const { id } = await saveDecisionToDb(
|
|
266
|
+
{
|
|
267
|
+
scope: params.scope,
|
|
268
|
+
decision: params.decision,
|
|
269
|
+
choice: params.choice,
|
|
270
|
+
rationale: params.rationale,
|
|
271
|
+
revisable: params.revisable,
|
|
272
|
+
when_context: params.when_context,
|
|
273
|
+
},
|
|
274
|
+
process.cwd(),
|
|
275
|
+
);
|
|
276
|
+
return {
|
|
277
|
+
content: [{ type: "text" as const, text: `Saved decision ${id}` }],
|
|
278
|
+
details: { operation: "save_decision", id },
|
|
279
|
+
};
|
|
280
|
+
} catch (err) {
|
|
281
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
282
|
+
process.stderr.write(`gsd-db: gsd_save_decision tool failed: ${msg}\n`);
|
|
283
|
+
return {
|
|
284
|
+
content: [{ type: "text" as const, text: `Error saving decision: ${msg}` }],
|
|
285
|
+
isError: true,
|
|
286
|
+
details: { operation: "save_decision", error: msg },
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
pi.registerTool({
|
|
293
|
+
name: "gsd_update_requirement",
|
|
294
|
+
label: "Update Requirement",
|
|
295
|
+
description:
|
|
296
|
+
"Update an existing requirement in the GSD database and regenerate REQUIREMENTS.md. " +
|
|
297
|
+
"Provide the requirement ID (e.g. R001) and any fields to update.",
|
|
298
|
+
promptSnippet: "Update an existing GSD requirement by ID (regenerates REQUIREMENTS.md)",
|
|
299
|
+
promptGuidelines: [
|
|
300
|
+
"Use gsd_update_requirement to change status, validation, notes, or other fields on an existing requirement.",
|
|
301
|
+
"The id parameter is required — it must be an existing RXXX identifier.",
|
|
302
|
+
"All other fields are optional — only provided fields are updated.",
|
|
303
|
+
"The tool verifies the requirement exists before updating.",
|
|
304
|
+
],
|
|
305
|
+
parameters: Type.Object({
|
|
306
|
+
id: Type.String({ description: "The requirement ID (e.g. R001, R014)" }),
|
|
307
|
+
status: Type.Optional(Type.String({ description: "New status (e.g. 'active', 'validated', 'deferred')" })),
|
|
308
|
+
validation: Type.Optional(Type.String({ description: "Validation criteria or proof" })),
|
|
309
|
+
notes: Type.Optional(Type.String({ description: "Additional notes" })),
|
|
310
|
+
description: Type.Optional(Type.String({ description: "Updated description" })),
|
|
311
|
+
primary_owner: Type.Optional(Type.String({ description: "Primary owning slice" })),
|
|
312
|
+
supporting_slices: Type.Optional(Type.String({ description: "Supporting slices" })),
|
|
313
|
+
}),
|
|
314
|
+
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
315
|
+
let dbAvailable = false;
|
|
316
|
+
try {
|
|
317
|
+
const db = await import("./gsd-db.js");
|
|
318
|
+
dbAvailable = db.isDbAvailable();
|
|
319
|
+
} catch { /* dynamic import failed */ }
|
|
320
|
+
|
|
321
|
+
if (!dbAvailable) {
|
|
322
|
+
return {
|
|
323
|
+
content: [{ type: "text" as const, text: "Error: GSD database is not available. Cannot update requirement." }],
|
|
324
|
+
isError: true,
|
|
325
|
+
details: { operation: "update_requirement", id: params.id, error: "db_unavailable" },
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
try {
|
|
330
|
+
// Verify requirement exists
|
|
331
|
+
const db = await import("./gsd-db.js");
|
|
332
|
+
const existing = db.getRequirementById(params.id);
|
|
333
|
+
if (!existing) {
|
|
334
|
+
return {
|
|
335
|
+
content: [{ type: "text" as const, text: `Error: Requirement ${params.id} not found.` }],
|
|
336
|
+
isError: true,
|
|
337
|
+
details: { operation: "update_requirement", id: params.id, error: "not_found" },
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const { updateRequirementInDb } = await import("./db-writer.js");
|
|
342
|
+
const updates: Record<string, string | undefined> = {};
|
|
343
|
+
if (params.status !== undefined) updates.status = params.status;
|
|
344
|
+
if (params.validation !== undefined) updates.validation = params.validation;
|
|
345
|
+
if (params.notes !== undefined) updates.notes = params.notes;
|
|
346
|
+
if (params.description !== undefined) updates.description = params.description;
|
|
347
|
+
if (params.primary_owner !== undefined) updates.primary_owner = params.primary_owner;
|
|
348
|
+
if (params.supporting_slices !== undefined) updates.supporting_slices = params.supporting_slices;
|
|
349
|
+
|
|
350
|
+
await updateRequirementInDb(params.id, updates, process.cwd());
|
|
351
|
+
|
|
352
|
+
return {
|
|
353
|
+
content: [{ type: "text" as const, text: `Updated requirement ${params.id}` }],
|
|
354
|
+
details: { operation: "update_requirement", id: params.id },
|
|
355
|
+
};
|
|
356
|
+
} catch (err) {
|
|
357
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
358
|
+
process.stderr.write(`gsd-db: gsd_update_requirement tool failed: ${msg}\n`);
|
|
359
|
+
return {
|
|
360
|
+
content: [{ type: "text" as const, text: `Error updating requirement: ${msg}` }],
|
|
361
|
+
isError: true,
|
|
362
|
+
details: { operation: "update_requirement", id: params.id, error: msg },
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
pi.registerTool({
|
|
369
|
+
name: "gsd_save_summary",
|
|
370
|
+
label: "Save Summary",
|
|
371
|
+
description:
|
|
372
|
+
"Save a summary, research, context, or assessment artifact to the GSD database and write it to disk. " +
|
|
373
|
+
"Computes the file path from milestone/slice/task IDs automatically.",
|
|
374
|
+
promptSnippet: "Save a GSD artifact (summary/research/context/assessment) to DB and disk",
|
|
375
|
+
promptGuidelines: [
|
|
376
|
+
"Use gsd_save_summary to persist structured artifacts (SUMMARY, RESEARCH, CONTEXT, ASSESSMENT).",
|
|
377
|
+
"milestone_id is required. slice_id and task_id are optional — they determine the file path.",
|
|
378
|
+
"The tool computes the relative path automatically: milestones/M001/M001-SUMMARY.md, milestones/M001/slices/S01/S01-SUMMARY.md, etc.",
|
|
379
|
+
"artifact_type must be one of: SUMMARY, RESEARCH, CONTEXT, ASSESSMENT.",
|
|
380
|
+
],
|
|
381
|
+
parameters: Type.Object({
|
|
382
|
+
milestone_id: Type.String({ description: "Milestone ID (e.g. M001)" }),
|
|
383
|
+
slice_id: Type.Optional(Type.String({ description: "Slice ID (e.g. S01)" })),
|
|
384
|
+
task_id: Type.Optional(Type.String({ description: "Task ID (e.g. T01)" })),
|
|
385
|
+
artifact_type: Type.String({ description: "One of: SUMMARY, RESEARCH, CONTEXT, ASSESSMENT" }),
|
|
386
|
+
content: Type.String({ description: "The full markdown content of the artifact" }),
|
|
387
|
+
}),
|
|
388
|
+
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
389
|
+
let dbAvailable = false;
|
|
390
|
+
try {
|
|
391
|
+
const db = await import("./gsd-db.js");
|
|
392
|
+
dbAvailable = db.isDbAvailable();
|
|
393
|
+
} catch { /* dynamic import failed */ }
|
|
394
|
+
|
|
395
|
+
if (!dbAvailable) {
|
|
396
|
+
return {
|
|
397
|
+
content: [{ type: "text" as const, text: "Error: GSD database is not available. Cannot save artifact." }],
|
|
398
|
+
isError: true,
|
|
399
|
+
details: { operation: "save_summary", error: "db_unavailable" },
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// Validate artifact_type
|
|
404
|
+
const validTypes = ["SUMMARY", "RESEARCH", "CONTEXT", "ASSESSMENT"];
|
|
405
|
+
if (!validTypes.includes(params.artifact_type)) {
|
|
406
|
+
return {
|
|
407
|
+
content: [{ type: "text" as const, text: `Error: Invalid artifact_type "${params.artifact_type}". Must be one of: ${validTypes.join(", ")}` }],
|
|
408
|
+
isError: true,
|
|
409
|
+
details: { operation: "save_summary", error: "invalid_artifact_type" },
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
try {
|
|
414
|
+
// Compute relative path from IDs
|
|
415
|
+
let relativePath: string;
|
|
416
|
+
if (params.task_id && params.slice_id) {
|
|
417
|
+
relativePath = `milestones/${params.milestone_id}/slices/${params.slice_id}/tasks/${params.task_id}-${params.artifact_type}.md`;
|
|
418
|
+
} else if (params.slice_id) {
|
|
419
|
+
relativePath = `milestones/${params.milestone_id}/slices/${params.slice_id}/${params.slice_id}-${params.artifact_type}.md`;
|
|
420
|
+
} else {
|
|
421
|
+
relativePath = `milestones/${params.milestone_id}/${params.milestone_id}-${params.artifact_type}.md`;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const { saveArtifactToDb } = await import("./db-writer.js");
|
|
425
|
+
await saveArtifactToDb(
|
|
426
|
+
{
|
|
427
|
+
path: relativePath,
|
|
428
|
+
artifact_type: params.artifact_type,
|
|
429
|
+
content: params.content,
|
|
430
|
+
milestone_id: params.milestone_id,
|
|
431
|
+
slice_id: params.slice_id,
|
|
432
|
+
task_id: params.task_id,
|
|
433
|
+
},
|
|
434
|
+
process.cwd(),
|
|
435
|
+
);
|
|
436
|
+
|
|
437
|
+
return {
|
|
438
|
+
content: [{ type: "text" as const, text: `Saved ${params.artifact_type} artifact to ${relativePath}` }],
|
|
439
|
+
details: { operation: "save_summary", path: relativePath, artifact_type: params.artifact_type },
|
|
440
|
+
};
|
|
441
|
+
} catch (err) {
|
|
442
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
443
|
+
process.stderr.write(`gsd-db: gsd_save_summary tool failed: ${msg}\n`);
|
|
444
|
+
return {
|
|
445
|
+
content: [{ type: "text" as const, text: `Error saving artifact: ${msg}` }],
|
|
446
|
+
isError: true,
|
|
447
|
+
details: { operation: "save_summary", error: msg },
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
},
|
|
451
|
+
});
|
|
452
|
+
|
|
193
453
|
// ── session_start: render branded GSD header + load tool keys + remote status ──
|
|
194
454
|
pi.on("session_start", async (_event, ctx) => {
|
|
195
455
|
// Theme access throws in RPC mode (no TUI) — header is decorative, skip it
|
|
@@ -257,6 +517,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
257
517
|
pi.on("before_agent_start", async (event, ctx: ExtensionContext) => {
|
|
258
518
|
if (!existsSync(join(process.cwd(), ".gsd"))) return;
|
|
259
519
|
|
|
520
|
+
const stopContextTimer = debugTime("context-inject");
|
|
260
521
|
const systemContent = loadPrompt("system");
|
|
261
522
|
const loadedPreferences = loadEffectiveGSDPreferences();
|
|
262
523
|
let preferenceBlock = "";
|
|
@@ -297,6 +558,13 @@ export default function (pi: ExtensionAPI) {
|
|
|
297
558
|
}
|
|
298
559
|
}
|
|
299
560
|
|
|
561
|
+
// Load agent instructions (global + project)
|
|
562
|
+
let agentInstructionsBlock = "";
|
|
563
|
+
const agentInstructions = loadAgentInstructions();
|
|
564
|
+
if (agentInstructions) {
|
|
565
|
+
agentInstructionsBlock = `\n\n## Agent Instructions\n\nThe following instructions were provided by the user and must be followed in every session:\n\n${agentInstructions}`;
|
|
566
|
+
}
|
|
567
|
+
|
|
300
568
|
const injection = await buildGuidedExecuteContextInjection(event.prompt, process.cwd());
|
|
301
569
|
|
|
302
570
|
// Worktree context — override the static CWD in the system prompt
|
|
@@ -340,8 +608,16 @@ export default function (pi: ExtensionAPI) {
|
|
|
340
608
|
].join("\n");
|
|
341
609
|
}
|
|
342
610
|
|
|
611
|
+
const fullSystem = `${event.systemPrompt}\n\n[SYSTEM CONTEXT — GSD]\n\n${systemContent}${preferenceBlock}${agentInstructionsBlock}${knowledgeBlock}${newSkillsBlock}${worktreeBlock}`;
|
|
612
|
+
stopContextTimer({
|
|
613
|
+
systemPromptSize: fullSystem.length,
|
|
614
|
+
injectionSize: injection?.length ?? 0,
|
|
615
|
+
hasPreferences: preferenceBlock.length > 0,
|
|
616
|
+
hasNewSkills: newSkillsBlock.length > 0,
|
|
617
|
+
});
|
|
618
|
+
|
|
343
619
|
return {
|
|
344
|
-
systemPrompt:
|
|
620
|
+
systemPrompt: fullSystem,
|
|
345
621
|
...(injection
|
|
346
622
|
? {
|
|
347
623
|
message: {
|