@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
|
@@ -14,7 +14,6 @@ import { MILESTONE_ID_RE } from "./milestone-ids.js";
|
|
|
14
14
|
import { appendEvent } from "./workflow-events.js";
|
|
15
15
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
16
16
|
import { clearParseCache } from "./files.js";
|
|
17
|
-
import { parseRoadmap as parseLegacyRoadmap, parsePlan as parseLegacyPlan } from "./parsers-legacy.js";
|
|
18
17
|
import {
|
|
19
18
|
isDbAvailable,
|
|
20
19
|
getTask,
|
|
@@ -72,6 +71,9 @@ import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
|
|
|
72
71
|
import { resolveWorktreeProjectRoot } from "./worktree-root.js";
|
|
73
72
|
import { hasImplementationArtifacts } from "./milestone-implementation-evidence.js";
|
|
74
73
|
import { loadAllCaptures, loadPendingCaptures } from "./captures.js";
|
|
74
|
+
import {
|
|
75
|
+
resolveArtifactVerificationBase,
|
|
76
|
+
} from "./artifact-verification.js";
|
|
75
77
|
import {
|
|
76
78
|
proveMilestoneCloseout,
|
|
77
79
|
type CloseoutProofFailureReason,
|
|
@@ -84,35 +86,12 @@ export {
|
|
|
84
86
|
type MilestoneSummaryOutcome,
|
|
85
87
|
} from "./milestone-summary-classifier.js";
|
|
86
88
|
export { hasImplementationArtifacts } from "./milestone-implementation-evidence.js";
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
* are otherwise unreachable because parseLegacyRoadmap is internally defensive
|
|
94
|
-
* against every malformed input.
|
|
95
|
-
* @internal
|
|
96
|
-
*/
|
|
97
|
-
let _roadmapParserFn: ((content: string) => { slices: Array<{ id: string; done: boolean; depends?: string[] }> }) | null = null;
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Inject an override for the legacy roadmap parser, returning a function that
|
|
101
|
-
* restores the default (real parser) behavior. No production caller.
|
|
102
|
-
* @internal
|
|
103
|
-
*/
|
|
104
|
-
export function _setRoadmapParserFnForTests(
|
|
105
|
-
fn: ((content: string) => { slices: Array<{ id: string; done: boolean; depends?: string[] }> }) | null,
|
|
106
|
-
): () => void {
|
|
107
|
-
const previous = _roadmapParserFn;
|
|
108
|
-
_roadmapParserFn = fn;
|
|
109
|
-
return () => { _roadmapParserFn = previous; };
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function parseRoadmapForRecovery(content: string): ReturnType<NonNullable<typeof _roadmapParserFn>> {
|
|
113
|
-
if (_roadmapParserFn) return _roadmapParserFn(content);
|
|
114
|
-
return parseLegacyRoadmap(content) as unknown as ReturnType<NonNullable<typeof _roadmapParserFn>>;
|
|
115
|
-
}
|
|
89
|
+
export {
|
|
90
|
+
verifyExpectedArtifact,
|
|
91
|
+
diagnoseWorktreeIntegrityFailure,
|
|
92
|
+
resolveArtifactVerificationBase,
|
|
93
|
+
_setRoadmapParserFnForTests,
|
|
94
|
+
} from "./artifact-verification.js";
|
|
116
95
|
|
|
117
96
|
/**
|
|
118
97
|
* Optional override for the detached GitHub milestone finalize invoked after DB
|
|
@@ -132,36 +111,7 @@ export function _setGithubFinalizeFnForTests(
|
|
|
132
111
|
return () => { _githubFinalizeFn = previous; };
|
|
133
112
|
}
|
|
134
113
|
|
|
135
|
-
// ───
|
|
136
|
-
|
|
137
|
-
export function diagnoseWorktreeIntegrityFailure(basePath: string): string | null {
|
|
138
|
-
if (!isGsdWorktreePath(basePath)) return null;
|
|
139
|
-
if (!existsSync(basePath)) {
|
|
140
|
-
return `Worktree integrity failure: ${basePath} does not exist. Repair or recreate the worktree before retrying.`;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const gitPath = join(basePath, ".git");
|
|
144
|
-
if (!existsSync(gitPath)) {
|
|
145
|
-
return `Worktree integrity failure: ${basePath} is not a valid git worktree (.git missing). Repair or recreate the worktree before retrying.`;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
try {
|
|
149
|
-
execFileSync("git", ["rev-parse", "--git-dir"], {
|
|
150
|
-
cwd: basePath,
|
|
151
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
152
|
-
encoding: "utf-8",
|
|
153
|
-
});
|
|
154
|
-
return null;
|
|
155
|
-
} catch (err) {
|
|
156
|
-
return `Worktree integrity failure: ${basePath} is not a valid git worktree (git rev-parse failed: ${getErrorMessage(err).split("\n")[0]}). Repair or recreate the worktree before retrying.`;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function resolveArtifactVerificationBase(unitId: string, base: string): string {
|
|
161
|
-
const { milestone } = parseUnitId(unitId);
|
|
162
|
-
if (!MILESTONE_ID_RE.test(milestone)) return base;
|
|
163
|
-
return resolveCanonicalMilestoneRoot(base, milestone);
|
|
164
|
-
}
|
|
114
|
+
// ─── Recovery DB refresh ──────────────────────────────────────────────────────
|
|
165
115
|
|
|
166
116
|
export type ArtifactRecoveryDbRefreshResult =
|
|
167
117
|
| { ok: true }
|
|
@@ -295,454 +245,6 @@ export function refreshRecoveryDbForArtifact(
|
|
|
295
245
|
return { ok: true };
|
|
296
246
|
}
|
|
297
247
|
|
|
298
|
-
function hasCapturedWorkflowPrefs(base: string): boolean {
|
|
299
|
-
const prefsPath = resolveExpectedArtifactPath("workflow-preferences", "WORKFLOW-PREFS", base);
|
|
300
|
-
if (!prefsPath || !existsSync(prefsPath)) return false;
|
|
301
|
-
const content = readFileSync(prefsPath, "utf-8");
|
|
302
|
-
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
303
|
-
return !!match && /^workflow_prefs_captured:\s*true\s*$/m.test(match[1]);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
function hasValidResearchDecision(base: string): boolean {
|
|
307
|
-
const decisionPath = resolveExpectedArtifactPath("research-decision", "RESEARCH-DECISION", base);
|
|
308
|
-
if (!decisionPath || !existsSync(decisionPath)) return false;
|
|
309
|
-
try {
|
|
310
|
-
const cfg = JSON.parse(readFileSync(decisionPath, "utf-8")) as Record<string, unknown>;
|
|
311
|
-
return cfg.decision === "research" || cfg.decision === "skip";
|
|
312
|
-
} catch {
|
|
313
|
-
return false;
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
function hasCompleteProjectResearch(base: string): boolean {
|
|
318
|
-
return getProjectResearchStatus(base).complete;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
function escapeRegExp(value: string): string {
|
|
322
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
function hasCheckedTaskCompletionOnDisk(base: string, mid: string, sid: string, tid: string): boolean {
|
|
326
|
-
const slicePath = resolveSlicePath(base, mid, sid);
|
|
327
|
-
if (!slicePath) return false;
|
|
328
|
-
|
|
329
|
-
const planAbs = resolveSliceFile(base, mid, sid, "PLAN");
|
|
330
|
-
if (!planAbs || !existsSync(planAbs)) return false;
|
|
331
|
-
|
|
332
|
-
const planContent = readFileSync(planAbs, "utf-8");
|
|
333
|
-
// Match legacy (`**T01: Title**`) and flat-phase (`**T01**: Title`) checkbox lines.
|
|
334
|
-
const cbRe = new RegExp(`^\\s*-\\s+\\[[xX]\\]\\s+\\*\\*${escapeRegExp(tid)}(?:\\*\\*)?:`, "m");
|
|
335
|
-
return cbRe.test(planContent);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Check whether the expected artifact(s) for a unit exist on disk.
|
|
340
|
-
* Returns true if all required artifacts exist, or if the unit type has no
|
|
341
|
-
* single verifiable artifact (e.g., replan-slice).
|
|
342
|
-
*
|
|
343
|
-
* complete-slice requires both SUMMARY and UAT files — verifying only
|
|
344
|
-
* the summary allowed the unit to be marked complete when the LLM
|
|
345
|
-
* skipped writing the UAT file (see #176).
|
|
346
|
-
*/
|
|
347
|
-
export function verifyExpectedArtifact(
|
|
348
|
-
unitType: string,
|
|
349
|
-
unitId: string,
|
|
350
|
-
base: string,
|
|
351
|
-
): boolean {
|
|
352
|
-
// Hook units have no standard artifact — always pass. Their lifecycle
|
|
353
|
-
// is managed by the hook engine, not the artifact verification system.
|
|
354
|
-
if (unitType.startsWith("hook/")) return true;
|
|
355
|
-
|
|
356
|
-
// Clear stale directory listing cache AND parse cache so artifact checks see
|
|
357
|
-
// fresh disk state (#431). The parse cache must also be cleared because
|
|
358
|
-
// cacheKey() uses length + first/last 100 chars — when a checkbox changes
|
|
359
|
-
// from [ ] to [x], the key collides with the pre-edit version, returning
|
|
360
|
-
// stale parsed results (e.g., slice.done = false when it's actually true).
|
|
361
|
-
clearPathCache();
|
|
362
|
-
clearParseCache();
|
|
363
|
-
|
|
364
|
-
if (unitType === "rewrite-docs") {
|
|
365
|
-
const overridesPath = resolveGsdRootFile(base, "OVERRIDES");
|
|
366
|
-
if (!existsSync(overridesPath)) return true;
|
|
367
|
-
const content = readFileSync(overridesPath, "utf-8");
|
|
368
|
-
return !content.includes("**Scope:** active");
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
if (unitType === "workflow-preferences") {
|
|
372
|
-
return hasCapturedWorkflowPrefs(base);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
if (unitType === "triage-captures") {
|
|
376
|
-
const pending = loadPendingCaptures(base);
|
|
377
|
-
if (pending.length === 0) return true;
|
|
378
|
-
logWarning("recovery", `verify-fail triage-captures ${unitId}: ${pending.length} pending capture(s) remain in CAPTURES.md`);
|
|
379
|
-
return false;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
if (unitType === "quick-task") {
|
|
383
|
-
const { slice: captureId } = parseUnitId(unitId);
|
|
384
|
-
const capture = captureId ? loadAllCaptures(base).find((entry) => entry.id === captureId) : undefined;
|
|
385
|
-
if (capture?.executed === true) return true;
|
|
386
|
-
logWarning("recovery", `verify-fail quick-task ${unitId}: capture ${captureId ?? "(missing capture id)"} not found or not marked executed`);
|
|
387
|
-
return false;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
if (unitType === "discuss-project") {
|
|
391
|
-
const projectPath = resolveExpectedArtifactPath(unitType, unitId, base);
|
|
392
|
-
return !!projectPath && existsSync(projectPath) && validateArtifact(projectPath, "project").ok;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
if (unitType === "discuss-requirements") {
|
|
396
|
-
const requirementsPath = resolveExpectedArtifactPath(unitType, unitId, base);
|
|
397
|
-
return !!requirementsPath && existsSync(requirementsPath) && validateArtifact(requirementsPath, "requirements").ok;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
if (unitType === "research-decision") {
|
|
401
|
-
return hasValidResearchDecision(base);
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
if (unitType === "research-project") {
|
|
405
|
-
return hasCompleteProjectResearch(base);
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
// Reactive-execute: verify that each dispatched task's summary exists.
|
|
409
|
-
// The unitId encodes the batch: "{mid}/{sid}/reactive+T02,T03"
|
|
410
|
-
if (unitType === "reactive-execute") {
|
|
411
|
-
const { milestone: mid, slice: sid, task: batchPart } = parseUnitId(unitId);
|
|
412
|
-
if (!mid || !sid || !batchPart) return false;
|
|
413
|
-
const blockerPath = resolveExpectedArtifactPath(unitType, unitId, base);
|
|
414
|
-
if (blockerPath && existsSync(blockerPath)) {
|
|
415
|
-
return true;
|
|
416
|
-
}
|
|
417
|
-
const slicePath = resolveSlicePath(base, mid, sid);
|
|
418
|
-
if (!slicePath) return false;
|
|
419
|
-
|
|
420
|
-
const plusIdx = batchPart.indexOf("+");
|
|
421
|
-
if (plusIdx === -1) {
|
|
422
|
-
// Legacy format "reactive" without batch IDs — fall back to "any summary"
|
|
423
|
-
const tDir = resolveTasksDir(base, mid, sid) ?? slicePath;
|
|
424
|
-
const summaryFiles = resolveTaskFiles(tDir, "SUMMARY");
|
|
425
|
-
return summaryFiles.length > 0;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
const batchIds = batchPart.slice(plusIdx + 1).split(",").filter(Boolean);
|
|
429
|
-
if (batchIds.length === 0) return false;
|
|
430
|
-
|
|
431
|
-
const tDir = resolveTasksDir(base, mid, sid) ?? slicePath;
|
|
432
|
-
|
|
433
|
-
const existingSummaries = new Set(
|
|
434
|
-
resolveTaskFiles(tDir, "SUMMARY").map((f) =>
|
|
435
|
-
f.replace(/-SUMMARY\.md$/i, "").toUpperCase(),
|
|
436
|
-
),
|
|
437
|
-
);
|
|
438
|
-
|
|
439
|
-
// Every dispatched task must have a summary file
|
|
440
|
-
for (const tid of batchIds) {
|
|
441
|
-
if (!existingSummaries.has(tid.toUpperCase())) return false;
|
|
442
|
-
}
|
|
443
|
-
return true;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
// Gate-evaluate: verify that each dispatched gate has been resolved in the DB.
|
|
447
|
-
// The unitId encodes the batch: "{mid}/{sid}/gates+Q3,Q4"
|
|
448
|
-
if (unitType === "gate-evaluate") {
|
|
449
|
-
const { milestone: mid, slice: sid, task: batchPart } = parseUnitId(unitId);
|
|
450
|
-
if (!mid || !sid || !batchPart) return false;
|
|
451
|
-
|
|
452
|
-
const plusIdx = batchPart.indexOf("+");
|
|
453
|
-
if (plusIdx === -1) return true; // no specific gates encoded — pass
|
|
454
|
-
|
|
455
|
-
const gateIds = batchPart.slice(plusIdx + 1).split(",").filter(Boolean);
|
|
456
|
-
if (gateIds.length === 0) return true;
|
|
457
|
-
|
|
458
|
-
try {
|
|
459
|
-
if (!isDbAvailable()) return false;
|
|
460
|
-
const pending = getPendingGatesForTurn(mid, sid, "gate-evaluate");
|
|
461
|
-
const pendingIds = new Set<string>(pending.map((g) => g.gate_id));
|
|
462
|
-
// All dispatched gates must no longer be pending
|
|
463
|
-
for (const gid of gateIds) {
|
|
464
|
-
if (pendingIds.has(gid)) return false;
|
|
465
|
-
}
|
|
466
|
-
} catch (err) {
|
|
467
|
-
// DB unavailable — treat as verified to avoid blocking
|
|
468
|
-
logWarning("recovery", `gate-evaluate DB check failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
469
|
-
}
|
|
470
|
-
return true;
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
// #4414: research-slice parallel-research sentinel. The unitId
|
|
474
|
-
// `{mid}/parallel-research` is not a real slice — it triggers a single agent
|
|
475
|
-
// that fans out research across multiple slices. Verify success by checking
|
|
476
|
-
// that every slice which was "research-ready" in the roadmap now has a
|
|
477
|
-
// RESEARCH file. Without this, resolveExpectedArtifactPath returns null and
|
|
478
|
-
// the retry/escalation machinery silently re-dispatches forever.
|
|
479
|
-
//
|
|
480
|
-
// #4068: Also treat a PARALLEL-BLOCKER placeholder as a terminal completion
|
|
481
|
-
// so that timeout-recovery can write the blocker, have verifyExpectedArtifact
|
|
482
|
-
// return true, and let the dispatch loop advance past this unit. Without
|
|
483
|
-
// this, the blocker is written but verification still returns false, the unit
|
|
484
|
-
// is never cleared from unitDispatchCount, and on the next iteration the
|
|
485
|
-
// dispatch rule (which correctly skips parallel-research when PARALLEL-BLOCKER
|
|
486
|
-
// exists) returns null — leaving the loop stuck re-deriving indefinitely.
|
|
487
|
-
//
|
|
488
|
-
// NOTE: this predicate mirrors the dispatch rule at
|
|
489
|
-
// auto-dispatch.ts parallel-research-slices — keep the two in sync.
|
|
490
|
-
if (unitType === "research-slice" && unitId.endsWith("/parallel-research")) {
|
|
491
|
-
const { milestone: mid } = parseUnitId(unitId);
|
|
492
|
-
if (!mid) return false;
|
|
493
|
-
|
|
494
|
-
// #4068: PARALLEL-BLOCKER written by timeout-recovery is a terminal state.
|
|
495
|
-
const blockerPath = resolveExpectedArtifactPath(unitType, unitId, base);
|
|
496
|
-
if (blockerPath && existsSync(blockerPath)) {
|
|
497
|
-
return true;
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
const roadmapFile = resolveExpectedArtifactPath("plan-milestone", mid, base);
|
|
501
|
-
if (!roadmapFile || !existsSync(roadmapFile)) {
|
|
502
|
-
logWarning("recovery", `verify-fail ${unitType} ${unitId}: roadmap missing`);
|
|
503
|
-
return false;
|
|
504
|
-
}
|
|
505
|
-
try {
|
|
506
|
-
const roadmap = parseRoadmapForRecovery(readFileSync(roadmapFile, "utf-8"));
|
|
507
|
-
const milestoneResearchFile = resolveExpectedArtifactPath("research-milestone", mid, base);
|
|
508
|
-
const hasMilestoneResearch = !!milestoneResearchFile && existsSync(milestoneResearchFile);
|
|
509
|
-
for (const slice of roadmap.slices) {
|
|
510
|
-
if (slice.done) continue;
|
|
511
|
-
if (hasMilestoneResearch && slice.id === "S01") continue;
|
|
512
|
-
const depsComplete = (slice.depends ?? []).every((depId) => {
|
|
513
|
-
const summaryPath = resolveExpectedArtifactPath("complete-slice", `${mid}/${depId}`, base);
|
|
514
|
-
return !!summaryPath && existsSync(summaryPath);
|
|
515
|
-
});
|
|
516
|
-
if (!depsComplete) continue;
|
|
517
|
-
const researchPath = resolveExpectedArtifactPath("research-slice", `${mid}/${slice.id}`, base);
|
|
518
|
-
if (!researchPath || !existsSync(researchPath)) {
|
|
519
|
-
logWarning("recovery", `verify-fail ${unitType} ${unitId}: slice ${slice.id} missing RESEARCH`);
|
|
520
|
-
return false;
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
return true;
|
|
524
|
-
} catch (err) {
|
|
525
|
-
logWarning("recovery", `parallel-research verification failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
526
|
-
return false;
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
const artifactBase = resolveArtifactVerificationBase(unitId, base);
|
|
531
|
-
let absPath = resolveExpectedArtifactPath(unitType, unitId, artifactBase);
|
|
532
|
-
// Worktree→project-root fallback: a milestone running in a worktree may not
|
|
533
|
-
// have its CONTEXT/ROADMAP/SUMMARY projected into the worktree yet (the
|
|
534
|
-
// worktree only has the META dir until planning writes its projections).
|
|
535
|
-
// When the worktree base yields null or a non-existent path, fall back to the
|
|
536
|
-
// project root — where the artifact genuinely lives. Without this, a
|
|
537
|
-
// discuss-milestone unit with CONTEXT at phases/NN-slug/ in the project root
|
|
538
|
-
// but not in the worktree resolves to null → "resolveExpectedArtifactPath
|
|
539
|
-
// returned null" → finalize-retry loop (#852).
|
|
540
|
-
if (artifactBase !== base) {
|
|
541
|
-
const projectRoot = resolve(resolveWorktreeProjectRoot(artifactBase));
|
|
542
|
-
if (projectRoot && projectRoot !== artifactBase) {
|
|
543
|
-
if (!absPath || !existsSync(absPath)) {
|
|
544
|
-
const projectPath = resolveExpectedArtifactPath(unitType, unitId, projectRoot);
|
|
545
|
-
if (projectPath && existsSync(projectPath)) {
|
|
546
|
-
absPath = projectPath;
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
// For unit types with no registered artifact contract (null path), treat the
|
|
552
|
-
// completion state as stale so the key gets evicted (#313).
|
|
553
|
-
if (!absPath) {
|
|
554
|
-
logWarning("recovery", `verify-fail ${unitType} ${unitId}: resolveExpectedArtifactPath returned null (no artifact contract registered for this unit type)`);
|
|
555
|
-
return false;
|
|
556
|
-
}
|
|
557
|
-
if (!existsSync(absPath)) {
|
|
558
|
-
const worktreeFailure = diagnoseWorktreeIntegrityFailure(artifactBase);
|
|
559
|
-
if (worktreeFailure) {
|
|
560
|
-
logError("recovery", `${worktreeFailure} Unit: ${unitType} ${unitId}.`);
|
|
561
|
-
return false;
|
|
562
|
-
}
|
|
563
|
-
logWarning("recovery", `verify-fail ${unitType} ${unitId}: existsSync false for ${absPath}`);
|
|
564
|
-
return false;
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
if (unitType === "validate-milestone") {
|
|
568
|
-
const validationContent = readFileSync(absPath, "utf-8");
|
|
569
|
-
if (!isValidationTerminal(validationContent)) {
|
|
570
|
-
logWarning("recovery", `verify-fail ${unitType} ${unitId}: validation not terminal (len=${validationContent.length}) at ${absPath}`);
|
|
571
|
-
return false;
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
if (unitType === "run-uat") {
|
|
576
|
-
const assessmentContent = readFileSync(absPath, "utf-8");
|
|
577
|
-
if (!hasVerdict(assessmentContent)) {
|
|
578
|
-
logWarning("recovery", `verify-fail ${unitType} ${unitId}: assessment missing verdict at ${absPath}`);
|
|
579
|
-
return false;
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
if (unitType === "plan-milestone") {
|
|
584
|
-
try {
|
|
585
|
-
const roadmap = parseRoadmapForRecovery(readFileSync(absPath, "utf-8"));
|
|
586
|
-
if (roadmap.slices.length === 0) {
|
|
587
|
-
logWarning("recovery", `verify-fail ${unitType} ${unitId}: roadmap has zero slices at ${absPath}`);
|
|
588
|
-
return false;
|
|
589
|
-
}
|
|
590
|
-
} catch (err) {
|
|
591
|
-
logWarning("recovery", `plan-milestone roadmap verification failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
592
|
-
return false;
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
// plan-slice verification is DB-primary. The slice plan is a projection, so
|
|
597
|
-
// DB task rows prove the slice was planned even if the rendered markdown no
|
|
598
|
-
// longer uses legacy checkbox/heading syntax.
|
|
599
|
-
if (unitType === "plan-slice") {
|
|
600
|
-
const { milestone: mid, slice: sid } = parseUnitId(unitId);
|
|
601
|
-
if (mid && sid) {
|
|
602
|
-
try {
|
|
603
|
-
let taskIds: string[] | null = null;
|
|
604
|
-
let dbPrimary = false;
|
|
605
|
-
if (isDbAvailable()) {
|
|
606
|
-
const refreshed = refreshWorkflowDatabaseFromDisk();
|
|
607
|
-
if (refreshed) {
|
|
608
|
-
const tasks = getSliceTasks(mid, sid);
|
|
609
|
-
if (tasks.length > 0) {
|
|
610
|
-
taskIds = tasks.map(t => t.id);
|
|
611
|
-
dbPrimary = true;
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
if (!taskIds) {
|
|
617
|
-
// LEGACY: DB unavailable or no tasks in DB. Require actual task
|
|
618
|
-
// entries so an empty scaffold cannot advance the pipeline (#699).
|
|
619
|
-
const planContent = readFileSync(absPath, "utf-8");
|
|
620
|
-
const hasCheckboxTask = /^\s*- \[[xX ]\] \*\*T\d+/m.test(planContent);
|
|
621
|
-
const hasHeadingTask = /^\s*#{2,4}\s+T\d+\s*(?:--|—|:)/m.test(planContent);
|
|
622
|
-
if (!hasCheckboxTask && !hasHeadingTask) {
|
|
623
|
-
logWarning("recovery", `verify-fail ${unitType} ${unitId}: plan has no task checkbox/heading (len=${planContent.length}) at ${absPath}`);
|
|
624
|
-
return false;
|
|
625
|
-
}
|
|
626
|
-
const plan = parseLegacyPlan(planContent);
|
|
627
|
-
if (plan.tasks.length > 0) taskIds = plan.tasks.map((t: { id: string }) => t.id);
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
// Per-task plan file check: applies when a tasks/ directory is present on
|
|
631
|
-
// disk (legacy layout), regardless of whether DB is primary. Flat-phase
|
|
632
|
-
// projects have no tasks/ dir, so the check is naturally skipped there.
|
|
633
|
-
// When DB is NOT primary and there is no tasks/ dir either, the missing
|
|
634
|
-
// dir itself is evidence of an incomplete plan (non-flat-phase projects must
|
|
635
|
-
// have a tasks/ dir).
|
|
636
|
-
if (taskIds && taskIds.length > 0) {
|
|
637
|
-
const tasksDir = join(dirname(absPath), "tasks");
|
|
638
|
-
if (existsSync(tasksDir)) {
|
|
639
|
-
for (const tid of taskIds) {
|
|
640
|
-
const taskPlanFile = join(tasksDir, `${tid}-PLAN.md`);
|
|
641
|
-
if (!existsSync(taskPlanFile)) {
|
|
642
|
-
logWarning("recovery", `verify-fail ${unitType} ${unitId}: task plan missing ${taskPlanFile}`);
|
|
643
|
-
return false;
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
} else if (!dbPrimary && !absPath.replace(/\\/g, "/").includes(`.gsd/${LAYOUT_SEGMENTS.level1}`)) {
|
|
647
|
-
logWarning("recovery", `verify-fail ${unitType} ${unitId}: tasks dir missing at ${tasksDir}`);
|
|
648
|
-
return false;
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
} catch (err) {
|
|
652
|
-
// Parse failure — don't block; slice plan may have non-standard format
|
|
653
|
-
logWarning("recovery", `plan-slice task plan verification failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
// execute-task: DB status is authoritative. Fall back to checked-checkbox
|
|
659
|
-
// detection when the DB is unavailable (unmigrated projects), or when the
|
|
660
|
-
// disk artifacts already reflect completion but the DB replay is one beat
|
|
661
|
-
// behind the completion write.
|
|
662
|
-
if (unitType === "execute-task") {
|
|
663
|
-
const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
|
|
664
|
-
if (mid && sid && tid) {
|
|
665
|
-
const dbTask = getTask(mid, sid, tid);
|
|
666
|
-
if (dbTask) {
|
|
667
|
-
if (dbTask.status !== "complete" && dbTask.status !== "done" && !hasCheckedTaskCompletionOnDisk(base, mid, sid, tid)) {
|
|
668
|
-
return false;
|
|
669
|
-
}
|
|
670
|
-
} else if (!isDbAvailable()) {
|
|
671
|
-
// LEGACY: Pre-migration fallback for projects without DB.
|
|
672
|
-
// Require a CHECKED checkbox — a bare heading or unchecked checkbox
|
|
673
|
-
// does not prove gsd_complete_task ran. Summary file on disk alone
|
|
674
|
-
// is not sufficient evidence (could be a rogue write) (#3607).
|
|
675
|
-
if (!hasCheckedTaskCompletionOnDisk(base, mid, sid, tid)) return false;
|
|
676
|
-
} else {
|
|
677
|
-
// DB available but task row not found — completion tool never ran (#3607)
|
|
678
|
-
return false;
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
// complete-slice: DB status is authoritative for whether the slice is done.
|
|
684
|
-
// Fall back to file-based check (roadmap [x]) when DB is unavailable.
|
|
685
|
-
if (unitType === "complete-slice") {
|
|
686
|
-
const { milestone: mid, slice: sid } = parseUnitId(unitId);
|
|
687
|
-
if (mid && sid) {
|
|
688
|
-
// resolveSliceFile only finds existing files; UAT may not exist yet.
|
|
689
|
-
// Fall back to the canonical expected location so a missing UAT always
|
|
690
|
-
// returns false (not a silent pass when resolveSliceFile returns null).
|
|
691
|
-
const uatPath = resolveSliceFile(base, mid, sid, "UAT")
|
|
692
|
-
?? join(base, relSliceFile(base, mid, sid, "UAT"));
|
|
693
|
-
if (!existsSync(uatPath)) return false;
|
|
694
|
-
|
|
695
|
-
const dbSlice = getSlice(mid, sid);
|
|
696
|
-
if (dbSlice) {
|
|
697
|
-
// DB available — trust it
|
|
698
|
-
if (dbSlice.status !== "complete") return false;
|
|
699
|
-
} else if (!isDbAvailable()) {
|
|
700
|
-
// LEGACY: Pre-migration fallback for projects without DB.
|
|
701
|
-
// Fall back to roadmap checkbox check via parsers-legacy
|
|
702
|
-
const roadmapFile = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
703
|
-
if (roadmapFile && existsSync(roadmapFile)) {
|
|
704
|
-
try {
|
|
705
|
-
const roadmapContent = readFileSync(roadmapFile, "utf-8");
|
|
706
|
-
const roadmap = parseRoadmapForRecovery(roadmapContent);
|
|
707
|
-
const slice = roadmap.slices.find((s) => s.id === sid);
|
|
708
|
-
if (slice && !slice.done) return false;
|
|
709
|
-
} catch (e) {
|
|
710
|
-
logWarning("recovery", `roadmap parse failed: ${(e as Error).message}`);
|
|
711
|
-
return false;
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
// else: DB available but slice not found — summary + UAT exist,
|
|
716
|
-
// treat as verified (slice may not be imported yet)
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
// complete-milestone must have produced implementation artifacts (#1703).
|
|
721
|
-
// A milestone with only .gsd/ plan files and zero implementation code is
|
|
722
|
-
// not genuinely complete — the LLM wrote plan files but skipped actual work.
|
|
723
|
-
if (unitType === "complete-milestone") {
|
|
724
|
-
const { milestone: mid } = parseUnitId(unitId);
|
|
725
|
-
if (!mid) return false;
|
|
726
|
-
const closeoutProof = proveMilestoneCloseout(mid, {
|
|
727
|
-
refreshFromDisk: true,
|
|
728
|
-
summaryArtifactBasePath: artifactBase,
|
|
729
|
-
implementationEvidence: {
|
|
730
|
-
basePath: base,
|
|
731
|
-
requirement: "not-absent",
|
|
732
|
-
},
|
|
733
|
-
});
|
|
734
|
-
if (!closeoutProof.ok) {
|
|
735
|
-
if (!isDbAvailable() && closeoutProof.reason === "db-unavailable") {
|
|
736
|
-
const summaryOutcome = classifyMilestoneSummaryContent(readFileSync(absPath, "utf-8"));
|
|
737
|
-
return summaryOutcome !== "failure" && hasImplementationArtifacts(base, mid) !== "absent";
|
|
738
|
-
}
|
|
739
|
-
return false;
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
return true;
|
|
744
|
-
}
|
|
745
|
-
|
|
746
248
|
export interface ReactiveExecuteBlockerRecovery {
|
|
747
249
|
blockerPath: string;
|
|
748
250
|
completedTaskIds: string[];
|
|
@@ -25,7 +25,6 @@ export type {
|
|
|
25
25
|
} from "./tool-surface-snapshot.js";
|
|
26
26
|
|
|
27
27
|
export const autoSession = new AutoSession();
|
|
28
|
-
let currentToolSurfaceSnapshot: ToolSurfaceSnapshot | null = null;
|
|
29
28
|
|
|
30
29
|
export type AutoRuntimeSnapshot = {
|
|
31
30
|
active: boolean;
|
|
@@ -48,17 +47,17 @@ export function getAutoRuntimeSnapshot(): AutoRuntimeSnapshot {
|
|
|
48
47
|
orchestrationPhase: orchestrationStatus?.phase,
|
|
49
48
|
orchestrationTransitionCount: orchestrationStatus?.transitionCount,
|
|
50
49
|
orchestrationLastTransitionAt: orchestrationStatus?.lastTransitionAt,
|
|
51
|
-
toolSurface: autoSession.active || autoSession.paused ?
|
|
50
|
+
toolSurface: autoSession.active || autoSession.paused ? autoSession.toolSurfaceSnapshot : null,
|
|
52
51
|
};
|
|
53
52
|
}
|
|
54
53
|
|
|
55
54
|
export function recordAutoToolSurfaceSnapshot(input: ToolSurfaceSnapshotInput): ToolSurfaceSnapshot {
|
|
56
|
-
|
|
57
|
-
return
|
|
55
|
+
autoSession.toolSurfaceSnapshot = createToolSurfaceSnapshot(input);
|
|
56
|
+
return autoSession.toolSurfaceSnapshot;
|
|
58
57
|
}
|
|
59
58
|
|
|
60
59
|
export function clearAutoToolSurfaceSnapshot(): void {
|
|
61
|
-
|
|
60
|
+
autoSession.toolSurfaceSnapshot = null;
|
|
62
61
|
}
|
|
63
62
|
|
|
64
63
|
export function isAutoActive(): boolean {
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import {
|
|
15
15
|
resolveExpectedArtifactPath,
|
|
16
16
|
diagnoseExpectedArtifact,
|
|
17
|
+
verifyExpectedArtifact,
|
|
17
18
|
writeBlockerPlaceholder,
|
|
18
19
|
} from "./auto-recovery.js";
|
|
19
20
|
import { existsSync } from "node:fs";
|
|
@@ -194,10 +195,10 @@ export async function recoverTimedOutUnit(
|
|
|
194
195
|
return "recovered";
|
|
195
196
|
}
|
|
196
197
|
|
|
197
|
-
// Check if the artifact already
|
|
198
|
+
// Check if the artifact is already valid on disk — agent may have written it
|
|
198
199
|
// without signaling completion.
|
|
199
200
|
const artifactPath = resolveExpectedArtifactPath(unitType, unitId, basePath);
|
|
200
|
-
if (artifactPath && existsSync(artifactPath)) {
|
|
201
|
+
if (artifactPath && existsSync(artifactPath) && verifyExpectedArtifact(unitType, unitId, basePath)) {
|
|
201
202
|
writeUnitRuntimeRecord(basePath, unitType, unitId, currentUnitStartedAt, {
|
|
202
203
|
phase: "finalized",
|
|
203
204
|
recoveryAttempts: recoveryAttempts + 1,
|