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
|
@@ -55,7 +55,7 @@ export async function inlineFileOptional(
|
|
|
55
55
|
* Load and inline dependency slice summaries (full content, not just paths).
|
|
56
56
|
*/
|
|
57
57
|
export async function inlineDependencySummaries(
|
|
58
|
-
mid: string, sid: string, base: string,
|
|
58
|
+
mid: string, sid: string, base: string, budgetChars?: number,
|
|
59
59
|
): Promise<string> {
|
|
60
60
|
const roadmapFile = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
61
61
|
const roadmapContent = roadmapFile ? await loadFile(roadmapFile) : null;
|
|
@@ -79,7 +79,14 @@ export async function inlineDependencySummaries(
|
|
|
79
79
|
sections.push(`- \`${relPath}\` _(not found)_`);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
-
|
|
82
|
+
|
|
83
|
+
const result = sections.join("\n\n");
|
|
84
|
+
// When a budget is provided, truncate at section boundaries to fit
|
|
85
|
+
if (budgetChars !== undefined && result.length > budgetChars) {
|
|
86
|
+
const { truncateAtSectionBoundary } = await import("./context-budget.js");
|
|
87
|
+
return truncateAtSectionBoundary(result, budgetChars).content;
|
|
88
|
+
}
|
|
89
|
+
return result;
|
|
83
90
|
}
|
|
84
91
|
|
|
85
92
|
/**
|
|
@@ -95,6 +102,76 @@ export async function inlineGsdRootFile(
|
|
|
95
102
|
return inlineFileOptional(absPath, relGsdRootFile(key), label);
|
|
96
103
|
}
|
|
97
104
|
|
|
105
|
+
// ─── DB-Aware Inline Helpers ──────────────────────────────────────────────
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Inline decisions with optional milestone scoping from the DB.
|
|
109
|
+
* Falls back to filesystem via inlineGsdRootFile when DB unavailable or empty.
|
|
110
|
+
*/
|
|
111
|
+
export async function inlineDecisionsFromDb(
|
|
112
|
+
base: string, milestoneId?: string, scope?: string,
|
|
113
|
+
): Promise<string | null> {
|
|
114
|
+
try {
|
|
115
|
+
const { isDbAvailable } = await import("./gsd-db.js");
|
|
116
|
+
if (isDbAvailable()) {
|
|
117
|
+
const { queryDecisions, formatDecisionsForPrompt } = await import("./context-store.js");
|
|
118
|
+
const decisions = queryDecisions({ milestoneId, scope });
|
|
119
|
+
if (decisions.length > 0) {
|
|
120
|
+
const formatted = formatDecisionsForPrompt(decisions);
|
|
121
|
+
return `### Decisions\nSource: \`.gsd/DECISIONS.md\`\n\n${formatted}`;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
} catch {
|
|
125
|
+
// DB not available — fall through to filesystem
|
|
126
|
+
}
|
|
127
|
+
return inlineGsdRootFile(base, "decisions.md", "Decisions");
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Inline requirements with optional slice scoping from the DB.
|
|
132
|
+
* Falls back to filesystem via inlineGsdRootFile when DB unavailable or empty.
|
|
133
|
+
*/
|
|
134
|
+
export async function inlineRequirementsFromDb(
|
|
135
|
+
base: string, sliceId?: string,
|
|
136
|
+
): Promise<string | null> {
|
|
137
|
+
try {
|
|
138
|
+
const { isDbAvailable } = await import("./gsd-db.js");
|
|
139
|
+
if (isDbAvailable()) {
|
|
140
|
+
const { queryRequirements, formatRequirementsForPrompt } = await import("./context-store.js");
|
|
141
|
+
const requirements = queryRequirements({ sliceId });
|
|
142
|
+
if (requirements.length > 0) {
|
|
143
|
+
const formatted = formatRequirementsForPrompt(requirements);
|
|
144
|
+
return `### Requirements\nSource: \`.gsd/REQUIREMENTS.md\`\n\n${formatted}`;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
} catch {
|
|
148
|
+
// DB not available — fall through to filesystem
|
|
149
|
+
}
|
|
150
|
+
return inlineGsdRootFile(base, "requirements.md", "Requirements");
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Inline project context from the DB.
|
|
155
|
+
* Falls back to filesystem via inlineGsdRootFile when DB unavailable or empty.
|
|
156
|
+
*/
|
|
157
|
+
export async function inlineProjectFromDb(
|
|
158
|
+
base: string,
|
|
159
|
+
): Promise<string | null> {
|
|
160
|
+
try {
|
|
161
|
+
const { isDbAvailable } = await import("./gsd-db.js");
|
|
162
|
+
if (isDbAvailable()) {
|
|
163
|
+
const { queryProject } = await import("./context-store.js");
|
|
164
|
+
const content = queryProject();
|
|
165
|
+
if (content) {
|
|
166
|
+
return `### Project\nSource: \`.gsd/PROJECT.md\`\n\n${content}`;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
} catch {
|
|
170
|
+
// DB not available — fall through to filesystem
|
|
171
|
+
}
|
|
172
|
+
return inlineGsdRootFile(base, "project.md", "Project");
|
|
173
|
+
}
|
|
174
|
+
|
|
98
175
|
// ─── Skill Discovery ──────────────────────────────────────────────────────
|
|
99
176
|
|
|
100
177
|
/**
|
|
@@ -371,11 +448,11 @@ export async function buildResearchMilestonePrompt(mid: string, midTitle: string
|
|
|
371
448
|
|
|
372
449
|
const inlined: string[] = [];
|
|
373
450
|
inlined.push(await inlineFile(contextPath, contextRel, "Milestone Context"));
|
|
374
|
-
const projectInline = await
|
|
451
|
+
const projectInline = await inlineProjectFromDb(base);
|
|
375
452
|
if (projectInline) inlined.push(projectInline);
|
|
376
|
-
const requirementsInline = await
|
|
453
|
+
const requirementsInline = await inlineRequirementsFromDb(base);
|
|
377
454
|
if (requirementsInline) inlined.push(requirementsInline);
|
|
378
|
-
const decisionsInline = await
|
|
455
|
+
const decisionsInline = await inlineDecisionsFromDb(base, mid);
|
|
379
456
|
if (decisionsInline) inlined.push(decisionsInline);
|
|
380
457
|
const knowledgeInlineRM = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
|
|
381
458
|
if (knowledgeInlineRM) inlined.push(knowledgeInlineRM);
|
|
@@ -389,7 +466,7 @@ export async function buildResearchMilestonePrompt(mid: string, midTitle: string
|
|
|
389
466
|
milestoneId: mid, milestoneTitle: midTitle,
|
|
390
467
|
milestonePath: relMilestonePath(base, mid),
|
|
391
468
|
contextPath: contextRel,
|
|
392
|
-
outputPath: outputRelPath,
|
|
469
|
+
outputPath: join(base, outputRelPath),
|
|
393
470
|
inlinedContext,
|
|
394
471
|
...buildSkillDiscoveryVars(),
|
|
395
472
|
});
|
|
@@ -409,12 +486,14 @@ export async function buildPlanMilestonePrompt(mid: string, midTitle: string, ba
|
|
|
409
486
|
const { inlinePriorMilestoneSummary } = await import("./files.js");
|
|
410
487
|
const priorSummaryInline = await inlinePriorMilestoneSummary(mid, base);
|
|
411
488
|
if (priorSummaryInline) inlined.push(priorSummaryInline);
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
489
|
+
if (inlineLevel !== "minimal") {
|
|
490
|
+
const projectInline = await inlineProjectFromDb(base);
|
|
491
|
+
if (projectInline) inlined.push(projectInline);
|
|
492
|
+
const requirementsInline = await inlineRequirementsFromDb(base);
|
|
493
|
+
if (requirementsInline) inlined.push(requirementsInline);
|
|
494
|
+
const decisionsInline = await inlineDecisionsFromDb(base, mid);
|
|
495
|
+
if (decisionsInline) inlined.push(decisionsInline);
|
|
496
|
+
}
|
|
418
497
|
const knowledgeInlinePM = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
|
|
419
498
|
if (knowledgeInlinePM) inlined.push(knowledgeInlinePM);
|
|
420
499
|
inlined.push(inlineTemplate("roadmap", "Roadmap"));
|
|
@@ -432,14 +511,14 @@ export async function buildPlanMilestonePrompt(mid: string, midTitle: string, ba
|
|
|
432
511
|
const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
433
512
|
|
|
434
513
|
const outputRelPath = relMilestoneFile(base, mid, "ROADMAP");
|
|
435
|
-
const secretsOutputPath = relMilestoneFile(base, mid, "SECRETS");
|
|
514
|
+
const secretsOutputPath = join(base, relMilestoneFile(base, mid, "SECRETS"));
|
|
436
515
|
return loadPrompt("plan-milestone", {
|
|
437
516
|
workingDirectory: base,
|
|
438
517
|
milestoneId: mid, milestoneTitle: midTitle,
|
|
439
518
|
milestonePath: relMilestonePath(base, mid),
|
|
440
519
|
contextPath: contextRel,
|
|
441
520
|
researchPath: researchRel,
|
|
442
|
-
outputPath: outputRelPath,
|
|
521
|
+
outputPath: join(base, outputRelPath),
|
|
443
522
|
secretsOutputPath,
|
|
444
523
|
inlinedContext,
|
|
445
524
|
});
|
|
@@ -461,9 +540,9 @@ export async function buildResearchSlicePrompt(
|
|
|
461
540
|
if (contextInline) inlined.push(contextInline);
|
|
462
541
|
const researchInline = await inlineFileOptional(milestoneResearchPath, milestoneResearchRel, "Milestone Research");
|
|
463
542
|
if (researchInline) inlined.push(researchInline);
|
|
464
|
-
const decisionsInline = await
|
|
543
|
+
const decisionsInline = await inlineDecisionsFromDb(base, mid);
|
|
465
544
|
if (decisionsInline) inlined.push(decisionsInline);
|
|
466
|
-
const requirementsInline = await
|
|
545
|
+
const requirementsInline = await inlineRequirementsFromDb(base, sid);
|
|
467
546
|
if (requirementsInline) inlined.push(requirementsInline);
|
|
468
547
|
const knowledgeInlineRS = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
|
|
469
548
|
if (knowledgeInlineRS) inlined.push(knowledgeInlineRS);
|
|
@@ -484,7 +563,7 @@ export async function buildResearchSlicePrompt(
|
|
|
484
563
|
roadmapPath: roadmapRel,
|
|
485
564
|
contextPath: contextRel,
|
|
486
565
|
milestoneResearchPath: milestoneResearchRel,
|
|
487
|
-
outputPath: outputRelPath,
|
|
566
|
+
outputPath: join(base, outputRelPath),
|
|
488
567
|
inlinedContext,
|
|
489
568
|
dependencySummaries: depContent,
|
|
490
569
|
...buildSkillDiscoveryVars(),
|
|
@@ -505,9 +584,9 @@ export async function buildPlanSlicePrompt(
|
|
|
505
584
|
const researchInline = await inlineFileOptional(researchPath, researchRel, "Slice Research");
|
|
506
585
|
if (researchInline) inlined.push(researchInline);
|
|
507
586
|
if (inlineLevel !== "minimal") {
|
|
508
|
-
const decisionsInline = await
|
|
587
|
+
const decisionsInline = await inlineDecisionsFromDb(base, mid);
|
|
509
588
|
if (decisionsInline) inlined.push(decisionsInline);
|
|
510
|
-
const requirementsInline = await
|
|
589
|
+
const requirementsInline = await inlineRequirementsFromDb(base, sid);
|
|
511
590
|
if (requirementsInline) inlined.push(requirementsInline);
|
|
512
591
|
}
|
|
513
592
|
const knowledgeInlinePS = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
|
|
@@ -531,7 +610,7 @@ export async function buildPlanSlicePrompt(
|
|
|
531
610
|
slicePath: relSlicePath(base, mid, sid),
|
|
532
611
|
roadmapPath: roadmapRel,
|
|
533
612
|
researchPath: researchRel,
|
|
534
|
-
outputPath: outputRelPath,
|
|
613
|
+
outputPath: join(base, outputRelPath),
|
|
535
614
|
inlinedContext,
|
|
536
615
|
dependencySummaries: depContent,
|
|
537
616
|
});
|
|
@@ -598,7 +677,7 @@ export async function buildExecuteTaskPrompt(
|
|
|
598
677
|
...(knowledgeInlineET ? [knowledgeInlineET] : []),
|
|
599
678
|
].join("\n\n---\n\n");
|
|
600
679
|
|
|
601
|
-
const taskSummaryPath = `${relSlicePath(base, mid, sid)}/tasks/${tid}-SUMMARY.md
|
|
680
|
+
const taskSummaryPath = join(base, `${relSlicePath(base, mid, sid)}/tasks/${tid}-SUMMARY.md`);
|
|
602
681
|
|
|
603
682
|
const activeOverrides = await loadActiveOverrides(base);
|
|
604
683
|
const overridesSection = formatOverridesSection(activeOverrides);
|
|
@@ -607,7 +686,7 @@ export async function buildExecuteTaskPrompt(
|
|
|
607
686
|
overridesSection,
|
|
608
687
|
workingDirectory: base,
|
|
609
688
|
milestoneId: mid, sliceId: sid, sliceTitle: sTitle, taskId: tid, taskTitle: tTitle,
|
|
610
|
-
planPath: relSliceFile(base, mid, sid, "PLAN"),
|
|
689
|
+
planPath: join(base, relSliceFile(base, mid, sid, "PLAN")),
|
|
611
690
|
slicePath: relSlicePath(base, mid, sid),
|
|
612
691
|
taskPlanPath: taskPlanRelPath,
|
|
613
692
|
taskPlanInline,
|
|
@@ -634,7 +713,7 @@ export async function buildCompleteSlicePrompt(
|
|
|
634
713
|
inlined.push(await inlineFile(roadmapPath, roadmapRel, "Milestone Roadmap"));
|
|
635
714
|
inlined.push(await inlineFile(slicePlanPath, slicePlanRel, "Slice Plan"));
|
|
636
715
|
if (inlineLevel !== "minimal") {
|
|
637
|
-
const requirementsInline = await
|
|
716
|
+
const requirementsInline = await inlineRequirementsFromDb(base, sid);
|
|
638
717
|
if (requirementsInline) inlined.push(requirementsInline);
|
|
639
718
|
}
|
|
640
719
|
const knowledgeInlineCS = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
|
|
@@ -665,14 +744,14 @@ export async function buildCompleteSlicePrompt(
|
|
|
665
744
|
const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
666
745
|
|
|
667
746
|
const sliceRel = relSlicePath(base, mid, sid);
|
|
668
|
-
const sliceSummaryPath = `${sliceRel}/${sid}-SUMMARY.md
|
|
669
|
-
const sliceUatPath = `${sliceRel}/${sid}-UAT.md
|
|
747
|
+
const sliceSummaryPath = join(base, `${sliceRel}/${sid}-SUMMARY.md`);
|
|
748
|
+
const sliceUatPath = join(base, `${sliceRel}/${sid}-UAT.md`);
|
|
670
749
|
|
|
671
750
|
return loadPrompt("complete-slice", {
|
|
672
751
|
workingDirectory: base,
|
|
673
752
|
milestoneId: mid, sliceId: sid, sliceTitle: sTitle,
|
|
674
753
|
slicePath: sliceRel,
|
|
675
|
-
roadmapPath: roadmapRel,
|
|
754
|
+
roadmapPath: join(base, roadmapRel),
|
|
676
755
|
inlinedContext,
|
|
677
756
|
sliceSummaryPath,
|
|
678
757
|
sliceUatPath,
|
|
@@ -705,11 +784,11 @@ export async function buildCompleteMilestonePrompt(
|
|
|
705
784
|
|
|
706
785
|
// Inline root GSD files (skip for minimal — completion can read these if needed)
|
|
707
786
|
if (inlineLevel !== "minimal") {
|
|
708
|
-
const requirementsInline = await
|
|
787
|
+
const requirementsInline = await inlineRequirementsFromDb(base);
|
|
709
788
|
if (requirementsInline) inlined.push(requirementsInline);
|
|
710
|
-
const decisionsInline = await
|
|
789
|
+
const decisionsInline = await inlineDecisionsFromDb(base, mid);
|
|
711
790
|
if (decisionsInline) inlined.push(decisionsInline);
|
|
712
|
-
const projectInline = await
|
|
791
|
+
const projectInline = await inlineProjectFromDb(base);
|
|
713
792
|
if (projectInline) inlined.push(projectInline);
|
|
714
793
|
}
|
|
715
794
|
const knowledgeInlineCM = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
|
|
@@ -723,7 +802,7 @@ export async function buildCompleteMilestonePrompt(
|
|
|
723
802
|
|
|
724
803
|
const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
725
804
|
|
|
726
|
-
const milestoneSummaryPath = `${relMilestonePath(base, mid)}/${mid}-SUMMARY.md
|
|
805
|
+
const milestoneSummaryPath = join(base, `${relMilestonePath(base, mid)}/${mid}-SUMMARY.md`);
|
|
727
806
|
|
|
728
807
|
return loadPrompt("complete-milestone", {
|
|
729
808
|
workingDirectory: base,
|
|
@@ -767,7 +846,7 @@ export async function buildReplanSlicePrompt(
|
|
|
767
846
|
}
|
|
768
847
|
|
|
769
848
|
// Inline decisions
|
|
770
|
-
const decisionsInline = await
|
|
849
|
+
const decisionsInline = await inlineDecisionsFromDb(base, mid);
|
|
771
850
|
if (decisionsInline) inlined.push(decisionsInline);
|
|
772
851
|
const replanActiveOverrides = await loadActiveOverrides(base);
|
|
773
852
|
const replanOverridesInline = formatOverridesSection(replanActiveOverrides);
|
|
@@ -775,7 +854,21 @@ export async function buildReplanSlicePrompt(
|
|
|
775
854
|
|
|
776
855
|
const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
777
856
|
|
|
778
|
-
const replanPath = `${relSlicePath(base, mid, sid)}/${sid}-REPLAN.md
|
|
857
|
+
const replanPath = join(base, `${relSlicePath(base, mid, sid)}/${sid}-REPLAN.md`);
|
|
858
|
+
|
|
859
|
+
// Build capture context for replan prompt (captures that triggered this replan)
|
|
860
|
+
let captureContext = "(none)";
|
|
861
|
+
try {
|
|
862
|
+
const { loadReplanCaptures } = await import("./triage-resolution.js");
|
|
863
|
+
const replanCaptures = loadReplanCaptures(base);
|
|
864
|
+
if (replanCaptures.length > 0) {
|
|
865
|
+
captureContext = replanCaptures.map(c =>
|
|
866
|
+
`- **${c.id}**: "${c.text}" — ${c.rationale ?? "no rationale"}`
|
|
867
|
+
).join("\n");
|
|
868
|
+
}
|
|
869
|
+
} catch {
|
|
870
|
+
// Non-fatal — captures module may not be available
|
|
871
|
+
}
|
|
779
872
|
|
|
780
873
|
return loadPrompt("replan-slice", {
|
|
781
874
|
workingDirectory: base,
|
|
@@ -783,10 +876,11 @@ export async function buildReplanSlicePrompt(
|
|
|
783
876
|
sliceId: sid,
|
|
784
877
|
sliceTitle: sTitle,
|
|
785
878
|
slicePath: relSlicePath(base, mid, sid),
|
|
786
|
-
planPath: slicePlanRel,
|
|
879
|
+
planPath: join(base, slicePlanRel),
|
|
787
880
|
blockerTaskId,
|
|
788
881
|
inlinedContext,
|
|
789
882
|
replanPath,
|
|
883
|
+
captureContext,
|
|
790
884
|
});
|
|
791
885
|
}
|
|
792
886
|
|
|
@@ -803,12 +897,12 @@ export async function buildRunUatPrompt(
|
|
|
803
897
|
if (summaryInline) inlined.push(summaryInline);
|
|
804
898
|
}
|
|
805
899
|
|
|
806
|
-
const projectInline = await
|
|
900
|
+
const projectInline = await inlineProjectFromDb(base);
|
|
807
901
|
if (projectInline) inlined.push(projectInline);
|
|
808
902
|
|
|
809
903
|
const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
810
904
|
|
|
811
|
-
const uatResultPath = relSliceFile(base, mid, sliceId, "UAT-RESULT");
|
|
905
|
+
const uatResultPath = join(base, relSliceFile(base, mid, sliceId, "UAT-RESULT"));
|
|
812
906
|
const uatType = extractUatType(uatContent) ?? "human-experience";
|
|
813
907
|
|
|
814
908
|
return loadPrompt("run-uat", {
|
|
@@ -835,11 +929,11 @@ export async function buildReassessRoadmapPrompt(
|
|
|
835
929
|
inlined.push(await inlineFile(roadmapPath, roadmapRel, "Current Roadmap"));
|
|
836
930
|
inlined.push(await inlineFile(summaryPath, summaryRel, `${completedSliceId} Summary`));
|
|
837
931
|
if (inlineLevel !== "minimal") {
|
|
838
|
-
const projectInline = await
|
|
932
|
+
const projectInline = await inlineProjectFromDb(base);
|
|
839
933
|
if (projectInline) inlined.push(projectInline);
|
|
840
|
-
const requirementsInline = await
|
|
934
|
+
const requirementsInline = await inlineRequirementsFromDb(base);
|
|
841
935
|
if (requirementsInline) inlined.push(requirementsInline);
|
|
842
|
-
const decisionsInline = await
|
|
936
|
+
const decisionsInline = await inlineDecisionsFromDb(base, mid);
|
|
843
937
|
if (decisionsInline) inlined.push(decisionsInline);
|
|
844
938
|
}
|
|
845
939
|
const knowledgeInlineRA = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
|
|
@@ -847,7 +941,21 @@ export async function buildReassessRoadmapPrompt(
|
|
|
847
941
|
|
|
848
942
|
const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
849
943
|
|
|
850
|
-
const assessmentPath = relSliceFile(base, mid, completedSliceId, "ASSESSMENT");
|
|
944
|
+
const assessmentPath = join(base, relSliceFile(base, mid, completedSliceId, "ASSESSMENT"));
|
|
945
|
+
|
|
946
|
+
// Build deferred captures context for reassess prompt
|
|
947
|
+
let deferredCaptures = "(none)";
|
|
948
|
+
try {
|
|
949
|
+
const { loadDeferredCaptures } = await import("./triage-resolution.js");
|
|
950
|
+
const deferred = loadDeferredCaptures(base);
|
|
951
|
+
if (deferred.length > 0) {
|
|
952
|
+
deferredCaptures = deferred.map(c =>
|
|
953
|
+
`- **${c.id}**: "${c.text}" — ${c.rationale ?? "deferred during triage"}`
|
|
954
|
+
).join("\n");
|
|
955
|
+
}
|
|
956
|
+
} catch {
|
|
957
|
+
// Non-fatal — captures module may not be available
|
|
958
|
+
}
|
|
851
959
|
|
|
852
960
|
return loadPrompt("reassess-roadmap", {
|
|
853
961
|
workingDirectory: base,
|
|
@@ -858,6 +966,7 @@ export async function buildReassessRoadmapPrompt(
|
|
|
858
966
|
completedSliceSummaryPath: summaryRel,
|
|
859
967
|
assessmentPath,
|
|
860
968
|
inlinedContext,
|
|
969
|
+
deferredCaptures,
|
|
861
970
|
});
|
|
862
971
|
}
|
|
863
972
|
|
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { existsSync, cpSync, readFileSync, realpathSync, utimesSync } from "node:fs";
|
|
10
|
-
import { join, resolve } from "node:path";
|
|
11
|
-
import {
|
|
10
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
11
|
+
import { copyWorktreeDb, reconcileWorktreeDb, isDbAvailable } from "./gsd-db.js";
|
|
12
|
+
import { execSync, execFileSync } from "node:child_process";
|
|
12
13
|
import {
|
|
13
14
|
createWorktree,
|
|
14
15
|
removeWorktree,
|
|
@@ -33,6 +34,7 @@ import {
|
|
|
33
34
|
nativeAddPaths,
|
|
34
35
|
nativeRmForce,
|
|
35
36
|
nativeBranchDelete,
|
|
37
|
+
nativeBranchExists,
|
|
36
38
|
} from "./native-git-bridge.js";
|
|
37
39
|
|
|
38
40
|
// ─── Module State ──────────────────────────────────────────────────────────
|
|
@@ -75,6 +77,48 @@ function nudgeGitBranchCache(previousCwd: string): void {
|
|
|
75
77
|
}
|
|
76
78
|
}
|
|
77
79
|
|
|
80
|
+
// ─── Worktree Post-Create Hook (#597) ────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Run the user-configured post-create hook script after worktree creation.
|
|
84
|
+
* The script receives SOURCE_DIR and WORKTREE_DIR as environment variables.
|
|
85
|
+
* Failure is non-fatal — returns the error message or null on success.
|
|
86
|
+
*
|
|
87
|
+
* Reads the hook path from git.worktree_post_create in preferences.
|
|
88
|
+
* Pass hookPath directly to bypass preference loading (useful for testing).
|
|
89
|
+
*/
|
|
90
|
+
export function runWorktreePostCreateHook(sourceDir: string, worktreeDir: string, hookPath?: string): string | null {
|
|
91
|
+
if (hookPath === undefined) {
|
|
92
|
+
const prefs = loadEffectiveGSDPreferences()?.preferences?.git;
|
|
93
|
+
hookPath = prefs?.worktree_post_create;
|
|
94
|
+
}
|
|
95
|
+
if (!hookPath) return null;
|
|
96
|
+
|
|
97
|
+
// Resolve relative paths against the source project root
|
|
98
|
+
const resolved = isAbsolute(hookPath) ? hookPath : join(sourceDir, hookPath);
|
|
99
|
+
if (!existsSync(resolved)) {
|
|
100
|
+
return `Worktree post-create hook not found: ${resolved}`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
execSync(resolved, {
|
|
105
|
+
cwd: worktreeDir,
|
|
106
|
+
env: {
|
|
107
|
+
...process.env,
|
|
108
|
+
SOURCE_DIR: sourceDir,
|
|
109
|
+
WORKTREE_DIR: worktreeDir,
|
|
110
|
+
},
|
|
111
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
112
|
+
encoding: "utf-8",
|
|
113
|
+
timeout: 30_000, // 30 second timeout
|
|
114
|
+
});
|
|
115
|
+
return null;
|
|
116
|
+
} catch (err) {
|
|
117
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
118
|
+
return `Worktree post-create hook failed: ${msg}`;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
78
122
|
// ─── Auto-Worktree Branch Naming ───────────────────────────────────────────
|
|
79
123
|
|
|
80
124
|
export function autoWorktreeBranch(milestoneId: string): string {
|
|
@@ -93,11 +137,21 @@ export function autoWorktreeBranch(milestoneId: string): string {
|
|
|
93
137
|
export function createAutoWorktree(basePath: string, milestoneId: string): string {
|
|
94
138
|
const branch = autoWorktreeBranch(milestoneId);
|
|
95
139
|
|
|
96
|
-
//
|
|
97
|
-
//
|
|
98
|
-
//
|
|
99
|
-
|
|
100
|
-
const
|
|
140
|
+
// Check if the milestone branch already exists — it survives auto-mode
|
|
141
|
+
// stop/pause and contains committed work from prior sessions. If it exists,
|
|
142
|
+
// re-attach the worktree to it WITHOUT resetting. Only create a fresh branch
|
|
143
|
+
// from the integration branch when no prior work exists.
|
|
144
|
+
const branchExists = nativeBranchExists(basePath, branch);
|
|
145
|
+
|
|
146
|
+
let info: { name: string; path: string; branch: string; exists: boolean };
|
|
147
|
+
if (branchExists) {
|
|
148
|
+
// Re-attach worktree to the existing milestone branch (preserving commits)
|
|
149
|
+
info = createWorktree(basePath, milestoneId, { branch, reuseExistingBranch: true });
|
|
150
|
+
} else {
|
|
151
|
+
// Fresh start — create branch from integration branch
|
|
152
|
+
const integrationBranch = readIntegrationBranch(basePath, milestoneId) ?? undefined;
|
|
153
|
+
info = createWorktree(basePath, milestoneId, { branch, startPoint: integrationBranch });
|
|
154
|
+
}
|
|
101
155
|
|
|
102
156
|
// Copy .gsd/ planning artifacts from the source repo into the new worktree.
|
|
103
157
|
// Worktrees are fresh git checkouts — untracked files don't carry over.
|
|
@@ -106,6 +160,13 @@ export function createAutoWorktree(basePath: string, milestoneId: string): strin
|
|
|
106
160
|
// on plan-slice because the plan file doesn't exist in the worktree.
|
|
107
161
|
copyPlanningArtifacts(basePath, info.path);
|
|
108
162
|
|
|
163
|
+
// Run user-configured post-create hook (#597) — e.g. copy .env, symlink assets
|
|
164
|
+
const hookError = runWorktreePostCreateHook(basePath, info.path);
|
|
165
|
+
if (hookError) {
|
|
166
|
+
// Non-fatal — log but don't prevent worktree usage
|
|
167
|
+
console.error(`[GSD] ${hookError}`);
|
|
168
|
+
}
|
|
169
|
+
|
|
109
170
|
const previousCwd = process.cwd();
|
|
110
171
|
|
|
111
172
|
try {
|
|
@@ -151,14 +212,28 @@ function copyPlanningArtifacts(srcBase: string, wtPath: string): void {
|
|
|
151
212
|
} catch { /* non-fatal */ }
|
|
152
213
|
}
|
|
153
214
|
}
|
|
215
|
+
|
|
216
|
+
// Copy gsd.db if present in source
|
|
217
|
+
const srcDb = join(srcGsd, "gsd.db");
|
|
218
|
+
const destDb = join(dstGsd, "gsd.db");
|
|
219
|
+
if (existsSync(srcDb)) {
|
|
220
|
+
try {
|
|
221
|
+
copyWorktreeDb(srcDb, destDb);
|
|
222
|
+
} catch { /* non-fatal */ }
|
|
223
|
+
}
|
|
154
224
|
}
|
|
155
225
|
|
|
156
226
|
/**
|
|
157
227
|
* Teardown an auto-worktree: chdir back to original base, then remove
|
|
158
228
|
* the worktree and its branch.
|
|
159
229
|
*/
|
|
160
|
-
export function teardownAutoWorktree(
|
|
230
|
+
export function teardownAutoWorktree(
|
|
231
|
+
originalBasePath: string,
|
|
232
|
+
milestoneId: string,
|
|
233
|
+
opts: { preserveBranch?: boolean } = {},
|
|
234
|
+
): void {
|
|
161
235
|
const branch = autoWorktreeBranch(milestoneId);
|
|
236
|
+
const { preserveBranch = false } = opts;
|
|
162
237
|
const previousCwd = process.cwd();
|
|
163
238
|
|
|
164
239
|
try {
|
|
@@ -171,7 +246,7 @@ export function teardownAutoWorktree(originalBasePath: string, milestoneId: stri
|
|
|
171
246
|
}
|
|
172
247
|
|
|
173
248
|
nudgeGitBranchCache(previousCwd);
|
|
174
|
-
removeWorktree(originalBasePath, milestoneId, { branch });
|
|
249
|
+
removeWorktree(originalBasePath, milestoneId, { branch, deleteBranch: !preserveBranch });
|
|
175
250
|
}
|
|
176
251
|
|
|
177
252
|
/**
|
|
@@ -299,6 +374,15 @@ export function mergeMilestoneToMain(
|
|
|
299
374
|
// 1. Auto-commit dirty state in worktree before leaving
|
|
300
375
|
autoCommitDirtyState(worktreeCwd);
|
|
301
376
|
|
|
377
|
+
// Reconcile worktree DB into main DB before leaving worktree context
|
|
378
|
+
if (isDbAvailable()) {
|
|
379
|
+
try {
|
|
380
|
+
const worktreeDbPath = join(worktreeCwd, ".gsd", "gsd.db");
|
|
381
|
+
const mainDbPath = join(originalBasePath_, ".gsd", "gsd.db");
|
|
382
|
+
reconcileWorktreeDb(mainDbPath, worktreeDbPath);
|
|
383
|
+
} catch { /* non-fatal */ }
|
|
384
|
+
}
|
|
385
|
+
|
|
302
386
|
// 2. Parse roadmap for slice listing
|
|
303
387
|
const roadmap = parseRoadmap(roadmapContent);
|
|
304
388
|
const completedSlices = roadmap.slices.filter(s => s.done);
|