@opengsd/gsd-pi 1.3.0-dev.65546769 → 1.3.0-dev.738160b9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli.js +17 -4
- package/dist/headless-answers.js +1 -1
- package/dist/headless-ui.d.ts +1 -1
- package/dist/headless-ui.js +1 -1
- package/dist/headless.js +1 -1
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/claude-code-cli/models.js +9 -0
- 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 +11 -0
- package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +1 -1
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +28 -1
- package/dist/resources/extensions/gsd/auto-budget.js +5 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +34 -20
- package/dist/resources/extensions/gsd/auto-post-unit.js +1 -1
- package/dist/resources/extensions/gsd/auto-prompts.js +29 -14
- package/dist/resources/extensions/gsd/auto-recovery.js +9 -510
- 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/auto-verification.js +5 -2
- package/dist/resources/extensions/gsd/auto.js +19 -10
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +103 -13
- package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +39 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +11 -5
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +41 -21
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -19
- package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +96 -10
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
- package/dist/resources/extensions/gsd/closeout-consistency-gate.js +3 -1
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +1 -1
- package/dist/resources/extensions/gsd/commands-context.js +19 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +17 -11
- package/dist/resources/extensions/gsd/commands-usage.js +1 -1
- 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/engine.js +4 -1
- package/dist/resources/extensions/gsd/db/queries.js +60 -0
- package/dist/resources/extensions/gsd/db-memory-fts-schema.js +34 -0
- package/dist/resources/extensions/gsd/db-workspace.js +55 -3
- package/dist/resources/extensions/gsd/delegation-policy.js +1 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +2 -2
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +192 -4
- package/dist/resources/extensions/gsd/doctor-providers.js +92 -8
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +3 -0
- package/dist/resources/extensions/gsd/exec-sandbox.js +53 -11
- package/dist/resources/extensions/gsd/flat-phase-migration.js +45 -0
- package/dist/resources/extensions/gsd/forensics.js +2 -32
- package/dist/resources/extensions/gsd/git-service.js +61 -4
- package/dist/resources/extensions/gsd/gitignore.js +4 -1
- 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/json-persistence.js +20 -0
- package/dist/resources/extensions/gsd/knowledge-backfill.js +18 -11
- 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-backfill.js +28 -21
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +44 -21
- package/dist/resources/extensions/gsd/metrics.js +4 -4
- package/dist/resources/extensions/gsd/migrate-external.js +11 -2
- 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/orphan-stash-audit.js +92 -16
- package/dist/resources/extensions/gsd/prompts/code-review.md +6 -4
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +3 -3
- package/dist/resources/extensions/gsd/quick.js +45 -2
- package/dist/resources/extensions/gsd/root-write-leak-guard.js +7 -1
- package/dist/resources/extensions/gsd/safety/destructive-guard.js +8 -1
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +16 -1
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +5 -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-milestone.js +4 -2
- 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/tools/plan-slice.js +59 -44
- package/dist/resources/extensions/gsd/tools/plan-task.js +28 -5
- package/dist/resources/extensions/gsd/undo.js +43 -6
- package/dist/resources/extensions/gsd/unit-context-composer.js +23 -7
- package/dist/resources/extensions/gsd/unit-registry.js +36 -6
- 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/verification-gate.js +7 -0
- package/dist/resources/extensions/gsd/workflow-manifest.js +126 -13
- 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/chunks/8357.js +1 -1
- 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-client.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js +23 -5
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js.map +1 -1
- 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 +35 -21
- 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/dist/agent-loop.js +3 -2
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +46 -0
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +38 -0
- package/packages/pi-ai/dist/models.generated.js.map +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/models.ts +9 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +20 -2
- package/src/resources/extensions/claude-code-cli/tests/index.test.ts +14 -0
- 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/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/orchestrator.ts +25 -11
- package/src/resources/extensions/gsd/auto/session.ts +14 -0
- package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +3 -1
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +47 -1
- package/src/resources/extensions/gsd/auto-budget.ts +12 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +35 -24
- package/src/resources/extensions/gsd/auto-post-unit.ts +1 -1
- package/src/resources/extensions/gsd/auto-prompts.ts +41 -15
- package/src/resources/extensions/gsd/auto-recovery.ts +13 -511
- 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/auto-verification.ts +5 -1
- package/src/resources/extensions/gsd/auto.ts +23 -8
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +125 -12
- package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +44 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +11 -5
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +52 -21
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +52 -18
- package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +104 -10
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
- package/src/resources/extensions/gsd/closeout-consistency-gate.ts +2 -1
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +1 -1
- package/src/resources/extensions/gsd/commands-context.ts +18 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +15 -10
- package/src/resources/extensions/gsd/commands-usage.ts +1 -1
- 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/engine.ts +8 -1
- package/src/resources/extensions/gsd/db/queries.ts +79 -0
- package/src/resources/extensions/gsd/db-memory-fts-schema.ts +45 -0
- package/src/resources/extensions/gsd/db-workspace.ts +61 -3
- package/src/resources/extensions/gsd/delegation-policy.ts +1 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +2 -2
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +233 -5
- package/src/resources/extensions/gsd/doctor-providers.ts +103 -9
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +3 -0
- package/src/resources/extensions/gsd/doctor-types.ts +3 -0
- package/src/resources/extensions/gsd/exec-sandbox.ts +56 -11
- package/src/resources/extensions/gsd/flat-phase-migration.ts +44 -0
- package/src/resources/extensions/gsd/forensics.ts +2 -33
- package/src/resources/extensions/gsd/git-service.ts +69 -5
- package/src/resources/extensions/gsd/gitignore.ts +4 -1
- 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/json-persistence.ts +20 -0
- package/src/resources/extensions/gsd/knowledge-backfill.ts +16 -10
- 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-backfill.ts +26 -20
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +51 -19
- package/src/resources/extensions/gsd/metrics.ts +4 -4
- package/src/resources/extensions/gsd/migrate-external.ts +8 -2
- 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/orphan-stash-audit.ts +108 -20
- package/src/resources/extensions/gsd/prompts/code-review.md +6 -4
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
- package/src/resources/extensions/gsd/prompts/plan-slice.md +3 -3
- package/src/resources/extensions/gsd/quick.ts +43 -2
- package/src/resources/extensions/gsd/root-write-leak-guard.ts +13 -1
- package/src/resources/extensions/gsd/safety/destructive-guard.ts +9 -1
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +16 -1
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +8 -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/artifact-retry-cap.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +98 -1
- package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +14 -5
- package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +182 -4
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +146 -1
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +30 -0
- 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-milestone.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +69 -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/db-memory-fts-schema.test.ts +58 -3
- package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +143 -0
- 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/doctor-scope-db-unavailable.test.ts +239 -2
- package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/exec-tool.test.ts +45 -1
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +37 -2
- package/src/resources/extensions/gsd/tests/forensics-error-filter.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +4 -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 +130 -3
- 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/json-persistence-atomic.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +35 -0
- 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/memory-store.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +31 -1
- package/src/resources/extensions/gsd/tests/metrics-prune-cache-invalidation.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/metrics.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +57 -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/orphan-stash-audit.test.ts +91 -7
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +103 -4
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +44 -1
- package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +4 -2
- 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/prompt-budget-enforcement.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -6
- 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/register-hooks-loop-guard-auto.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/root-write-leak-guard.test.ts +20 -1
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +15 -3
- 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 +208 -0
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +32 -3
- package/src/resources/extensions/gsd/tests/undo.test.ts +74 -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/uok-gitops-turn-action.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +69 -4
- package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +96 -15
- package/src/resources/extensions/gsd/tests/workflow-mcp-preflight.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +8 -4
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +6 -5
- 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-milestone.ts +3 -2
- 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/tools/plan-slice.ts +60 -47
- package/src/resources/extensions/gsd/tools/plan-task.ts +30 -5
- package/src/resources/extensions/gsd/undo.ts +47 -6
- package/src/resources/extensions/gsd/unit-context-composer.ts +33 -7
- package/src/resources/extensions/gsd/unit-registry.ts +36 -6
- 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/verification-gate.ts +8 -0
- package/src/resources/extensions/gsd/workflow-manifest.ts +141 -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 → 2A_WqqCS-EoYZxN9_v3d2}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → 2A_WqqCS-EoYZxN9_v3d2}/_ssgManifest.js +0 -0
|
@@ -17,7 +17,8 @@ import {
|
|
|
17
17
|
getSlice,
|
|
18
18
|
} from "../gsd-db.ts";
|
|
19
19
|
import { autoHealSketchFlags } from "../state-reconciliation/drift/sketch-flag.ts";
|
|
20
|
-
import { deriveState, deriveStateFromDb } from "../state.ts";
|
|
20
|
+
import { deriveState, deriveStateFromDb, invalidateStateCache } from "../state.ts";
|
|
21
|
+
import { reconcileBeforeDispatch } from "../state-reconciliation.ts";
|
|
21
22
|
import { resolveDispatch } from "../auto-dispatch.ts";
|
|
22
23
|
import type { DispatchContext } from "../auto-dispatch.ts";
|
|
23
24
|
|
|
@@ -174,7 +175,7 @@ test("ADR-011: refining + flag flipped OFF mid-milestone → falls through to pl
|
|
|
174
175
|
}
|
|
175
176
|
});
|
|
176
177
|
|
|
177
|
-
test("ADR-011: existing PLAN
|
|
178
|
+
test("ADR-011: existing PLAN + stale sketch flag heals via reconcileBeforeDispatch, then dispatch routes past refining (progressive_planning ON)", async (t) => {
|
|
178
179
|
const originalCwd = process.cwd();
|
|
179
180
|
const base = makeFixtureBase();
|
|
180
181
|
t.after(() => cleanup(base, originalCwd));
|
|
@@ -188,11 +189,22 @@ test("ADR-011: existing PLAN heals stale sketch flag via deriveStateFromDb (prog
|
|
|
188
189
|
);
|
|
189
190
|
process.chdir(base);
|
|
190
191
|
|
|
191
|
-
//
|
|
192
|
-
//
|
|
192
|
+
// Derivation is pure (ADR-017): a stale sketch flag (PLAN on disk but
|
|
193
|
+
// is_sketch=1) yields 'refining' and must NOT mutate the DB. Healing is
|
|
194
|
+
// owned by reconcileBeforeDispatch, which runs before every dispatch.
|
|
195
|
+
invalidateStateCache();
|
|
196
|
+
const beforeReconcile = await deriveStateFromDb(base);
|
|
197
|
+
assert.equal(beforeReconcile.activeSlice?.id, "S02");
|
|
198
|
+
assert.equal(beforeReconcile.phase, "refining", "derive alone must not heal the stale sketch flag");
|
|
199
|
+
assert.equal(getSlice("M001", "S02")?.is_sketch, 1, "derive must not mutate is_sketch");
|
|
200
|
+
|
|
201
|
+
const reconcile = await reconcileBeforeDispatch(base);
|
|
202
|
+
assert.equal(reconcile.ok, true);
|
|
203
|
+
assert.equal(getSlice("M001", "S02")?.is_sketch, 0, "reconcile clears the stale sketch flag once PLAN exists");
|
|
204
|
+
|
|
205
|
+
invalidateStateCache();
|
|
193
206
|
const state = await deriveStateFromDb(base);
|
|
194
|
-
assert.equal(
|
|
195
|
-
assert.equal(state.phase, "planning", "derive: phase advances past refining once flag is healed");
|
|
207
|
+
assert.equal(state.phase, "planning", "re-derive advances past refining once the flag is healed");
|
|
196
208
|
|
|
197
209
|
const ctx: DispatchContext = {
|
|
198
210
|
basePath: base,
|
|
@@ -229,7 +241,7 @@ test("ADR-011: autoHealSketchFlags flips is_sketch=0 when PLAN file exists", asy
|
|
|
229
241
|
assert.equal(getSlice("M001", "S02")?.is_sketch, 0, "post-heal: flag cleared");
|
|
230
242
|
});
|
|
231
243
|
|
|
232
|
-
test("ADR-011:
|
|
244
|
+
test("ADR-011: reconcileBeforeDispatch auto-heals stale sketch flag when PLAN exists", async (t) => {
|
|
233
245
|
const originalCwd = process.cwd();
|
|
234
246
|
const base = makeFixtureBase();
|
|
235
247
|
t.after(() => cleanup(base, originalCwd));
|
|
@@ -244,12 +256,23 @@ test("ADR-011: deriveStateFromDb auto-heals stale sketch flag when PLAN exists",
|
|
|
244
256
|
);
|
|
245
257
|
process.chdir(base);
|
|
246
258
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
259
|
+
// Pure derivation reports the stale flag as 'refining' without repairing it.
|
|
260
|
+
invalidateStateCache();
|
|
261
|
+
const stale = await deriveStateFromDb(base);
|
|
262
|
+
assert.equal(stale.phase, "refining", "derive alone must not heal the stale flag");
|
|
263
|
+
assert.equal(getSlice("M001", "S02")?.is_sketch, 1, "is_sketch unchanged before reconcile");
|
|
264
|
+
|
|
265
|
+
// Reconciliation owns the repair (ADR-017 stale-sketch-flag drift handler).
|
|
266
|
+
const reconcile = await reconcileBeforeDispatch(base);
|
|
267
|
+
assert.equal(reconcile.ok, true);
|
|
268
|
+
assert.equal(getSlice("M001", "S02")?.is_sketch, 0, "reconcile should clear stale is_sketch");
|
|
269
|
+
|
|
270
|
+
invalidateStateCache();
|
|
271
|
+
const healed = await deriveStateFromDb(base);
|
|
272
|
+
assert.equal(healed.phase, "planning", "state advances past refining once the stale flag is healed");
|
|
250
273
|
});
|
|
251
274
|
|
|
252
|
-
test("ADR-011: deriveState
|
|
275
|
+
test("ADR-011: deriveState stays pure across worktree/canonical-root; healing belongs to reconcile at the canonical artifact root", async (t) => {
|
|
253
276
|
const originalCwd = process.cwd();
|
|
254
277
|
const base = makeFixtureBase();
|
|
255
278
|
t.after(() => cleanup(base, originalCwd));
|
|
@@ -265,9 +288,22 @@ test("ADR-011: deriveState uses canonical artifact root for sketch-flag healing"
|
|
|
265
288
|
mkdirSync(worktreePath, { recursive: true });
|
|
266
289
|
process.chdir(worktreePath);
|
|
267
290
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
291
|
+
// Deriving from the worktree with reads routed to the canonical artifact
|
|
292
|
+
// root resolves DB state but never mutates it (ADR-017: derive is pure).
|
|
293
|
+
// The legacy projectRootForReads-driven heal is gone; healing now happens
|
|
294
|
+
// in reconcileBeforeDispatch, which auto runs against canonicalProjectRoot.
|
|
295
|
+
invalidateStateCache();
|
|
296
|
+
const beforeReconcile = await deriveState(worktreePath, { projectRootForReads: base });
|
|
297
|
+
assert.equal(beforeReconcile.phase, "refining", "derive alone must not heal, even via projectRootForReads");
|
|
298
|
+
assert.equal(getSlice("M001", "S02")?.is_sketch, 1, "derive must not mutate is_sketch");
|
|
299
|
+
|
|
300
|
+
const reconcile = await reconcileBeforeDispatch(base);
|
|
301
|
+
assert.equal(reconcile.ok, true);
|
|
302
|
+
assert.equal(getSlice("M001", "S02")?.is_sketch, 0, "reconcile at the canonical root heals the stale flag");
|
|
303
|
+
|
|
304
|
+
invalidateStateCache();
|
|
305
|
+
const healed = await deriveState(worktreePath, { projectRootForReads: base });
|
|
306
|
+
assert.equal(healed.phase, "planning", "re-derive advances past refining once healed at the canonical root");
|
|
271
307
|
});
|
|
272
308
|
|
|
273
309
|
test("ADR-011: schema v16 is idempotent — re-opening DB preserves is_sketch and sketch_scope columns", async (t) => {
|
|
@@ -72,6 +72,25 @@ function setupDependencyFixture(
|
|
|
72
72
|
mkdirSync(targetSliceDir, { recursive: true });
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
function setupFlatPhaseSlicePlan(base: string): void {
|
|
76
|
+
const phaseDir = join(base, ".gsd", "phases", "01-flat-phase");
|
|
77
|
+
mkdirSync(phaseDir, { recursive: true });
|
|
78
|
+
writeFileSync(
|
|
79
|
+
join(phaseDir, "01-01-PLAN.md"),
|
|
80
|
+
[
|
|
81
|
+
"# S01: Flat phase slice",
|
|
82
|
+
"",
|
|
83
|
+
"## Tasks",
|
|
84
|
+
"",
|
|
85
|
+
"- [ ] **T01: Flat task** `est:15m`",
|
|
86
|
+
"",
|
|
87
|
+
"## Verification",
|
|
88
|
+
"",
|
|
89
|
+
"- Rendered prompt points at this slice plan.",
|
|
90
|
+
].join("\n"),
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
75
94
|
// ─── inlineDependencySummaries truncation ─────────────────────────────────────
|
|
76
95
|
|
|
77
96
|
describe("prompt-budget: inlineDependencySummaries truncation", () => {
|
|
@@ -412,6 +431,26 @@ describe("prompt-budget: execute-task template", () => {
|
|
|
412
431
|
}
|
|
413
432
|
});
|
|
414
433
|
|
|
434
|
+
it("flat-phase execute-task fallback points at the slice plan", async () => {
|
|
435
|
+
const base = createFixtureBase();
|
|
436
|
+
try {
|
|
437
|
+
setupFlatPhaseSlicePlan(base);
|
|
438
|
+
|
|
439
|
+
const prompt = await buildExecuteTaskPrompt("M001", "S01", "Slice", "T01", "Task", base, {
|
|
440
|
+
level: "minimal",
|
|
441
|
+
sessionContextWindow: 128_000,
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
assert.match(
|
|
445
|
+
prompt,
|
|
446
|
+
/Task plan not found at dispatch time\. Read `\.gsd\/phases\/01-flat-phase\/01-01-PLAN\.md` before executing\./,
|
|
447
|
+
);
|
|
448
|
+
assert.doesNotMatch(prompt, /\.gsd\/phases\/01-flat-phase\/tasks\/T01-PLAN\.md/);
|
|
449
|
+
} finally {
|
|
450
|
+
cleanup(base);
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
|
|
415
454
|
it("verificationBudget format varies with context window size", () => {
|
|
416
455
|
const budget128K = computeBudgets(128_000);
|
|
417
456
|
const budget1M = computeBudgets(1_000_000);
|
|
@@ -566,6 +605,25 @@ describe("prompt-budget: execute-task builder truncation pattern", () => {
|
|
|
566
605
|
});
|
|
567
606
|
|
|
568
607
|
describe("prompt-budget: reactive-execute builder", () => {
|
|
608
|
+
it("flat-phase subagent fallback points at the slice plan", async () => {
|
|
609
|
+
const base = createFixtureBase();
|
|
610
|
+
try {
|
|
611
|
+
setupFlatPhaseSlicePlan(base);
|
|
612
|
+
|
|
613
|
+
const prompt = await buildReactiveExecutePrompt("M001", "Milestone", "S01", "Slice", ["T01"], base, undefined, {
|
|
614
|
+
sessionContextWindow: 128_000,
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
assert.match(
|
|
618
|
+
prompt,
|
|
619
|
+
/Task plan not found at dispatch time\. Read `\.gsd\/phases\/01-flat-phase\/01-01-PLAN\.md` before executing\./,
|
|
620
|
+
);
|
|
621
|
+
assert.doesNotMatch(prompt, /\.gsd\/phases\/01-flat-phase\/tasks\/T01-PLAN\.md/);
|
|
622
|
+
} finally {
|
|
623
|
+
cleanup(base);
|
|
624
|
+
}
|
|
625
|
+
});
|
|
626
|
+
|
|
569
627
|
it("caps dependency carry-forward per ready subagent", async () => {
|
|
570
628
|
const base = createFixtureBase();
|
|
571
629
|
try {
|
|
@@ -533,6 +533,7 @@ test("plan-milestone prompt references DB-backed planning tool and explicitly fo
|
|
|
533
533
|
assert.match(prompt, /Do \*\*not\*\* write `?\{\{outputPath\}\}`?, `?ROADMAP\.md`?, or other planning artifacts manually/i);
|
|
534
534
|
assert.match(prompt, /NEVER call `gsd_plan_milestone` with only `milestoneId` and `sliceId`/);
|
|
535
535
|
assert.match(prompt, /gsd_plan_slice/);
|
|
536
|
+
assert.match(prompt, /gsd_plan_task/);
|
|
536
537
|
});
|
|
537
538
|
|
|
538
539
|
test("discuss prompts forbid gsd_plan_milestone slice-only tool args", () => {
|
|
@@ -548,12 +549,12 @@ test("plan-slice prompt no longer frames direct PLAN writes as the source of tru
|
|
|
548
549
|
assert.match(prompt, /Do \*\*not\*\* rely on direct `PLAN\.md` writes as the source of truth/i);
|
|
549
550
|
});
|
|
550
551
|
|
|
551
|
-
test("plan-slice prompt explicitly names
|
|
552
|
+
test("plan-slice prompt explicitly names incremental DB-backed planning tools", () => {
|
|
552
553
|
const prompt = readPrompt("plan-slice");
|
|
553
554
|
assert.match(prompt, /gsd_plan_slice/);
|
|
554
555
|
assert.match(prompt, /gsd_plan_task/);
|
|
555
|
-
|
|
556
|
-
assert.match(prompt, /DB-backed
|
|
556
|
+
assert.match(prompt, /Persist incrementally through DB-backed tools/i);
|
|
557
|
+
assert.match(prompt, /DB-backed tools are the canonical write path/i);
|
|
557
558
|
});
|
|
558
559
|
|
|
559
560
|
test("plan-slice prompt does not instruct direct file writes as a primary step", () => {
|
|
@@ -562,11 +563,12 @@ test("plan-slice prompt does not instruct direct file writes as a primary step",
|
|
|
562
563
|
assert.doesNotMatch(prompt, /^\d+\.\s+Write `?\{\{outputPath\}\}`?\s*$/m);
|
|
563
564
|
});
|
|
564
565
|
|
|
565
|
-
test("plan-slice prompt
|
|
566
|
+
test("plan-slice prompt requires per-task incremental persistence", () => {
|
|
566
567
|
const prompt = readPrompt("plan-slice");
|
|
567
|
-
// gsd_plan_slice persists tasks in its transaction — no separate gsd_plan_task calls needed
|
|
568
568
|
assert.match(prompt, /gsd_plan_task/);
|
|
569
|
-
assert.match(prompt, /
|
|
569
|
+
assert.match(prompt, /omit `tasks` for this metadata call/i);
|
|
570
|
+
assert.match(prompt, /call `gsd_plan_task` once per task/i);
|
|
571
|
+
assert.doesNotMatch(prompt, /do not call `gsd_plan_task`/i);
|
|
570
572
|
});
|
|
571
573
|
|
|
572
574
|
test("plan-slice prompt references web app UAT guidance when planning browser work", () => {
|
|
@@ -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
|
+
});
|