gsd-pi 2.80.0-dev.c5f2443b3 → 2.80.0-dev.e51d2c88c
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 +4 -2
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +2 -2
- package/dist/resources/extensions/github-sync/templates.js +39 -8
- package/dist/resources/extensions/gsd/auto/loop.js +48 -10
- package/dist/resources/extensions/gsd/auto/phases.js +66 -45
- package/dist/resources/extensions/gsd/auto/resolve.js +17 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +32 -16
- package/dist/resources/extensions/gsd/auto-dashboard.js +51 -15
- package/dist/resources/extensions/gsd/auto-dispatch.js +10 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +10 -10
- package/dist/resources/extensions/gsd/auto-prompts.js +124 -2
- package/dist/resources/extensions/gsd/auto-recovery.js +197 -9
- package/dist/resources/extensions/gsd/auto-start.js +2 -3
- package/dist/resources/extensions/gsd/auto-supervisor.js +8 -1
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +2 -2
- package/dist/resources/extensions/gsd/auto.js +75 -5
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +36 -3
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +27 -20
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +32 -1
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +129 -1
- package/dist/resources/extensions/gsd/clean-root-preflight.js +42 -4
- package/dist/resources/extensions/gsd/commands/dispatcher.js +5 -0
- package/dist/resources/extensions/gsd/commands-extract-learnings.js +17 -12
- package/dist/resources/extensions/gsd/context-budget.js +37 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +56 -10
- package/dist/resources/extensions/gsd/custom-workflow-engine.js +22 -2
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +39 -0
- package/dist/resources/extensions/gsd/db-base-schema.js +18 -2
- package/dist/resources/extensions/gsd/db-migration-steps.js +22 -0
- package/dist/resources/extensions/gsd/detection.js +106 -0
- package/dist/resources/extensions/gsd/graph.js +9 -3
- package/dist/resources/extensions/gsd/gsd-db.js +146 -13
- package/dist/resources/extensions/gsd/guided-flow.js +82 -16
- package/dist/resources/extensions/gsd/memory-store.js +69 -12
- package/dist/resources/extensions/gsd/migrate/command.js +40 -1
- package/dist/resources/extensions/gsd/migration-auto-check.js +87 -0
- package/dist/resources/extensions/gsd/planning-path-scope.js +26 -0
- package/dist/resources/extensions/gsd/pr-evidence.js +57 -16
- package/dist/resources/extensions/gsd/prompt-loader.js +28 -2
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +19 -19
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -5
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
- package/dist/resources/extensions/gsd/quick.js +34 -2
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +10 -2
- package/dist/resources/extensions/gsd/tools/context-mode-tool-result.js +15 -0
- package/dist/resources/extensions/gsd/tools/exec-search-tool.js +5 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +3 -15
- package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -0
- package/dist/resources/extensions/gsd/tools/plan-slice.js +9 -0
- package/dist/resources/extensions/gsd/tools/plan-task.js +9 -0
- package/dist/resources/extensions/gsd/tools/resume-tool.js +5 -0
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +1 -1
- package/dist/resources/extensions/gsd/unit-context-composer.js +12 -3
- package/dist/resources/extensions/gsd/unit-runtime.js +22 -0
- package/dist/resources/extensions/gsd/working-output-messages.js +64 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +16 -14
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
- package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/{8336.6f6f30e410419aff.js → 8336.631939fb583761fa.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{webpack-d82dbee6356c1733.js → webpack-0481f1221120a7c6.js} +1 -1
- package/package.json +12 -8
- package/packages/contracts/package.json +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +22 -17
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/workflow-tools.test.ts +75 -2
- package/packages/mcp-server/src/workflow-tools.ts +30 -16
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/models/fake-model.d.ts +12 -0
- package/packages/pi-ai/dist/models/fake-model.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/fake-model.js +27 -0
- package/packages/pi-ai/dist/models/fake-model.js.map +1 -0
- package/packages/pi-ai/dist/models/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/index.js +8 -0
- package/packages/pi-ai/dist/models/index.js.map +1 -1
- package/packages/pi-ai/dist/providers/fake.d.ts +42 -0
- package/packages/pi-ai/dist/providers/fake.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/fake.js +319 -0
- package/packages/pi-ai/dist/providers/fake.js.map +1 -0
- package/packages/pi-ai/dist/providers/register-builtins.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/register-builtins.js +24 -0
- package/packages/pi-ai/dist/providers/register-builtins.js.map +1 -1
- package/packages/pi-ai/src/models/fake-model.ts +30 -0
- package/packages/pi-ai/src/models/index.ts +9 -0
- package/packages/pi-ai/src/providers/fake.ts +376 -0
- package/packages/pi-ai/src/providers/register-builtins.ts +23 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +32 -0
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +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 +8 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +76 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js +9 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js +103 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts +15 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.js +66 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.js +24 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +17 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +99 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +7 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +5 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +24 -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 +33 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
- package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js +6 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +54 -15
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +26 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +112 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +51 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +10 -9
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +11 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +7 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +17 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +109 -17
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +69 -2
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +93 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +26 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +20 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js +79 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js +13 -0
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +18 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +36 -27
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts +11 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js +18 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +48 -0
- package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +10 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +3 -2
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +36 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +8 -0
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +89 -0
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +18 -0
- package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
- package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
- package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +110 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +19 -1
- package/packages/pi-coding-agent/src/core/extensions/types.ts +7 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +4 -0
- package/packages/pi-coding-agent/src/core/settings-manager.ts +51 -1
- package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts +7 -5
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +78 -15
- package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +59 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +160 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +10 -9
- package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +10 -9
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +122 -17
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +99 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +92 -3
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +28 -0
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.test.ts +95 -0
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +24 -1
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.ts +13 -0
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +32 -2
- package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +36 -27
- package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +65 -0
- package/packages/pi-coding-agent/src/modes/interactive/tui-mode.ts +29 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +14 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +3 -2
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/style.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/style.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/style.test.js +63 -0
- package/packages/pi-tui/dist/__tests__/style.test.js.map +1 -0
- package/packages/pi-tui/dist/__tests__/tui.test.js +24 -3
- package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
- package/packages/pi-tui/dist/index.d.ts +1 -0
- package/packages/pi-tui/dist/index.d.ts.map +1 -1
- package/packages/pi-tui/dist/index.js +2 -0
- package/packages/pi-tui/dist/index.js.map +1 -1
- package/packages/pi-tui/dist/style.d.ts +41 -0
- package/packages/pi-tui/dist/style.d.ts.map +1 -0
- package/packages/pi-tui/dist/style.js +158 -0
- package/packages/pi-tui/dist/style.js.map +1 -0
- package/packages/pi-tui/dist/tui.d.ts +0 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +21 -16
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/__tests__/style.test.ts +76 -0
- package/packages/pi-tui/src/__tests__/tui.test.ts +29 -3
- package/packages/pi-tui/src/index.ts +9 -0
- package/packages/pi-tui/src/style.ts +225 -0
- package/packages/pi-tui/src/tui.ts +23 -16
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/pkg/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
- package/pkg/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme-schema.js +13 -0
- package/pkg/dist/modes/interactive/theme/theme-schema.js.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
- package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme.js +18 -1
- package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
- package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/themes.js +36 -27
- package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
- package/src/resources/GSD-WORKFLOW.md +2 -2
- package/src/resources/extensions/github-sync/templates.ts +38 -8
- package/src/resources/extensions/github-sync/tests/inline-code.test.ts +66 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/loop.ts +67 -18
- package/src/resources/extensions/gsd/auto/phases.ts +77 -48
- package/src/resources/extensions/gsd/auto/resolve.ts +23 -1
- package/src/resources/extensions/gsd/auto/run-unit.ts +42 -15
- package/src/resources/extensions/gsd/auto-dashboard.ts +57 -8
- package/src/resources/extensions/gsd/auto-dispatch.ts +17 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +10 -10
- package/src/resources/extensions/gsd/auto-prompts.ts +133 -2
- package/src/resources/extensions/gsd/auto-recovery.ts +207 -7
- package/src/resources/extensions/gsd/auto-start.ts +7 -6
- package/src/resources/extensions/gsd/auto-supervisor.ts +7 -0
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +2 -2
- package/src/resources/extensions/gsd/auto.ts +90 -4
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +37 -2
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +27 -19
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +39 -1
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +135 -1
- package/src/resources/extensions/gsd/clean-root-preflight.ts +41 -3
- package/src/resources/extensions/gsd/commands/dispatcher.ts +6 -0
- package/src/resources/extensions/gsd/commands-extract-learnings.ts +17 -12
- package/src/resources/extensions/gsd/context-budget.ts +44 -2
- package/src/resources/extensions/gsd/crash-recovery.ts +67 -10
- package/src/resources/extensions/gsd/custom-workflow-engine.ts +24 -1
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +41 -0
- package/src/resources/extensions/gsd/db-base-schema.ts +19 -2
- package/src/resources/extensions/gsd/db-migration-steps.ts +25 -0
- package/src/resources/extensions/gsd/detection.ts +128 -0
- package/src/resources/extensions/gsd/graph.ts +12 -5
- package/src/resources/extensions/gsd/gsd-db.ts +168 -13
- package/src/resources/extensions/gsd/guided-flow.ts +98 -16
- package/src/resources/extensions/gsd/memory-store.ts +77 -12
- package/src/resources/extensions/gsd/migrate/command.ts +47 -1
- package/src/resources/extensions/gsd/migration-auto-check.ts +129 -0
- package/src/resources/extensions/gsd/planning-path-scope.ts +35 -0
- package/src/resources/extensions/gsd/pr-evidence.ts +63 -5
- package/src/resources/extensions/gsd/preferences-types.ts +1 -1
- package/src/resources/extensions/gsd/prompt-loader.ts +27 -2
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +19 -19
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/quick-task.md +1 -5
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
- package/src/resources/extensions/gsd/quick.ts +37 -2
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +11 -2
- package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +155 -5
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +56 -13
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +184 -2
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +88 -2
- package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +14 -1
- package/src/resources/extensions/gsd/tests/context-budget.test.ts +10 -1
- package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +112 -6
- package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +40 -2
- package/src/resources/extensions/gsd/tests/db-migration-steps.integration.test.ts +428 -0
- package/src/resources/extensions/gsd/tests/db-schema-metadata.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/detection.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +313 -0
- package/src/resources/extensions/gsd/tests/exec-history.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-basic.md +52 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-empty-optionals.md +42 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +55 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +60 -0
- package/src/resources/extensions/gsd/tests/graph-operations.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/has-pending-deep-stage.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +234 -0
- package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/pr-evidence-equivalence.test.ts +102 -0
- package/src/resources/extensions/gsd/tests/pr-evidence-hardening.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/right-sized-workflow-prompts.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -1
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +101 -2
- package/src/resources/extensions/gsd/tests/status-db-open.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +136 -4
- package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/working-output-messages.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +37 -6
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +9 -2
- package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +179 -0
- package/src/resources/extensions/gsd/tools/context-mode-tool-result.ts +25 -0
- package/src/resources/extensions/gsd/tools/exec-search-tool.ts +7 -7
- package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -23
- package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +10 -0
- package/src/resources/extensions/gsd/tools/resume-tool.ts +7 -7
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +1 -1
- package/src/resources/extensions/gsd/unit-context-composer.ts +19 -4
- package/src/resources/extensions/gsd/unit-runtime.ts +25 -0
- package/src/resources/extensions/gsd/working-output-messages.ts +120 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +15 -4
- package/packages/contracts/tsconfig.tsbuildinfo +0 -1
- /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → 8F5YpnZNBaooIWGF4GBV3}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → 8F5YpnZNBaooIWGF4GBV3}/_ssgManifest.js +0 -0
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
// intentionally independent store for cross-worktree claim races and is
|
|
23
23
|
// excluded from this invariant.
|
|
24
24
|
import { createRequire } from "node:module";
|
|
25
|
+
import { createHash } from "node:crypto";
|
|
25
26
|
import { existsSync, copyFileSync, mkdirSync, realpathSync } from "node:fs";
|
|
26
27
|
import { dirname } from "node:path";
|
|
27
28
|
import { GSDError, GSD_STALE_STATE } from "./errors.js";
|
|
@@ -36,7 +37,7 @@ import { rowToActiveDecision, rowToActiveRequirement, rowToDecision, rowToRequir
|
|
|
36
37
|
import { rowToGate } from "./db-gate-rows.js";
|
|
37
38
|
import { rowToArtifact, rowToMilestone } from "./db-milestone-artifact-rows.js";
|
|
38
39
|
import { backupDatabaseBeforeMigration } from "./db-migration-backup.js";
|
|
39
|
-
import { applyMigrationV2Artifacts, applyMigrationV3Memories, applyMigrationV4DecisionMadeBy, applyMigrationV5HierarchyTables, applyMigrationV6SliceSummaries, applyMigrationV7Dependencies, applyMigrationV8PlanningFields, applyMigrationV9Ordering, applyMigrationV10ReplanTrigger, applyMigrationV11TaskPlanning, applyMigrationV12QualityGates, applyMigrationV13HotPathIndexes, applyMigrationV14SliceDependencies, applyMigrationV15AuditTables, applyMigrationV16EscalationSource, applyMigrationV17TaskEscalation, applyMigrationV18MemorySources, applyMigrationV19MemoryFts, applyMigrationV20MemoryRelations, applyMigrationV21StructuredMemories, applyMigrationV22QualityGateRepair, applyMigrationV23MilestoneQueue, } from "./db-migration-steps.js";
|
|
40
|
+
import { applyMigrationV2Artifacts, applyMigrationV3Memories, applyMigrationV4DecisionMadeBy, applyMigrationV5HierarchyTables, applyMigrationV6SliceSummaries, applyMigrationV7Dependencies, applyMigrationV8PlanningFields, applyMigrationV9Ordering, applyMigrationV10ReplanTrigger, applyMigrationV11TaskPlanning, applyMigrationV12QualityGates, applyMigrationV13HotPathIndexes, applyMigrationV14SliceDependencies, applyMigrationV15AuditTables, applyMigrationV16EscalationSource, applyMigrationV17TaskEscalation, applyMigrationV18MemorySources, applyMigrationV19MemoryFts, applyMigrationV20MemoryRelations, applyMigrationV21StructuredMemories, applyMigrationV22QualityGateRepair, applyMigrationV23MilestoneQueue, applyMigrationV26MilestoneCommitAttributions, applyMigrationV27ArtifactHash, applyMigrationV28MemoryLastHitAt, } from "./db-migration-steps.js";
|
|
40
41
|
import { isMemoriesFtsAvailableSchema, tryCreateMemoriesFtsSchema } from "./db-memory-fts-schema.js";
|
|
41
42
|
import { createDbOpenState } from "./db-open-state.js";
|
|
42
43
|
import { createRuntimeKvTableV25 } from "./db-runtime-kv-schema.js";
|
|
@@ -52,7 +53,7 @@ const providerLoader = createSqliteProviderLoader({
|
|
|
52
53
|
nodeVersion: process.versions.node,
|
|
53
54
|
writeStderr: (message) => process.stderr.write(message),
|
|
54
55
|
});
|
|
55
|
-
export const SCHEMA_VERSION =
|
|
56
|
+
export const SCHEMA_VERSION = 28;
|
|
56
57
|
function initSchema(db, fileBacked) {
|
|
57
58
|
if (fileBacked)
|
|
58
59
|
db.exec("PRAGMA journal_mode=WAL");
|
|
@@ -246,6 +247,18 @@ function migrateSchema(db) {
|
|
|
246
247
|
createRuntimeKvTableV25(db);
|
|
247
248
|
recordSchemaVersion(db, 25);
|
|
248
249
|
}
|
|
250
|
+
if (currentVersion < 26) {
|
|
251
|
+
applyMigrationV26MilestoneCommitAttributions(db);
|
|
252
|
+
recordSchemaVersion(db, 26);
|
|
253
|
+
}
|
|
254
|
+
if (currentVersion < 27) {
|
|
255
|
+
applyMigrationV27ArtifactHash(db);
|
|
256
|
+
recordSchemaVersion(db, 27);
|
|
257
|
+
}
|
|
258
|
+
if (currentVersion < 28) {
|
|
259
|
+
applyMigrationV28MemoryLastHitAt(db);
|
|
260
|
+
recordSchemaVersion(db, 28);
|
|
261
|
+
}
|
|
249
262
|
db.exec("COMMIT");
|
|
250
263
|
}
|
|
251
264
|
catch (err) {
|
|
@@ -817,8 +830,9 @@ export function clearArtifacts() {
|
|
|
817
830
|
export function insertArtifact(a) {
|
|
818
831
|
if (!currentDb)
|
|
819
832
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
820
|
-
|
|
821
|
-
|
|
833
|
+
const contentHash = createHash("sha256").update(a.full_content).digest("hex");
|
|
834
|
+
currentDb.prepare(`INSERT OR REPLACE INTO artifacts (path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at, content_hash)
|
|
835
|
+
VALUES (:path, :artifact_type, :milestone_id, :slice_id, :task_id, :full_content, :imported_at, :content_hash)`).run({
|
|
822
836
|
":path": a.path,
|
|
823
837
|
":artifact_type": a.artifact_type,
|
|
824
838
|
":milestone_id": a.milestone_id,
|
|
@@ -826,6 +840,7 @@ export function insertArtifact(a) {
|
|
|
826
840
|
":task_id": a.task_id,
|
|
827
841
|
":full_content": a.full_content,
|
|
828
842
|
":imported_at": new Date().toISOString(),
|
|
843
|
+
":content_hash": contentHash,
|
|
829
844
|
});
|
|
830
845
|
}
|
|
831
846
|
export function insertMilestone(m) {
|
|
@@ -1158,6 +1173,47 @@ export function getSliceTasks(milestoneId, sliceId) {
|
|
|
1158
1173
|
const rows = currentDb.prepare("SELECT * FROM tasks WHERE milestone_id = :mid AND slice_id = :sid ORDER BY sequence, id").all({ ":mid": milestoneId, ":sid": sliceId });
|
|
1159
1174
|
return rows.map(rowToTask);
|
|
1160
1175
|
}
|
|
1176
|
+
export function getCompletedMilestoneTaskFileHints(milestoneId) {
|
|
1177
|
+
if (!currentDb)
|
|
1178
|
+
return [];
|
|
1179
|
+
const rows = currentDb.prepare(`SELECT files, key_files
|
|
1180
|
+
FROM tasks
|
|
1181
|
+
WHERE milestone_id = :mid AND status IN ('complete', 'done')`).all({ ":mid": milestoneId });
|
|
1182
|
+
const hints = new Set();
|
|
1183
|
+
for (const row of rows) {
|
|
1184
|
+
for (const raw of [row["files"], row["key_files"]]) {
|
|
1185
|
+
for (const file of parseStringArrayColumn(raw)) {
|
|
1186
|
+
const normalized = normalizeRepoPath(file);
|
|
1187
|
+
if (normalized)
|
|
1188
|
+
hints.add(normalized);
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
return [...hints];
|
|
1193
|
+
}
|
|
1194
|
+
function parseStringArrayColumn(raw) {
|
|
1195
|
+
if (Array.isArray(raw))
|
|
1196
|
+
return raw.filter((entry) => typeof entry === "string");
|
|
1197
|
+
if (typeof raw !== "string")
|
|
1198
|
+
return [];
|
|
1199
|
+
const trimmed = raw.trim();
|
|
1200
|
+
if (!trimmed)
|
|
1201
|
+
return [];
|
|
1202
|
+
try {
|
|
1203
|
+
const parsed = JSON.parse(trimmed);
|
|
1204
|
+
if (Array.isArray(parsed))
|
|
1205
|
+
return parsed.filter((entry) => typeof entry === "string");
|
|
1206
|
+
if (typeof parsed === "string")
|
|
1207
|
+
return [parsed];
|
|
1208
|
+
}
|
|
1209
|
+
catch {
|
|
1210
|
+
return trimmed.split(",");
|
|
1211
|
+
}
|
|
1212
|
+
return [];
|
|
1213
|
+
}
|
|
1214
|
+
function normalizeRepoPath(file) {
|
|
1215
|
+
return file.trim().replace(/\\/g, "/").replace(/^\.\/+/, "");
|
|
1216
|
+
}
|
|
1161
1217
|
// ─── ADR-011 Phase 2 escalation helpers ──────────────────────────────────
|
|
1162
1218
|
/** Set pause-on-escalation state on a completed task. Mutually exclusive with awaiting_review. */
|
|
1163
1219
|
export function setTaskEscalationPending(milestoneId, sliceId, taskId, artifactPath) {
|
|
@@ -1476,6 +1532,13 @@ export function reconcileWorktreeDb(mainDbPath, worktreeDbPath) {
|
|
|
1476
1532
|
const hasEscalationAwaiting = wtTaskInfo.some((col) => col["name"] === "escalation_awaiting_review");
|
|
1477
1533
|
const hasEscalationArtifact = wtTaskInfo.some((col) => col["name"] === "escalation_artifact_path");
|
|
1478
1534
|
const hasEscalationOverride = wtTaskInfo.some((col) => col["name"] === "escalation_override_applied_at");
|
|
1535
|
+
const wtArtifactInfo = adapter.prepare("PRAGMA wt.table_info('artifacts')").all();
|
|
1536
|
+
const hasArtifactContentHash = wtArtifactInfo.some((col) => col["name"] === "content_hash");
|
|
1537
|
+
const wtMemoryInfo = adapter.prepare("PRAGMA wt.table_info('memories')").all();
|
|
1538
|
+
const hasMemoryScope = wtMemoryInfo.some((col) => col["name"] === "scope");
|
|
1539
|
+
const hasMemoryTags = wtMemoryInfo.some((col) => col["name"] === "tags");
|
|
1540
|
+
const hasMemoryStructuredFields = wtMemoryInfo.some((col) => col["name"] === "structured_fields");
|
|
1541
|
+
const hasMemoryLastHitAt = wtMemoryInfo.some((col) => col["name"] === "last_hit_at");
|
|
1479
1542
|
const decConf = adapter.prepare(`SELECT m.id FROM decisions m INNER JOIN wt.decisions w ON m.id = w.id WHERE m.decision != w.decision OR m.choice != w.choice OR m.rationale != w.rationale OR ${hasMadeBy ? "m.made_by != w.made_by" : "'agent' != 'agent'"} OR m.superseded_by IS NOT w.superseded_by`).all();
|
|
1480
1543
|
for (const row of decConf)
|
|
1481
1544
|
conflicts.push(`decision ${row["id"]}: modified in both`);
|
|
@@ -1508,12 +1571,17 @@ export function reconcileWorktreeDb(mainDbPath, worktreeDbPath) {
|
|
|
1508
1571
|
supporting_slices, validation, notes, full_content, superseded_by
|
|
1509
1572
|
FROM wt.requirements
|
|
1510
1573
|
`).run());
|
|
1574
|
+
// V27: preserve content_hash. If the worktree predates V27 (no column),
|
|
1575
|
+
// fall back to the main DB's existing hash so reconcile doesn't null
|
|
1576
|
+
// out integrity fingerprints on artifacts that were unchanged in wt.
|
|
1511
1577
|
merged.artifacts = countChanges(adapter.prepare(`
|
|
1512
1578
|
INSERT OR REPLACE INTO artifacts (
|
|
1513
|
-
path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at
|
|
1579
|
+
path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at, content_hash
|
|
1514
1580
|
)
|
|
1515
|
-
SELECT path, artifact_type, milestone_id, slice_id, task_id, full_content, imported_at
|
|
1516
|
-
|
|
1581
|
+
SELECT w.path, w.artifact_type, w.milestone_id, w.slice_id, w.task_id, w.full_content, w.imported_at,
|
|
1582
|
+
${hasArtifactContentHash ? "w.content_hash" : "m.content_hash"}
|
|
1583
|
+
FROM wt.artifacts w
|
|
1584
|
+
LEFT JOIN artifacts m ON m.path = w.path
|
|
1517
1585
|
`).run());
|
|
1518
1586
|
// Merge milestones — worktree may have updated status/planning fields.
|
|
1519
1587
|
// Never downgrade status: complete > active > pre-planning (#4372).
|
|
@@ -1611,15 +1679,25 @@ export function reconcileWorktreeDb(mainDbPath, worktreeDbPath) {
|
|
|
1611
1679
|
FROM wt.tasks w
|
|
1612
1680
|
LEFT JOIN tasks m ON m.milestone_id = w.milestone_id AND m.slice_id = w.slice_id AND m.id = w.id
|
|
1613
1681
|
`).run());
|
|
1614
|
-
// Merge memories — keep worktree-learned insights
|
|
1682
|
+
// Merge memories — keep worktree-learned insights.
|
|
1683
|
+
// V18 (scope, tags), V21 (structured_fields), V28 (last_hit_at): for each
|
|
1684
|
+
// column the wt may not yet have (older worktree DB), fall back to the
|
|
1685
|
+
// main DB's existing value via LEFT JOIN so reconcile never silently
|
|
1686
|
+
// resets these fields to defaults on rows that already had them.
|
|
1615
1687
|
merged.memories = countChanges(adapter.prepare(`
|
|
1616
1688
|
INSERT OR REPLACE INTO memories (
|
|
1617
1689
|
seq, id, category, content, confidence, source_unit_type, source_unit_id,
|
|
1618
|
-
created_at, updated_at, superseded_by, hit_count
|
|
1690
|
+
created_at, updated_at, superseded_by, hit_count,
|
|
1691
|
+
scope, tags, structured_fields, last_hit_at
|
|
1619
1692
|
)
|
|
1620
|
-
SELECT seq, id, category, content, confidence, source_unit_type, source_unit_id,
|
|
1621
|
-
created_at, updated_at, superseded_by, hit_count
|
|
1622
|
-
|
|
1693
|
+
SELECT w.seq, w.id, w.category, w.content, w.confidence, w.source_unit_type, w.source_unit_id,
|
|
1694
|
+
w.created_at, w.updated_at, w.superseded_by, w.hit_count,
|
|
1695
|
+
${hasMemoryScope ? "w.scope" : "COALESCE(m.scope, 'project')"},
|
|
1696
|
+
${hasMemoryTags ? "w.tags" : "COALESCE(m.tags, '[]')"},
|
|
1697
|
+
${hasMemoryStructuredFields ? "w.structured_fields" : "m.structured_fields"},
|
|
1698
|
+
${hasMemoryLastHitAt ? "w.last_hit_at" : "m.last_hit_at"}
|
|
1699
|
+
FROM wt.memories w
|
|
1700
|
+
LEFT JOIN memories m ON m.id = w.id
|
|
1623
1701
|
`).run());
|
|
1624
1702
|
// Merge verification evidence — append-only, use INSERT OR IGNORE to avoid duplicates
|
|
1625
1703
|
merged.verification_evidence = countChanges(adapter.prepare(`
|
|
@@ -1735,6 +1813,7 @@ export function deleteMilestone(milestoneId) {
|
|
|
1735
1813
|
currentDb.prepare(`DELETE FROM replan_history WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
|
|
1736
1814
|
currentDb.prepare(`DELETE FROM assessments WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
|
|
1737
1815
|
currentDb.prepare(`DELETE FROM artifacts WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
|
|
1816
|
+
currentDb.prepare(`DELETE FROM milestone_commit_attributions WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
|
|
1738
1817
|
currentDb.prepare(`DELETE FROM milestone_leases WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
|
|
1739
1818
|
currentDb.prepare(`DELETE FROM milestones WHERE id = :mid`).run({ ":mid": milestoneId });
|
|
1740
1819
|
});
|
|
@@ -1962,6 +2041,59 @@ export function upsertTurnGitTransaction(entry) {
|
|
|
1962
2041
|
":updated_at": entry.updatedAt,
|
|
1963
2042
|
});
|
|
1964
2043
|
}
|
|
2044
|
+
export function getMilestoneCommitAttributionShas(milestoneId) {
|
|
2045
|
+
if (!currentDb)
|
|
2046
|
+
return [];
|
|
2047
|
+
const rows = currentDb.prepare(`SELECT commit_sha
|
|
2048
|
+
FROM milestone_commit_attributions
|
|
2049
|
+
WHERE milestone_id = :mid
|
|
2050
|
+
ORDER BY created_at, commit_sha`).all({ ":mid": milestoneId });
|
|
2051
|
+
return rows
|
|
2052
|
+
.map((row) => typeof row["commit_sha"] === "string" ? row["commit_sha"] : "")
|
|
2053
|
+
.filter(Boolean);
|
|
2054
|
+
}
|
|
2055
|
+
export function recordMilestoneCommitAttribution(entry) {
|
|
2056
|
+
if (!currentDb)
|
|
2057
|
+
return;
|
|
2058
|
+
transaction(() => {
|
|
2059
|
+
currentDb.prepare(`INSERT OR REPLACE INTO milestone_commit_attributions (
|
|
2060
|
+
commit_sha, milestone_id, slice_id, task_id, source, confidence, files_json, created_at
|
|
2061
|
+
) VALUES (
|
|
2062
|
+
:commit_sha, :milestone_id, :slice_id, :task_id, :source, :confidence, :files_json, :created_at
|
|
2063
|
+
)`).run({
|
|
2064
|
+
":commit_sha": entry.commitSha,
|
|
2065
|
+
":milestone_id": entry.milestoneId,
|
|
2066
|
+
":slice_id": entry.sliceId ?? null,
|
|
2067
|
+
":task_id": entry.taskId ?? null,
|
|
2068
|
+
":source": entry.source,
|
|
2069
|
+
":confidence": entry.confidence,
|
|
2070
|
+
":files_json": JSON.stringify(entry.files),
|
|
2071
|
+
":created_at": entry.createdAt,
|
|
2072
|
+
});
|
|
2073
|
+
currentDb.prepare(`INSERT OR IGNORE INTO audit_events (
|
|
2074
|
+
event_id, trace_id, turn_id, caused_by, category, type, ts, payload_json
|
|
2075
|
+
) VALUES (
|
|
2076
|
+
:event_id, :trace_id, :turn_id, :caused_by, :category, :type, :ts, :payload_json
|
|
2077
|
+
)`).run({
|
|
2078
|
+
":event_id": `milestone-commit-attribution:${entry.milestoneId}:${entry.commitSha}`,
|
|
2079
|
+
":trace_id": "milestone-commit-attribution",
|
|
2080
|
+
":turn_id": null,
|
|
2081
|
+
":caused_by": null,
|
|
2082
|
+
":category": "git",
|
|
2083
|
+
":type": "milestone-commit-attribution-recorded",
|
|
2084
|
+
":ts": entry.createdAt,
|
|
2085
|
+
":payload_json": JSON.stringify({
|
|
2086
|
+
commitSha: entry.commitSha,
|
|
2087
|
+
milestoneId: entry.milestoneId,
|
|
2088
|
+
sliceId: entry.sliceId ?? null,
|
|
2089
|
+
taskId: entry.taskId ?? null,
|
|
2090
|
+
source: entry.source,
|
|
2091
|
+
confidence: entry.confidence,
|
|
2092
|
+
files: entry.files,
|
|
2093
|
+
}),
|
|
2094
|
+
});
|
|
2095
|
+
});
|
|
2096
|
+
}
|
|
1965
2097
|
export function insertAuditEvent(entry) {
|
|
1966
2098
|
if (!currentDb)
|
|
1967
2099
|
return;
|
|
@@ -2048,6 +2180,7 @@ export function clearEngineHierarchy() {
|
|
|
2048
2180
|
currentDb.exec("DELETE FROM slice_dependencies");
|
|
2049
2181
|
currentDb.exec("DELETE FROM assessments");
|
|
2050
2182
|
currentDb.exec("DELETE FROM replan_history");
|
|
2183
|
+
currentDb.exec("DELETE FROM milestone_commit_attributions");
|
|
2051
2184
|
currentDb.exec("DELETE FROM tasks");
|
|
2052
2185
|
currentDb.exec("DELETE FROM slices");
|
|
2053
2186
|
currentDb.exec("DELETE FROM milestone_leases");
|
|
@@ -2323,7 +2456,7 @@ export function updateMemoryContentRow(id, content, confidence, updatedAt) {
|
|
|
2323
2456
|
export function incrementMemoryHitCount(id, updatedAt) {
|
|
2324
2457
|
if (!currentDb)
|
|
2325
2458
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
2326
|
-
currentDb.prepare("UPDATE memories SET hit_count = hit_count + 1, updated_at = :updated_at WHERE id = :id").run({ ":updated_at": updatedAt, ":id": id });
|
|
2459
|
+
currentDb.prepare("UPDATE memories SET hit_count = hit_count + 1, updated_at = :updated_at, last_hit_at = :last_hit_at WHERE id = :id").run({ ":updated_at": updatedAt, ":last_hit_at": updatedAt, ":id": id });
|
|
2327
2460
|
}
|
|
2328
2461
|
export function supersedeMemoryRow(oldId, newId, updatedAt) {
|
|
2329
2462
|
if (!currentDb)
|
|
@@ -16,7 +16,7 @@ import { invalidateAllCaches } from "./cache.js";
|
|
|
16
16
|
import { startAutoDetached } from "./auto.js";
|
|
17
17
|
import { clearLock } from "./crash-recovery.js";
|
|
18
18
|
import { assessInterruptedSession, formatInterruptedSessionRunningMessage, formatInterruptedSessionSummary, } from "./interrupted-session.js";
|
|
19
|
-
import { listUnitRuntimeRecords, clearUnitRuntimeRecord } from "./unit-runtime.js";
|
|
19
|
+
import { listUnitRuntimeRecords, clearUnitRuntimeRecord, isInFlightRuntimePhase } from "./unit-runtime.js";
|
|
20
20
|
import { resolveExpectedArtifactPath } from "./auto.js";
|
|
21
21
|
import { gsdHome } from "./gsd-home.js";
|
|
22
22
|
import { gsdRoot, milestonesDir, resolveMilestoneFile, resolveMilestonePath, resolveSliceFile, resolveSlicePath, resolveGsdRootFile, relGsdRootFile, relMilestoneFile, relSliceFile, clearPathCache, } from "./paths.js";
|
|
@@ -51,6 +51,21 @@ export { showQueue, handleQueueReorder, showQueueAdd, buildExistingMilestonesCon
|
|
|
51
51
|
import { logWarning } from "./workflow-logger.js";
|
|
52
52
|
import { deleteRuntimeKv } from "./db/runtime-kv.js";
|
|
53
53
|
import { PAUSED_SESSION_KV_KEY } from "./interrupted-session.js";
|
|
54
|
+
function scheduleAutoStartAfterIdle(ctx, pi, basePath, verboseMode, options, launch = startAutoDetached) {
|
|
55
|
+
const waitForIdle = typeof ctx.waitForIdle === "function"
|
|
56
|
+
? ctx.waitForIdle.bind(ctx)
|
|
57
|
+
: async () => { };
|
|
58
|
+
void waitForIdle()
|
|
59
|
+
.then(() => {
|
|
60
|
+
setTimeout(() => launch(ctx, pi, basePath, verboseMode, options), 0);
|
|
61
|
+
})
|
|
62
|
+
.catch((err) => {
|
|
63
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
64
|
+
ctx.ui.notify(`Auto-start failed while waiting for the prior turn to settle: ${message}`, "error");
|
|
65
|
+
logWarning("guided", `auto-start idle wait failed: ${message}`);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
export const _scheduleAutoStartAfterIdleForTest = scheduleAutoStartAfterIdle;
|
|
54
69
|
// ─── Scope-based validator wrappers ──────────────────────────────────────────
|
|
55
70
|
// These thin wrappers accept a MilestoneScope so callers that already hold a
|
|
56
71
|
// pinned scope never have to re-derive (basePath, milestoneId) separately.
|
|
@@ -71,6 +86,19 @@ export function verifyExpectedArtifactForScope(scope, unitType, unitId) {
|
|
|
71
86
|
export function resolveExpectedArtifactPathForScope(scope, unitType, unitId) {
|
|
72
87
|
return resolveExpectedArtifactPath(unitType, unitId, scope.workspace.projectRoot);
|
|
73
88
|
}
|
|
89
|
+
async function runQuickTaskChoice(ctx, pi) {
|
|
90
|
+
if (!ctx.hasUI) {
|
|
91
|
+
ctx.ui.notify("Run /gsd quick <task> for small bounded work, or /gsd do <task> for natural-language routing.", "info");
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const task = (await ctx.ui.input("Quick task", "Describe the small task to run with /gsd quick"))?.trim();
|
|
95
|
+
if (!task) {
|
|
96
|
+
ctx.ui.notify("Quick task cancelled.", "info");
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const { handleQuick } = await import("./quick.js");
|
|
100
|
+
await handleQuick(task, ctx, pi);
|
|
101
|
+
}
|
|
74
102
|
/**
|
|
75
103
|
* Scope-based overload of isGhostMilestone.
|
|
76
104
|
* Binds basePath and milestoneId from the scope, ensuring path resolution
|
|
@@ -312,7 +340,7 @@ async function dispatchNextDeepProjectSetupStage(entry) {
|
|
|
312
340
|
const { DISPATCH_RULES, hasPendingDeepStage } = await import("./auto-dispatch.js");
|
|
313
341
|
if (!hasPendingDeepStage(prefs, entry.basePath)) {
|
|
314
342
|
pendingDeepProjectSetupMap.delete(entry.basePath);
|
|
315
|
-
|
|
343
|
+
scheduleAutoStartAfterIdle(entry.ctx, entry.pi, entry.basePath, false, { step: entry.step });
|
|
316
344
|
return true;
|
|
317
345
|
}
|
|
318
346
|
const state = await deriveState(entry.basePath);
|
|
@@ -346,14 +374,14 @@ async function dispatchNextDeepProjectSetupStage(entry) {
|
|
|
346
374
|
}
|
|
347
375
|
else if (hasPendingDeepStage(prefs, entry.basePath)) {
|
|
348
376
|
pendingDeepProjectSetupMap.delete(entry.basePath);
|
|
349
|
-
|
|
377
|
+
scheduleAutoStartAfterIdle(entry.ctx, entry.pi, entry.basePath, false, { step: entry.step });
|
|
350
378
|
return true;
|
|
351
379
|
}
|
|
352
380
|
return false;
|
|
353
381
|
}
|
|
354
382
|
if (!USER_DRIVEN_DEEP_SETUP_UNITS.has(result.unitType)) {
|
|
355
383
|
pendingDeepProjectSetupMap.delete(entry.basePath);
|
|
356
|
-
|
|
384
|
+
scheduleAutoStartAfterIdle(entry.ctx, entry.pi, entry.basePath, false, { step: entry.step });
|
|
357
385
|
return true;
|
|
358
386
|
}
|
|
359
387
|
entry.currentUnitType = result.unitType;
|
|
@@ -531,7 +559,7 @@ export function checkAutoStartAfterDiscuss() {
|
|
|
531
559
|
}
|
|
532
560
|
pendingAutoStartMap.delete(basePath);
|
|
533
561
|
ctx.ui.notify(`Milestone ${milestoneId} ready.`, "success");
|
|
534
|
-
|
|
562
|
+
scheduleAutoStartAfterIdle(ctx, pi, basePath, false, { step });
|
|
535
563
|
return true;
|
|
536
564
|
}
|
|
537
565
|
/**
|
|
@@ -1469,8 +1497,8 @@ function selfHealRuntimeRecords(basePath, ctx) {
|
|
|
1469
1497
|
cleared++;
|
|
1470
1498
|
continue;
|
|
1471
1499
|
}
|
|
1472
|
-
// Clear records stuck in
|
|
1473
|
-
if (phase
|
|
1500
|
+
// Clear records stuck in an in-flight phase (process died mid-unit).
|
|
1501
|
+
if (isInFlightRuntimePhase(phase)) {
|
|
1474
1502
|
clearUnitRuntimeRecord(basePath, unitType, unitId);
|
|
1475
1503
|
cleared++;
|
|
1476
1504
|
}
|
|
@@ -1695,6 +1723,20 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1695
1723
|
return;
|
|
1696
1724
|
}
|
|
1697
1725
|
}
|
|
1726
|
+
if (interrupted.classification !== "recoverable") {
|
|
1727
|
+
try {
|
|
1728
|
+
const { autoImportMarkdownHierarchyIfDbMismatch } = await import("./migration-auto-check.js");
|
|
1729
|
+
const result = await autoImportMarkdownHierarchyIfDbMismatch(basePath);
|
|
1730
|
+
if (result.action === "imported") {
|
|
1731
|
+
ctx.ui.notify(`Recovered migrated planning state into gsd.db (${result.reason}): ${result.afterDb.milestones} milestone(s), ${result.afterDb.slices} slice(s), ${result.afterDb.tasks} task(s).`, "info");
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
catch (err) {
|
|
1735
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1736
|
+
ctx.ui.notify(`GSD could not auto-import existing planning state into gsd.db: ${message}`, "warning");
|
|
1737
|
+
logWarning("guided", `planning state auto-import failed: ${message}`, { file: "guided-flow.ts" });
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1698
1740
|
// Always derive from the project root — the assessment may have derived
|
|
1699
1741
|
// state from a worktree path that was cleaned up in the stale branch above.
|
|
1700
1742
|
const state = await deriveState(basePath);
|
|
@@ -1716,8 +1758,8 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1716
1758
|
// standard wizard below.
|
|
1717
1759
|
{
|
|
1718
1760
|
const prefs = loadEffectiveGSDPreferences(basePath)?.preferences;
|
|
1719
|
-
const {
|
|
1720
|
-
if (
|
|
1761
|
+
const { shouldRunDeepProjectSetup } = await import("./auto-dispatch.js");
|
|
1762
|
+
if (shouldRunDeepProjectSetup(state, prefs, basePath)) {
|
|
1721
1763
|
await startDeepProjectSetupForeground(ctx, pi, basePath, stepMode);
|
|
1722
1764
|
return;
|
|
1723
1765
|
}
|
|
@@ -1780,16 +1822,24 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1780
1822
|
title: "GSD — Get Shit Done",
|
|
1781
1823
|
summary: ["No active milestone."],
|
|
1782
1824
|
actions: [
|
|
1825
|
+
{
|
|
1826
|
+
id: "quick_task",
|
|
1827
|
+
label: "Quick task",
|
|
1828
|
+
description: "For small bounded work, run /gsd quick <task> or /gsd do <task>.",
|
|
1829
|
+
recommended: true,
|
|
1830
|
+
},
|
|
1783
1831
|
{
|
|
1784
1832
|
id: "new_milestone",
|
|
1785
1833
|
label: "Create next milestone",
|
|
1786
|
-
description: "Define
|
|
1787
|
-
recommended: true,
|
|
1834
|
+
description: "Define a larger body of work with planning artifacts.",
|
|
1788
1835
|
},
|
|
1789
1836
|
],
|
|
1790
1837
|
notYetMessage: "Run /gsd when ready.",
|
|
1791
1838
|
});
|
|
1792
|
-
if (choice === "
|
|
1839
|
+
if (choice === "quick_task") {
|
|
1840
|
+
await runQuickTaskChoice(ctx, pi);
|
|
1841
|
+
}
|
|
1842
|
+
else if (choice === "new_milestone") {
|
|
1793
1843
|
setPendingAutoStart(basePath, { ctx, pi, basePath, milestoneId: nextId, step: stepMode });
|
|
1794
1844
|
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, pi, nextId, `New milestone ${nextId}.`, basePath), "gsd-run", ctx, "discuss-milestone");
|
|
1795
1845
|
}
|
|
@@ -1809,11 +1859,16 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1809
1859
|
title: `GSD — ${milestoneId}: ${milestoneTitle}`,
|
|
1810
1860
|
summary: ["All milestones complete."],
|
|
1811
1861
|
actions: [
|
|
1862
|
+
{
|
|
1863
|
+
id: "quick_task",
|
|
1864
|
+
label: "Quick task",
|
|
1865
|
+
description: "Do a small bounded task without opening a milestone.",
|
|
1866
|
+
recommended: true,
|
|
1867
|
+
},
|
|
1812
1868
|
{
|
|
1813
1869
|
id: "new_milestone",
|
|
1814
1870
|
label: "Start new milestone",
|
|
1815
1871
|
description: "Define and plan the next milestone.",
|
|
1816
|
-
recommended: true,
|
|
1817
1872
|
},
|
|
1818
1873
|
{
|
|
1819
1874
|
id: "status",
|
|
@@ -1823,7 +1878,10 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1823
1878
|
],
|
|
1824
1879
|
notYetMessage: "Run /gsd when ready.",
|
|
1825
1880
|
});
|
|
1826
|
-
if (choice === "
|
|
1881
|
+
if (choice === "quick_task") {
|
|
1882
|
+
await runQuickTaskChoice(ctx, pi);
|
|
1883
|
+
}
|
|
1884
|
+
else if (choice === "new_milestone") {
|
|
1827
1885
|
const milestoneIds = findMilestoneIds(basePath);
|
|
1828
1886
|
const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
|
|
1829
1887
|
const nextId = nextMilestoneIdReserved(milestoneIds, uniqueMilestoneIds, basePath);
|
|
@@ -1916,13 +1974,18 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1916
1974
|
const contextFile = resolveMilestoneFile(basePath, milestoneId, "CONTEXT");
|
|
1917
1975
|
const hasContext = !!(contextFile && await loadFile(contextFile));
|
|
1918
1976
|
const actions = [
|
|
1977
|
+
{
|
|
1978
|
+
id: "quick_task",
|
|
1979
|
+
label: "Quick task instead",
|
|
1980
|
+
description: "Use this when the work is small and should not become a milestone.",
|
|
1981
|
+
recommended: true,
|
|
1982
|
+
},
|
|
1919
1983
|
{
|
|
1920
1984
|
id: "plan",
|
|
1921
1985
|
label: "Create roadmap",
|
|
1922
1986
|
description: hasContext
|
|
1923
1987
|
? "Context captured. Decompose into slices with a boundary map."
|
|
1924
1988
|
: "Decompose the milestone into slices with a boundary map.",
|
|
1925
|
-
recommended: true,
|
|
1926
1989
|
},
|
|
1927
1990
|
...(!hasContext ? [{
|
|
1928
1991
|
id: "discuss",
|
|
@@ -1946,7 +2009,10 @@ export async function showSmartEntry(ctx, pi, basePath, options) {
|
|
|
1946
2009
|
actions,
|
|
1947
2010
|
notYetMessage: "Run /gsd when ready.",
|
|
1948
2011
|
});
|
|
1949
|
-
if (choice === "
|
|
2012
|
+
if (choice === "quick_task") {
|
|
2013
|
+
await runQuickTaskChoice(ctx, pi);
|
|
2014
|
+
}
|
|
2015
|
+
else if (choice === "plan") {
|
|
1950
2016
|
setPendingAutoStart(basePath, { ctx, pi, basePath, milestoneId, step: stepMode });
|
|
1951
2017
|
await dispatchWorkflow(pi, await buildPlanMilestonePrompt(milestoneId, milestoneTitle, basePath), "gsd-run", ctx, "plan-milestone");
|
|
1952
2018
|
}
|
|
@@ -14,6 +14,27 @@ const CATEGORY_PRIORITY = {
|
|
|
14
14
|
environment: 4,
|
|
15
15
|
preference: 5,
|
|
16
16
|
};
|
|
17
|
+
// ─── Scoring Helpers ─────────────────────────────────────────────────────────
|
|
18
|
+
/**
|
|
19
|
+
* Time-decay factor for memory relevance scoring.
|
|
20
|
+
* Returns 1.0 for never-hit or recently-hit memories, decaying linearly to
|
|
21
|
+
* 0.7 for memories not accessed in 90+ days. Floor at 0.7 keeps old-but-valid
|
|
22
|
+
* knowledge from being fully suppressed.
|
|
23
|
+
*
|
|
24
|
+
* Defensive parsing: invalid timestamp strings (NaN from Date.parse) are
|
|
25
|
+
* treated as "no decay" rather than propagating NaN into score arithmetic.
|
|
26
|
+
* Future timestamps (clock skew, manual DB edits) clamp to daysAgo=0 so the
|
|
27
|
+
* factor stays in the documented [0.7, 1.0] contract.
|
|
28
|
+
*/
|
|
29
|
+
export function memoryDecayFactor(lastHitAt) {
|
|
30
|
+
if (!lastHitAt)
|
|
31
|
+
return 1.0;
|
|
32
|
+
const ts = Date.parse(lastHitAt);
|
|
33
|
+
if (!Number.isFinite(ts))
|
|
34
|
+
return 1.0;
|
|
35
|
+
const daysAgo = Math.max(0, (Date.now() - ts) / 86_400_000);
|
|
36
|
+
return Math.max(0.7, 1.0 - 0.3 * Math.min(1.0, daysAgo / 90));
|
|
37
|
+
}
|
|
17
38
|
// ─── Row Mapping ────────────────────────────────────────────────────────────
|
|
18
39
|
function rowToMemory(row) {
|
|
19
40
|
return {
|
|
@@ -31,6 +52,7 @@ function rowToMemory(row) {
|
|
|
31
52
|
scope: row['scope'] ?? 'project',
|
|
32
53
|
tags: parseTags(row['tags']),
|
|
33
54
|
structured_fields: parseStructuredFields(row['structured_fields']),
|
|
55
|
+
last_hit_at: row['last_hit_at'] ?? null,
|
|
34
56
|
};
|
|
35
57
|
}
|
|
36
58
|
function parseStructuredFields(raw) {
|
|
@@ -114,15 +136,37 @@ export function queryMemoriesRanked(opts) {
|
|
|
114
136
|
? semanticSearch(adapter, opts.queryVector, activeClause, 50)
|
|
115
137
|
: [];
|
|
116
138
|
if (keywordHits.length === 0 && semanticHits.length === 0 && !trimmedQuery) {
|
|
117
|
-
// No query at all —
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
139
|
+
// No query at all — return top-k by decay-aware ranked score.
|
|
140
|
+
//
|
|
141
|
+
// Build the candidate pool from a direct SQL query that honors the
|
|
142
|
+
// request's activeClause (i.e. include_superseded). Using
|
|
143
|
+
// getActiveMemoriesRanked here would silently drop superseded rows even
|
|
144
|
+
// when the caller explicitly opted in, and would slice by raw score
|
|
145
|
+
// before decay/filters had a chance to reorder.
|
|
146
|
+
const candidatePool = Math.min(Math.max(k * 5, 50), 500);
|
|
147
|
+
const rows = adapter
|
|
148
|
+
.prepare(`SELECT * FROM memories ${activeClause}
|
|
149
|
+
ORDER BY (confidence * (1.0 + hit_count * 0.1)) DESC
|
|
150
|
+
LIMIT :limit`)
|
|
151
|
+
.all({ ':limit': candidatePool });
|
|
152
|
+
const ranked = [];
|
|
153
|
+
for (const row of rows) {
|
|
154
|
+
const memory = rowToMemory(row);
|
|
155
|
+
if (!passesFilters(memory, opts))
|
|
156
|
+
continue;
|
|
157
|
+
const decay = memoryDecayFactor(memory.last_hit_at);
|
|
158
|
+
const score = memory.confidence * (1 + memory.hit_count * 0.1) * decay;
|
|
159
|
+
ranked.push({
|
|
160
|
+
memory,
|
|
161
|
+
score,
|
|
162
|
+
keywordRank: null,
|
|
163
|
+
semanticRank: null,
|
|
164
|
+
confidenceBoost: score,
|
|
165
|
+
reason: 'ranked',
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
ranked.sort((a, b) => b.score - a.score);
|
|
169
|
+
return ranked.slice(0, k);
|
|
126
170
|
}
|
|
127
171
|
// 3) Reciprocal rank fusion — each hit contributes 1/(rrfK + rank).
|
|
128
172
|
const fused = new Map();
|
|
@@ -155,7 +199,7 @@ export function queryMemoriesRanked(opts) {
|
|
|
155
199
|
for (const entry of fused.values()) {
|
|
156
200
|
if (!passesFilters(entry.memory, opts))
|
|
157
201
|
continue;
|
|
158
|
-
const boost = entry.memory.confidence * (1 + entry.memory.hit_count * 0.1);
|
|
202
|
+
const boost = entry.memory.confidence * (1 + entry.memory.hit_count * 0.1) * memoryDecayFactor(entry.memory.last_hit_at);
|
|
159
203
|
const reason = entry.kwRank != null && entry.semRank != null
|
|
160
204
|
? 'both'
|
|
161
205
|
: entry.kwRank != null
|
|
@@ -194,6 +238,7 @@ function passesFilters(memory, filters) {
|
|
|
194
238
|
}
|
|
195
239
|
return true;
|
|
196
240
|
}
|
|
241
|
+
let ftsWarningEmitted = false;
|
|
197
242
|
function keywordSearch(adapter, rawQuery, activeClause, limit) {
|
|
198
243
|
const ftsAvailable = isFtsAvailable(adapter);
|
|
199
244
|
if (ftsAvailable) {
|
|
@@ -215,14 +260,26 @@ function keywordSearch(adapter, rawQuery, activeClause, limit) {
|
|
|
215
260
|
// fall through to LIKE
|
|
216
261
|
}
|
|
217
262
|
}
|
|
218
|
-
// LIKE fallback — scans
|
|
263
|
+
// LIKE fallback — scans a capped candidate pool.
|
|
264
|
+
if (!ftsWarningEmitted) {
|
|
265
|
+
ftsWarningEmitted = true;
|
|
266
|
+
logWarning('memory-store', 'FTS5 unavailable — using LIKE fallback scan (consider enabling FTS5)');
|
|
267
|
+
}
|
|
219
268
|
const terms = rawQuery
|
|
220
269
|
.toLowerCase()
|
|
221
270
|
.split(/[^a-z0-9_]+/)
|
|
222
271
|
.filter((t) => t.length >= 2);
|
|
223
272
|
if (terms.length === 0)
|
|
224
273
|
return [];
|
|
225
|
-
const
|
|
274
|
+
const preScanCap = Math.min(limit * 20, 2000);
|
|
275
|
+
// ORDER BY confidence-weighted hit_count DESC so the cap keeps the most
|
|
276
|
+
// valuable candidates instead of the oldest-by-rowid (which would silently
|
|
277
|
+
// exclude recently-stored memories on tables larger than preScanCap).
|
|
278
|
+
const rows = adapter
|
|
279
|
+
.prepare(`SELECT * FROM memories ${activeClause}
|
|
280
|
+
ORDER BY (confidence * (1.0 + hit_count * 0.1)) DESC
|
|
281
|
+
LIMIT :preScanCap`)
|
|
282
|
+
.all({ ':preScanCap': preScanCap });
|
|
226
283
|
const scored = [];
|
|
227
284
|
for (const row of rows) {
|
|
228
285
|
const memory = rowToMemory(row);
|