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
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
// prompt-db: Tests for DB-aware inline helpers (inlineDecisionsFromDb, inlineRequirementsFromDb, inlineProjectFromDb)
|
|
2
|
+
//
|
|
3
|
+
// Validates:
|
|
4
|
+
// (a) DB-aware helpers return scoped content when DB has data
|
|
5
|
+
// (b) Helpers fall back to non-null output when DB unavailable
|
|
6
|
+
// (c) Scoped filtering actually reduces content
|
|
7
|
+
|
|
8
|
+
import { createTestContext } from './test-helpers.ts';
|
|
9
|
+
import {
|
|
10
|
+
openDatabase,
|
|
11
|
+
closeDatabase,
|
|
12
|
+
isDbAvailable,
|
|
13
|
+
insertDecision,
|
|
14
|
+
insertRequirement,
|
|
15
|
+
insertArtifact,
|
|
16
|
+
} from '../gsd-db.ts';
|
|
17
|
+
import {
|
|
18
|
+
queryDecisions,
|
|
19
|
+
queryRequirements,
|
|
20
|
+
queryProject,
|
|
21
|
+
formatDecisionsForPrompt,
|
|
22
|
+
formatRequirementsForPrompt,
|
|
23
|
+
} from '../context-store.ts';
|
|
24
|
+
|
|
25
|
+
const { assertEq, assertTrue, assertMatch, assertNoMatch, report } = createTestContext();
|
|
26
|
+
|
|
27
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
28
|
+
// prompt-db: DB-aware decisions helper returns scoped content
|
|
29
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
30
|
+
|
|
31
|
+
console.log('\n=== prompt-db: scoped decisions from DB ===');
|
|
32
|
+
{
|
|
33
|
+
openDatabase(':memory:');
|
|
34
|
+
|
|
35
|
+
// Insert decisions across 3 milestones
|
|
36
|
+
for (let i = 1; i <= 10; i++) {
|
|
37
|
+
const milestoneNum = ((i - 1) % 3) + 1;
|
|
38
|
+
insertDecision({
|
|
39
|
+
id: `D${String(i).padStart(3, '0')}`,
|
|
40
|
+
when_context: `M00${milestoneNum}/S01`,
|
|
41
|
+
scope: 'architecture',
|
|
42
|
+
decision: `decision ${i}`,
|
|
43
|
+
choice: `choice ${i}`,
|
|
44
|
+
rationale: `rationale ${i}`,
|
|
45
|
+
revisable: 'yes',
|
|
46
|
+
superseded_by: null,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Query scoped to M001
|
|
51
|
+
const m001Decisions = queryDecisions({ milestoneId: 'M001' });
|
|
52
|
+
assertTrue(m001Decisions.length > 0, 'M001 decisions should exist');
|
|
53
|
+
assertTrue(m001Decisions.length < 10, `scoped query should return fewer than 10 (got ${m001Decisions.length})`);
|
|
54
|
+
|
|
55
|
+
// Verify all returned decisions are for M001
|
|
56
|
+
for (const d of m001Decisions) {
|
|
57
|
+
assertMatch(d.when_context, /M001/, `decision ${d.id} should be for M001`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Format and verify wrapping
|
|
61
|
+
const formatted = formatDecisionsForPrompt(m001Decisions);
|
|
62
|
+
assertTrue(formatted.length > 0, 'formatted decisions should be non-empty');
|
|
63
|
+
assertMatch(formatted, /\| # \| When \| Scope/, 'formatted decisions have table header');
|
|
64
|
+
|
|
65
|
+
// Verify the expected wrapper format that inlineDecisionsFromDb would produce
|
|
66
|
+
const wrapped = `### Decisions\nSource: \`.gsd/DECISIONS.md\`\n\n${formatted}`;
|
|
67
|
+
assertMatch(wrapped, /^### Decisions/, 'wrapped decisions start with ### Decisions');
|
|
68
|
+
assertMatch(wrapped, /Source:.*DECISIONS\.md/, 'wrapped decisions have source path');
|
|
69
|
+
|
|
70
|
+
closeDatabase();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
74
|
+
// prompt-db: DB-aware requirements helper returns scoped content
|
|
75
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
76
|
+
|
|
77
|
+
console.log('\n=== prompt-db: scoped requirements from DB ===');
|
|
78
|
+
{
|
|
79
|
+
openDatabase(':memory:');
|
|
80
|
+
|
|
81
|
+
// Insert requirements across different slices
|
|
82
|
+
insertRequirement({
|
|
83
|
+
id: 'R001', class: 'functional', status: 'active',
|
|
84
|
+
description: 'feature A', why: 'needed', source: 'M001', primary_owner: 'S01',
|
|
85
|
+
supporting_slices: '', validation: 'test', notes: '', full_content: '',
|
|
86
|
+
superseded_by: null,
|
|
87
|
+
});
|
|
88
|
+
insertRequirement({
|
|
89
|
+
id: 'R002', class: 'functional', status: 'active',
|
|
90
|
+
description: 'feature B', why: 'needed', source: 'M001', primary_owner: 'S02',
|
|
91
|
+
supporting_slices: 'S01', validation: 'test', notes: '', full_content: '',
|
|
92
|
+
superseded_by: null,
|
|
93
|
+
});
|
|
94
|
+
insertRequirement({
|
|
95
|
+
id: 'R003', class: 'functional', status: 'active',
|
|
96
|
+
description: 'feature C', why: 'needed', source: 'M001', primary_owner: 'S03',
|
|
97
|
+
supporting_slices: '', validation: 'test', notes: '', full_content: '',
|
|
98
|
+
superseded_by: null,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Query scoped to S01 — should get R001 (primary) and R002 (supporting)
|
|
102
|
+
const s01Reqs = queryRequirements({ sliceId: 'S01' });
|
|
103
|
+
assertEq(s01Reqs.length, 2, 'S01 requirements should be 2 (primary + supporting)');
|
|
104
|
+
const ids = s01Reqs.map(r => r.id).sort();
|
|
105
|
+
assertEq(ids, ['R001', 'R002'], 'S01 owns R001 and supports R002');
|
|
106
|
+
|
|
107
|
+
// Unscoped query returns all 3
|
|
108
|
+
const allReqs = queryRequirements();
|
|
109
|
+
assertEq(allReqs.length, 3, 'unscoped requirements should return all 3');
|
|
110
|
+
|
|
111
|
+
// Format and verify wrapping
|
|
112
|
+
const formatted = formatRequirementsForPrompt(s01Reqs);
|
|
113
|
+
assertTrue(formatted.length > 0, 'formatted requirements should be non-empty');
|
|
114
|
+
assertMatch(formatted, /### R001/, 'formatted requirements include R001');
|
|
115
|
+
assertMatch(formatted, /### R002/, 'formatted requirements include R002');
|
|
116
|
+
assertNoMatch(formatted, /### R003/, 'formatted requirements exclude R003');
|
|
117
|
+
|
|
118
|
+
// Verify the expected wrapper format that inlineRequirementsFromDb would produce
|
|
119
|
+
const wrapped = `### Requirements\nSource: \`.gsd/REQUIREMENTS.md\`\n\n${formatted}`;
|
|
120
|
+
assertMatch(wrapped, /^### Requirements/, 'wrapped requirements start with ### Requirements');
|
|
121
|
+
assertMatch(wrapped, /Source:.*REQUIREMENTS\.md/, 'wrapped requirements have source path');
|
|
122
|
+
|
|
123
|
+
closeDatabase();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
127
|
+
// prompt-db: DB-aware project helper returns content from DB
|
|
128
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
129
|
+
|
|
130
|
+
console.log('\n=== prompt-db: project content from DB ===');
|
|
131
|
+
{
|
|
132
|
+
openDatabase(':memory:');
|
|
133
|
+
|
|
134
|
+
insertArtifact({
|
|
135
|
+
path: 'PROJECT.md',
|
|
136
|
+
artifact_type: 'project',
|
|
137
|
+
milestone_id: null,
|
|
138
|
+
slice_id: null,
|
|
139
|
+
task_id: null,
|
|
140
|
+
full_content: '# Test Project\n\nThis is the project description.',
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
const content = queryProject();
|
|
144
|
+
assertEq(content, '# Test Project\n\nThis is the project description.', 'queryProject returns content');
|
|
145
|
+
|
|
146
|
+
// Verify the expected wrapper format that inlineProjectFromDb would produce
|
|
147
|
+
const wrapped = `### Project\nSource: \`.gsd/PROJECT.md\`\n\n${content}`;
|
|
148
|
+
assertMatch(wrapped, /^### Project/, 'wrapped project starts with ### Project');
|
|
149
|
+
assertMatch(wrapped, /Source:.*PROJECT\.md/, 'wrapped project has source path');
|
|
150
|
+
assertMatch(wrapped, /# Test Project/, 'wrapped project includes content');
|
|
151
|
+
|
|
152
|
+
closeDatabase();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
156
|
+
// prompt-db: fallback when DB unavailable
|
|
157
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
158
|
+
|
|
159
|
+
console.log('\n=== prompt-db: fallback when DB unavailable ===');
|
|
160
|
+
{
|
|
161
|
+
closeDatabase();
|
|
162
|
+
assertTrue(!isDbAvailable(), 'DB should not be available');
|
|
163
|
+
|
|
164
|
+
// queryDecisions returns [] when DB closed — helper would fall back
|
|
165
|
+
const decisions = queryDecisions({ milestoneId: 'M001' });
|
|
166
|
+
assertEq(decisions, [], 'queryDecisions returns [] when DB closed');
|
|
167
|
+
|
|
168
|
+
// queryRequirements returns [] when DB closed — helper would fall back
|
|
169
|
+
const requirements = queryRequirements({ sliceId: 'S01' });
|
|
170
|
+
assertEq(requirements, [], 'queryRequirements returns [] when DB closed');
|
|
171
|
+
|
|
172
|
+
// queryProject returns null when DB closed — helper would fall back
|
|
173
|
+
const project = queryProject();
|
|
174
|
+
assertEq(project, null, 'queryProject returns null when DB closed');
|
|
175
|
+
|
|
176
|
+
// formatDecisionsForPrompt returns '' for empty input
|
|
177
|
+
const formatted = formatDecisionsForPrompt([]);
|
|
178
|
+
assertEq(formatted, '', 'formatDecisionsForPrompt returns empty for empty input');
|
|
179
|
+
|
|
180
|
+
// formatRequirementsForPrompt returns '' for empty input
|
|
181
|
+
const formattedReqs = formatRequirementsForPrompt([]);
|
|
182
|
+
assertEq(formattedReqs, '', 'formatRequirementsForPrompt returns empty for empty input');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
186
|
+
// prompt-db: scoped filtering reduces content vs unscoped
|
|
187
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
188
|
+
|
|
189
|
+
console.log('\n=== prompt-db: scoped filtering reduces content ===');
|
|
190
|
+
{
|
|
191
|
+
openDatabase(':memory:');
|
|
192
|
+
|
|
193
|
+
// Insert 10 decisions across 3 milestones
|
|
194
|
+
for (let i = 1; i <= 10; i++) {
|
|
195
|
+
const milestoneNum = ((i - 1) % 3) + 1;
|
|
196
|
+
insertDecision({
|
|
197
|
+
id: `D${String(i).padStart(3, '0')}`,
|
|
198
|
+
when_context: `M00${milestoneNum}/S01`,
|
|
199
|
+
scope: 'architecture',
|
|
200
|
+
decision: `decision ${i} with some lengthy description for token measurement`,
|
|
201
|
+
choice: `choice ${i}`,
|
|
202
|
+
rationale: `rationale ${i} with additional context`,
|
|
203
|
+
revisable: 'yes',
|
|
204
|
+
superseded_by: null,
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const allDecisions = queryDecisions();
|
|
209
|
+
const m001Decisions = queryDecisions({ milestoneId: 'M001' });
|
|
210
|
+
|
|
211
|
+
assertEq(allDecisions.length, 10, 'unscoped returns all 10 decisions');
|
|
212
|
+
assertTrue(m001Decisions.length < 10, `M001-scoped returns fewer than 10 (got ${m001Decisions.length})`);
|
|
213
|
+
assertTrue(m001Decisions.length > 0, 'M001-scoped returns at least 1');
|
|
214
|
+
|
|
215
|
+
// Format both and compare sizes — scoped should be shorter
|
|
216
|
+
const allFormatted = formatDecisionsForPrompt(allDecisions);
|
|
217
|
+
const scopedFormatted = formatDecisionsForPrompt(m001Decisions);
|
|
218
|
+
|
|
219
|
+
assertTrue(
|
|
220
|
+
scopedFormatted.length < allFormatted.length,
|
|
221
|
+
`scoped content (${scopedFormatted.length} chars) should be shorter than unscoped (${allFormatted.length} chars)`,
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
// Insert requirements across 4 slices
|
|
225
|
+
for (let i = 1; i <= 8; i++) {
|
|
226
|
+
const sliceNum = ((i - 1) % 4) + 1;
|
|
227
|
+
insertRequirement({
|
|
228
|
+
id: `R${String(i).padStart(3, '0')}`,
|
|
229
|
+
class: 'functional',
|
|
230
|
+
status: 'active',
|
|
231
|
+
description: `requirement ${i} with detailed description`,
|
|
232
|
+
why: `justification ${i}`,
|
|
233
|
+
source: 'M001',
|
|
234
|
+
primary_owner: `S0${sliceNum}`,
|
|
235
|
+
supporting_slices: '',
|
|
236
|
+
validation: `validation ${i}`,
|
|
237
|
+
notes: '',
|
|
238
|
+
full_content: '',
|
|
239
|
+
superseded_by: null,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const allReqs = queryRequirements();
|
|
244
|
+
const s01Reqs = queryRequirements({ sliceId: 'S01' });
|
|
245
|
+
|
|
246
|
+
assertEq(allReqs.length, 8, 'unscoped returns all 8 requirements');
|
|
247
|
+
assertTrue(s01Reqs.length < 8, `S01-scoped returns fewer than 8 (got ${s01Reqs.length})`);
|
|
248
|
+
assertTrue(s01Reqs.length > 0, 'S01-scoped returns at least 1');
|
|
249
|
+
|
|
250
|
+
const allReqsFormatted = formatRequirementsForPrompt(allReqs);
|
|
251
|
+
const scopedReqsFormatted = formatRequirementsForPrompt(s01Reqs);
|
|
252
|
+
|
|
253
|
+
assertTrue(
|
|
254
|
+
scopedReqsFormatted.length < allReqsFormatted.length,
|
|
255
|
+
`scoped requirements (${scopedReqsFormatted.length} chars) should be shorter than unscoped (${allReqsFormatted.length} chars)`,
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
closeDatabase();
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
262
|
+
// prompt-db: DB helpers produce correct wrapper format
|
|
263
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
264
|
+
|
|
265
|
+
console.log('\n=== prompt-db: DB helpers wrapper format matches expected pattern ===');
|
|
266
|
+
{
|
|
267
|
+
openDatabase(':memory:');
|
|
268
|
+
|
|
269
|
+
insertDecision({
|
|
270
|
+
id: 'D001', when_context: 'M001/S01', scope: 'architecture',
|
|
271
|
+
decision: 'use SQLite', choice: 'better-sqlite3', rationale: 'fast',
|
|
272
|
+
revisable: 'yes', superseded_by: null,
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
insertRequirement({
|
|
276
|
+
id: 'R001', class: 'functional', status: 'active',
|
|
277
|
+
description: 'persist decisions', why: 'memory', source: 'M001',
|
|
278
|
+
primary_owner: 'S01', supporting_slices: '', validation: 'test',
|
|
279
|
+
notes: '', full_content: '', superseded_by: null,
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
insertArtifact({
|
|
283
|
+
path: 'PROJECT.md',
|
|
284
|
+
artifact_type: 'project',
|
|
285
|
+
milestone_id: null,
|
|
286
|
+
slice_id: null,
|
|
287
|
+
task_id: null,
|
|
288
|
+
full_content: '# Project Name\n\nDescription.',
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
// Simulate what inlineDecisionsFromDb does
|
|
292
|
+
const decisions = queryDecisions({ milestoneId: 'M001' });
|
|
293
|
+
assertTrue(decisions.length === 1, 'got 1 decision for M001');
|
|
294
|
+
const dFormatted = formatDecisionsForPrompt(decisions);
|
|
295
|
+
const dWrapped = `### Decisions\nSource: \`.gsd/DECISIONS.md\`\n\n${dFormatted}`;
|
|
296
|
+
assertMatch(dWrapped, /^### Decisions\nSource: `.gsd\/DECISIONS\.md`\n\n\| #/, 'decisions wrapper format correct');
|
|
297
|
+
|
|
298
|
+
// Simulate what inlineRequirementsFromDb does
|
|
299
|
+
const reqs = queryRequirements({ sliceId: 'S01' });
|
|
300
|
+
assertTrue(reqs.length === 1, 'got 1 requirement for S01');
|
|
301
|
+
const rFormatted = formatRequirementsForPrompt(reqs);
|
|
302
|
+
const rWrapped = `### Requirements\nSource: \`.gsd/REQUIREMENTS.md\`\n\n${rFormatted}`;
|
|
303
|
+
assertMatch(rWrapped, /^### Requirements\nSource: `.gsd\/REQUIREMENTS\.md`\n\n### R001/, 'requirements wrapper format correct');
|
|
304
|
+
|
|
305
|
+
// Simulate what inlineProjectFromDb does
|
|
306
|
+
const project = queryProject();
|
|
307
|
+
assertTrue(project !== null, 'project content exists');
|
|
308
|
+
const pWrapped = `### Project\nSource: \`.gsd/PROJECT.md\`\n\n${project}`;
|
|
309
|
+
assertMatch(pWrapped, /^### Project\nSource: `.gsd\/PROJECT\.md`\n\n# Project Name/, 'project wrapper format correct');
|
|
310
|
+
|
|
311
|
+
closeDatabase();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
315
|
+
// prompt-db: re-import updates DB when source markdown changes
|
|
316
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
317
|
+
|
|
318
|
+
import { mkdtempSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
319
|
+
import { join } from 'node:path';
|
|
320
|
+
import { tmpdir } from 'node:os';
|
|
321
|
+
import { migrateFromMarkdown } from '../md-importer.ts';
|
|
322
|
+
|
|
323
|
+
console.log('\n=== prompt-db: re-import updates DB when source markdown changes ===');
|
|
324
|
+
{
|
|
325
|
+
// Create a temp dir simulating a project with .gsd/DECISIONS.md
|
|
326
|
+
const tmpDir = mkdtempSync(join(tmpdir(), 'prompt-db-reimport-'));
|
|
327
|
+
const gsdDir = join(tmpDir, '.gsd');
|
|
328
|
+
mkdirSync(gsdDir, { recursive: true });
|
|
329
|
+
|
|
330
|
+
// Write initial DECISIONS.md with 2 decisions
|
|
331
|
+
const initialDecisions = `# Decisions Register
|
|
332
|
+
|
|
333
|
+
| # | When | Scope | Decision | Choice | Rationale | Revisable? |
|
|
334
|
+
|---|------|-------|----------|--------|-----------|------------|
|
|
335
|
+
| D001 | M001/S01 | architecture | use SQLite | better-sqlite3 | fast and embedded | yes |
|
|
336
|
+
| D002 | M001/S01 | tooling | use vitest | vitest | modern test runner | yes |
|
|
337
|
+
`;
|
|
338
|
+
writeFileSync(join(gsdDir, 'DECISIONS.md'), initialDecisions);
|
|
339
|
+
|
|
340
|
+
// Open in-memory DB and do initial import
|
|
341
|
+
openDatabase(':memory:');
|
|
342
|
+
migrateFromMarkdown(tmpDir);
|
|
343
|
+
|
|
344
|
+
// Verify initial state: 2 decisions
|
|
345
|
+
const initial = queryDecisions();
|
|
346
|
+
assertEq(initial.length, 2, 're-import: initial import has 2 decisions');
|
|
347
|
+
const initialIds = initial.map(d => d.id).sort();
|
|
348
|
+
assertEq(initialIds, ['D001', 'D002'], 're-import: initial decisions are D001, D002');
|
|
349
|
+
|
|
350
|
+
// Now "the LLM modifies DECISIONS.md" — add a third decision
|
|
351
|
+
const updatedDecisions = `# Decisions Register
|
|
352
|
+
|
|
353
|
+
| # | When | Scope | Decision | Choice | Rationale | Revisable? |
|
|
354
|
+
|---|------|-------|----------|--------|-----------|------------|
|
|
355
|
+
| D001 | M001/S01 | architecture | use SQLite | better-sqlite3 | fast and embedded | yes |
|
|
356
|
+
| D002 | M001/S01 | tooling | use vitest | vitest | modern test runner | yes |
|
|
357
|
+
| D003 | M001/S02 | runtime | dynamic imports | D014 pattern | lazy loading | yes |
|
|
358
|
+
`;
|
|
359
|
+
writeFileSync(join(gsdDir, 'DECISIONS.md'), updatedDecisions);
|
|
360
|
+
|
|
361
|
+
// Re-import (simulating what handleAgentEnd does)
|
|
362
|
+
migrateFromMarkdown(tmpDir);
|
|
363
|
+
|
|
364
|
+
// Verify DB now has 3 decisions
|
|
365
|
+
const afterReimport = queryDecisions();
|
|
366
|
+
assertEq(afterReimport.length, 3, 're-import: after re-import has 3 decisions');
|
|
367
|
+
const afterIds = afterReimport.map(d => d.id).sort();
|
|
368
|
+
assertEq(afterIds, ['D001', 'D002', 'D003'], 're-import: decisions are D001, D002, D003');
|
|
369
|
+
|
|
370
|
+
// Verify the new decision has correct data
|
|
371
|
+
const d003 = afterReimport.find(d => d.id === 'D003');
|
|
372
|
+
assertTrue(d003 !== undefined, 're-import: D003 exists');
|
|
373
|
+
assertEq(d003!.when_context, 'M001/S02', 're-import: D003 when_context is M001/S02');
|
|
374
|
+
assertEq(d003!.scope, 'runtime', 're-import: D003 scope is runtime');
|
|
375
|
+
assertEq(d003!.choice, 'D014 pattern', 're-import: D003 choice is D014 pattern');
|
|
376
|
+
|
|
377
|
+
// Verify scoped query picks up the new decision
|
|
378
|
+
const m001Scoped = queryDecisions({ milestoneId: 'M001' });
|
|
379
|
+
assertTrue(m001Scoped.length === 3, 're-import: all 3 decisions are for M001');
|
|
380
|
+
|
|
381
|
+
closeDatabase();
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// ─── Final Report ──────────────────────────────────────────────────────────
|
|
385
|
+
report();
|