@opengsd/gsd-pi 1.3.0-dev.65546769 → 1.3.0-dev.72e3af2a
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/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +11 -2
- package/dist/resources/extensions/google-cli/stream-adapter.js +82 -15
- package/dist/resources/extensions/gsd/artifact-verification.js +427 -0
- package/dist/resources/extensions/gsd/auto/orchestrator.js +12 -3
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +28 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +20 -19
- package/dist/resources/extensions/gsd/auto-prompts.js +26 -11
- package/dist/resources/extensions/gsd/auto-recovery.js +6 -507
- package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -5
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +3 -3
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +103 -13
- package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +38 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +6 -1
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +10 -19
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -19
- package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +68 -10
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
- package/dist/resources/extensions/gsd/commands-context.js +19 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +16 -10
- package/dist/resources/extensions/gsd/commands-worktree.js +12 -10
- package/dist/resources/extensions/gsd/dashboard-overlay.js +32 -3
- package/dist/resources/extensions/gsd/db/queries.js +60 -0
- package/dist/resources/extensions/gsd/db-workspace.js +55 -3
- package/dist/resources/extensions/gsd/doctor-providers.js +92 -8
- package/dist/resources/extensions/gsd/exec-sandbox.js +45 -9
- package/dist/resources/extensions/gsd/forensics.js +2 -32
- package/dist/resources/extensions/gsd/git-service.js +4 -4
- package/dist/resources/extensions/gsd/guided-flow-queue.js +66 -5
- package/dist/resources/extensions/gsd/health-widget.js +55 -29
- package/dist/resources/extensions/gsd/layout-policy.js +3 -1
- package/dist/resources/extensions/gsd/markdown-renderer.js +8 -9
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +44 -21
- package/dist/resources/extensions/gsd/migration-auto-check.js +22 -0
- package/dist/resources/extensions/gsd/milestone-ids.js +32 -2
- package/dist/resources/extensions/gsd/milestone-implementation-evidence.js +26 -20
- package/dist/resources/extensions/gsd/prompts/code-review.md +6 -4
- package/dist/resources/extensions/gsd/quick.js +45 -2
- package/dist/resources/extensions/gsd/session-forensics.js +11 -1
- package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
- package/dist/resources/extensions/gsd/state/derive/cache.js +28 -0
- package/dist/resources/extensions/gsd/state/derive/db-open.js +39 -0
- package/dist/resources/extensions/gsd/state/derive/from-db.js +452 -0
- package/dist/resources/extensions/gsd/state/derive/index.js +75 -0
- package/dist/resources/extensions/gsd/state/derive/interrupted-work.js +21 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +45 -2
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +48 -23
- package/dist/resources/extensions/gsd/state-reconciliation/registry.js +32 -28
- package/dist/resources/extensions/gsd/state.js +12 -611
- package/dist/resources/extensions/gsd/tools/complete-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/complete-task.js +43 -14
- package/dist/resources/extensions/gsd/tools/exec-tool.js +7 -2
- package/dist/resources/extensions/gsd/unit-context-composer.js +23 -7
- package/dist/resources/extensions/gsd/unit-registry.js +32 -4
- package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +33 -3
- package/dist/resources/extensions/gsd/validation-block-guard.js +9 -4
- package/dist/resources/extensions/gsd/workflow-projections.js +19 -14
- package/dist/resources/extensions/gsd/workspace-git-preflight.js +30 -1
- package/dist/resources/extensions/gsd/worktree-manager.js +44 -2
- 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 +10 -10
- 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 +9 -9
- 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_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 +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/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +2 -2
- 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 +2 -2
- 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/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
- 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/{2659.b7b129ee6a769448.js → 2659.58e950899a9bb82f.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/2772.a7c1fcc69a4685ef.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{3616.3c60753b8ffcbd2e.js → 3616.61a2af74bb8833c8.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{4283.8e446784528ed9dc.js → 4283.d0d9e0a955e441cb.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{5826.a46ecdd1cfe8dabc.js → 5826.5421d66c72b9f34e.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{8785.481aa5869991b760.js → 8785.e29b3134cab1d153.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/8937.640dc9c2aaa1dfad.js +10 -0
- package/dist/web/standalone/.next/static/chunks/app/{page-6644fc6ee8ca1247.js → page-72a856634ad14c10.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/webpack-9c401904f87ded16.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/workflow.d.ts +1 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +2 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/agent-session.d.ts +1 -0
- package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/agent-session.js +3 -0
- package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts +41 -0
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts.map +1 -0
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.js +62 -0
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.js.map +1 -0
- package/packages/gsd-agent-core/dist/index.d.ts +2 -0
- package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/index.js +2 -0
- package/packages/gsd-agent-core/dist/index.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-events.js +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-events.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +1 -0
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts +5 -0
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +60 -3
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
- package/packages/gsd-agent-core/dist/transcript-store.d.ts +58 -0
- package/packages/gsd-agent-core/dist/transcript-store.d.ts.map +1 -0
- package/packages/gsd-agent-core/dist/transcript-store.js +132 -0
- package/packages/gsd-agent-core/dist/transcript-store.js.map +1 -0
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts +4 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js +7 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +3 -24
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +26 -829
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts +58 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js +312 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts +31 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js +130 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts +15 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +258 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts +13 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js +118 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts +9 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts +54 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js +20 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +4 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +9 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts +56 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js +44 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts +5 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js +77 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +18 -0
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/README.md +1 -1
- package/packages/mcp-server/dist/server.d.ts +1 -1
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +3 -3
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +34 -20
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +4 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/README.md +3 -2
- package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-context.js +94 -0
- package/packages/pi-coding-agent/dist/core/session-manager-context.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts +8 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.js +244 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts +12 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.js +84 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +135 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.js +2 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts +6 -154
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.js +22 -459
- package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts +75 -75
- package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme-schema.js +1 -1
- package/packages/pi-coding-agent/dist/theme/theme-schema.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.js +11 -7
- package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/dist/theme/theme-schema.d.ts +75 -75
- package/pkg/dist/theme/theme-schema.d.ts.map +1 -1
- package/pkg/dist/theme/theme-schema.js +1 -1
- package/pkg/dist/theme/theme-schema.js.map +1 -1
- package/pkg/dist/theme/theme.d.ts.map +1 -1
- package/pkg/dist/theme/theme.js +11 -7
- package/pkg/dist/theme/theme.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +20 -2
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +80 -0
- package/src/resources/extensions/google-cli/stream-adapter.ts +106 -19
- package/src/resources/extensions/gsd/artifact-verification.ts +464 -0
- package/src/resources/extensions/gsd/auto/orchestrator.ts +25 -11
- package/src/resources/extensions/gsd/auto/session.ts +5 -0
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +47 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +21 -23
- package/src/resources/extensions/gsd/auto-prompts.ts +38 -12
- package/src/resources/extensions/gsd/auto-recovery.ts +10 -508
- package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -5
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +3 -2
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +125 -12
- package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +43 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +6 -1
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +11 -19
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +52 -18
- package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +74 -10
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
- package/src/resources/extensions/gsd/commands-context.ts +18 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +14 -9
- package/src/resources/extensions/gsd/commands-worktree.ts +12 -10
- package/src/resources/extensions/gsd/dashboard-overlay.ts +32 -3
- package/src/resources/extensions/gsd/db/queries.ts +79 -0
- package/src/resources/extensions/gsd/db-workspace.ts +61 -3
- package/src/resources/extensions/gsd/doctor-providers.ts +103 -9
- package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
- package/src/resources/extensions/gsd/forensics.ts +2 -33
- package/src/resources/extensions/gsd/git-service.ts +5 -5
- package/src/resources/extensions/gsd/guided-flow-queue.ts +89 -4
- package/src/resources/extensions/gsd/health-widget.ts +69 -32
- package/src/resources/extensions/gsd/layout-policy.ts +2 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +8 -11
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +51 -19
- package/src/resources/extensions/gsd/migration-auto-check.ts +23 -0
- package/src/resources/extensions/gsd/milestone-ids.ts +31 -2
- package/src/resources/extensions/gsd/milestone-implementation-evidence.ts +35 -21
- package/src/resources/extensions/gsd/prompts/code-review.md +6 -4
- package/src/resources/extensions/gsd/quick.ts +43 -2
- package/src/resources/extensions/gsd/session-forensics.ts +11 -1
- package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
- package/src/resources/extensions/gsd/state/derive/cache.ts +46 -0
- package/src/resources/extensions/gsd/state/derive/db-open.ts +45 -0
- package/src/resources/extensions/gsd/state/derive/from-db.ts +561 -0
- package/src/resources/extensions/gsd/state/derive/index.ts +104 -0
- package/src/resources/extensions/gsd/state/derive/interrupted-work.ts +31 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +81 -7
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +50 -24
- package/src/resources/extensions/gsd/state-reconciliation/registry.ts +43 -28
- package/src/resources/extensions/gsd/state.ts +32 -732
- package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +98 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +111 -1
- package/src/resources/extensions/gsd/tests/commands-context.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +80 -0
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +48 -8
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +55 -2
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +70 -2
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/exec-tool.test.ts +45 -1
- package/src/resources/extensions/gsd/tests/forensics-error-filter.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +268 -3
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +119 -1
- package/src/resources/extensions/gsd/tests/integration/queue-active-milestone-context-budget.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/integration/quick-branch-lifecycle.test.ts +56 -9
- package/src/resources/extensions/gsd/tests/knowledge-cold-start.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/orchestrator-logs.test.ts +43 -1
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +54 -1
- package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +50 -14
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +195 -1
- package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +185 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +191 -0
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +151 -0
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +193 -14
- package/src/resources/extensions/gsd/tests/unmerged-milestone-guard.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +151 -2
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +39 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/complete-task.ts +53 -15
- package/src/resources/extensions/gsd/tools/exec-tool.ts +7 -3
- package/src/resources/extensions/gsd/unit-context-composer.ts +33 -7
- package/src/resources/extensions/gsd/unit-registry.ts +32 -4
- package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +41 -5
- package/src/resources/extensions/gsd/validation-block-guard.ts +13 -7
- package/src/resources/extensions/gsd/workflow-projections.ts +20 -14
- package/src/resources/extensions/gsd/workspace-git-preflight.ts +31 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +41 -1
- package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +0 -1
- package/dist/web/standalone/.next/static/chunks/796.e0bdc932325d7e03.js +0 -10
- package/dist/web/standalone/.next/static/chunks/webpack-f46ea08200a0227e.js +0 -1
- /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → O7xDYXO0r4zFhIzY1hrWV}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → O7xDYXO0r4zFhIzY1hrWV}/_ssgManifest.js +0 -0
|
@@ -11,6 +11,7 @@ import { formatPercent, formatTokenCount } from "./metrics.js";
|
|
|
11
11
|
import { countTokensSync, type TokenProvider } from "./token-counter.js";
|
|
12
12
|
import { writeContextChartHtml } from "./context-chart-html.js";
|
|
13
13
|
import { openInBrowser } from "./export.js";
|
|
14
|
+
import { truncateWithEllipsis } from "../shared/format-utils.js";
|
|
14
15
|
|
|
15
16
|
export interface ContextSectionBreakdown {
|
|
16
17
|
label: string;
|
|
@@ -34,6 +35,7 @@ export interface ContextBreakdownReport {
|
|
|
34
35
|
subagentSpawns: number;
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
const REDACTED_TOOL_ARGUMENT_KEYS = new Set(["content", "oldText", "newText"]);
|
|
37
39
|
|
|
38
40
|
function resolveProvider(provider: string | undefined): TokenProvider {
|
|
39
41
|
const normalized = (provider ?? "unknown").toLowerCase();
|
|
@@ -206,6 +208,21 @@ export function parseSystemPromptSections(systemPrompt: string, provider: TokenP
|
|
|
206
208
|
return sections;
|
|
207
209
|
}
|
|
208
210
|
|
|
211
|
+
function redactToolCallArguments(value: unknown): unknown {
|
|
212
|
+
if (Array.isArray(value)) return value.map(redactToolCallArguments);
|
|
213
|
+
if (!value || typeof value !== "object") return value;
|
|
214
|
+
|
|
215
|
+
const safe: Record<string, unknown> = {};
|
|
216
|
+
for (const [key, child] of Object.entries(value)) {
|
|
217
|
+
if (REDACTED_TOOL_ARGUMENT_KEYS.has(key)) {
|
|
218
|
+
safe[key] = typeof child === "string" ? truncateWithEllipsis(child, 101) : "[redacted]";
|
|
219
|
+
} else {
|
|
220
|
+
safe[key] = redactToolCallArguments(child);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return safe;
|
|
224
|
+
}
|
|
225
|
+
|
|
209
226
|
function messageToText(message: SessionMessageEntry["message"]): string {
|
|
210
227
|
const role = message.role;
|
|
211
228
|
|
|
@@ -220,7 +237,7 @@ function messageToText(message: SessionMessageEntry["message"]): string {
|
|
|
220
237
|
if (typed.type === "thinking" && typed.thinking) parts.push(typed.thinking);
|
|
221
238
|
if (typed.type === "toolCall") {
|
|
222
239
|
parts.push(typed.name ?? "tool");
|
|
223
|
-
parts.push(JSON.stringify(typed.arguments ?? {}));
|
|
240
|
+
parts.push(JSON.stringify(redactToolCallArguments(typed.arguments ?? {})));
|
|
224
241
|
}
|
|
225
242
|
}
|
|
226
243
|
}
|
|
@@ -1724,17 +1724,22 @@ export function serializePreferencesToFrontmatter(prefs: Record<string, unknown>
|
|
|
1724
1724
|
const entries = Object.entries(item as Record<string, unknown>);
|
|
1725
1725
|
if (entries.length > 0) {
|
|
1726
1726
|
const [firstKey, firstVal] = entries[0];
|
|
1727
|
-
|
|
1727
|
+
if (Array.isArray(firstVal)) {
|
|
1728
|
+
lines.push(`${prefix} - ${firstKey}:`);
|
|
1729
|
+
for (const arrItem of firstVal) {
|
|
1730
|
+
lines.push(`${prefix} - ${yamlSafeString(arrItem)}`);
|
|
1731
|
+
}
|
|
1732
|
+
} else if (typeof firstVal === "object" && firstVal !== null) {
|
|
1733
|
+
lines.push(`${prefix} - ${firstKey}:`);
|
|
1734
|
+
for (const [k, v] of Object.entries(firstVal as Record<string, unknown>)) {
|
|
1735
|
+
serializeValue(k, v, indent + 3);
|
|
1736
|
+
}
|
|
1737
|
+
} else {
|
|
1738
|
+
lines.push(`${prefix} - ${firstKey}: ${yamlSafeString(firstVal)}`);
|
|
1739
|
+
}
|
|
1728
1740
|
for (let i = 1; i < entries.length; i++) {
|
|
1729
1741
|
const [k, v] = entries[i];
|
|
1730
|
-
|
|
1731
|
-
lines.push(`${prefix} ${k}:`);
|
|
1732
|
-
for (const arrItem of v) {
|
|
1733
|
-
lines.push(`${prefix} - ${yamlSafeString(arrItem)}`);
|
|
1734
|
-
}
|
|
1735
|
-
} else {
|
|
1736
|
-
lines.push(`${prefix} ${k}: ${yamlSafeString(v)}`);
|
|
1737
|
-
}
|
|
1742
|
+
serializeValue(k, v, indent + 2);
|
|
1738
1743
|
}
|
|
1739
1744
|
}
|
|
1740
1745
|
} else {
|
|
@@ -42,9 +42,9 @@ export interface WorktreeStatus {
|
|
|
42
42
|
|
|
43
43
|
// ─── Status helper ─────────────────────────────────────────────────────────
|
|
44
44
|
|
|
45
|
-
function getStatus(basePath: string, name: string, wtPath: string): WorktreeStatus {
|
|
46
|
-
const diff = diffWorktreeAll(basePath, name);
|
|
47
|
-
const numstat = diffWorktreeNumstat(basePath, name);
|
|
45
|
+
function getStatus(basePath: string, name: string, wtPath: string, mainBranch: string): WorktreeStatus {
|
|
46
|
+
const diff = diffWorktreeAll(basePath, name, undefined, mainBranch);
|
|
47
|
+
const numstat = diffWorktreeNumstat(basePath, name, undefined, mainBranch);
|
|
48
48
|
const filesChanged = diff.added.length + diff.modified.length + diff.removed.length;
|
|
49
49
|
let linesAdded = 0;
|
|
50
50
|
let linesRemoved = 0;
|
|
@@ -62,8 +62,7 @@ function getStatus(basePath: string, name: string, wtPath: string): WorktreeStat
|
|
|
62
62
|
|
|
63
63
|
let commits = 0;
|
|
64
64
|
try {
|
|
65
|
-
|
|
66
|
-
commits = nativeCommitCountBetween(basePath, main, worktreeBranchName(name));
|
|
65
|
+
commits = nativeCommitCountBetween(basePath, mainBranch, worktreeBranchName(name));
|
|
67
66
|
} catch {
|
|
68
67
|
// commit count unavailable → leave at 0
|
|
69
68
|
}
|
|
@@ -129,7 +128,8 @@ export function formatCleanKeepReason(status: WorktreeStatus): string {
|
|
|
129
128
|
async function handleList(ctx: ExtensionCommandContext): Promise<void> {
|
|
130
129
|
const basePath = projectRoot();
|
|
131
130
|
const worktrees = listWorktrees(basePath);
|
|
132
|
-
const
|
|
131
|
+
const mainBranch = worktrees.length > 0 ? nativeDetectMainBranch(basePath) : "";
|
|
132
|
+
const statuses = worktrees.map((wt) => getStatus(basePath, wt.name, wt.path, mainBranch));
|
|
133
133
|
ctx.ui.notify(formatWorktreeList(statuses), "info");
|
|
134
134
|
}
|
|
135
135
|
|
|
@@ -161,7 +161,8 @@ async function handleMerge(args: string, ctx: ExtensionCommandContext): Promise<
|
|
|
161
161
|
return;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
const
|
|
164
|
+
const mainBranch = nativeDetectMainBranch(basePath);
|
|
165
|
+
const status = getStatus(basePath, target, wt.path, mainBranch);
|
|
165
166
|
if (status.filesChanged === 0 && !status.uncommitted) {
|
|
166
167
|
try {
|
|
167
168
|
removeWorktree(basePath, target, { deleteBranch: true });
|
|
@@ -194,7 +195,6 @@ async function handleMerge(args: string, ctx: ExtensionCommandContext): Promise<
|
|
|
194
195
|
}
|
|
195
196
|
|
|
196
197
|
const commitType = inferCommitType(target);
|
|
197
|
-
const mainBranch = nativeDetectMainBranch(basePath);
|
|
198
198
|
const commitMessage = `${commitType}: merge worktree ${target}\n\nGSD-Worktree: ${target}`;
|
|
199
199
|
|
|
200
200
|
try {
|
|
@@ -250,8 +250,9 @@ async function handleClean(ctx: ExtensionCommandContext): Promise<void> {
|
|
|
250
250
|
|
|
251
251
|
const removed: string[] = [];
|
|
252
252
|
const kept: string[] = [];
|
|
253
|
+
const mainBranch = nativeDetectMainBranch(basePath);
|
|
253
254
|
for (const wt of worktrees) {
|
|
254
|
-
const status = getStatus(basePath, wt.name, wt.path);
|
|
255
|
+
const status = getStatus(basePath, wt.name, wt.path, mainBranch);
|
|
255
256
|
if (status.filesChanged === 0 && !status.uncommitted) {
|
|
256
257
|
try {
|
|
257
258
|
removeWorktree(basePath, wt.name, { deleteBranch: true });
|
|
@@ -298,7 +299,8 @@ async function handleRemove(args: string, ctx: ExtensionCommandContext): Promise
|
|
|
298
299
|
return;
|
|
299
300
|
}
|
|
300
301
|
|
|
301
|
-
const
|
|
302
|
+
const mainBranch = nativeDetectMainBranch(basePath);
|
|
303
|
+
const status = getStatus(basePath, name, wt.path, mainBranch);
|
|
302
304
|
if ((status.filesChanged > 0 || status.uncommitted) && !force) {
|
|
303
305
|
ctx.ui.notify(
|
|
304
306
|
[
|
|
@@ -29,7 +29,7 @@ import { getWorkerBatches, hasActiveWorkers, type WorkerEntry } from "../subagen
|
|
|
29
29
|
import { formatDuration, padRight, joinColumns, centerLine, fitColumns, STATUS_GLYPH, STATUS_COLOR } from "../shared/mod.js";
|
|
30
30
|
import { estimateTimeRemaining } from "./auto-dashboard.js";
|
|
31
31
|
import { computeProgressScore, formatProgressLine } from "./progress-score.js";
|
|
32
|
-
import {
|
|
32
|
+
import { runEnvironmentChecksAsync, type EnvironmentCheckResult } from "./doctor-environment.js";
|
|
33
33
|
import { formattedShortcutPair } from "./shortcut-defs.js";
|
|
34
34
|
import { renderDialogFrame, renderKeyHints } from "./tui/render-kit.js";
|
|
35
35
|
|
|
@@ -71,6 +71,9 @@ export class GSDDashboardOverlay {
|
|
|
71
71
|
private loading = true;
|
|
72
72
|
private loadedDashboardIdentity?: string;
|
|
73
73
|
private refreshInFlight: Promise<void> | null = null;
|
|
74
|
+
private envRefreshInFlight: Promise<void> | null = null;
|
|
75
|
+
private cachedEnvBasePath?: string;
|
|
76
|
+
private cachedEnvIssues: EnvironmentCheckResult[] = [];
|
|
74
77
|
private disposed = false;
|
|
75
78
|
private resizeHandler: (() => void) | null = null;
|
|
76
79
|
private cachedMetrics: {
|
|
@@ -181,12 +184,39 @@ export class GSDDashboardOverlay {
|
|
|
181
184
|
this.loading = false;
|
|
182
185
|
}
|
|
183
186
|
|
|
187
|
+
this.scheduleEnvironmentRefresh(this.dashData.basePath || process.cwd());
|
|
188
|
+
|
|
184
189
|
if (identityChanged) {
|
|
185
190
|
this.invalidate();
|
|
186
191
|
}
|
|
187
192
|
this.tui.requestRender();
|
|
188
193
|
}
|
|
189
194
|
|
|
195
|
+
private scheduleEnvironmentRefresh(basePath: string): void {
|
|
196
|
+
if (this.cachedEnvBasePath !== basePath) {
|
|
197
|
+
this.cachedEnvBasePath = basePath;
|
|
198
|
+
this.cachedEnvIssues = [];
|
|
199
|
+
this.invalidate();
|
|
200
|
+
}
|
|
201
|
+
if (this.envRefreshInFlight || this.disposed) return;
|
|
202
|
+
this.envRefreshInFlight = this.refreshEnvironmentHealth(basePath)
|
|
203
|
+
.finally(() => {
|
|
204
|
+
this.envRefreshInFlight = null;
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private async refreshEnvironmentHealth(basePath: string): Promise<void> {
|
|
209
|
+
try {
|
|
210
|
+
const envResults = await runEnvironmentChecksAsync(basePath);
|
|
211
|
+
if (this.disposed || this.cachedEnvBasePath !== basePath) return;
|
|
212
|
+
this.cachedEnvIssues = envResults.filter(r => r.status !== "ok");
|
|
213
|
+
this.invalidate();
|
|
214
|
+
this.tui.requestRender();
|
|
215
|
+
} catch {
|
|
216
|
+
// Non-fatal — keep last known environment issues
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
190
220
|
private async loadData(): Promise<boolean> {
|
|
191
221
|
const base = this.dashData.basePath || process.cwd();
|
|
192
222
|
try {
|
|
@@ -629,8 +659,7 @@ export class GSDDashboardOverlay {
|
|
|
629
659
|
}
|
|
630
660
|
|
|
631
661
|
// Environment health section (#1221) — only show issues
|
|
632
|
-
const
|
|
633
|
-
const envIssues = envResults.filter(r => r.status !== "ok");
|
|
662
|
+
const envIssues = this.cachedEnvIssues;
|
|
634
663
|
if (envIssues.length > 0) {
|
|
635
664
|
lines.push(blank());
|
|
636
665
|
lines.push(hr());
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
import { rowToGate } from "../db-gate-rows.js";
|
|
29
29
|
import { rowToArtifact, rowToMilestone, type ArtifactRow, type MilestoneRow } from "../db-milestone-artifact-rows.js";
|
|
30
30
|
import { rowToSlice, rowToTask, type SliceRow, type TaskRow } from "../db-task-slice-rows.js";
|
|
31
|
+
import { TERMINAL_STATUS_SQL } from "./sql-constants.js";
|
|
31
32
|
|
|
32
33
|
|
|
33
34
|
function parseStringArrayColumn(raw: unknown): string[] {
|
|
@@ -49,6 +50,59 @@ function normalizeRepoPath(file: string): string {
|
|
|
49
50
|
return file.trim().replace(/\\/g, "/").replace(/^\.\/+/, "");
|
|
50
51
|
}
|
|
51
52
|
|
|
53
|
+
export interface HierarchyCompletionCounts {
|
|
54
|
+
milestones: number;
|
|
55
|
+
milestonesTotal: number;
|
|
56
|
+
slices: number;
|
|
57
|
+
slicesTotal: number;
|
|
58
|
+
tasks: number;
|
|
59
|
+
tasksTotal: number;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function numberColumn(row: Record<string, unknown> | undefined, column: string): number {
|
|
63
|
+
const value = row?.[column];
|
|
64
|
+
if (typeof value === "number") return value;
|
|
65
|
+
if (typeof value === "bigint") return Number(value);
|
|
66
|
+
if (typeof value === "string") {
|
|
67
|
+
const parsed = Number(value);
|
|
68
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
69
|
+
}
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function getCompletionCount(table: "milestones" | "slices" | "tasks"): { completed: number; total: number } {
|
|
74
|
+
const row = getDbOrNull()!.prepare(
|
|
75
|
+
`SELECT
|
|
76
|
+
COUNT(*) AS total,
|
|
77
|
+
COALESCE(SUM(CASE WHEN status IN (${TERMINAL_STATUS_SQL}) THEN 1 ELSE 0 END), 0) AS completed
|
|
78
|
+
FROM ${table}`,
|
|
79
|
+
).get();
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
completed: numberColumn(row, "completed"),
|
|
83
|
+
total: numberColumn(row, "total"),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function getHierarchyCompletionCounts(): HierarchyCompletionCounts {
|
|
88
|
+
if (!getDbOrNull()!) {
|
|
89
|
+
return { milestones: 0, milestonesTotal: 0, slices: 0, slicesTotal: 0, tasks: 0, tasksTotal: 0 };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const milestones = getCompletionCount("milestones");
|
|
93
|
+
const slices = getCompletionCount("slices");
|
|
94
|
+
const tasks = getCompletionCount("tasks");
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
milestones: milestones.completed,
|
|
98
|
+
milestonesTotal: milestones.total,
|
|
99
|
+
slices: slices.completed,
|
|
100
|
+
slicesTotal: slices.total,
|
|
101
|
+
tasks: tasks.completed,
|
|
102
|
+
tasksTotal: tasks.total,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
52
106
|
export function getDecisionById(id: string): Decision | null {
|
|
53
107
|
if (!getDbOrNull()!) return null;
|
|
54
108
|
const row = getDbOrNull()!.prepare("SELECT * FROM decisions WHERE id = ?").get(id);
|
|
@@ -490,6 +544,31 @@ export function getAssessment(path: string): Record<string, unknown> | null {
|
|
|
490
544
|
return row ?? null;
|
|
491
545
|
}
|
|
492
546
|
|
|
547
|
+
/**
|
|
548
|
+
* Look up a slice's `run-uat` assessment by (milestoneId, sliceId) identity,
|
|
549
|
+
* independent of the artifact `path`. Used as a DB fallback by the UAT
|
|
550
|
+
* closeout gate when a path migration orphans the ASSESSMENT markdown from its
|
|
551
|
+
* canonical expected path (ADR-017: DB-authoritative UAT sign-off).
|
|
552
|
+
*
|
|
553
|
+
* `status` holds the normalized verdict (`pass`/`fail`/…) written by
|
|
554
|
+
* `executeUatResultSave`; `fullContent` carries the ASSESSMENT body so callers
|
|
555
|
+
* can derive `uatType` without re-reading a file that may not exist.
|
|
556
|
+
*/
|
|
557
|
+
export function getSliceRunUatAssessment(
|
|
558
|
+
milestoneId: string,
|
|
559
|
+
sliceId: string,
|
|
560
|
+
): { status: string; fullContent: string } | null {
|
|
561
|
+
if (!getDbOrNull()!) return null;
|
|
562
|
+
const row = getDbOrNull()!.prepare(
|
|
563
|
+
`SELECT status, full_content AS fullContent FROM assessments
|
|
564
|
+
WHERE milestone_id = :mid AND slice_id = :sid AND scope = 'run-uat'
|
|
565
|
+
ORDER BY created_at DESC, ROWID DESC
|
|
566
|
+
LIMIT 1`,
|
|
567
|
+
).get({ ":mid": milestoneId, ":sid": sliceId });
|
|
568
|
+
if (!row) return null;
|
|
569
|
+
return { status: String(row["status"] ?? ""), fullContent: String(row["fullContent"] ?? "") };
|
|
570
|
+
}
|
|
571
|
+
|
|
493
572
|
export function getLatestAssessmentByScope(
|
|
494
573
|
milestoneId: string,
|
|
495
574
|
scope: string,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// File Purpose: Workspace-facing Interface for opening and maintaining the workflow database.
|
|
3
3
|
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
|
-
import { dirname } from "node:path";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
6
|
|
|
7
7
|
import type { GsdWorkspace, MilestoneScope } from "./workspace.js";
|
|
8
8
|
import type { DbAdapter } from "./db-adapter.js";
|
|
@@ -24,8 +24,8 @@ import {
|
|
|
24
24
|
vacuumDatabase,
|
|
25
25
|
wasDbOpenAttempted,
|
|
26
26
|
} from "./gsd-db.js";
|
|
27
|
-
import { resolveGsdPathContract } from "./paths.js";
|
|
28
|
-
import { setLogBasePath } from "./workflow-logger.js";
|
|
27
|
+
import { resolveGsdPathContract, gsdRoot } from "./paths.js";
|
|
28
|
+
import { logWarning, setLogBasePath } from "./workflow-logger.js";
|
|
29
29
|
|
|
30
30
|
export interface WorkflowDatabaseLocation {
|
|
31
31
|
projectRoot: string;
|
|
@@ -56,6 +56,20 @@ export type WorkflowDatabaseOpenResult =
|
|
|
56
56
|
export type WorkflowDatabaseStatus = ReturnType<typeof getDbStatus>;
|
|
57
57
|
export type WorkflowDatabaseProvider = ReturnType<typeof getDbProvider>;
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Global SQLite handle invariants:
|
|
61
|
+
*
|
|
62
|
+
* - `openWorkflowDatabase` / `openDatabase` switch the process-global handle consumed by
|
|
63
|
+
* deriveState, dispatch, reconciliation repairs, and domain writers. Only one active
|
|
64
|
+
* project database should own the global handle at a time.
|
|
65
|
+
* - `openWorkflowDatabaseIsolated` opens a caller-owned connection that does not clobber
|
|
66
|
+
* the global handle. Use for read-only observers (parallel monitor) and other background
|
|
67
|
+
* probes that must not disturb the active workflow session.
|
|
68
|
+
* - Reconciliation repairs that write markdown/DB state must use `ensureWorkflowDbForBase`
|
|
69
|
+
* so repairs target the correct project; those paths intentionally re-open the global handle.
|
|
70
|
+
* - Pair ad-hoc project switches with `closeWorkflowDatabase()` or restore via
|
|
71
|
+
* `ensureWorkflowDbForBase(..., { refresh: true })` before returning to derive/dispatch.
|
|
72
|
+
*/
|
|
59
73
|
export function resolveWorkflowDatabaseLocation(basePath: string): WorkflowDatabaseLocation {
|
|
60
74
|
const contract = resolveGsdPathContract(basePath);
|
|
61
75
|
return {
|
|
@@ -172,6 +186,50 @@ export function refreshWorkflowDatabaseFromDisk(): boolean {
|
|
|
172
186
|
return refreshOpenDatabaseFromDisk();
|
|
173
187
|
}
|
|
174
188
|
|
|
189
|
+
export function expectedWorkflowDbPathForBase(basePath: string): string {
|
|
190
|
+
return join(gsdRoot(basePath), "gsd.db");
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export interface EnsureWorkflowDbOptions {
|
|
194
|
+
/** When true, refresh from disk before reopening if already open on the correct path. */
|
|
195
|
+
refresh?: boolean;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function ensureWorkflowDbAtPath(dbPath: string | null): boolean {
|
|
199
|
+
if (!dbPath || dbPath === ":memory:") return isDbAvailable();
|
|
200
|
+
if (isDbAvailable() && getWorkflowDatabasePath() === dbPath) return true;
|
|
201
|
+
if (!existsSync(dbPath)) return false;
|
|
202
|
+
try {
|
|
203
|
+
return openWorkflowDatabasePath(dbPath);
|
|
204
|
+
} catch (err) {
|
|
205
|
+
logWarning("reconcile", `ensureWorkflowDbAtPath could not reopen DB: ${(err as Error).message}`);
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function ensureWorkflowDbForBase(
|
|
211
|
+
basePath: string,
|
|
212
|
+
options: EnsureWorkflowDbOptions = {},
|
|
213
|
+
): boolean {
|
|
214
|
+
const dbPath = expectedWorkflowDbPathForBase(basePath);
|
|
215
|
+
if (!existsSync(dbPath)) return false;
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
if (options.refresh) {
|
|
219
|
+
if (isDbAvailable() && getWorkflowDatabasePath() === dbPath && refreshWorkflowDatabaseFromDisk()) {
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
return openWorkflowDatabasePath(dbPath);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (isDbAvailable() && getWorkflowDatabasePath() === dbPath) return true;
|
|
226
|
+
return openWorkflowDatabasePath(dbPath);
|
|
227
|
+
} catch (err) {
|
|
228
|
+
logWarning("reconcile", `ensureWorkflowDbForBase could not reopen DB: ${(err as Error).message}`);
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
175
233
|
export function checkpointWorkflowDatabase(): void {
|
|
176
234
|
checkpointDatabase();
|
|
177
235
|
}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { existsSync, readFileSync } from "node:fs";
|
|
15
|
+
import { access, readFile } from "node:fs/promises";
|
|
15
16
|
import { delimiter, join } from "node:path";
|
|
16
17
|
import { AuthStorage } from "@gsd/pi-coding-agent";
|
|
17
18
|
import { getEnvApiKey } from "@gsd/pi-ai";
|
|
@@ -166,15 +167,11 @@ const CLI_AUTH_PATH_CHECK_PROVIDERS = new Set([
|
|
|
166
167
|
"google-antigravity",
|
|
167
168
|
]);
|
|
168
169
|
|
|
169
|
-
|
|
170
|
-
* Check if a CLI provider's binary exists anywhere in PATH.
|
|
171
|
-
* Fast filesystem scan — no subprocess, no network, sub-1ms.
|
|
172
|
-
*/
|
|
173
|
-
function isCliBinaryInPath(providerId: string): boolean {
|
|
174
|
-
const binaries = CLI_BINARY_MAP[providerId];
|
|
175
|
-
if (!binaries) return false;
|
|
170
|
+
let asyncCliBinaryPathCache: Map<string, boolean> | null = null;
|
|
176
171
|
|
|
177
|
-
|
|
172
|
+
function cliExecutableNames(providerId: string): string[] {
|
|
173
|
+
const binaries = CLI_BINARY_MAP[providerId];
|
|
174
|
+
if (!binaries) return [];
|
|
178
175
|
|
|
179
176
|
// On Windows, command shims are commonly installed as .cmd/.exe/.bat/.com.
|
|
180
177
|
// Scan PATHEXT candidates in addition to the bare binary name.
|
|
@@ -196,9 +193,51 @@ function isCliBinaryInPath(providerId: string): boolean {
|
|
|
196
193
|
}
|
|
197
194
|
}
|
|
198
195
|
|
|
196
|
+
return executableNames;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Check if a CLI provider's binary exists anywhere in PATH.
|
|
201
|
+
* Fast filesystem scan — no subprocess, no network, sub-1ms.
|
|
202
|
+
*/
|
|
203
|
+
function isCliBinaryInPath(providerId: string): boolean {
|
|
204
|
+
const cached = asyncCliBinaryPathCache?.get(providerId);
|
|
205
|
+
if (cached !== undefined) return cached;
|
|
206
|
+
|
|
207
|
+
const executableNames = cliExecutableNames(providerId);
|
|
208
|
+
if (executableNames.length === 0) return false;
|
|
209
|
+
|
|
210
|
+
const pathDirs = (process.env.PATH ?? "").split(delimiter).filter(Boolean);
|
|
211
|
+
|
|
199
212
|
return pathDirs.some(dir => executableNames.some(name => existsSync(join(dir, name))));
|
|
200
213
|
}
|
|
201
214
|
|
|
215
|
+
async function isCliBinaryInPathAsync(providerId: string): Promise<boolean> {
|
|
216
|
+
const executableNames = cliExecutableNames(providerId);
|
|
217
|
+
if (executableNames.length === 0) return false;
|
|
218
|
+
|
|
219
|
+
const pathDirs = (process.env.PATH ?? "").split(delimiter).filter(Boolean);
|
|
220
|
+
const candidates = pathDirs.flatMap(dir => executableNames.map(name => join(dir, name)));
|
|
221
|
+
if (candidates.length === 0) return false;
|
|
222
|
+
|
|
223
|
+
try {
|
|
224
|
+
await Promise.any(candidates.map(candidate => access(candidate)));
|
|
225
|
+
return true;
|
|
226
|
+
} catch {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async function loadCliBinaryPathCache(): Promise<Map<string, boolean>> {
|
|
232
|
+
const entries = await Promise.all(
|
|
233
|
+
Object.keys(CLI_BINARY_MAP).map(async providerId => [
|
|
234
|
+
providerId,
|
|
235
|
+
await isCliBinaryInPathAsync(providerId),
|
|
236
|
+
] as const),
|
|
237
|
+
);
|
|
238
|
+
return new Map(entries);
|
|
239
|
+
}
|
|
240
|
+
|
|
202
241
|
function modelsJsonPaths(): string[] {
|
|
203
242
|
const home = homedir();
|
|
204
243
|
return [
|
|
@@ -208,7 +247,13 @@ function modelsJsonPaths(): string[] {
|
|
|
208
247
|
];
|
|
209
248
|
}
|
|
210
249
|
|
|
250
|
+
let asyncModelsJsonApiKeyCache: Set<string> | null = null;
|
|
251
|
+
|
|
211
252
|
function hasModelsJsonApiKey(providerId: string): boolean {
|
|
253
|
+
if (asyncModelsJsonApiKeyCache) {
|
|
254
|
+
return asyncModelsJsonApiKeyCache.has(providerId);
|
|
255
|
+
}
|
|
256
|
+
|
|
212
257
|
for (const path of modelsJsonPaths()) {
|
|
213
258
|
if (!existsSync(path)) continue;
|
|
214
259
|
try {
|
|
@@ -226,7 +271,27 @@ function hasModelsJsonApiKey(providerId: string): boolean {
|
|
|
226
271
|
return false;
|
|
227
272
|
}
|
|
228
273
|
|
|
229
|
-
function
|
|
274
|
+
async function loadModelsJsonApiKeyCache(): Promise<Set<string>> {
|
|
275
|
+
const providersWithKeys = new Set<string>();
|
|
276
|
+
for (const path of modelsJsonPaths()) {
|
|
277
|
+
try {
|
|
278
|
+
const parsed = JSON.parse(await readFile(path, "utf-8")) as {
|
|
279
|
+
providers?: Record<string, { apiKey?: unknown }>;
|
|
280
|
+
};
|
|
281
|
+
for (const [providerId, provider] of Object.entries(parsed.providers ?? {})) {
|
|
282
|
+
const apiKey = provider.apiKey;
|
|
283
|
+
if (typeof apiKey === "string" && apiKey.trim().length > 0) {
|
|
284
|
+
providersWithKeys.add(providerId);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
} catch {
|
|
288
|
+
// Missing or malformed models.json should not break dashboard health checks.
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return providersWithKeys;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function resolveKeyFromAuthOrEnv(providerId: string): KeyLookup | null {
|
|
230
295
|
const info = PROVIDER_REGISTRY.find(p => p.id === providerId);
|
|
231
296
|
|
|
232
297
|
if (providerId === "anthropic-vertex" && process.env.ANTHROPIC_VERTEX_PROJECT_ID) {
|
|
@@ -276,6 +341,13 @@ function resolveKey(providerId: string): KeyLookup {
|
|
|
276
341
|
return { found: true, source: "env", backedOff: false };
|
|
277
342
|
}
|
|
278
343
|
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function resolveKey(providerId: string): KeyLookup {
|
|
348
|
+
const direct = resolveKeyFromAuthOrEnv(providerId);
|
|
349
|
+
if (direct) return direct;
|
|
350
|
+
|
|
279
351
|
if (hasModelsJsonApiKey(providerId)) {
|
|
280
352
|
return { found: true, source: "models.json", backedOff: false };
|
|
281
353
|
}
|
|
@@ -495,6 +567,28 @@ export function runProviderChecks(): ProviderCheckResult[] {
|
|
|
495
567
|
return results;
|
|
496
568
|
}
|
|
497
569
|
|
|
570
|
+
/**
|
|
571
|
+
* Non-blocking equivalent of `runProviderChecks` for the health-widget
|
|
572
|
+
* background refresh. PATH checks and custom models.json discovery use async
|
|
573
|
+
* filesystem APIs so periodic widget refreshes do not stall the input loop.
|
|
574
|
+
*/
|
|
575
|
+
export async function runProviderChecksAsync(): Promise<ProviderCheckResult[]> {
|
|
576
|
+
const [cliCache, modelsJsonCache] = await Promise.all([
|
|
577
|
+
loadCliBinaryPathCache(),
|
|
578
|
+
loadModelsJsonApiKeyCache(),
|
|
579
|
+
]);
|
|
580
|
+
const previousCliCache = asyncCliBinaryPathCache;
|
|
581
|
+
const previousModelsJsonCache = asyncModelsJsonApiKeyCache;
|
|
582
|
+
asyncCliBinaryPathCache = cliCache;
|
|
583
|
+
asyncModelsJsonApiKeyCache = modelsJsonCache;
|
|
584
|
+
try {
|
|
585
|
+
return runProviderChecks();
|
|
586
|
+
} finally {
|
|
587
|
+
asyncCliBinaryPathCache = previousCliCache;
|
|
588
|
+
asyncModelsJsonApiKeyCache = previousModelsJsonCache;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
498
592
|
/**
|
|
499
593
|
* Format provider check results as a human-readable report string.
|
|
500
594
|
*/
|