@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
|
@@ -48,6 +48,8 @@ export interface ExecSandboxOptions {
|
|
|
48
48
|
now?: () => Date;
|
|
49
49
|
/** Optional override for id generation (tests). */
|
|
50
50
|
generateId?: () => string;
|
|
51
|
+
/** Optional request cancellation signal. Aborting kills the child process tree. */
|
|
52
|
+
signal?: AbortSignal;
|
|
51
53
|
/**
|
|
52
54
|
* Grace period (ms) between SIGTERM and SIGKILL on timeout.
|
|
53
55
|
* Defaults to SIGKILL_GRACE_MS. Exposed as a test seam.
|
|
@@ -67,6 +69,8 @@ export interface ExecSandboxResult {
|
|
|
67
69
|
exit_code: number | null;
|
|
68
70
|
signal: NodeJS.Signals | null;
|
|
69
71
|
timed_out: boolean;
|
|
72
|
+
/** True when an external AbortSignal terminated the child process tree. */
|
|
73
|
+
aborted?: boolean;
|
|
70
74
|
/**
|
|
71
75
|
* True when the result came from the hard-deadline force-resolve (a non-closing
|
|
72
76
|
* D-state child that never emitted 'close') rather than an observed process exit.
|
|
@@ -260,11 +264,23 @@ export function runExecSandbox(
|
|
|
260
264
|
const effectiveForceResolveDelay = opts.force_resolve_delay_ms ?? (effectiveGraceMs + HARD_DEADLINE_MS);
|
|
261
265
|
|
|
262
266
|
let timedOut = false;
|
|
267
|
+
let aborted = false;
|
|
263
268
|
let settled = false;
|
|
269
|
+
let killInitiated = false;
|
|
270
|
+
let timer: NodeJS.Timeout | undefined;
|
|
264
271
|
let forceResolveTimer: NodeJS.Timeout | undefined;
|
|
272
|
+
let abortListener: (() => void) | undefined;
|
|
265
273
|
|
|
266
|
-
const
|
|
267
|
-
|
|
274
|
+
const removeAbortListener = () => {
|
|
275
|
+
if (opts.signal && abortListener) {
|
|
276
|
+
opts.signal.removeEventListener("abort", abortListener);
|
|
277
|
+
abortListener = undefined;
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
const initiateKill = () => {
|
|
282
|
+
if (killInitiated) return;
|
|
283
|
+
killInitiated = true;
|
|
268
284
|
// killProcessTree handles both platforms and kills the whole tree: on Unix
|
|
269
285
|
// it signals the process group (SIGTERM -> grace -> SIGKILL); on Windows it
|
|
270
286
|
// force-kills the tree via taskkill /F /T. Using child.kill("SIGTERM") here
|
|
@@ -281,14 +297,14 @@ export function runExecSandbox(
|
|
|
281
297
|
finalize(null, "SIGKILL", true);
|
|
282
298
|
}, effectiveForceResolveDelay);
|
|
283
299
|
forceResolveTimer.unref?.();
|
|
284
|
-
}
|
|
285
|
-
timer.unref?.();
|
|
300
|
+
};
|
|
286
301
|
|
|
287
302
|
const finalize = (exitCode: number | null, signal: NodeJS.Signals | null, forceResolved = false) => {
|
|
288
303
|
if (settled) return;
|
|
289
304
|
settled = true;
|
|
290
305
|
clearTimeout(timer);
|
|
291
306
|
clearTimeout(forceResolveTimer);
|
|
307
|
+
removeAbortListener();
|
|
292
308
|
const duration = Date.now() - started;
|
|
293
309
|
const stdoutBuf = Buffer.concat(stdoutChunks);
|
|
294
310
|
const stderrBuf = Buffer.concat(stderrChunks);
|
|
@@ -301,11 +317,13 @@ export function runExecSandbox(
|
|
|
301
317
|
const digest =
|
|
302
318
|
digestBody.length > 0
|
|
303
319
|
? digestBody
|
|
304
|
-
:
|
|
305
|
-
? "[no stdout —
|
|
306
|
-
:
|
|
307
|
-
?
|
|
308
|
-
:
|
|
320
|
+
: aborted
|
|
321
|
+
? "[no stdout — aborted]"
|
|
322
|
+
: timedOut
|
|
323
|
+
? "[no stdout — timed out]"
|
|
324
|
+
: stderrBuf.length > 0
|
|
325
|
+
? `[no stdout — tail of stderr]\n${tail(stderrBuf, opts.digest_chars)}`
|
|
326
|
+
: "[no output]";
|
|
309
327
|
|
|
310
328
|
const result: ExecSandboxResult = {
|
|
311
329
|
id,
|
|
@@ -313,6 +331,7 @@ export function runExecSandbox(
|
|
|
313
331
|
exit_code: exitCode,
|
|
314
332
|
signal,
|
|
315
333
|
timed_out: timedOut,
|
|
334
|
+
aborted,
|
|
316
335
|
force_resolved: forceResolved,
|
|
317
336
|
duration_ms: duration,
|
|
318
337
|
stdout_bytes: stdoutBytes,
|
|
@@ -328,6 +347,26 @@ export function runExecSandbox(
|
|
|
328
347
|
resolveP(result);
|
|
329
348
|
};
|
|
330
349
|
|
|
350
|
+
timer = setTimeout(() => {
|
|
351
|
+
timedOut = true;
|
|
352
|
+
initiateKill();
|
|
353
|
+
}, timeoutMs);
|
|
354
|
+
timer.unref?.();
|
|
355
|
+
|
|
356
|
+
if (opts.signal) {
|
|
357
|
+
abortListener = () => {
|
|
358
|
+
if (settled || timedOut) return;
|
|
359
|
+
aborted = true;
|
|
360
|
+
clearTimeout(timer);
|
|
361
|
+
initiateKill();
|
|
362
|
+
};
|
|
363
|
+
if (opts.signal.aborted) {
|
|
364
|
+
abortListener();
|
|
365
|
+
} else {
|
|
366
|
+
opts.signal.addEventListener("abort", abortListener, { once: true });
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
331
370
|
child.on("error", (err) => {
|
|
332
371
|
const message = err instanceof Error ? err.message : String(err);
|
|
333
372
|
const line = `child error: ${message}\n`;
|
|
@@ -364,6 +403,7 @@ function writeMeta(
|
|
|
364
403
|
exit_code: result.exit_code,
|
|
365
404
|
signal: result.signal,
|
|
366
405
|
timed_out: result.timed_out,
|
|
406
|
+
aborted: result.aborted === true,
|
|
367
407
|
force_resolved: result.force_resolved,
|
|
368
408
|
duration_ms: result.duration_ms,
|
|
369
409
|
stdout_bytes: result.stdout_bytes,
|
|
@@ -28,8 +28,7 @@ import { deriveState } from "./state.js";
|
|
|
28
28
|
import { isAutoActive } from "./auto.js";
|
|
29
29
|
import { loadPrompt } from "./prompt-loader.js";
|
|
30
30
|
import { gsdRoot } from "./paths.js";
|
|
31
|
-
import { isDbAvailable,
|
|
32
|
-
import { isClosedStatus } from "./status-guards.js";
|
|
31
|
+
import { isDbAvailable, getHierarchyCompletionCounts } from "./gsd-db.js";
|
|
33
32
|
import { formatDuration } from "../shared/format-utils.js";
|
|
34
33
|
import { getAutoWorktreePath } from "./auto-worktree.js";
|
|
35
34
|
import { clearGSDPreferencesCache, loadEffectiveGSDPreferences, loadGlobalGSDPreferences, getGlobalGSDPreferencesPath } from "./preferences.js";
|
|
@@ -759,37 +758,7 @@ function loadCompletedKeys(basePath: string): string[] {
|
|
|
759
758
|
function getDbCompletionCounts(): DbCompletionCounts | null {
|
|
760
759
|
if (!isDbAvailable()) return null;
|
|
761
760
|
|
|
762
|
-
|
|
763
|
-
let completedMilestones = 0;
|
|
764
|
-
let totalSlices = 0;
|
|
765
|
-
let completedSlices = 0;
|
|
766
|
-
let totalTasks = 0;
|
|
767
|
-
let completedTasks = 0;
|
|
768
|
-
|
|
769
|
-
for (const m of milestones) {
|
|
770
|
-
if (isClosedStatus(m.status)) completedMilestones++;
|
|
771
|
-
|
|
772
|
-
const slices = getMilestoneSlices(m.id);
|
|
773
|
-
for (const s of slices) {
|
|
774
|
-
totalSlices++;
|
|
775
|
-
if (isClosedStatus(s.status)) completedSlices++;
|
|
776
|
-
|
|
777
|
-
const tasks = getSliceTasks(m.id, s.id);
|
|
778
|
-
for (const t of tasks) {
|
|
779
|
-
totalTasks++;
|
|
780
|
-
if (isClosedStatus(t.status)) completedTasks++;
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
return {
|
|
786
|
-
milestones: completedMilestones,
|
|
787
|
-
milestonesTotal: milestones.length,
|
|
788
|
-
slices: completedSlices,
|
|
789
|
-
slicesTotal: totalSlices,
|
|
790
|
-
tasks: completedTasks,
|
|
791
|
-
tasksTotal: totalTasks,
|
|
792
|
-
};
|
|
761
|
+
return getHierarchyCompletionCounts();
|
|
793
762
|
}
|
|
794
763
|
|
|
795
764
|
// ─── Anomaly Detectors ───────────────────────────────────────────────────────
|
|
@@ -378,6 +378,8 @@ export const RUNTIME_EXCLUSION_PATHS: readonly string[] = [
|
|
|
378
378
|
".gsd/DISCUSSION-MANIFEST.json",
|
|
379
379
|
];
|
|
380
380
|
|
|
381
|
+
const runtimeFilesCleanedUpRepos = new Set<string>();
|
|
382
|
+
|
|
381
383
|
// ─── Integration Branch Metadata ───────────────────────────────────────────
|
|
382
384
|
|
|
383
385
|
/**
|
|
@@ -755,7 +757,8 @@ export class GitServiceImpl {
|
|
|
755
757
|
// and the worktree is torn down. This prevents a mid-execution behavioral
|
|
756
758
|
// discontinuity where the first half of a milestone has .gsd/ artifacts
|
|
757
759
|
// committed but the second half doesn't (#1326).
|
|
758
|
-
|
|
760
|
+
const cleanupRepoKey = resolve(this.basePath);
|
|
761
|
+
if (!runtimeFilesCleanedUpRepos.has(cleanupRepoKey)) {
|
|
759
762
|
let cleaned = false;
|
|
760
763
|
for (const exclusion of RUNTIME_EXCLUSION_PATHS) {
|
|
761
764
|
const removed = nativeRmCached(this.basePath, [exclusion]);
|
|
@@ -764,7 +767,7 @@ export class GitServiceImpl {
|
|
|
764
767
|
if (cleaned) {
|
|
765
768
|
nativeCommit(this.basePath, "chore: untrack .gsd/ runtime files from git index", { allowEmpty: false });
|
|
766
769
|
}
|
|
767
|
-
|
|
770
|
+
runtimeFilesCleanedUpRepos.add(cleanupRepoKey);
|
|
768
771
|
}
|
|
769
772
|
|
|
770
773
|
// Stage everything using pathspec exclusions so excluded paths are never
|
|
@@ -893,9 +896,6 @@ export class GitServiceImpl {
|
|
|
893
896
|
}
|
|
894
897
|
}
|
|
895
898
|
|
|
896
|
-
/** Tracks whether runtime file cleanup has run this session. */
|
|
897
|
-
private _runtimeFilesCleanedUp = false;
|
|
898
|
-
|
|
899
899
|
/**
|
|
900
900
|
* Stage files (smart staging) and commit.
|
|
901
901
|
* Returns the commit message string on success, or null if nothing to commit.
|
|
@@ -20,6 +20,7 @@ import { invalidateAllCaches } from "./cache.js";
|
|
|
20
20
|
import {
|
|
21
21
|
gsdRoot, resolveMilestoneFile, resolveSliceFile,
|
|
22
22
|
resolveGsdRootFile, relGsdRootFile, relSliceFile,
|
|
23
|
+
relMilestoneFile,
|
|
23
24
|
} from "./paths.js";
|
|
24
25
|
import { readFileSync, writeFileSync, existsSync } from "node:fs";
|
|
25
26
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
@@ -29,6 +30,10 @@ import { loadQueueOrder, sortByQueueOrder, saveQueueOrder } from "./queue-order.
|
|
|
29
30
|
import { findMilestoneIds, nextMilestoneId } from "./milestone-ids.js";
|
|
30
31
|
import { isFutureMilestoneStatus } from "./status-guards.js";
|
|
31
32
|
|
|
33
|
+
const QUEUE_ARTIFACT_EXCERPT_MAX_CHARS = 20_000;
|
|
34
|
+
const QUEUE_EXISTING_MILESTONES_CONTEXT_MAX_CHARS = 120_000;
|
|
35
|
+
const QUEUE_CONTEXT_SECTION_SEPARATOR = "\n\n---\n\n";
|
|
36
|
+
|
|
32
37
|
// ─── Queue Entry Point ──────────────────────────────────────────────────────
|
|
33
38
|
|
|
34
39
|
/**
|
|
@@ -280,7 +285,9 @@ export async function buildExistingMilestonesContext(
|
|
|
280
285
|
if (contextFile) {
|
|
281
286
|
const content = await loadFile(contextFile);
|
|
282
287
|
if (content) {
|
|
283
|
-
parts.push(
|
|
288
|
+
parts.push(
|
|
289
|
+
`\n**Context:**\n${summarizeArtifactForQueue(content, relMilestoneFile(basePath, mid, "CONTEXT"))}`,
|
|
290
|
+
);
|
|
284
291
|
}
|
|
285
292
|
} else {
|
|
286
293
|
// No full CONTEXT.md — check for CONTEXT-DRAFT.md (draft seed from prior discussion)
|
|
@@ -288,7 +295,9 @@ export async function buildExistingMilestonesContext(
|
|
|
288
295
|
if (draftFile) {
|
|
289
296
|
const draftContent = await loadFile(draftFile);
|
|
290
297
|
if (draftContent) {
|
|
291
|
-
parts.push(
|
|
298
|
+
parts.push(
|
|
299
|
+
`\n**Draft context available:**\n${summarizeArtifactForQueue(draftContent, relMilestoneFile(basePath, mid, "CONTEXT-DRAFT"))}`,
|
|
300
|
+
);
|
|
292
301
|
}
|
|
293
302
|
}
|
|
294
303
|
}
|
|
@@ -300,7 +309,9 @@ export async function buildExistingMilestonesContext(
|
|
|
300
309
|
if (roadmapFile) {
|
|
301
310
|
const content = await loadFile(roadmapFile);
|
|
302
311
|
if (content) {
|
|
303
|
-
parts.push(
|
|
312
|
+
parts.push(
|
|
313
|
+
`\n**Roadmap:**\n${summarizeArtifactForQueue(content, relMilestoneFile(basePath, mid, "ROADMAP"))}`,
|
|
314
|
+
);
|
|
304
315
|
}
|
|
305
316
|
}
|
|
306
317
|
}
|
|
@@ -317,7 +328,81 @@ export async function buildExistingMilestonesContext(
|
|
|
317
328
|
}
|
|
318
329
|
}
|
|
319
330
|
|
|
320
|
-
return sections
|
|
331
|
+
return capExistingMilestonesContext(sections);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function summarizeArtifactForQueue(
|
|
335
|
+
content: string,
|
|
336
|
+
sourcePath: string,
|
|
337
|
+
cap = QUEUE_ARTIFACT_EXCERPT_MAX_CHARS,
|
|
338
|
+
): string {
|
|
339
|
+
const trimmed = content.trim();
|
|
340
|
+
if (trimmed.length <= cap) {
|
|
341
|
+
return `Source: \`${sourcePath}\`\n\n${trimmed}`;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const excerpt = trimmed.slice(0, cap).trimEnd();
|
|
345
|
+
const omittedChars = trimmed.length - excerpt.length;
|
|
346
|
+
return [
|
|
347
|
+
`Source: \`${sourcePath}\``,
|
|
348
|
+
"",
|
|
349
|
+
excerpt,
|
|
350
|
+
"",
|
|
351
|
+
`[Truncated ${omittedChars} chars. Read \`${sourcePath}\` for full content.]`,
|
|
352
|
+
].join("\n");
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function capExistingMilestonesContext(
|
|
356
|
+
sections: string[],
|
|
357
|
+
cap = QUEUE_EXISTING_MILESTONES_CONTEXT_MAX_CHARS,
|
|
358
|
+
): string {
|
|
359
|
+
const fullContext = sections.join(QUEUE_CONTEXT_SECTION_SEPARATOR);
|
|
360
|
+
if (fullContext.length <= cap) return fullContext;
|
|
361
|
+
|
|
362
|
+
const notice = `[Existing milestones context truncated to ${cap} chars. Read source paths in this prompt or the corresponding .gsd artifacts for full details.]`;
|
|
363
|
+
const noticeSuffix = `${QUEUE_CONTEXT_SECTION_SEPARATOR}${notice}`;
|
|
364
|
+
|
|
365
|
+
const selected: string[] = [];
|
|
366
|
+
for (const section of sections) {
|
|
367
|
+
const candidate = [...selected, section].join(QUEUE_CONTEXT_SECTION_SEPARATOR) + noticeSuffix;
|
|
368
|
+
if (candidate.length <= cap) {
|
|
369
|
+
selected.push(section);
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (selected.length === sections.length) {
|
|
376
|
+
return selected.join(QUEUE_CONTEXT_SECTION_SEPARATOR) + noticeSuffix;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const compactTail = sections.slice(selected.length).map(compactSectionForQueueBudget);
|
|
380
|
+
const hybrid = [...selected, ...compactTail].join(QUEUE_CONTEXT_SECTION_SEPARATOR) + noticeSuffix;
|
|
381
|
+
if (hybrid.length <= cap) return hybrid;
|
|
382
|
+
|
|
383
|
+
const compact = sections.map(compactSectionForQueueBudget);
|
|
384
|
+
const compactContext = compact.join(QUEUE_CONTEXT_SECTION_SEPARATOR) + noticeSuffix;
|
|
385
|
+
if (compactContext.length <= cap) return compactContext;
|
|
386
|
+
|
|
387
|
+
return `${compactContext.slice(0, Math.max(0, cap - notice.length - 2)).trimEnd()}\n\n${notice}`;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function compactSectionForQueueBudget(section: string): string {
|
|
391
|
+
const lines = section.split("\n");
|
|
392
|
+
const compact: string[] = [];
|
|
393
|
+
|
|
394
|
+
if (lines[0]) compact.push(lines[0]);
|
|
395
|
+
|
|
396
|
+
const statusLine = lines.find(line => line.startsWith("**Status:**"));
|
|
397
|
+
if (statusLine) compact.push(statusLine);
|
|
398
|
+
|
|
399
|
+
const sourceLines = lines.filter(line => line.startsWith("Source: `"));
|
|
400
|
+
if (sourceLines.length > 0) {
|
|
401
|
+
compact.push("", "**Sources:**", ...sourceLines);
|
|
402
|
+
compact.push("", "[Artifact excerpts omitted due to total queue/rethink context budget.]");
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return compact.join("\n");
|
|
321
406
|
}
|
|
322
407
|
|
|
323
408
|
// ─── Internal Helpers ───────────────────────────────────────────────────────
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
// File Purpose: Always-on ambient health signal rendered below the editor.
|
|
3
3
|
|
|
4
4
|
import type { ExtensionContext } from "@gsd/pi-coding-agent";
|
|
5
|
+
import { execFile } from "node:child_process";
|
|
5
6
|
import type { GSDState } from "./types.js";
|
|
6
|
-
import { runProviderChecks, summariseProviderIssues } from "./doctor-providers.js";
|
|
7
|
+
import { runProviderChecks, runProviderChecksAsync, summariseProviderIssues } from "./doctor-providers.js";
|
|
7
8
|
import { runEnvironmentChecks, runEnvironmentChecksAsync } from "./doctor-environment.js";
|
|
8
9
|
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
9
|
-
import {
|
|
10
|
+
import { GIT_NO_PROMPT_ENV } from "./git-constants.js";
|
|
10
11
|
import { loadLedgerFromDisk, getProjectTotals } from "./metrics.js";
|
|
11
12
|
import { describeNextUnit, estimateTimeRemaining, updateSliceProgressCache } from "./auto-dashboard.js";
|
|
12
13
|
import { projectRoot } from "./commands/context.js";
|
|
@@ -15,32 +16,75 @@ import {
|
|
|
15
16
|
buildHealthLines,
|
|
16
17
|
detectHealthWidgetProjectState,
|
|
17
18
|
type HealthWidgetData,
|
|
19
|
+
type HealthWidgetProjectState,
|
|
18
20
|
} from "./health-widget-core.js";
|
|
19
21
|
|
|
20
22
|
export const HEALTH_WIDGET_ACTIVE_HINTS =
|
|
21
23
|
" /gsd auto to run · /gsd status to inspect · /gsd report for snapshots · /gsd notifications for history · /gsd help";
|
|
22
24
|
|
|
25
|
+
const LAST_COMMIT_LOOKUP_TIMEOUT_MS = 3_000;
|
|
26
|
+
const REFRESH_INTERVAL_MS = 60_000;
|
|
27
|
+
const PROJECT_STATE_CACHE_TTL_MS = REFRESH_INTERVAL_MS;
|
|
28
|
+
|
|
23
29
|
// ── Data loader ────────────────────────────────────────────────────────────────
|
|
24
30
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
const projectStateCache = new Map<string, { state: HealthWidgetProjectState; computedAt: number }>();
|
|
32
|
+
|
|
33
|
+
export function getCachedProjectState(basePath: string, force?: boolean): HealthWidgetProjectState {
|
|
34
|
+
const now = Date.now();
|
|
35
|
+
const cached = projectStateCache.get(basePath);
|
|
36
|
+
if (!force && cached && now - cached.computedAt <= PROJECT_STATE_CACHE_TTL_MS) {
|
|
37
|
+
return cached.state;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const state = detectHealthWidgetProjectState(basePath);
|
|
41
|
+
projectStateCache.set(basePath, { state, computedAt: now });
|
|
42
|
+
return state;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function runHealthWidgetGit(basePath: string, args: string[]): Promise<string | null> {
|
|
46
|
+
return new Promise((resolve) => {
|
|
47
|
+
const child = execFile(
|
|
48
|
+
"git",
|
|
49
|
+
args,
|
|
50
|
+
{
|
|
51
|
+
cwd: basePath,
|
|
52
|
+
timeout: LAST_COMMIT_LOOKUP_TIMEOUT_MS,
|
|
53
|
+
encoding: "utf-8",
|
|
54
|
+
env: GIT_NO_PROMPT_ENV,
|
|
55
|
+
},
|
|
56
|
+
(err, stdout) => resolve(err ? null : String(stdout).trimEnd()),
|
|
57
|
+
);
|
|
58
|
+
child.on("error", () => resolve(null));
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function loadLastCommitInfoAsync(basePath: string): Promise<{ epoch: number | null; message: string | null }> {
|
|
29
63
|
try {
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
const epoch = nativeLastCommitEpoch(basePath, branch || "HEAD");
|
|
33
|
-
if (epoch > 0) {
|
|
34
|
-
return { epoch, message: nativeCommitSubject(basePath, branch || "HEAD") || null };
|
|
35
|
-
}
|
|
64
|
+
if ((await runHealthWidgetGit(basePath, ["rev-parse", "--git-dir"])) === null) {
|
|
65
|
+
return { epoch: null, message: null };
|
|
36
66
|
}
|
|
37
|
-
|
|
38
|
-
|
|
67
|
+
|
|
68
|
+
const branch = await runHealthWidgetGit(basePath, ["branch", "--show-current"]);
|
|
69
|
+
const ref = branch || "HEAD";
|
|
70
|
+
const raw = await runHealthWidgetGit(basePath, ["log", "-1", "--format=%ct%x00%s", ref]);
|
|
71
|
+
if (!raw) return { epoch: null, message: null };
|
|
72
|
+
|
|
73
|
+
const separator = raw.indexOf("\0");
|
|
74
|
+
const epochText = separator >= 0 ? raw.slice(0, separator) : raw;
|
|
75
|
+
const epoch = parseInt(epochText.trim(), 10) || 0;
|
|
76
|
+
if (epoch <= 0) return { epoch: null, message: null };
|
|
77
|
+
|
|
78
|
+
const message = separator >= 0 ? raw.slice(separator + 1).trim() : "";
|
|
79
|
+
return { epoch, message: message || null };
|
|
80
|
+
} catch {
|
|
81
|
+
return { epoch: null, message: null };
|
|
82
|
+
}
|
|
39
83
|
}
|
|
40
84
|
|
|
41
85
|
function loadHealthWidgetData(
|
|
42
86
|
basePath: string,
|
|
43
|
-
options?: { includeChecks?: boolean },
|
|
87
|
+
options?: { includeChecks?: boolean; forceProjectState?: boolean },
|
|
44
88
|
): HealthWidgetData {
|
|
45
89
|
// `includeChecks` gates the expensive subprocess-backed checks (provider +
|
|
46
90
|
// environment doctor: `lsof`, `docker`, `node --version`, ...). The initial
|
|
@@ -55,7 +99,7 @@ function loadHealthWidgetData(
|
|
|
55
99
|
let lastCommitEpoch: number | null = null;
|
|
56
100
|
let lastCommitMessage: string | null = null;
|
|
57
101
|
|
|
58
|
-
const projectState =
|
|
102
|
+
const projectState = getCachedProjectState(basePath, options?.forceProjectState);
|
|
59
103
|
|
|
60
104
|
try {
|
|
61
105
|
const prefs = loadEffectiveGSDPreferences();
|
|
@@ -83,13 +127,6 @@ function loadHealthWidgetData(
|
|
|
83
127
|
} catch { /* non-fatal */ }
|
|
84
128
|
}
|
|
85
129
|
|
|
86
|
-
// ── Last commit info ── (git spawns — gated like the other expensive checks)
|
|
87
|
-
if (includeChecks) {
|
|
88
|
-
const commit = loadLastCommitInfo(basePath);
|
|
89
|
-
lastCommitEpoch = commit.epoch;
|
|
90
|
-
lastCommitMessage = commit.message;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
130
|
return {
|
|
94
131
|
projectState,
|
|
95
132
|
budgetCeiling,
|
|
@@ -104,10 +141,8 @@ function loadHealthWidgetData(
|
|
|
104
141
|
}
|
|
105
142
|
|
|
106
143
|
// Non-blocking variant used by the widget's background refresh: the cheap fields
|
|
107
|
-
// come from the synchronous snapshot, then provider
|
|
108
|
-
// layered in off the event-loop critical path
|
|
109
|
-
// runEnvironmentChecksAsync). Keeps the always-on widget from stalling the UI on
|
|
110
|
-
// its initial enrichment or its 60s refresh.
|
|
144
|
+
// come from the synchronous snapshot, then provider, environment, and last-commit
|
|
145
|
+
// checks are layered in off the event-loop critical path.
|
|
111
146
|
async function loadHealthWidgetDataAsync(basePath: string): Promise<HealthWidgetData> {
|
|
112
147
|
const data = loadHealthWidgetData(basePath, { includeChecks: false });
|
|
113
148
|
let providerIssue = data.providerIssue;
|
|
@@ -115,7 +150,7 @@ async function loadHealthWidgetDataAsync(basePath: string): Promise<HealthWidget
|
|
|
115
150
|
let environmentWarningCount = 0;
|
|
116
151
|
|
|
117
152
|
try {
|
|
118
|
-
providerIssue = summariseProviderIssues(
|
|
153
|
+
providerIssue = summariseProviderIssues(await runProviderChecksAsync());
|
|
119
154
|
} catch { /* non-fatal */ }
|
|
120
155
|
|
|
121
156
|
try {
|
|
@@ -126,7 +161,7 @@ async function loadHealthWidgetDataAsync(basePath: string): Promise<HealthWidget
|
|
|
126
161
|
}
|
|
127
162
|
} catch { /* non-fatal */ }
|
|
128
163
|
|
|
129
|
-
const commit =
|
|
164
|
+
const commit = await loadLastCommitInfoAsync(basePath);
|
|
130
165
|
|
|
131
166
|
return {
|
|
132
167
|
...data,
|
|
@@ -141,8 +176,6 @@ async function loadHealthWidgetDataAsync(basePath: string): Promise<HealthWidget
|
|
|
141
176
|
|
|
142
177
|
// ── Widget init ────────────────────────────────────────────────────────────────
|
|
143
178
|
|
|
144
|
-
const REFRESH_INTERVAL_MS = 60_000;
|
|
145
|
-
|
|
146
179
|
/**
|
|
147
180
|
* Initialize the always-on gsd-health widget (belowEditor).
|
|
148
181
|
* Call once from the extension entry point after context is available.
|
|
@@ -152,13 +185,17 @@ export function initHealthWidget(ctx: ExtensionContext): void {
|
|
|
152
185
|
|
|
153
186
|
const basePath = projectRoot();
|
|
154
187
|
|
|
188
|
+
// Re-init must reflect filesystem changes immediately; the TTL cache is for
|
|
189
|
+
// interval refreshes, not this one-off synchronous paint.
|
|
190
|
+
projectStateCache.delete(basePath);
|
|
191
|
+
|
|
155
192
|
// String-array fallback — used in RPC mode (factory is a no-op there).
|
|
156
193
|
// Skip the expensive provider/environment doctor checks here: this runs
|
|
157
194
|
// synchronously on the interactive-startup path, where running them would
|
|
158
195
|
// block first paint by ~0.9s (lsof/docker probes, otherwise run again
|
|
159
196
|
// immediately by the factory below). The factory's async refresh fills in
|
|
160
197
|
// real health once the screen is up.
|
|
161
|
-
const initialData = loadHealthWidgetData(basePath, { includeChecks: false });
|
|
198
|
+
const initialData = loadHealthWidgetData(basePath, { includeChecks: false, forceProjectState: true });
|
|
162
199
|
ctx.ui.setWidget("gsd-health", buildHealthLines(initialData), { placement: "belowEditor" });
|
|
163
200
|
|
|
164
201
|
// Factory-based widget for TUI mode — replaces the string-array above
|
|
@@ -47,8 +47,9 @@ export function dbPath(basePath: string): string {
|
|
|
47
47
|
* Used by the renderer to derive the phase number from the DB's milestone_id.
|
|
48
48
|
*/
|
|
49
49
|
export function milestoneIdToPhaseNum(milestoneId: string): number {
|
|
50
|
-
// No $ anchor: accepts bare (M012)
|
|
50
|
+
// No $ anchor: accepts bare (M012), team-suffixed (M012-abc123), and legacy numeric IDs.
|
|
51
51
|
const m = milestoneId.match(/^M0*(\d+)/i);
|
|
52
|
+
if (!m && /^\d+$/.test(milestoneId)) return Number.parseInt(milestoneId, 10);
|
|
52
53
|
return m ? Number.parseInt(m[1]!, 10) : 1;
|
|
53
54
|
}
|
|
54
55
|
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
insertArtifact,
|
|
26
26
|
deleteArtifactByPath,
|
|
27
27
|
getGateResults,
|
|
28
|
+
isDbAvailable,
|
|
28
29
|
} from "./gsd-db.js";
|
|
29
30
|
import type { MilestoneRow, ArtifactRow } from "./db-milestone-artifact-rows.js";
|
|
30
31
|
import type { SliceRow, TaskRow } from "./db-task-slice-rows.js";
|
|
@@ -631,16 +632,8 @@ export async function renderRoadmapCheckboxes(
|
|
|
631
632
|
basePath: string,
|
|
632
633
|
milestoneId: string,
|
|
633
634
|
): Promise<boolean> {
|
|
634
|
-
const
|
|
635
|
-
|
|
636
|
-
process.stderr.write(
|
|
637
|
-
`markdown-renderer: no slices found for milestone ${milestoneId}\n`,
|
|
638
|
-
);
|
|
639
|
-
return false;
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
await renderRoadmapFromDb(basePath, milestoneId);
|
|
643
|
-
return true;
|
|
635
|
+
const rendered = await renderRoadmapFromDb(basePath, milestoneId);
|
|
636
|
+
return !("skipped" in rendered);
|
|
644
637
|
}
|
|
645
638
|
|
|
646
639
|
/**
|
|
@@ -737,7 +730,8 @@ function isAutoRecoveryPlaceholderPlan(content: string): boolean {
|
|
|
737
730
|
* projection (the 4S/0T-vs-5S/13T drift class). The artifacts table is an
|
|
738
731
|
* output sink, never a render input.
|
|
739
732
|
*
|
|
740
|
-
* @returns true if the plan was written, false
|
|
733
|
+
* @returns true if the plan was written, false when the DB slice has no tasks
|
|
734
|
+
* @throws when the DB connection is unavailable or the render write fails
|
|
741
735
|
*/
|
|
742
736
|
export async function renderPlanCheckboxes(
|
|
743
737
|
basePath: string,
|
|
@@ -747,6 +741,9 @@ export async function renderPlanCheckboxes(
|
|
|
747
741
|
): Promise<boolean> {
|
|
748
742
|
const tasks = getSliceTasks(milestoneId, sliceId);
|
|
749
743
|
if (tasks.length === 0) {
|
|
744
|
+
if (!isDbAvailable()) {
|
|
745
|
+
throw new Error(`database unavailable while rendering plan checkboxes for ${milestoneId}/${sliceId}`);
|
|
746
|
+
}
|
|
750
747
|
process.stderr.write(
|
|
751
748
|
`markdown-renderer: no tasks found for ${milestoneId}/${sliceId}\n`,
|
|
752
749
|
);
|