gsd-pi 2.72.0-dev.de4c4b3 → 2.73.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 +12 -2
- package/dist/cli.js +59 -3
- package/dist/onboarding.js +10 -0
- package/dist/resources/extensions/async-jobs/await-tool.js +7 -4
- package/dist/resources/extensions/async-jobs/job-manager.js +28 -3
- package/dist/resources/extensions/claude-code-cli/partial-builder.js +40 -12
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +48 -23
- package/dist/resources/extensions/gsd/auto/loop.js +84 -1
- package/dist/resources/extensions/gsd/auto-post-unit.js +6 -0
- package/dist/resources/extensions/gsd/auto-recovery.js +11 -0
- package/dist/resources/extensions/gsd/auto.js +25 -19
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +9 -11
- package/dist/resources/extensions/gsd/commands-handlers.js +4 -1
- package/dist/resources/extensions/gsd/context-injector.js +1 -1
- package/dist/resources/extensions/gsd/custom-workflow-engine.js +3 -7
- package/dist/resources/extensions/gsd/definition-io.js +15 -0
- package/dist/resources/extensions/gsd/dispatch-guard.js +4 -0
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +6 -3
- package/dist/resources/extensions/gsd/git-service.js +11 -8
- package/dist/resources/extensions/gsd/gitignore.js +12 -6
- package/dist/resources/extensions/gsd/gsd-db.js +49 -6
- package/dist/resources/extensions/gsd/key-manager.js +2 -0
- package/dist/resources/extensions/gsd/preferences-skills.js +2 -34
- package/dist/resources/extensions/gsd/preferences-types.js +15 -0
- package/dist/resources/extensions/gsd/preferences.js +16 -3
- package/dist/resources/extensions/gsd/prompt-loader.js +4 -1
- package/dist/resources/extensions/gsd/prompts/discuss.md +122 -13
- package/dist/resources/extensions/gsd/prompts/system.md +1 -1
- package/dist/resources/extensions/gsd/state.js +21 -1
- package/dist/resources/extensions/gsd/workflow-projections.js +7 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +30 -3
- package/dist/resources/extensions/gsd/write-intercept.js +10 -1
- package/dist/resources/extensions/ollama/index.js +4 -5
- package/dist/resources/extensions/ollama/ollama-client.js +35 -6
- package/dist/resources/extensions/ollama/ollama-discovery.js +32 -6
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
- package/dist/web/standalone/.next/server/chunks/2331.js +16 -16
- package/dist/web/standalone/.next/server/chunks/4741.js +12 -12
- package/dist/web/standalone/.next/server/chunks/5822.js +2 -2
- package/dist/web/standalone/.next/server/chunks/63.js +8 -8
- package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
- package/dist/web/standalone/.next/server/edge-runtime-webpack.js +2 -0
- package/dist/web/standalone/.next/server/functions-config-manifest.json +0 -9
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +29 -2
- package/dist/web/standalone/.next/server/middleware.js +4 -12
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/package.json +1 -1
- package/packages/pi-ai/dist/env-api-keys.js +1 -0
- package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
- package/packages/pi-ai/dist/models.custom.d.ts +105 -0
- package/packages/pi-ai/dist/models.custom.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.custom.js +97 -0
- package/packages/pi-ai/dist/models.custom.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +648 -140
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +867 -370
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.test.d.ts +2 -0
- package/packages/pi-ai/dist/models.generated.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/models.generated.test.js +334 -0
- package/packages/pi-ai/dist/models.generated.test.js.map +1 -0
- package/packages/pi-ai/dist/models.test.js +105 -0
- package/packages/pi-ai/dist/models.test.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +1 -1
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js +5 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js +57 -0
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js.map +1 -0
- package/packages/pi-ai/src/env-api-keys.ts +1 -0
- package/packages/pi-ai/src/models.custom.ts +98 -0
- package/packages/pi-ai/src/models.generated.test.ts +373 -0
- package/packages/pi-ai/src/models.generated.ts +867 -370
- package/packages/pi-ai/src/models.test.ts +135 -0
- package/packages/pi-ai/src/types.ts +1 -0
- package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +71 -0
- package/packages/pi-ai/src/utils/oauth/github-copilot.ts +4 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +9 -0
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -0
- 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/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +87 -12
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
- package/packages/pi-coding-agent/src/core/sdk.ts +10 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +72 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +84 -12
- package/packages/pi-tui/dist/components/__tests__/editor.test.js +12 -0
- package/packages/pi-tui/dist/components/__tests__/editor.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/input.test.js +12 -0
- package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
- package/packages/pi-tui/dist/keys.d.ts.map +1 -1
- package/packages/pi-tui/dist/keys.js +27 -0
- package/packages/pi-tui/dist/keys.js.map +1 -1
- package/packages/pi-tui/src/components/__tests__/editor.test.ts +18 -0
- package/packages/pi-tui/src/components/__tests__/input.test.ts +18 -0
- package/packages/pi-tui/src/keys.ts +32 -0
- package/pkg/package.json +1 -1
- package/src/resources/extensions/async-jobs/await-tool.test.ts +40 -7
- package/src/resources/extensions/async-jobs/await-tool.ts +7 -4
- package/src/resources/extensions/async-jobs/job-manager.ts +33 -3
- package/src/resources/extensions/claude-code-cli/partial-builder.ts +45 -12
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +49 -24
- package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +91 -2
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +112 -0
- package/src/resources/extensions/gsd/auto/loop.ts +89 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +7 -0
- package/src/resources/extensions/gsd/auto-recovery.ts +10 -0
- package/src/resources/extensions/gsd/auto.ts +25 -20
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +8 -10
- package/src/resources/extensions/gsd/commands-handlers.ts +5 -1
- package/src/resources/extensions/gsd/context-injector.ts +1 -1
- package/src/resources/extensions/gsd/custom-workflow-engine.ts +4 -8
- package/src/resources/extensions/gsd/definition-io.ts +18 -0
- package/src/resources/extensions/gsd/dispatch-guard.ts +5 -0
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +6 -3
- package/src/resources/extensions/gsd/git-service.ts +11 -8
- package/src/resources/extensions/gsd/gitignore.ts +12 -6
- package/src/resources/extensions/gsd/gsd-db.ts +54 -6
- package/src/resources/extensions/gsd/key-manager.ts +2 -0
- package/src/resources/extensions/gsd/preferences-skills.ts +2 -36
- package/src/resources/extensions/gsd/preferences-types.ts +16 -0
- package/src/resources/extensions/gsd/preferences.ts +19 -6
- package/src/resources/extensions/gsd/prompt-loader.ts +6 -1
- package/src/resources/extensions/gsd/prompts/discuss.md +122 -13
- package/src/resources/extensions/gsd/prompts/system.md +1 -1
- package/src/resources/extensions/gsd/state.ts +20 -0
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/block-db-writes.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/definition-io.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/doctor-heal-fixable-warnings.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +104 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +107 -5
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +8 -6
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/plan-milestone-artifact-verification.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/preferences-formatting.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/projection-regression.test.ts +96 -1
- package/src/resources/extensions/gsd/tests/prompt-loader-working-directory.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +41 -0
- package/src/resources/extensions/gsd/workflow-projections.ts +8 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +29 -3
- package/src/resources/extensions/gsd/write-intercept.ts +10 -1
- package/src/resources/extensions/ollama/index.ts +4 -5
- package/src/resources/extensions/ollama/ollama-client.ts +35 -6
- package/src/resources/extensions/ollama/ollama-discovery.ts +37 -6
- package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +54 -0
- package/dist/resources/extensions/gsd/auto-observability.js +0 -54
- package/dist/resources/extensions/gsd/file-watcher.js +0 -80
- package/dist/resources/extensions/gsd/rtk-status.js +0 -43
- package/dist/web/standalone/.next/static/chunks/app/page-f1e30ab6bb269149.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
- package/src/resources/extensions/gsd/auto-observability.ts +0 -72
- package/src/resources/extensions/gsd/file-watcher.ts +0 -100
- package/src/resources/extensions/gsd/rtk-status.ts +0 -53
- /package/dist/web/standalone/.next/static/{f-Gremw0nLxxFUySaHRPw → KSZ2dcC3p4z6lOmUpPpzr}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{f-Gremw0nLxxFUySaHRPw → KSZ2dcC3p4z6lOmUpPpzr}/_ssgManifest.js +0 -0
|
@@ -677,9 +677,13 @@ function cleanupAfterLoopExit(ctx: ExtensionContext): void {
|
|
|
677
677
|
logWarning("session", `lock cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
678
678
|
}
|
|
679
679
|
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
680
|
+
// A transient provider-error pause intentionally leaves the paused badge
|
|
681
|
+
// visible so the user still has a resumable auto-mode signal on screen.
|
|
682
|
+
if (!s.paused) {
|
|
683
|
+
ctx.ui.setStatus("gsd-auto", undefined);
|
|
684
|
+
ctx.ui.setWidget("gsd-progress", undefined);
|
|
685
|
+
ctx.ui.setFooter(undefined);
|
|
686
|
+
}
|
|
683
687
|
|
|
684
688
|
// Restore CWD out of worktree back to original project root
|
|
685
689
|
if (s.originalBasePath) {
|
|
@@ -791,7 +795,22 @@ export async function stopAuto(
|
|
|
791
795
|
debugLog("stop-cleanup-worktree", { error: e instanceof Error ? e.message : String(e) });
|
|
792
796
|
}
|
|
793
797
|
|
|
794
|
-
// ── Step 5: DB
|
|
798
|
+
// ── Step 5: Rebuild state while DB is still open (#3599) ──
|
|
799
|
+
// rebuildState() calls deriveState() which needs the DB for authoritative
|
|
800
|
+
// state. Previously this ran after closeDatabase(), forcing a filesystem
|
|
801
|
+
// fallback that could disagree with the DB-backed dispatch decisions —
|
|
802
|
+
// a split-brain where dispatch says "blocked" but STATE.md shows work.
|
|
803
|
+
if (s.basePath) {
|
|
804
|
+
try {
|
|
805
|
+
await rebuildState(s.basePath);
|
|
806
|
+
} catch (e) {
|
|
807
|
+
debugLog("stop-rebuild-state-failed", {
|
|
808
|
+
error: e instanceof Error ? e.message : String(e),
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
// ── Step 6: DB cleanup ──
|
|
795
814
|
if (isDbAvailable()) {
|
|
796
815
|
try {
|
|
797
816
|
const { closeDatabase } = await import("./gsd-db.js");
|
|
@@ -803,7 +822,7 @@ export async function stopAuto(
|
|
|
803
822
|
}
|
|
804
823
|
}
|
|
805
824
|
|
|
806
|
-
// ── Step
|
|
825
|
+
// ── Step 7: Restore basePath and chdir ──
|
|
807
826
|
try {
|
|
808
827
|
if (s.originalBasePath) {
|
|
809
828
|
s.basePath = s.originalBasePath;
|
|
@@ -818,7 +837,7 @@ export async function stopAuto(
|
|
|
818
837
|
debugLog("stop-cleanup-basepath", { error: e instanceof Error ? e.message : String(e) });
|
|
819
838
|
}
|
|
820
839
|
|
|
821
|
-
// ── Step
|
|
840
|
+
// ── Step 8: Ledger notification ──
|
|
822
841
|
try {
|
|
823
842
|
const ledger = getLedger();
|
|
824
843
|
if (ledger && ledger.units.length > 0) {
|
|
@@ -834,17 +853,6 @@ export async function stopAuto(
|
|
|
834
853
|
debugLog("stop-cleanup-ledger", { error: e instanceof Error ? e.message : String(e) });
|
|
835
854
|
}
|
|
836
855
|
|
|
837
|
-
// ── Step 8: Rebuild state ──
|
|
838
|
-
if (s.basePath) {
|
|
839
|
-
try {
|
|
840
|
-
await rebuildState(s.basePath);
|
|
841
|
-
} catch (e) {
|
|
842
|
-
debugLog("stop-rebuild-state-failed", {
|
|
843
|
-
error: e instanceof Error ? e.message : String(e),
|
|
844
|
-
});
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
|
|
848
856
|
// ── Step 9: Cmux sidebar / event log ──
|
|
849
857
|
try {
|
|
850
858
|
clearCmuxSidebar(loadedPreferences);
|
|
@@ -1713,9 +1721,6 @@ export async function dispatchHookUnit(
|
|
|
1713
1721
|
return true;
|
|
1714
1722
|
}
|
|
1715
1723
|
|
|
1716
|
-
// Direct phase dispatch → auto-direct-dispatch.ts
|
|
1717
|
-
export { dispatchDirectPhase } from "./auto-direct-dispatch.js";
|
|
1718
|
-
|
|
1719
1724
|
// Re-export recovery functions for external consumers
|
|
1720
1725
|
export {
|
|
1721
1726
|
buildLoopRemediationSteps,
|
|
@@ -181,14 +181,10 @@ export function registerHooks(pi: ExtensionAPI): void {
|
|
|
181
181
|
// Only gate-shaped ask_user_questions calls should block execution.
|
|
182
182
|
// The gate stays pending until the user selects the approval option.
|
|
183
183
|
if (event.toolName === "ask_user_questions") {
|
|
184
|
-
const
|
|
185
|
-
const
|
|
186
|
-
if (
|
|
187
|
-
|
|
188
|
-
const questionId = questions.find((question) => typeof question?.id === "string" && isGateQuestionId(question.id))?.id;
|
|
189
|
-
if (typeof questionId === "string") {
|
|
190
|
-
setPendingGate(questionId);
|
|
191
|
-
}
|
|
184
|
+
const questions: any[] = (event.input as any)?.questions ?? [];
|
|
185
|
+
const questionId = questions.find((question) => typeof question?.id === "string" && isGateQuestionId(question.id))?.id;
|
|
186
|
+
if (typeof questionId === "string") {
|
|
187
|
+
setPendingGate(questionId);
|
|
192
188
|
}
|
|
193
189
|
}
|
|
194
190
|
|
|
@@ -286,7 +282,6 @@ export function registerHooks(pi: ExtensionAPI): void {
|
|
|
286
282
|
if (event.toolName !== "ask_user_questions") return;
|
|
287
283
|
const milestoneId = getDiscussionMilestoneId(process.cwd());
|
|
288
284
|
const queueActive = isQueuePhaseActive();
|
|
289
|
-
if (!milestoneId && !queueActive) return;
|
|
290
285
|
|
|
291
286
|
const details = event.details as any;
|
|
292
287
|
|
|
@@ -319,13 +314,16 @@ export function registerHooks(pi: ExtensionAPI): void {
|
|
|
319
314
|
// Only unlock the gate if the user selected the first option (confirmation).
|
|
320
315
|
// Cross-references against the question's defined options to reject free-form "Other" text.
|
|
321
316
|
const answer = details.response?.answers?.[question.id];
|
|
317
|
+
const inferredMilestoneId = extractDepthVerificationMilestoneId(question.id) ?? milestoneId;
|
|
322
318
|
if (isDepthConfirmationAnswer(answer?.selected, question.options)) {
|
|
323
|
-
markDepthVerified(
|
|
319
|
+
markDepthVerified(inferredMilestoneId);
|
|
320
|
+
clearPendingGate();
|
|
324
321
|
}
|
|
325
322
|
break;
|
|
326
323
|
}
|
|
327
324
|
}
|
|
328
325
|
|
|
326
|
+
if (!milestoneId && !queueActive) return;
|
|
329
327
|
if (!milestoneId) return;
|
|
330
328
|
|
|
331
329
|
const basePath = process.cwd();
|
|
@@ -78,6 +78,10 @@ export function parseDoctorArgs(args: string) {
|
|
|
78
78
|
return { jsonMode, dryRun, fixFlag, includeBuild, includeTests, mode, requestedScope };
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
export function isDoctorHealActionable(issue: { fixable: boolean; severity: string }): boolean {
|
|
82
|
+
return issue.fixable && issue.severity !== "info";
|
|
83
|
+
}
|
|
84
|
+
|
|
81
85
|
export async function handleDoctor(args: string, ctx: ExtensionCommandContext, pi: ExtensionAPI): Promise<void> {
|
|
82
86
|
const { jsonMode, dryRun, fixFlag, includeBuild, includeTests, mode, requestedScope } = parseDoctorArgs(args);
|
|
83
87
|
const scope = await selectDoctorScope(projectRoot(), requestedScope);
|
|
@@ -109,7 +113,7 @@ export async function handleDoctor(args: string, ctx: ExtensionCommandContext, p
|
|
|
109
113
|
scope: effectiveScope,
|
|
110
114
|
includeWarnings: true,
|
|
111
115
|
});
|
|
112
|
-
const actionable = unresolved.filter(
|
|
116
|
+
const actionable = unresolved.filter(isDoctorHealActionable);
|
|
113
117
|
if (actionable.length === 0) {
|
|
114
118
|
ctx.ui.notify("Doctor heal found nothing actionable to hand off to the LLM.", "info");
|
|
115
119
|
return;
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import { readFileSync, existsSync } from "node:fs";
|
|
17
17
|
import { join, resolve, sep } from "node:path";
|
|
18
18
|
import type { StepDefinition } from "./definition-loader.js";
|
|
19
|
-
import { readFrozenDefinition } from "./
|
|
19
|
+
import { readFrozenDefinition } from "./definition-io.js";
|
|
20
20
|
|
|
21
21
|
/** Maximum characters per artifact to prevent context window blowout. */
|
|
22
22
|
const MAX_CONTEXT_CHARS = 10_000;
|
|
@@ -22,7 +22,6 @@ import type {
|
|
|
22
22
|
} from "./engine-types.js";
|
|
23
23
|
import { readFileSync } from "node:fs";
|
|
24
24
|
import { join } from "node:path";
|
|
25
|
-
import { parse } from "yaml";
|
|
26
25
|
import {
|
|
27
26
|
readGraph,
|
|
28
27
|
writeGraph,
|
|
@@ -32,16 +31,13 @@ import {
|
|
|
32
31
|
type WorkflowGraph,
|
|
33
32
|
} from "./graph.js";
|
|
34
33
|
import { injectContext } from "./context-injector.js";
|
|
35
|
-
import type {
|
|
34
|
+
import type { StepDefinition } from "./definition-loader.js";
|
|
35
|
+
import { readFrozenDefinition } from "./definition-io.js";
|
|
36
36
|
import { parseUnitId } from "./unit-id.js";
|
|
37
37
|
import { withFileLock } from "./file-lock.js";
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
export
|
|
41
|
-
const defPath = join(runDir, "DEFINITION.yaml");
|
|
42
|
-
const raw = readFileSync(defPath, "utf-8");
|
|
43
|
-
return parse(raw, { schema: "core" }) as WorkflowDefinition;
|
|
44
|
-
}
|
|
39
|
+
// Re-export for downstream consumers
|
|
40
|
+
export { readFrozenDefinition } from "./definition-io.js";
|
|
45
41
|
|
|
46
42
|
export class CustomWorkflowEngine implements WorkflowEngine {
|
|
47
43
|
readonly engineId = "custom";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* definition-io.ts — Read frozen DEFINITION.yaml from a run directory.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from custom-workflow-engine.ts to break the circular dependency
|
|
5
|
+
* between context-injector.ts and custom-workflow-engine.ts.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { readFileSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { parse } from "yaml";
|
|
11
|
+
import type { WorkflowDefinition } from "./definition-loader.js";
|
|
12
|
+
|
|
13
|
+
/** Read and parse the frozen DEFINITION.yaml from a run directory. */
|
|
14
|
+
export function readFrozenDefinition(runDir: string): WorkflowDefinition {
|
|
15
|
+
const defPath = join(runDir, "DEFINITION.yaml");
|
|
16
|
+
const raw = readFileSync(defPath, "utf-8");
|
|
17
|
+
return parse(raw, { schema: "core" }) as WorkflowDefinition;
|
|
18
|
+
}
|
|
@@ -107,6 +107,11 @@ export function getPriorSliceCompletionBlocker(
|
|
|
107
107
|
// it may be a cross-milestone reference handled elsewhere.
|
|
108
108
|
}
|
|
109
109
|
} else {
|
|
110
|
+
const milestoneUsesExplicitDeps = slices.some((slice) => slice.depends.length > 0);
|
|
111
|
+
if (milestoneUsesExplicitDeps) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
110
115
|
// Positional fallback is only a heuristic for legacy slices with no
|
|
111
116
|
// declared dependencies. Skip any earlier slice that depends on the
|
|
112
117
|
// target, directly or transitively, or we can deadlock a valid zero-dep
|
|
@@ -303,13 +303,16 @@ export async function checkRuntimeHealth(
|
|
|
303
303
|
content.split("\n").map(l => l.trim()).filter(l => l && !l.startsWith("#")),
|
|
304
304
|
);
|
|
305
305
|
|
|
306
|
-
// Check for critical runtime patterns that must be present
|
|
306
|
+
// Check for critical runtime patterns that must be present.
|
|
307
|
+
// NOTE: GSD_RUNTIME_PATTERNS in gitignore.ts is the canonical source of truth.
|
|
308
|
+
// This is a minimal subset for the doctor check.
|
|
307
309
|
const criticalPatterns = [
|
|
308
310
|
".gsd/activity/",
|
|
309
311
|
".gsd/runtime/",
|
|
310
312
|
".gsd/auto.lock",
|
|
311
|
-
".gsd/gsd.db",
|
|
312
|
-
".gsd/completed-units
|
|
313
|
+
".gsd/gsd.db*",
|
|
314
|
+
".gsd/completed-units*.json",
|
|
315
|
+
".gsd/event-log.jsonl",
|
|
313
316
|
];
|
|
314
317
|
|
|
315
318
|
// If blanket .gsd/ or .gsd is present, all patterns are covered
|
|
@@ -192,22 +192,25 @@ export interface PreMergeCheckResult {
|
|
|
192
192
|
/**
|
|
193
193
|
* GSD runtime paths that should be excluded from smart staging.
|
|
194
194
|
* These are transient/generated artifacts that should never be committed.
|
|
195
|
-
*
|
|
196
|
-
*
|
|
195
|
+
*
|
|
196
|
+
* NOTE: GSD_RUNTIME_PATTERNS in gitignore.ts is the canonical source of truth.
|
|
197
|
+
* This array must stay synchronized with it.
|
|
197
198
|
*/
|
|
198
199
|
export const RUNTIME_EXCLUSION_PATHS: readonly string[] = [
|
|
199
200
|
".gsd/activity/",
|
|
201
|
+
".gsd/forensics/",
|
|
200
202
|
".gsd/runtime/",
|
|
201
203
|
".gsd/worktrees/",
|
|
204
|
+
".gsd/parallel/",
|
|
202
205
|
".gsd/auto.lock",
|
|
203
206
|
".gsd/metrics.json",
|
|
204
|
-
".gsd/completed-units
|
|
207
|
+
".gsd/completed-units*.json", // covers completed-units.json and archived completed-units-{MID}.json
|
|
208
|
+
".gsd/state-manifest.json",
|
|
205
209
|
".gsd/STATE.md",
|
|
206
|
-
".gsd/gsd.db",
|
|
207
|
-
".gsd/
|
|
208
|
-
".gsd/
|
|
209
|
-
".gsd/
|
|
210
|
-
".gsd/doctor-history.jsonl", // doctor run history (#2296)
|
|
210
|
+
".gsd/gsd.db*",
|
|
211
|
+
".gsd/journal/",
|
|
212
|
+
".gsd/doctor-history.jsonl",
|
|
213
|
+
".gsd/event-log.jsonl",
|
|
211
214
|
".gsd/DISCUSSION-MANIFEST.json",
|
|
212
215
|
];
|
|
213
216
|
|
|
@@ -15,6 +15,12 @@ import { GIT_NO_PROMPT_ENV } from "./git-constants.js";
|
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* GSD runtime patterns for git index cleanup.
|
|
18
|
+
*
|
|
19
|
+
* CANONICAL SOURCE OF TRUTH: This array is the authoritative list of runtime
|
|
20
|
+
* ignore patterns. Other modules (RUNTIME_EXCLUSION_PATHS in git-service.ts,
|
|
21
|
+
* SKIP_* arrays in worktree-manager.ts, criticalPatterns in doctor-runtime-checks.ts)
|
|
22
|
+
* must stay synchronized with this list.
|
|
23
|
+
*
|
|
18
24
|
* With external state (symlink), these are a no-op in most cases,
|
|
19
25
|
* but retained for backwards compatibility during migration.
|
|
20
26
|
*/
|
|
@@ -26,13 +32,13 @@ const GSD_RUNTIME_PATTERNS = [
|
|
|
26
32
|
".gsd/parallel/",
|
|
27
33
|
".gsd/auto.lock",
|
|
28
34
|
".gsd/metrics.json",
|
|
29
|
-
".gsd/completed-units
|
|
35
|
+
".gsd/completed-units*.json", // covers completed-units.json and archived completed-units-{MID}.json
|
|
36
|
+
".gsd/state-manifest.json",
|
|
30
37
|
".gsd/STATE.md",
|
|
31
|
-
".gsd/gsd.db",
|
|
32
|
-
".gsd/
|
|
33
|
-
".gsd/
|
|
34
|
-
".gsd/
|
|
35
|
-
".gsd/doctor-history.jsonl", // doctor run history (#2296)
|
|
38
|
+
".gsd/gsd.db*",
|
|
39
|
+
".gsd/journal/",
|
|
40
|
+
".gsd/doctor-history.jsonl",
|
|
41
|
+
".gsd/event-log.jsonl",
|
|
36
42
|
".gsd/DISCUSSION-MANIFEST.json",
|
|
37
43
|
".gsd/milestones/**/*-CONTINUE.md",
|
|
38
44
|
".gsd/milestones/**/continue.md",
|
|
@@ -163,13 +163,36 @@ function openRawDb(path: string): unknown {
|
|
|
163
163
|
|
|
164
164
|
const SCHEMA_VERSION = 14;
|
|
165
165
|
|
|
166
|
+
function indexExists(db: DbAdapter, name: string): boolean {
|
|
167
|
+
return !!db.prepare(
|
|
168
|
+
"SELECT 1 as present FROM sqlite_master WHERE type = 'index' AND name = ?",
|
|
169
|
+
).get(name);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function dedupeVerificationEvidenceRows(db: DbAdapter): void {
|
|
173
|
+
db.exec(`
|
|
174
|
+
DELETE FROM verification_evidence
|
|
175
|
+
WHERE rowid NOT IN (
|
|
176
|
+
SELECT MIN(rowid)
|
|
177
|
+
FROM verification_evidence
|
|
178
|
+
GROUP BY task_id, slice_id, milestone_id, command, verdict
|
|
179
|
+
)
|
|
180
|
+
`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function ensureVerificationEvidenceDedupIndex(db: DbAdapter): void {
|
|
184
|
+
if (indexExists(db, "idx_verification_evidence_dedup")) return;
|
|
185
|
+
dedupeVerificationEvidenceRows(db);
|
|
186
|
+
db.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_verification_evidence_dedup ON verification_evidence(task_id, slice_id, milestone_id, command, verdict)");
|
|
187
|
+
}
|
|
188
|
+
|
|
166
189
|
function initSchema(db: DbAdapter, fileBacked: boolean): void {
|
|
167
190
|
if (fileBacked) db.exec("PRAGMA journal_mode=WAL");
|
|
168
191
|
if (fileBacked) db.exec("PRAGMA busy_timeout = 5000");
|
|
169
192
|
if (fileBacked) db.exec("PRAGMA synchronous = NORMAL");
|
|
170
193
|
if (fileBacked) db.exec("PRAGMA auto_vacuum = INCREMENTAL");
|
|
171
194
|
if (fileBacked) db.exec("PRAGMA cache_size = -8000"); // 8 MB page cache
|
|
172
|
-
if (fileBacked) db.exec("PRAGMA mmap_size = 67108864"); // 64 MB mmap
|
|
195
|
+
if (fileBacked && process.platform !== "darwin") db.exec("PRAGMA mmap_size = 67108864"); // 64 MB mmap
|
|
173
196
|
db.exec("PRAGMA temp_store = MEMORY");
|
|
174
197
|
db.exec("PRAGMA foreign_keys = ON");
|
|
175
198
|
|
|
@@ -410,7 +433,7 @@ function initSchema(db: DbAdapter, fileBacked: boolean): void {
|
|
|
410
433
|
db.exec("CREATE INDEX IF NOT EXISTS idx_milestones_status ON milestones(status)");
|
|
411
434
|
db.exec("CREATE INDEX IF NOT EXISTS idx_quality_gates_pending ON quality_gates(milestone_id, slice_id, status)");
|
|
412
435
|
db.exec("CREATE INDEX IF NOT EXISTS idx_verification_evidence_task ON verification_evidence(milestone_id, slice_id, task_id)");
|
|
413
|
-
db
|
|
436
|
+
ensureVerificationEvidenceDedupIndex(db);
|
|
414
437
|
|
|
415
438
|
// v14 index — slice dependency lookups
|
|
416
439
|
db.exec("CREATE INDEX IF NOT EXISTS idx_slice_deps_target ON slice_dependencies(milestone_id, depends_on_slice_id)");
|
|
@@ -743,7 +766,7 @@ function migrateSchema(db: DbAdapter): void {
|
|
|
743
766
|
db.exec("CREATE INDEX IF NOT EXISTS idx_milestones_status ON milestones(status)");
|
|
744
767
|
db.exec("CREATE INDEX IF NOT EXISTS idx_quality_gates_pending ON quality_gates(milestone_id, slice_id, status)");
|
|
745
768
|
db.exec("CREATE INDEX IF NOT EXISTS idx_verification_evidence_task ON verification_evidence(milestone_id, slice_id, task_id)");
|
|
746
|
-
db
|
|
769
|
+
ensureVerificationEvidenceDedupIndex(db);
|
|
747
770
|
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
748
771
|
":version": 13,
|
|
749
772
|
":applied_at": new Date().toISOString(),
|
|
@@ -857,6 +880,7 @@ export function closeDatabase(): void {
|
|
|
857
880
|
currentDb = null;
|
|
858
881
|
currentPath = null;
|
|
859
882
|
currentPid = 0;
|
|
883
|
+
_dbOpenAttempted = false;
|
|
860
884
|
}
|
|
861
885
|
}
|
|
862
886
|
|
|
@@ -1541,6 +1565,30 @@ export interface TaskRow {
|
|
|
1541
1565
|
}
|
|
1542
1566
|
|
|
1543
1567
|
function rowToTask(row: Record<string, unknown>): TaskRow {
|
|
1568
|
+
const parseTaskArray = (value: unknown): string[] => {
|
|
1569
|
+
if (Array.isArray(value)) {
|
|
1570
|
+
return value.filter((entry): entry is string => typeof entry === "string");
|
|
1571
|
+
}
|
|
1572
|
+
if (typeof value !== "string") return [];
|
|
1573
|
+
|
|
1574
|
+
const trimmed = value.trim();
|
|
1575
|
+
if (!trimmed) return [];
|
|
1576
|
+
|
|
1577
|
+
try {
|
|
1578
|
+
const parsed = JSON.parse(trimmed);
|
|
1579
|
+
if (Array.isArray(parsed)) {
|
|
1580
|
+
return parsed.filter((entry): entry is string => typeof entry === "string");
|
|
1581
|
+
}
|
|
1582
|
+
if (typeof parsed === "string" && parsed.trim()) {
|
|
1583
|
+
return [parsed.trim()];
|
|
1584
|
+
}
|
|
1585
|
+
} catch {
|
|
1586
|
+
// Older/corrupt DB rows may contain raw comma-separated paths instead of JSON arrays.
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
return trimmed.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
1590
|
+
};
|
|
1591
|
+
|
|
1544
1592
|
return {
|
|
1545
1593
|
milestone_id: row["milestone_id"] as string,
|
|
1546
1594
|
slice_id: row["slice_id"] as string,
|
|
@@ -1560,10 +1608,10 @@ function rowToTask(row: Record<string, unknown>): TaskRow {
|
|
|
1560
1608
|
full_summary_md: row["full_summary_md"] as string,
|
|
1561
1609
|
description: (row["description"] as string) ?? "",
|
|
1562
1610
|
estimate: (row["estimate"] as string) ?? "",
|
|
1563
|
-
files:
|
|
1611
|
+
files: parseTaskArray(row["files"]),
|
|
1564
1612
|
verify: (row["verify"] as string) ?? "",
|
|
1565
|
-
inputs:
|
|
1566
|
-
expected_output:
|
|
1613
|
+
inputs: parseTaskArray(row["inputs"]),
|
|
1614
|
+
expected_output: parseTaskArray(row["expected_output"]),
|
|
1567
1615
|
observability_impact: (row["observability_impact"] as string) ?? "",
|
|
1568
1616
|
full_plan_md: (row["full_plan_md"] as string) ?? "",
|
|
1569
1617
|
sequence: (row["sequence"] as number) ?? 0,
|
|
@@ -49,6 +49,8 @@ export const PROVIDER_REGISTRY: ProviderInfo[] = [
|
|
|
49
49
|
{ id: "custom-openai", label: "Custom (OpenAI-compat)", category: "llm", envVar: "CUSTOM_OPENAI_API_KEY" },
|
|
50
50
|
{ id: "cerebras", label: "Cerebras", category: "llm", envVar: "CEREBRAS_API_KEY" },
|
|
51
51
|
{ id: "azure-openai-responses", label: "Azure OpenAI", category: "llm", envVar: "AZURE_OPENAI_API_KEY" },
|
|
52
|
+
{ id: "alibaba-coding-plan", label: "Alibaba Coding Plan", category: "llm", envVar: "ALIBABA_API_KEY", dashboardUrl: "bailian.console.aliyun.com" },
|
|
53
|
+
{ id: "alibaba-dashscope", label: "Alibaba DashScope", category: "llm", envVar: "DASHSCOPE_API_KEY", dashboardUrl: "dashscope.console.aliyun.com" },
|
|
52
54
|
|
|
53
55
|
// Tool Keys
|
|
54
56
|
{ id: "context7", label: "Context7 Docs", category: "tool", envVar: "CONTEXT7_API_KEY", dashboardUrl: "context7.com/dashboard" },
|
|
@@ -17,7 +17,6 @@ import type {
|
|
|
17
17
|
SkillResolutionReport,
|
|
18
18
|
} from "./preferences-types.js";
|
|
19
19
|
import { validatePreferences } from "./preferences-validation.js";
|
|
20
|
-
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
21
20
|
|
|
22
21
|
// Re-export types so existing consumers of ./preferences-skills.js keep working
|
|
23
22
|
export type { GSDSkillRule, SkillDiscoveryMode, SkillResolution, SkillResolutionReport } from "./preferences-types.js";
|
|
@@ -143,38 +142,5 @@ export function resolveAllSkillReferences(preferences: GSDPreferences, cwd: stri
|
|
|
143
142
|
return { resolutions, warnings };
|
|
144
143
|
}
|
|
145
144
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
* If resolved, shows the path so the agent knows exactly where to read.
|
|
149
|
-
* If unresolved, marks it clearly.
|
|
150
|
-
*/
|
|
151
|
-
export function formatSkillRef(ref: string, resolutions: Map<string, SkillResolution>): string {
|
|
152
|
-
const resolution = resolutions.get(ref);
|
|
153
|
-
if (!resolution || resolution.method === "unresolved") {
|
|
154
|
-
return `${ref} (⚠ not found — check skill name or path)`;
|
|
155
|
-
}
|
|
156
|
-
// For absolute paths where SKILL.md is just appended, don't clutter the output
|
|
157
|
-
if (resolution.method === "absolute-path" || resolution.method === "absolute-dir") {
|
|
158
|
-
return ref;
|
|
159
|
-
}
|
|
160
|
-
// For bare names resolved from skill directories, show the resolved path
|
|
161
|
-
return `${ref} → \`${resolution.resolvedPath}\``;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Resolve the skill discovery mode from effective preferences.
|
|
166
|
-
* Defaults to "suggest" -- skills are identified during research but not installed automatically.
|
|
167
|
-
*/
|
|
168
|
-
export function resolveSkillDiscoveryMode(): SkillDiscoveryMode {
|
|
169
|
-
const prefs = loadEffectiveGSDPreferences();
|
|
170
|
-
return prefs?.preferences.skill_discovery ?? "suggest";
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Resolve the skill staleness threshold in days.
|
|
175
|
-
* Returns 0 if disabled, default 60 if not configured.
|
|
176
|
-
*/
|
|
177
|
-
export function resolveSkillStalenessDays(): number {
|
|
178
|
-
const prefs = loadEffectiveGSDPreferences();
|
|
179
|
-
return prefs?.preferences.skill_staleness_days ?? 60;
|
|
180
|
-
}
|
|
145
|
+
// resolveSkillDiscoveryMode and resolveSkillStalenessDays moved to
|
|
146
|
+
// preferences.ts to break circular dependency (they need loadEffectiveGSDPreferences).
|
|
@@ -384,3 +384,19 @@ export interface SkillResolutionReport {
|
|
|
384
384
|
/** References that could not be resolved. */
|
|
385
385
|
warnings: string[];
|
|
386
386
|
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Format a skill reference for the system prompt.
|
|
390
|
+
* If resolved, shows the path so the agent knows exactly where to read.
|
|
391
|
+
* If unresolved, marks it clearly.
|
|
392
|
+
*/
|
|
393
|
+
export function formatSkillRef(ref: string, resolutions: Map<string, SkillResolution>): string {
|
|
394
|
+
const resolution = resolutions.get(ref);
|
|
395
|
+
if (!resolution || resolution.method === "unresolved") {
|
|
396
|
+
return `${ref} (⚠ not found — check skill name or path)`;
|
|
397
|
+
}
|
|
398
|
+
if (resolution.method === "absolute-path" || resolution.method === "absolute-dir") {
|
|
399
|
+
return ref;
|
|
400
|
+
}
|
|
401
|
+
return `${ref} → \`${resolution.resolvedPath}\``;
|
|
402
|
+
}
|
|
@@ -29,9 +29,10 @@ import {
|
|
|
29
29
|
type GSDPreferences,
|
|
30
30
|
type LoadedGSDPreferences,
|
|
31
31
|
type SkillResolution,
|
|
32
|
+
type SkillDiscoveryMode,
|
|
33
|
+
formatSkillRef,
|
|
32
34
|
} from "./preferences-types.js";
|
|
33
35
|
import { validatePreferences } from "./preferences-validation.js";
|
|
34
|
-
import { formatSkillRef } from "./preferences-skills.js";
|
|
35
36
|
|
|
36
37
|
// ─── Re-exports: types ──────────────────────────────────────────────────────
|
|
37
38
|
// Every type/interface that was previously exported from this file is
|
|
@@ -60,11 +61,20 @@ export type {
|
|
|
60
61
|
export { validatePreferences } from "./preferences-validation.js";
|
|
61
62
|
|
|
62
63
|
// ─── Re-exports: skills ─────────────────────────────────────────────────────
|
|
63
|
-
export {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
export { resolveAllSkillReferences } from "./preferences-skills.js";
|
|
65
|
+
|
|
66
|
+
// These lived in preferences-skills.ts but imported loadEffectiveGSDPreferences
|
|
67
|
+
// back from this file, creating a circular dependency. Moved here since they
|
|
68
|
+
// are trivial wrappers over loadEffectiveGSDPreferences.
|
|
69
|
+
export function resolveSkillDiscoveryMode(): SkillDiscoveryMode {
|
|
70
|
+
const prefs = loadEffectiveGSDPreferences();
|
|
71
|
+
return prefs?.preferences.skill_discovery ?? "suggest";
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function resolveSkillStalenessDays(): number {
|
|
75
|
+
const prefs = loadEffectiveGSDPreferences();
|
|
76
|
+
return prefs?.preferences.skill_staleness_days ?? 60;
|
|
77
|
+
}
|
|
68
78
|
|
|
69
79
|
// ─── Re-exports: models ─────────────────────────────────────────────────────
|
|
70
80
|
export {
|
|
@@ -389,6 +399,9 @@ function mergePreferences(base: GSDPreferences, override: GSDPreferences): GSDPr
|
|
|
389
399
|
github: (base.github || override.github)
|
|
390
400
|
? { ...(base.github ?? {}), ...(override.github ?? {}) } as import("../github-sync/types.js").GitHubSyncConfig
|
|
391
401
|
: undefined,
|
|
402
|
+
experimental: (base.experimental || override.experimental)
|
|
403
|
+
? { ...(base.experimental ?? {}), ...(override.experimental ?? {}) }
|
|
404
|
+
: undefined,
|
|
392
405
|
service_tier: override.service_tier ?? base.service_tier,
|
|
393
406
|
forensics_dedup: override.forensics_dedup ?? base.forensics_dedup,
|
|
394
407
|
show_token_cost: override.show_token_cost ?? base.show_token_cost,
|
|
@@ -143,10 +143,15 @@ export function loadPrompt(name: string, vars: Record<string, string> = {}): str
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
for (const [key, value] of Object.entries(effectiveVars)) {
|
|
146
|
+
const safeValue =
|
|
147
|
+
key === "workingDirectory" && typeof value === "string"
|
|
148
|
+
? value.replaceAll("\\", "/")
|
|
149
|
+
: value;
|
|
150
|
+
|
|
146
151
|
// Use split/join instead of replaceAll to avoid JavaScript's special
|
|
147
152
|
// replacement patterns ($', $`, $&) being interpreted in the value.
|
|
148
153
|
// See: https://github.com/gsd-build/gsd-2/issues/2968
|
|
149
|
-
content = content.split(`{{${key}}}`).join(
|
|
154
|
+
content = content.split(`{{${key}}}`).join(safeValue);
|
|
150
155
|
}
|
|
151
156
|
|
|
152
157
|
return content.trim();
|