@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
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import test from "node:test";
|
|
9
9
|
import assert from "node:assert/strict";
|
|
10
|
-
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
10
|
+
import { mkdtempSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
11
11
|
import { tmpdir } from "node:os";
|
|
12
12
|
import { join } from "node:path";
|
|
13
13
|
import { classifyError, isTransient, isTransientNetworkError } from "../error-classifier.ts";
|
|
@@ -26,6 +26,10 @@ import { _buildCancelledUnitStopReason } from "../auto/phase-helpers.ts";
|
|
|
26
26
|
import { _classifyZeroToolProviderMessageForTest } from "../auto/unit-phase.ts";
|
|
27
27
|
import { autoSession } from "../auto-runtime-state.ts";
|
|
28
28
|
import { getNextFallbackModel } from "../preferences.ts";
|
|
29
|
+
import { clearGuidedUnitContext, getGuidedUnitContext, setGuidedUnitContext } from "../guided-unit-context.ts";
|
|
30
|
+
import { initNotificationStore, readNotifications, _resetNotificationStore } from "../notification-store.ts";
|
|
31
|
+
import { installNotifyInterceptor } from "../bootstrap/notify-interceptor.ts";
|
|
32
|
+
import { extractTrace } from "../session-forensics.ts";
|
|
29
33
|
// Zero-import module — imported by path rather than through the package
|
|
30
34
|
// barrel to avoid pulling the full AgentSession / @gsd/pi-ai dep graph into
|
|
31
35
|
// this unit test (see #4837).
|
|
@@ -488,6 +492,63 @@ test("pauseAutoForProviderError falls back to indefinite pause when not rate lim
|
|
|
488
492
|
]);
|
|
489
493
|
});
|
|
490
494
|
|
|
495
|
+
test("agent_end retries when empty errorMessage has stream failure in content (#956)", async () => {
|
|
496
|
+
const originalSetTimeout = globalThis.setTimeout;
|
|
497
|
+
const notifications: Array<{ message: string; level?: string }> = [];
|
|
498
|
+
const sendMessageCalls: unknown[][] = [];
|
|
499
|
+
const timers: Array<{ fn: () => void; delay: number }> = [];
|
|
500
|
+
|
|
501
|
+
resetTransientRetryState();
|
|
502
|
+
autoSession.reset();
|
|
503
|
+
// handleAgentEnd returns at the isAutoActive() guard unless auto-mode is
|
|
504
|
+
// active. Set the minimum fields needed to reach the stopReason === "error"
|
|
505
|
+
// branch without requiring a real DB or worktree.
|
|
506
|
+
autoSession.active = true;
|
|
507
|
+
autoSession.currentUnit = { type: "execute-task", id: "M001/S01/T01", startedAt: Date.now() };
|
|
508
|
+
|
|
509
|
+
globalThis.setTimeout = ((fn: () => void, delay?: number) => {
|
|
510
|
+
timers.push({ fn, delay: delay ?? 0 });
|
|
511
|
+
return 0 as unknown as ReturnType<typeof setTimeout>;
|
|
512
|
+
}) as typeof setTimeout;
|
|
513
|
+
|
|
514
|
+
try {
|
|
515
|
+
await handleAgentEnd({
|
|
516
|
+
sendMessage: (...args: unknown[]) => {
|
|
517
|
+
sendMessageCalls.push(args);
|
|
518
|
+
},
|
|
519
|
+
} as any, {
|
|
520
|
+
messages: [{
|
|
521
|
+
role: "assistant",
|
|
522
|
+
stopReason: "error",
|
|
523
|
+
errorMessage: "",
|
|
524
|
+
content: [{ type: "text", text: "API Error: stream idle timeout - partial response received" }],
|
|
525
|
+
}],
|
|
526
|
+
} as any, {
|
|
527
|
+
model: { provider: "openai-codex", id: "gpt-5.5" },
|
|
528
|
+
ui: {
|
|
529
|
+
notify(message: string, level?: "info" | "warning" | "error" | "success") {
|
|
530
|
+
notifications.push({ message, level });
|
|
531
|
+
},
|
|
532
|
+
},
|
|
533
|
+
} as any);
|
|
534
|
+
|
|
535
|
+
assert.equal(timers.length, 1, "empty errorMessage stream failures should use the network retry path");
|
|
536
|
+
assert.equal(timers[0].delay, 3_000);
|
|
537
|
+
assert.deepEqual(notifications[0], {
|
|
538
|
+
message: "Network error on gpt-5.5: API Error: stream idle timeout - partial response received. Retry 1/2 in 3s...",
|
|
539
|
+
level: "warning",
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
timers[0].fn();
|
|
543
|
+
assert.equal(sendMessageCalls.length, 1);
|
|
544
|
+
assert.deepEqual(sendMessageCalls[0][1], { triggerTurn: true });
|
|
545
|
+
} finally {
|
|
546
|
+
globalThis.setTimeout = originalSetTimeout;
|
|
547
|
+
resetTransientRetryState();
|
|
548
|
+
autoSession.reset();
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
|
|
491
552
|
test("rate-limit agent_end walks past unavailable fallback models before pausing (#716 follow-up)", async () => {
|
|
492
553
|
const originalCwd = process.cwd();
|
|
493
554
|
const originalSetTimeout = globalThis.setTimeout;
|
|
@@ -648,6 +709,139 @@ test("does not suppress deleted-worktree provider errors outside terminal comple
|
|
|
648
709
|
assert.equal(event.message.stopReason, "error");
|
|
649
710
|
});
|
|
650
711
|
|
|
712
|
+
test("manual guided discuss provider error records warning and activity marker (#944)", async () => {
|
|
713
|
+
const originalCwd = process.cwd();
|
|
714
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-manual-discuss-error-"));
|
|
715
|
+
const notifications: Array<{ message: string; level?: string }> = [];
|
|
716
|
+
const sendMessageCalls: unknown[][] = [];
|
|
717
|
+
|
|
718
|
+
try {
|
|
719
|
+
autoSession.reset();
|
|
720
|
+
mkdirSync(join(base, ".git"), { recursive: true });
|
|
721
|
+
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
722
|
+
process.chdir(base);
|
|
723
|
+
initNotificationStore(base);
|
|
724
|
+
|
|
725
|
+
// Use base as the guided context path so gsdRoot(base) hits the fast path
|
|
726
|
+
// (.gsd exists at base directly) and doesn't need git to walk up from a
|
|
727
|
+
// subdirectory — the empty .git folder is not a real repo and git resolution
|
|
728
|
+
// from a child directory would return the wrong .gsd path.
|
|
729
|
+
setGuidedUnitContext(base, "discuss-slice");
|
|
730
|
+
|
|
731
|
+
const ctx = {
|
|
732
|
+
model: { provider: "openai-codex", id: "gpt-5.1-codex" },
|
|
733
|
+
modelRegistry: { getAvailable: () => [] },
|
|
734
|
+
ui: {
|
|
735
|
+
notify(message: string, level?: "info" | "warning" | "error" | "success") {
|
|
736
|
+
notifications.push({ message, level });
|
|
737
|
+
},
|
|
738
|
+
},
|
|
739
|
+
} as any;
|
|
740
|
+
installNotifyInterceptor(ctx);
|
|
741
|
+
|
|
742
|
+
const pi = {
|
|
743
|
+
sendMessage: (...args: unknown[]) => {
|
|
744
|
+
sendMessageCalls.push(args);
|
|
745
|
+
},
|
|
746
|
+
} as any;
|
|
747
|
+
|
|
748
|
+
await handleAgentEnd(pi, {
|
|
749
|
+
messages: [{
|
|
750
|
+
role: "assistant",
|
|
751
|
+
stopReason: "error",
|
|
752
|
+
errorMessage: "",
|
|
753
|
+
content: [{ type: "text", text: "stream idle timeout while saving summary" }],
|
|
754
|
+
}],
|
|
755
|
+
} as any, ctx);
|
|
756
|
+
|
|
757
|
+
assert.deepEqual(sendMessageCalls, [], "manual discuss terminal errors must not auto-retry or redispatch");
|
|
758
|
+
assert.equal(getGuidedUnitContext(base), null, "guided unit context must still be cleared after the turn");
|
|
759
|
+
assert.equal(notifications.length, 1);
|
|
760
|
+
assert.equal(notifications[0]?.level, "warning");
|
|
761
|
+
assert.match(notifications[0]?.message ?? "", /Manual \/gsd discuss discuss-slice ended with a provider error/);
|
|
762
|
+
assert.match(notifications[0]?.message ?? "", /openai-codex\/gpt-5\.1-codex/);
|
|
763
|
+
assert.match(notifications[0]?.message ?? "", /stream idle timeout/);
|
|
764
|
+
|
|
765
|
+
const persisted = readNotifications(base);
|
|
766
|
+
assert.equal(persisted.length, 1, "wrapped notify should persist exactly one warning notification");
|
|
767
|
+
assert.equal(persisted[0]?.severity, "warning");
|
|
768
|
+
assert.equal(persisted[0]?.source, "notify");
|
|
769
|
+
|
|
770
|
+
const activityDir = join(base, ".gsd", "activity");
|
|
771
|
+
const files = readdirSync(activityDir).filter((file) => file.endsWith(".jsonl"));
|
|
772
|
+
assert.equal(files.length, 1, "manual guided provider error should write one activity marker");
|
|
773
|
+
const entries = readFileSync(join(activityDir, files[0]!), "utf-8")
|
|
774
|
+
.split("\n")
|
|
775
|
+
.filter(Boolean)
|
|
776
|
+
.map((line) => JSON.parse(line));
|
|
777
|
+
const trace = extractTrace(entries);
|
|
778
|
+
assert.equal(trace.errors.length, 1);
|
|
779
|
+
assert.match(trace.errors[0] ?? "", /discuss-slice/);
|
|
780
|
+
assert.match(trace.errors[0] ?? "", /openai-codex\/gpt-5\.1-codex/);
|
|
781
|
+
assert.match(trace.errors[0] ?? "", /stream idle timeout/);
|
|
782
|
+
} finally {
|
|
783
|
+
clearGuidedUnitContext();
|
|
784
|
+
_resetNotificationStore();
|
|
785
|
+
autoSession.reset();
|
|
786
|
+
process.chdir(originalCwd);
|
|
787
|
+
rmSync(base, { recursive: true, force: true });
|
|
788
|
+
}
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
test("manual guided discuss user-cancel is not treated as a provider error (#944)", async () => {
|
|
792
|
+
const originalCwd = process.cwd();
|
|
793
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-manual-discuss-cancel-"));
|
|
794
|
+
const guidedBase = join(base, "slice-work");
|
|
795
|
+
const notifications: Array<{ message: string; level?: string }> = [];
|
|
796
|
+
|
|
797
|
+
try {
|
|
798
|
+
autoSession.reset();
|
|
799
|
+
mkdirSync(join(base, ".git"), { recursive: true });
|
|
800
|
+
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
801
|
+
mkdirSync(guidedBase, { recursive: true });
|
|
802
|
+
process.chdir(base);
|
|
803
|
+
initNotificationStore(base);
|
|
804
|
+
|
|
805
|
+
setGuidedUnitContext(guidedBase, "discuss-slice");
|
|
806
|
+
|
|
807
|
+
const ctx = {
|
|
808
|
+
model: { provider: "anthropic", id: "claude-opus-4" },
|
|
809
|
+
modelRegistry: { getAvailable: () => [] },
|
|
810
|
+
ui: {
|
|
811
|
+
notify(message: string, level?: "info" | "warning" | "error" | "success") {
|
|
812
|
+
notifications.push({ message, level });
|
|
813
|
+
},
|
|
814
|
+
},
|
|
815
|
+
} as any;
|
|
816
|
+
installNotifyInterceptor(ctx);
|
|
817
|
+
|
|
818
|
+
const pi = { sendMessage: () => {} } as any;
|
|
819
|
+
|
|
820
|
+
await handleAgentEnd(pi, {
|
|
821
|
+
messages: [{
|
|
822
|
+
role: "assistant",
|
|
823
|
+
stopReason: "error",
|
|
824
|
+
errorMessage: "Request aborted by user",
|
|
825
|
+
content: [],
|
|
826
|
+
}],
|
|
827
|
+
} as any, ctx);
|
|
828
|
+
|
|
829
|
+
assert.deepEqual(notifications, [], "user-cancel stopReason=error must not emit a provider-error warning");
|
|
830
|
+
assert.equal(getGuidedUnitContext(guidedBase), null, "context must be cleared even for user-cancel");
|
|
831
|
+
|
|
832
|
+
// No activity directory should have been created
|
|
833
|
+
let activityExists = false;
|
|
834
|
+
try { readdirSync(join(base, ".gsd", "activity")); activityExists = true; } catch { /* expected */ }
|
|
835
|
+
assert.equal(activityExists, false, "user-cancel must not write an activity error marker");
|
|
836
|
+
} finally {
|
|
837
|
+
clearGuidedUnitContext();
|
|
838
|
+
_resetNotificationStore();
|
|
839
|
+
autoSession.reset();
|
|
840
|
+
process.chdir(originalCwd);
|
|
841
|
+
rmSync(base, { recursive: true, force: true });
|
|
842
|
+
}
|
|
843
|
+
});
|
|
844
|
+
|
|
651
845
|
// ── resumeAutoAfterProviderDelay ────────────────────────────────────────────
|
|
652
846
|
|
|
653
847
|
test("resumeAutoAfterProviderDelay restarts paused auto-mode from the recorded base path", async () => {
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Behavioural regression test for the milestone-closeout UAT gate —
|
|
3
|
+
* `readUatGateVerdict`.
|
|
4
|
+
*
|
|
5
|
+
* The gate (ADR-017: DB-authoritative UAT sign-off) reads a slice's UAT
|
|
6
|
+
* verdict from its ASSESSMENT artifact via the *canonical* expected path
|
|
7
|
+
* (`resolveSliceFile` + a path-keyed `getAssessment`). When a milestone
|
|
8
|
+
* artifact-layout migration orphans the ASSESSMENT markdown from that canonical
|
|
9
|
+
* path (e.g. `phases/…` → `milestones/…`), the gate used to return `null` and
|
|
10
|
+
* block milestone closure with "missing UAT PASS verdict" — even though the
|
|
11
|
+
* verdict was correctly recorded in the `assessments` table by
|
|
12
|
+
* `gsd_uat_result_save`.
|
|
13
|
+
*
|
|
14
|
+
* The DB fallback added to `readUatGateVerdict` consults the authoritative
|
|
15
|
+
* `assessments` table by (milestoneId, sliceId, scope='run-uat') identity,
|
|
16
|
+
* independent of path. These tests pin that behaviour.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { describe, test, beforeEach, afterEach } from 'node:test';
|
|
20
|
+
import assert from 'node:assert/strict';
|
|
21
|
+
import * as fs from 'node:fs';
|
|
22
|
+
import * as path from 'node:path';
|
|
23
|
+
import * as os from 'node:os';
|
|
24
|
+
|
|
25
|
+
import {
|
|
26
|
+
openDatabase,
|
|
27
|
+
closeDatabase,
|
|
28
|
+
insertMilestone,
|
|
29
|
+
insertSlice,
|
|
30
|
+
insertAssessment,
|
|
31
|
+
} from '../gsd-db.ts';
|
|
32
|
+
import { readUatGateVerdict } from '../auto-dispatch.ts';
|
|
33
|
+
|
|
34
|
+
function tempDbPath(): string {
|
|
35
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-uat-gate-'));
|
|
36
|
+
return path.join(dir, 'test.db');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function cleanupDb(dbPath: string): void {
|
|
40
|
+
closeDatabase();
|
|
41
|
+
try { fs.rmSync(path.dirname(dbPath), { recursive: true, force: true }); } catch { /* */ }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const MID = 'M001';
|
|
45
|
+
const SLICE = 'S01';
|
|
46
|
+
|
|
47
|
+
/** Canonical on-disk ASSESSMENT path produced by `resolveSliceFile`. */
|
|
48
|
+
function canonicalAssessmentPath(basePath: string): string {
|
|
49
|
+
return path.join(basePath, '.gsd', 'milestones', MID, 'slices', SLICE, `${SLICE}-ASSESSMENT.md`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** An ASSESSMENT body that declares a runtime-executable UAT type and a PASS verdict. */
|
|
53
|
+
const RUNTIME_PASS_BODY = [
|
|
54
|
+
'---',
|
|
55
|
+
'verdict: pass',
|
|
56
|
+
'---',
|
|
57
|
+
'',
|
|
58
|
+
'# S01 UAT Assessment',
|
|
59
|
+
'',
|
|
60
|
+
'## UAT Type',
|
|
61
|
+
'- UAT mode: runtime-executable',
|
|
62
|
+
'',
|
|
63
|
+
'## Result',
|
|
64
|
+
'All checks passed.',
|
|
65
|
+
].join('\n');
|
|
66
|
+
|
|
67
|
+
describe('readUatGateVerdict — DB fallback for orphaned ASSESSMENT', () => {
|
|
68
|
+
let dbPath: string;
|
|
69
|
+
let basePath: string;
|
|
70
|
+
|
|
71
|
+
beforeEach(() => {
|
|
72
|
+
dbPath = tempDbPath();
|
|
73
|
+
openDatabase(dbPath);
|
|
74
|
+
basePath = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-uat-gate-proj-'));
|
|
75
|
+
insertMilestone({ id: MID });
|
|
76
|
+
insertSlice({ id: SLICE, milestoneId: MID });
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
afterEach(() => {
|
|
80
|
+
cleanupDb(dbPath);
|
|
81
|
+
try { fs.rmSync(basePath, { recursive: true, force: true }); } catch { /* */ }
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('returns pass when the ASSESSMENT is keyed by a legacy/orphaned path (the bug)', async () => {
|
|
85
|
+
// Reproduces milestone 15: `gsd_uat_result_save` wrote S01's assessment row
|
|
86
|
+
// under a now-migrated path; the canonical file never existed on disk and
|
|
87
|
+
// the `assessments.path` is not what `resolveSliceFile` computes.
|
|
88
|
+
insertAssessment({
|
|
89
|
+
// Deliberately non-canonical — a legacy `phases/…` path.
|
|
90
|
+
path: `.gsd/phases/01-some-feature/01-01-ASSESSMENT.md`,
|
|
91
|
+
milestoneId: MID,
|
|
92
|
+
sliceId: SLICE,
|
|
93
|
+
status: 'pass',
|
|
94
|
+
scope: 'run-uat',
|
|
95
|
+
fullContent: RUNTIME_PASS_BODY,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const result = await readUatGateVerdict(basePath, MID, SLICE);
|
|
99
|
+
|
|
100
|
+
assert.ok(result, 'expected the DB fallback to resolve a verdict, got null');
|
|
101
|
+
assert.equal(result!.verdict, 'pass');
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('the DB fallback derives uatType from the assessment body when no file exists', async () => {
|
|
105
|
+
insertAssessment({
|
|
106
|
+
path: `.gsd/phases/01-some-feature/01-01-ASSESSMENT.md`,
|
|
107
|
+
milestoneId: MID,
|
|
108
|
+
sliceId: SLICE,
|
|
109
|
+
status: 'pass',
|
|
110
|
+
scope: 'run-uat',
|
|
111
|
+
fullContent: RUNTIME_PASS_BODY,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const result = await readUatGateVerdict(basePath, MID, SLICE);
|
|
115
|
+
|
|
116
|
+
assert.ok(result);
|
|
117
|
+
assert.equal(result!.verdict, 'pass');
|
|
118
|
+
assert.equal(result!.uatType, 'runtime-executable');
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test('canonical ASSESSMENT file on disk still resolves (regression guard)', async () => {
|
|
122
|
+
// When the file is present at the canonical path, the existing path-keyed
|
|
123
|
+
// lookup must resolve it without needing the fallback.
|
|
124
|
+
const file = canonicalAssessmentPath(basePath);
|
|
125
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
126
|
+
fs.writeFileSync(file, RUNTIME_PASS_BODY);
|
|
127
|
+
// Also seed the path-keyed assessments row, mirroring a normal save.
|
|
128
|
+
insertAssessment({
|
|
129
|
+
path: `.gsd/milestones/${MID}/slices/${SLICE}/${SLICE}-ASSESSMENT.md`,
|
|
130
|
+
milestoneId: MID,
|
|
131
|
+
sliceId: SLICE,
|
|
132
|
+
status: 'pass',
|
|
133
|
+
scope: 'run-uat',
|
|
134
|
+
fullContent: RUNTIME_PASS_BODY,
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const result = await readUatGateVerdict(basePath, MID, SLICE);
|
|
138
|
+
|
|
139
|
+
assert.ok(result);
|
|
140
|
+
assert.equal(result!.verdict, 'pass');
|
|
141
|
+
assert.equal(result!.uatType, 'runtime-executable');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test('a roadmap-scoped assessment does NOT satisfy the UAT gate', async () => {
|
|
145
|
+
// `reassess-roadmap` writes roadmap-scoped assessments to the same
|
|
146
|
+
// S##-ASSESSMENT path; those must never be treated as a UAT verdict. The
|
|
147
|
+
// legacy-path fallback queries scope='run-uat', so a roadmap-only row is
|
|
148
|
+
// invisible and the gate returns null.
|
|
149
|
+
insertAssessment({
|
|
150
|
+
path: `.gsd/milestones/${MID}/slices/${SLICE}/${SLICE}-ASSESSMENT.md`,
|
|
151
|
+
milestoneId: MID,
|
|
152
|
+
sliceId: SLICE,
|
|
153
|
+
status: 'pass',
|
|
154
|
+
scope: 'roadmap',
|
|
155
|
+
fullContent: RUNTIME_PASS_BODY,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const result = await readUatGateVerdict(basePath, MID, SLICE);
|
|
159
|
+
|
|
160
|
+
assert.equal(result, null, 'roadmap-scoped assessments must not satisfy the UAT gate');
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test('returns null when no assessment and no file exist (fallback does not hallucinate)', async () => {
|
|
164
|
+
const result = await readUatGateVerdict(basePath, MID, SLICE);
|
|
165
|
+
assert.equal(result, null);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
test('surfaces a recorded non-pass verdict via the DB fallback', async () => {
|
|
169
|
+
// A failing verdict stored under a legacy path must surface (not be masked
|
|
170
|
+
// as "missing") so the gate's non-PASS branch can act on it.
|
|
171
|
+
insertAssessment({
|
|
172
|
+
path: `.gsd/phases/01-some-feature/01-01-ASSESSMENT.md`,
|
|
173
|
+
milestoneId: MID,
|
|
174
|
+
sliceId: SLICE,
|
|
175
|
+
status: 'fail',
|
|
176
|
+
scope: 'run-uat',
|
|
177
|
+
fullContent: RUNTIME_PASS_BODY.replace('verdict: pass', 'verdict: fail'),
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
const result = await readUatGateVerdict(basePath, MID, SLICE);
|
|
181
|
+
|
|
182
|
+
assert.ok(result);
|
|
183
|
+
assert.equal(result!.verdict, 'fail');
|
|
184
|
+
});
|
|
185
|
+
});
|
|
@@ -970,6 +970,93 @@ test("register-hooks agent_end does not re-arm deferred gate after workflow MCP
|
|
|
970
970
|
});
|
|
971
971
|
});
|
|
972
972
|
|
|
973
|
+
test("register-hooks message_update uses in-memory write-gate snapshot instead of disk reconcile", async (t) => {
|
|
974
|
+
const dir = makeTempDir("message-update-memory-snapshot");
|
|
975
|
+
const originalCwd = process.cwd();
|
|
976
|
+
const originalEnv = process.env.GSD_PERSIST_WRITE_GATE_STATE;
|
|
977
|
+
process.chdir(dir);
|
|
978
|
+
process.env.GSD_PERSIST_WRITE_GATE_STATE = "1";
|
|
979
|
+
resetWriteGateState(dir);
|
|
980
|
+
clearPendingAutoStart(dir);
|
|
981
|
+
|
|
982
|
+
const gateId = "depth_verification_M012_confirm";
|
|
983
|
+
const statePath = join(dir, ".gsd", "runtime", "write-gate-state.json");
|
|
984
|
+
|
|
985
|
+
t.after(() => {
|
|
986
|
+
try {
|
|
987
|
+
resetWriteGateState(dir);
|
|
988
|
+
clearPendingAutoStart(dir);
|
|
989
|
+
} finally {
|
|
990
|
+
if (originalEnv === undefined) {
|
|
991
|
+
delete process.env.GSD_PERSIST_WRITE_GATE_STATE;
|
|
992
|
+
} else {
|
|
993
|
+
process.env.GSD_PERSIST_WRITE_GATE_STATE = originalEnv;
|
|
994
|
+
}
|
|
995
|
+
process.chdir(originalCwd);
|
|
996
|
+
rmSync(dir, { recursive: true, force: true });
|
|
997
|
+
}
|
|
998
|
+
});
|
|
999
|
+
|
|
1000
|
+
const handlers = new Map<string, Array<(event: any, ctx?: any) => Promise<any> | any>>();
|
|
1001
|
+
const pi = {
|
|
1002
|
+
on(event: string, handler: (event: any, ctx?: any) => Promise<any> | any) {
|
|
1003
|
+
const existing = handlers.get(event) ?? [];
|
|
1004
|
+
existing.push(handler);
|
|
1005
|
+
handlers.set(event, existing);
|
|
1006
|
+
},
|
|
1007
|
+
} as any;
|
|
1008
|
+
|
|
1009
|
+
const notices: Array<{ text: string; level: string }> = [];
|
|
1010
|
+
const ctx = {
|
|
1011
|
+
cwd: dir,
|
|
1012
|
+
ui: { notify: (text: string, level: string) => notices.push({ text, level }) },
|
|
1013
|
+
} as any;
|
|
1014
|
+
|
|
1015
|
+
registerHooks(pi, []);
|
|
1016
|
+
setPendingAutoStart(dir, {
|
|
1017
|
+
basePath: dir,
|
|
1018
|
+
milestoneId: "M012",
|
|
1019
|
+
ctx,
|
|
1020
|
+
pi: { sendMessage: () => undefined } as any,
|
|
1021
|
+
});
|
|
1022
|
+
|
|
1023
|
+
mkdirSync(join(dir, ".gsd", "runtime"), { recursive: true });
|
|
1024
|
+
writeFileSync(statePath, JSON.stringify({
|
|
1025
|
+
verifiedDepthMilestones: ["M012"],
|
|
1026
|
+
verifiedApprovalGates: [gateId],
|
|
1027
|
+
activeQueuePhase: false,
|
|
1028
|
+
pendingGateId: null,
|
|
1029
|
+
}, null, 2), "utf-8");
|
|
1030
|
+
|
|
1031
|
+
const approvalMessage = {
|
|
1032
|
+
role: "assistant",
|
|
1033
|
+
content: [
|
|
1034
|
+
{ type: "text", text: "Here is the milestone plan.\n\nDid I capture the project correctly?" },
|
|
1035
|
+
],
|
|
1036
|
+
};
|
|
1037
|
+
|
|
1038
|
+
for (const handler of handlers.get("message_update") ?? []) {
|
|
1039
|
+
await handler({ message: approvalMessage }, ctx);
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
assert.equal(
|
|
1043
|
+
notices.some((n) => /discuss-milestone M012 is waiting for your approval - pausing/.test(n.text)),
|
|
1044
|
+
true,
|
|
1045
|
+
"streaming hook must not suppress the pause from a disk-only verification",
|
|
1046
|
+
);
|
|
1047
|
+
assert.equal(
|
|
1048
|
+
shouldBlockContextArtifactSave("CONTEXT", "M012", null, dir).block,
|
|
1049
|
+
true,
|
|
1050
|
+
"streaming hook must not reconcile disk-only verification into the in-memory snapshot",
|
|
1051
|
+
);
|
|
1052
|
+
|
|
1053
|
+
for (const handler of handlers.get("agent_end") ?? []) {
|
|
1054
|
+
await handler({ messages: [] }, ctx);
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
assert.equal(getPendingGate(dir), null, "agent_end still reconciles disk and suppresses durable re-arm");
|
|
1058
|
+
});
|
|
1059
|
+
|
|
973
1060
|
// ── External-engine post-hoc gate replay (write-gate two-process sync) ──────
|
|
974
1061
|
// On claude-code-cli, pi ingests the SDK turn's tool blocks after the workflow
|
|
975
1062
|
// MCP child already executed them. The depth gate can therefore arrive at
|
|
@@ -177,6 +177,13 @@ test("auto Unit tool scope allows status/read helpers named by closeout prompts"
|
|
|
177
177
|
}
|
|
178
178
|
});
|
|
179
179
|
|
|
180
|
+
test("auto Unit tool scope allows reactive-execute status and diagnostic tools", () => {
|
|
181
|
+
for (const toolName of ["gsd_milestone_status", "gsd_exec"]) {
|
|
182
|
+
const result = shouldBlockAutoUnitToolCall("reactive-execute", toolName);
|
|
183
|
+
assert.equal(result.block, false, `reactive-execute should be able to call ${toolName}`);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
180
187
|
test("auto Unit tool scope blocks stale per-task planner in slice planning phases", () => {
|
|
181
188
|
for (const unitType of ["plan-slice", "refine-slice", "replan-slice"]) {
|
|
182
189
|
const result = shouldBlockAutoUnitToolCall(unitType, "gsd_plan_task");
|
|
@@ -48,6 +48,16 @@ function makeRecordingPi() {
|
|
|
48
48
|
} as any;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
function makeRecordingCtx() {
|
|
52
|
+
const notifications: Array<{ message: string; level: string }> = [];
|
|
53
|
+
return {
|
|
54
|
+
notifications,
|
|
55
|
+
ui: {
|
|
56
|
+
notify: (message: string, level: string) => { notifications.push({ message, level }); },
|
|
57
|
+
},
|
|
58
|
+
} as any;
|
|
59
|
+
}
|
|
60
|
+
|
|
51
61
|
// ═══ #1855: empty RecoveryContext (basePath undefined) crashes ════════════════
|
|
52
62
|
|
|
53
63
|
{
|
|
@@ -111,6 +121,52 @@ function makeRecordingPi() {
|
|
|
111
121
|
}
|
|
112
122
|
}
|
|
113
123
|
|
|
124
|
+
// ═══ plan-slice timeout recovery verifies stale PLAN before advancing ═══════
|
|
125
|
+
|
|
126
|
+
{
|
|
127
|
+
console.log("\n=== plan-slice timeout recovery rejects stale placeholder PLAN ===");
|
|
128
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-timeout-stale-plan-"));
|
|
129
|
+
const sliceDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
|
|
130
|
+
mkdirSync(sliceDir, { recursive: true });
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
134
|
+
insertMilestone({ id: "M001", title: "Milestone", status: "active" });
|
|
135
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Slice", status: "pending" });
|
|
136
|
+
writeFileSync(
|
|
137
|
+
join(sliceDir, "S01-PLAN.md"),
|
|
138
|
+
"# S01: Slice\n\n## Tasks\n\nPlanning was interrupted before task rows were persisted.\n",
|
|
139
|
+
"utf-8",
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
const ctx = makeRecordingCtx();
|
|
143
|
+
const pi = makeRecordingPi();
|
|
144
|
+
const result = await recoverTimedOutUnit(ctx, pi, "plan-slice", "M001/S01", "idle", {
|
|
145
|
+
basePath: base,
|
|
146
|
+
verbose: false,
|
|
147
|
+
currentUnitStartedAt: Date.now(),
|
|
148
|
+
unitRecoveryCount: new Map(),
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
assert.equal(result, "recovered", "invalid existing plan should enter steering recovery");
|
|
152
|
+
assert.equal(pi.messages.length, 1, "invalid existing plan should trigger steering instead of advancing");
|
|
153
|
+
assert.ok(
|
|
154
|
+
ctx.notifications.some((entry: { message: string }) => entry.message.includes("steering plan-slice M001/S01")),
|
|
155
|
+
"recovery notification should describe steering, not artifact advance",
|
|
156
|
+
);
|
|
157
|
+
assert.ok(
|
|
158
|
+
!ctx.notifications.some((entry: { message: string }) => entry.message.includes("artifact already exists on disk. Advancing.")),
|
|
159
|
+
"stale placeholder plan should not use the advance-on-existence path",
|
|
160
|
+
);
|
|
161
|
+
const runtime = JSON.parse(readFileSync(join(base, ".gsd", "runtime", "units", "plan-slice-M001-S01.json"), "utf-8"));
|
|
162
|
+
assert.equal(runtime.phase, "recovered", "stale placeholder plan must not be finalized");
|
|
163
|
+
assert.equal(runtime.recoveryAttempts, 1, "steering recovery attempt should be recorded");
|
|
164
|
+
} finally {
|
|
165
|
+
closeDatabase();
|
|
166
|
+
rmSync(base, { recursive: true, force: true });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
114
170
|
// ═══ #1855: valid RecoveryContext does not crash ═════════════════════════════
|
|
115
171
|
|
|
116
172
|
{
|