gsd-pi 2.81.0-dev.72a81bdf3 → 2.82.0-dev.20138ae42
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 +50 -31
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +10 -1
- package/dist/resources/extensions/browser-tools/tools/screenshot.js +1 -0
- package/dist/resources/extensions/browser-tools/tools/zoom.js +1 -0
- package/dist/resources/extensions/claude-code-cli/partial-builder.js +2 -1
- package/dist/resources/extensions/cmux/index.js +5 -0
- package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
- package/dist/resources/extensions/gsd/auto/loop.js +5 -5
- package/dist/resources/extensions/gsd/auto/orchestrator.js +124 -6
- package/dist/resources/extensions/gsd/auto/phases.js +30 -1
- package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +66 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +13 -6
- package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +233 -127
- package/dist/resources/extensions/gsd/auto-prompts.js +13 -5
- package/dist/resources/extensions/gsd/auto-recovery.js +31 -1
- package/dist/resources/extensions/gsd/auto-start.js +85 -12
- package/dist/resources/extensions/gsd/auto-verification.js +28 -22
- package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
- package/dist/resources/extensions/gsd/auto.js +158 -55
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +25 -6
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +9 -8
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +9 -2
- package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +55 -12
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +16 -2
- package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
- package/dist/resources/extensions/gsd/commands/catalog.js +4 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +38 -1
- package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +15 -2
- package/dist/resources/extensions/gsd/context-store.js +112 -0
- package/dist/resources/extensions/gsd/crash-recovery.js +31 -5
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
- package/dist/resources/extensions/gsd/db-writer.js +150 -84
- package/dist/resources/extensions/gsd/dispatch-guard.js +2 -2
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/dist/resources/extensions/gsd/doctor-git-checks.js +41 -6
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +28 -11
- package/dist/resources/extensions/gsd/doctor.js +2 -28
- package/dist/resources/extensions/gsd/export-html.js +27 -425
- package/dist/resources/extensions/gsd/git-service.js +39 -1
- package/dist/resources/extensions/gsd/gsd-db.js +1 -0
- package/dist/resources/extensions/gsd/guided-flow.js +93 -111
- package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
- package/dist/resources/extensions/gsd/knowledge-backfill.js +144 -0
- package/dist/resources/extensions/gsd/knowledge-capture.js +136 -0
- package/dist/resources/extensions/gsd/knowledge-parser.js +154 -0
- package/dist/resources/extensions/gsd/knowledge-projection.js +210 -0
- package/dist/resources/extensions/gsd/markdown-renderer.js +6 -1
- package/dist/resources/extensions/gsd/md-importer.js +1 -1
- package/dist/resources/extensions/gsd/memory-backfill.js +73 -17
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +222 -0
- package/dist/resources/extensions/gsd/migrate/command.js +5 -0
- package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
- package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
- package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
- package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
- package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
- package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
- package/dist/resources/extensions/gsd/native-git-bridge.js +48 -12
- package/dist/resources/extensions/gsd/pending-auto-start.js +52 -0
- package/dist/resources/extensions/gsd/post-execution-checks.js +73 -2
- package/dist/resources/extensions/gsd/pre-execution-checks.js +28 -1
- package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
- package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
- package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
- package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
- package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/dist/resources/extensions/gsd/prompts/system.md +2 -2
- package/dist/resources/extensions/gsd/provider-switch-observer.js +146 -0
- package/dist/resources/extensions/gsd/smart-entry-routing.js +36 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
- package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
- package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
- package/dist/resources/extensions/gsd/status-guards.js +4 -0
- package/dist/resources/extensions/gsd/templates/knowledge.md +2 -2
- package/dist/resources/extensions/gsd/templates/plan.md +8 -5
- package/dist/resources/extensions/gsd/templates/task-plan.md +4 -2
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -8
- package/dist/resources/extensions/gsd/tools/complete-slice.js +6 -8
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
- package/dist/resources/extensions/gsd/tools/plan-slice.js +89 -14
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +119 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +32 -10
- package/dist/resources/extensions/gsd/validation.js +23 -1
- package/dist/resources/extensions/gsd/verification-gate.js +68 -7
- package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
- package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +54 -10
- package/dist/resources/extensions/shared/html-shell.js +388 -0
- package/dist/resources/extensions/subagent/index.js +448 -78
- package/dist/resources/extensions/subagent/launch.js +77 -0
- package/dist/resources/extensions/subagent/run-store.js +148 -0
- package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
- package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
- package/dist/resources/extensions/visual-brief/index.js +5 -0
- package/dist/resources/extensions/visual-brief/page-contract.js +124 -0
- package/dist/resources/extensions/visual-brief/prompts.js +140 -0
- 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 +12 -12
- 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 +3 -3
- 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.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +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 +4 -7
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
- 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 +4 -5
- 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 +2 -5
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -7
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -7
- 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 +4 -5
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page.js.nft.json +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 +12 -12
- package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
- 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/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +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/2973.33f26573894b6153.js +2 -0
- package/dist/web/standalone/.next/static/chunks/{8359.e059d86b255fce1c.js → 8359.7eb3bb8f8ecf4c01.js} +2 -2
- package/dist/web/standalone/.next/static/chunks/app/layout-8c10ec293ae0f1d5.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-9a4db269f9ed63ad.js} +1 -1
- package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
- package/package.json +6 -5
- package/packages/contracts/dist/rpc.test.js +7 -0
- package/packages/contracts/dist/rpc.test.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +21 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +24 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/src/rpc.test.ts +8 -0
- package/packages/contracts/src/workflow.ts +24 -0
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/README.md +14 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +80 -0
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/workflow-tools-parity.test.ts +244 -0
- package/packages/mcp-server/src/workflow-tools.test.ts +23 -1
- package/packages/mcp-server/src/workflow-tools.ts +168 -0
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- package/packages/native/tsconfig.json +2 -1
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/index.d.ts +2 -2
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -1
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js +82 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +52 -0
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/simple-options.d.ts +2 -4
- package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.js +5 -6
- package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/simple-options.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/simple-options.test.js +50 -0
- package/packages/pi-ai/dist/providers/simple-options.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/transform-messages.d.ts +11 -0
- package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.js +20 -0
- package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/index.ts +7 -2
- package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
- package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
- package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
- package/packages/pi-ai/src/providers/simple-options.ts +5 -6
- package/packages/pi-ai/src/providers/transform-messages.ts +24 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +4 -4
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +24 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js +17 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
- package/packages/pi-coding-agent/src/core/system-prompt.ts +4 -4
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
- package/packages/pi-coding-agent/src/tests/system-prompt-file-safety.test.ts +22 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +5 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/tui.ts +6 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +10 -1
- package/src/resources/extensions/browser-tools/tools/screenshot.ts +1 -0
- package/src/resources/extensions/browser-tools/tools/zoom.ts +1 -0
- package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
- package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
- package/src/resources/extensions/cmux/index.ts +6 -0
- package/src/resources/extensions/gsd/auto/contracts.ts +59 -16
- package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
- package/src/resources/extensions/gsd/auto/loop.ts +8 -5
- package/src/resources/extensions/gsd/auto/orchestrator.ts +129 -6
- package/src/resources/extensions/gsd/auto/phases.ts +36 -1
- package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +72 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +14 -6
- package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +266 -139
- package/src/resources/extensions/gsd/auto-prompts.ts +13 -5
- package/src/resources/extensions/gsd/auto-recovery.ts +29 -0
- package/src/resources/extensions/gsd/auto-start.ts +92 -9
- package/src/resources/extensions/gsd/auto-verification.ts +36 -34
- package/src/resources/extensions/gsd/auto-worktree.ts +119 -1
- package/src/resources/extensions/gsd/auto.ts +167 -53
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +33 -6
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +9 -8
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +10 -2
- package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +58 -15
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +19 -3
- package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
- package/src/resources/extensions/gsd/commands/catalog.ts +4 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +41 -1
- package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +19 -2
- package/src/resources/extensions/gsd/context-store.ts +120 -1
- package/src/resources/extensions/gsd/crash-recovery.ts +30 -4
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
- package/src/resources/extensions/gsd/db-writer.ts +167 -84
- package/src/resources/extensions/gsd/dispatch-guard.ts +2 -2
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/src/resources/extensions/gsd/doctor-git-checks.ts +44 -6
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
- package/src/resources/extensions/gsd/doctor-types.ts +2 -0
- package/src/resources/extensions/gsd/doctor.ts +2 -27
- package/src/resources/extensions/gsd/export-html.ts +27 -427
- package/src/resources/extensions/gsd/git-service.ts +45 -1
- package/src/resources/extensions/gsd/gsd-db.ts +3 -0
- package/src/resources/extensions/gsd/guided-flow.ts +126 -128
- package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
- package/src/resources/extensions/gsd/knowledge-backfill.ts +164 -0
- package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
- package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
- package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +6 -1
- package/src/resources/extensions/gsd/md-importer.ts +1 -1
- package/src/resources/extensions/gsd/memory-backfill.ts +89 -17
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
- package/src/resources/extensions/gsd/migrate/command.ts +5 -0
- package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
- package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
- package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
- package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
- package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
- package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
- package/src/resources/extensions/gsd/native-git-bridge.ts +54 -12
- package/src/resources/extensions/gsd/pending-auto-start.ts +79 -0
- package/src/resources/extensions/gsd/post-execution-checks.ts +87 -2
- package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -1
- package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
- package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
- package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
- package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
- package/src/resources/extensions/gsd/prompts/queue.md +4 -4
- package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/src/resources/extensions/gsd/prompts/system.md +2 -2
- package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
- package/src/resources/extensions/gsd/smart-entry-routing.ts +77 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
- package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
- package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
- package/src/resources/extensions/gsd/status-guards.ts +5 -0
- package/src/resources/extensions/gsd/templates/knowledge.md +2 -2
- package/src/resources/extensions/gsd/templates/plan.md +8 -5
- package/src/resources/extensions/gsd/templates/task-plan.md +4 -2
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +129 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +487 -4
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +12 -11
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +53 -2
- package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +12 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +15 -1
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
- package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/browser-tools-compatibility-declarations.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +107 -2
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +11 -2
- package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +5 -9
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
- package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +43 -2
- package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +13 -8
- package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
- package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +59 -2
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +8 -4
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +11 -7
- package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +59 -11
- package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +7 -7
- package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
- package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +103 -1
- package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +13 -5
- package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +323 -0
- package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -2
- package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +63 -2
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
- package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
- package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +29 -5
- package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +225 -1
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +17 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +86 -0
- package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +20 -1
- package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
- package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +46 -2
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +16 -4
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +53 -2
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
- package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +86 -7
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +110 -1
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +21 -1
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +54 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +8 -10
- package/src/resources/extensions/gsd/tools/complete-slice.ts +6 -8
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
- package/src/resources/extensions/gsd/tools/plan-slice.ts +98 -12
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
- package/src/resources/extensions/gsd/types.ts +1 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +47 -11
- package/src/resources/extensions/gsd/validation.ts +23 -1
- package/src/resources/extensions/gsd/verification-gate.ts +78 -6
- package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +4 -0
- package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +61 -10
- package/src/resources/extensions/shared/html-shell.ts +412 -0
- package/src/resources/extensions/subagent/index.ts +567 -103
- package/src/resources/extensions/subagent/launch.ts +131 -0
- package/src/resources/extensions/subagent/run-store.ts +218 -0
- package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
- package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
- package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
- package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
- package/src/resources/extensions/visual-brief/index.ts +8 -0
- package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
- package/src/resources/extensions/visual-brief/prompts.ts +183 -0
- package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
- package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
- package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +0 -1
- package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
- package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
- package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
- package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
- /package/dist/web/standalone/.next/static/{rIkMv4YSNlfSeqmGqWVns → xRy4LqKSNKdT7y6ATYyEl}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{rIkMv4YSNlfSeqmGqWVns → xRy4LqKSNKdT7y6ATYyEl}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
// ADR-013 Phase 6 cutover (Stage 3) — destructive lock-in.
|
|
2
|
+
//
|
|
3
|
+
// After this stage, new decisions written via gsd_save_decision land ONLY in
|
|
4
|
+
// the memories table. The decisions table receives no new rows; its existing
|
|
5
|
+
// rows remain for backwards-compat reads until #5756 drops the table.
|
|
6
|
+
//
|
|
7
|
+
// Tests cover five properties:
|
|
8
|
+
// 1. New saveDecisionToDb call does NOT insert into the decisions table
|
|
9
|
+
// 2. The new decision DOES appear as a memory row with sourceDecisionId
|
|
10
|
+
// 3. The rendered DECISIONS.md projection includes the new decision
|
|
11
|
+
// 4. Pre-existing decisions-table rows are untouched
|
|
12
|
+
// 5. Decision IDs are monotonic across both surfaces (max of either + 1)
|
|
13
|
+
|
|
14
|
+
import test from "node:test";
|
|
15
|
+
import assert from "node:assert/strict";
|
|
16
|
+
import {
|
|
17
|
+
existsSync,
|
|
18
|
+
mkdirSync,
|
|
19
|
+
mkdtempSync,
|
|
20
|
+
readFileSync,
|
|
21
|
+
rmSync,
|
|
22
|
+
} from "node:fs";
|
|
23
|
+
import { join } from "node:path";
|
|
24
|
+
import { tmpdir } from "node:os";
|
|
25
|
+
|
|
26
|
+
import {
|
|
27
|
+
_getAdapter,
|
|
28
|
+
closeDatabase,
|
|
29
|
+
insertDecision,
|
|
30
|
+
openDatabase,
|
|
31
|
+
} from "../gsd-db.ts";
|
|
32
|
+
import { saveDecisionToDb } from "../db-writer.ts";
|
|
33
|
+
import {
|
|
34
|
+
getAllDecisionsFromMemories,
|
|
35
|
+
queryDecisions,
|
|
36
|
+
} from "../context-store.ts";
|
|
37
|
+
|
|
38
|
+
function makeTmpBase(): string {
|
|
39
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-decisions-stage3-"));
|
|
40
|
+
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
41
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
42
|
+
return base;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function cleanup(base: string): void {
|
|
46
|
+
try {
|
|
47
|
+
closeDatabase();
|
|
48
|
+
} catch {
|
|
49
|
+
/* noop */
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
rmSync(base, { recursive: true, force: true });
|
|
53
|
+
} catch {
|
|
54
|
+
/* noop */
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function countDecisionRows(): number {
|
|
59
|
+
const adapter = _getAdapter();
|
|
60
|
+
if (!adapter) return 0;
|
|
61
|
+
const row = adapter
|
|
62
|
+
.prepare("SELECT COUNT(*) as n FROM decisions")
|
|
63
|
+
.get() as { n: number };
|
|
64
|
+
return row.n;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function seedLegacyDecision(args: {
|
|
68
|
+
id: string;
|
|
69
|
+
when_context: string;
|
|
70
|
+
scope: string;
|
|
71
|
+
decision: string;
|
|
72
|
+
choice: string;
|
|
73
|
+
rationale: string;
|
|
74
|
+
superseded_by?: string | null;
|
|
75
|
+
}): void {
|
|
76
|
+
insertDecision({
|
|
77
|
+
id: args.id,
|
|
78
|
+
when_context: args.when_context,
|
|
79
|
+
scope: args.scope,
|
|
80
|
+
decision: args.decision,
|
|
81
|
+
choice: args.choice,
|
|
82
|
+
rationale: args.rationale,
|
|
83
|
+
revisable: "Yes",
|
|
84
|
+
made_by: "agent",
|
|
85
|
+
superseded_by: args.superseded_by ?? null,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ─── Core invariants ────────────────────────────────────────────────────────
|
|
90
|
+
|
|
91
|
+
test("saveDecisionToDb no longer writes to the decisions table", async () => {
|
|
92
|
+
const base = makeTmpBase();
|
|
93
|
+
try {
|
|
94
|
+
const before = countDecisionRows();
|
|
95
|
+
assert.equal(before, 0);
|
|
96
|
+
|
|
97
|
+
await saveDecisionToDb(
|
|
98
|
+
{
|
|
99
|
+
when_context: "M001 discuss",
|
|
100
|
+
scope: "M001",
|
|
101
|
+
decision: "Stage 3 destructive: memories-only writes",
|
|
102
|
+
choice: "Drop the upsertDecision call",
|
|
103
|
+
rationale: "Cutover step required by ADR-013 Phase 6",
|
|
104
|
+
revisable: "Yes",
|
|
105
|
+
made_by: "agent",
|
|
106
|
+
},
|
|
107
|
+
base,
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
const after = countDecisionRows();
|
|
111
|
+
assert.equal(after, 0, "decisions table must remain empty after Stage 3 save");
|
|
112
|
+
} finally {
|
|
113
|
+
cleanup(base);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("saveDecisionToDb writes the new decision into memories with sourceDecisionId", async () => {
|
|
118
|
+
const base = makeTmpBase();
|
|
119
|
+
try {
|
|
120
|
+
const { id } = await saveDecisionToDb(
|
|
121
|
+
{
|
|
122
|
+
when_context: "M001 discuss",
|
|
123
|
+
scope: "M001",
|
|
124
|
+
decision: "Use atomic file writes",
|
|
125
|
+
choice: "atomicWriteSync",
|
|
126
|
+
rationale: "crash-safe markdown projections",
|
|
127
|
+
revisable: "Yes",
|
|
128
|
+
made_by: "agent",
|
|
129
|
+
},
|
|
130
|
+
base,
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
const fromMemories = getAllDecisionsFromMemories();
|
|
134
|
+
assert.equal(fromMemories.length, 1);
|
|
135
|
+
assert.equal(fromMemories[0]?.id, id);
|
|
136
|
+
assert.equal(fromMemories[0]?.decision, "Use atomic file writes");
|
|
137
|
+
} finally {
|
|
138
|
+
cleanup(base);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("DECISIONS.md projection includes the memory-only decision", async () => {
|
|
143
|
+
const base = makeTmpBase();
|
|
144
|
+
try {
|
|
145
|
+
await saveDecisionToDb(
|
|
146
|
+
{
|
|
147
|
+
when_context: "M001 discuss",
|
|
148
|
+
scope: "M001",
|
|
149
|
+
decision: "Adopt SQLite",
|
|
150
|
+
choice: "better-sqlite3",
|
|
151
|
+
rationale: "synchronous + native",
|
|
152
|
+
revisable: "Yes",
|
|
153
|
+
made_by: "agent",
|
|
154
|
+
},
|
|
155
|
+
base,
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
const md = readFileSync(join(base, ".gsd", "DECISIONS.md"), "utf-8");
|
|
159
|
+
assert.match(md, /\| D001 \|/);
|
|
160
|
+
assert.match(md, /Adopt SQLite/);
|
|
161
|
+
assert.match(md, /# Decisions Register/);
|
|
162
|
+
} finally {
|
|
163
|
+
cleanup(base);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// ─── Existing decisions table is preserved ──────────────────────────────────
|
|
168
|
+
|
|
169
|
+
test("pre-existing decisions-table rows are untouched by Stage 3 saves", async () => {
|
|
170
|
+
const base = makeTmpBase();
|
|
171
|
+
try {
|
|
172
|
+
// Seed two legacy decisions directly into the table — simulates a
|
|
173
|
+
// pre-cutover project.
|
|
174
|
+
seedLegacyDecision({
|
|
175
|
+
id: "D001",
|
|
176
|
+
when_context: "M001 historical",
|
|
177
|
+
scope: "M001",
|
|
178
|
+
decision: "Legacy decision one",
|
|
179
|
+
choice: "A",
|
|
180
|
+
rationale: "r1",
|
|
181
|
+
});
|
|
182
|
+
seedLegacyDecision({
|
|
183
|
+
id: "D002",
|
|
184
|
+
when_context: "M001 historical",
|
|
185
|
+
scope: "M001",
|
|
186
|
+
decision: "Legacy decision two",
|
|
187
|
+
choice: "B",
|
|
188
|
+
rationale: "r2",
|
|
189
|
+
});
|
|
190
|
+
assert.equal(countDecisionRows(), 2);
|
|
191
|
+
|
|
192
|
+
// New save via the cutover path.
|
|
193
|
+
await saveDecisionToDb(
|
|
194
|
+
{
|
|
195
|
+
when_context: "M001 today",
|
|
196
|
+
scope: "M001",
|
|
197
|
+
decision: "Post-cutover decision",
|
|
198
|
+
choice: "C",
|
|
199
|
+
rationale: "r3",
|
|
200
|
+
revisable: "Yes",
|
|
201
|
+
made_by: "agent",
|
|
202
|
+
},
|
|
203
|
+
base,
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
// Decisions table unchanged.
|
|
207
|
+
assert.equal(countDecisionRows(), 2);
|
|
208
|
+
|
|
209
|
+
// Legacy reads still see the pre-existing rows.
|
|
210
|
+
const fromLegacy = queryDecisions();
|
|
211
|
+
assert.equal(fromLegacy.length, 2);
|
|
212
|
+
assert.deepEqual(
|
|
213
|
+
fromLegacy.map((d) => d.id).sort(),
|
|
214
|
+
["D001", "D002"],
|
|
215
|
+
);
|
|
216
|
+
} finally {
|
|
217
|
+
cleanup(base);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
// ─── Cross-surface ID monotonicity ─────────────────────────────────────────
|
|
222
|
+
|
|
223
|
+
test("decision IDs are monotonic across legacy table + memory surfaces", async () => {
|
|
224
|
+
const base = makeTmpBase();
|
|
225
|
+
try {
|
|
226
|
+
// Pre-cutover project with D001..D005 in the legacy table (no memory
|
|
227
|
+
// backfill yet — simulates an upgrade that hasn't run backfill).
|
|
228
|
+
for (let i = 1; i <= 5; i++) {
|
|
229
|
+
seedLegacyDecision({
|
|
230
|
+
id: `D${String(i).padStart(3, "0")}`,
|
|
231
|
+
when_context: "historical",
|
|
232
|
+
scope: "M001",
|
|
233
|
+
decision: `Decision ${i}`,
|
|
234
|
+
choice: "x",
|
|
235
|
+
rationale: "y",
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
assert.equal(countDecisionRows(), 5);
|
|
239
|
+
|
|
240
|
+
// First Stage 3 save: must pick the next-after-table ID.
|
|
241
|
+
const a = await saveDecisionToDb(
|
|
242
|
+
{
|
|
243
|
+
when_context: "M001 today",
|
|
244
|
+
scope: "M001",
|
|
245
|
+
decision: "First post-cutover",
|
|
246
|
+
choice: "A",
|
|
247
|
+
rationale: "r",
|
|
248
|
+
revisable: "Yes",
|
|
249
|
+
made_by: "agent",
|
|
250
|
+
},
|
|
251
|
+
base,
|
|
252
|
+
);
|
|
253
|
+
assert.equal(a.id, "D006", "first cutover save must follow the legacy table max (D005 -> D006)");
|
|
254
|
+
|
|
255
|
+
// Second save: must pick the next-after-memory ID.
|
|
256
|
+
const b = await saveDecisionToDb(
|
|
257
|
+
{
|
|
258
|
+
when_context: "M001 today",
|
|
259
|
+
scope: "M001",
|
|
260
|
+
decision: "Second post-cutover",
|
|
261
|
+
choice: "B",
|
|
262
|
+
rationale: "r",
|
|
263
|
+
revisable: "Yes",
|
|
264
|
+
made_by: "agent",
|
|
265
|
+
},
|
|
266
|
+
base,
|
|
267
|
+
);
|
|
268
|
+
assert.equal(b.id, "D007", "second cutover save must follow memory max (D006 -> D007)");
|
|
269
|
+
|
|
270
|
+
// Decisions table still has only the original five.
|
|
271
|
+
assert.equal(countDecisionRows(), 5);
|
|
272
|
+
} finally {
|
|
273
|
+
cleanup(base);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
test("next-ID falls back to D001 when both surfaces are empty", async () => {
|
|
278
|
+
const base = makeTmpBase();
|
|
279
|
+
try {
|
|
280
|
+
const { id } = await saveDecisionToDb(
|
|
281
|
+
{
|
|
282
|
+
when_context: "M001",
|
|
283
|
+
scope: "M001",
|
|
284
|
+
decision: "First ever",
|
|
285
|
+
choice: "A",
|
|
286
|
+
rationale: "r",
|
|
287
|
+
revisable: "Yes",
|
|
288
|
+
made_by: "agent",
|
|
289
|
+
},
|
|
290
|
+
base,
|
|
291
|
+
);
|
|
292
|
+
assert.equal(id, "D001");
|
|
293
|
+
} finally {
|
|
294
|
+
cleanup(base);
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
test("next-ID skips beyond memory-only entries when the legacy table is empty", async () => {
|
|
299
|
+
const base = makeTmpBase();
|
|
300
|
+
try {
|
|
301
|
+
// Three memory-only saves on a fresh project.
|
|
302
|
+
const a = await saveDecisionToDb(
|
|
303
|
+
{ when_context: "M001", scope: "M001", decision: "A", choice: "1", rationale: "r", revisable: "Yes", made_by: "agent" },
|
|
304
|
+
base,
|
|
305
|
+
);
|
|
306
|
+
const b = await saveDecisionToDb(
|
|
307
|
+
{ when_context: "M001", scope: "M001", decision: "B", choice: "2", rationale: "r", revisable: "Yes", made_by: "agent" },
|
|
308
|
+
base,
|
|
309
|
+
);
|
|
310
|
+
const c = await saveDecisionToDb(
|
|
311
|
+
{ when_context: "M001", scope: "M001", decision: "C", choice: "3", rationale: "r", revisable: "Yes", made_by: "agent" },
|
|
312
|
+
base,
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
assert.deepEqual([a.id, b.id, c.id], ["D001", "D002", "D003"]);
|
|
316
|
+
assert.equal(countDecisionRows(), 0, "no decisions-table writes despite three saves");
|
|
317
|
+
} finally {
|
|
318
|
+
cleanup(base);
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
// ─── Defensive: malformed structured_fields don't break next-ID ────────────
|
|
323
|
+
|
|
324
|
+
test("malformed structuredFields in memories are silently skipped during next-ID computation", async () => {
|
|
325
|
+
const base = makeTmpBase();
|
|
326
|
+
try {
|
|
327
|
+
// Insert a memory with broken JSON in structured_fields. The next-ID
|
|
328
|
+
// logic must not throw.
|
|
329
|
+
const adapter = _getAdapter();
|
|
330
|
+
assert.ok(adapter);
|
|
331
|
+
adapter
|
|
332
|
+
.prepare(
|
|
333
|
+
"INSERT INTO memories (id, category, content, confidence, created_at, updated_at, structured_fields) VALUES ('mem-broken', 'architecture', 'oops', 0.5, datetime('now'), datetime('now'), '{\"sourceDecisionId\":\"D999\"')",
|
|
334
|
+
)
|
|
335
|
+
.run();
|
|
336
|
+
|
|
337
|
+
const { id } = await saveDecisionToDb(
|
|
338
|
+
{ when_context: "M001", scope: "M001", decision: "Survivor", choice: "x", rationale: "y", revisable: "Yes", made_by: "agent" },
|
|
339
|
+
base,
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
// Broken JSON for D999 doesn't parse, so the surfaced max stays at 0.
|
|
343
|
+
// The new save must still produce a valid sequential ID.
|
|
344
|
+
assert.equal(id, "D001");
|
|
345
|
+
} finally {
|
|
346
|
+
cleanup(base);
|
|
347
|
+
}
|
|
348
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import test from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
-
import { existsSync, mkdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { execFileSync } from "node:child_process";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
import { join } from "node:path";
|
|
@@ -10,7 +10,7 @@ import { runDispatch, runPreDispatch } from "../auto/phases.ts";
|
|
|
10
10
|
import { AutoSession } from "../auto/session.ts";
|
|
11
11
|
import { resolveUnitSupervisionTimeouts } from "../auto-timers.ts";
|
|
12
12
|
import { bootstrapAutoSession } from "../auto-start.ts";
|
|
13
|
-
import { postUnitPreVerification } from "../auto-post-unit.ts";
|
|
13
|
+
import { postUnitPostVerification, postUnitPreVerification } from "../auto-post-unit.ts";
|
|
14
14
|
import { resolveDispatch, setResearchProjectPromptBuilderForTest } from "../auto-dispatch.ts";
|
|
15
15
|
import { resolveExpectedArtifactPath, verifyExpectedArtifact, writeBlockerPlaceholder } from "../auto-recovery.ts";
|
|
16
16
|
import { finalizeProjectResearchTimeout } from "../project-research-policy.ts";
|
|
@@ -272,6 +272,7 @@ test("deep project setup: bootstrap can start auto-mode without an active milest
|
|
|
272
272
|
{
|
|
273
273
|
shouldUseWorktreeIsolation: () => false,
|
|
274
274
|
registerSigtermHandler: () => {},
|
|
275
|
+
registerAutoWorkerForSession: () => {},
|
|
275
276
|
lockBase: () => base,
|
|
276
277
|
buildLifecycle: () => ({
|
|
277
278
|
adoptSessionRoot: (sessionBase: string, originalBase?: string) => {
|
|
@@ -386,6 +387,7 @@ test("deep project setup: bootstrap continues queued M002 without milestone cont
|
|
|
386
387
|
{
|
|
387
388
|
shouldUseWorktreeIsolation: () => false,
|
|
388
389
|
registerSigtermHandler: () => {},
|
|
390
|
+
registerAutoWorkerForSession: () => {},
|
|
389
391
|
lockBase: () => base,
|
|
390
392
|
buildLifecycle: () => ({
|
|
391
393
|
adoptSessionRoot: (sessionBase: string, originalBase?: string) => {
|
|
@@ -1587,6 +1589,61 @@ test("deep project setup: discuss-milestone question failure pauses instead of a
|
|
|
1587
1589
|
}
|
|
1588
1590
|
});
|
|
1589
1591
|
|
|
1592
|
+
test("verified task git closeout failure retries and continues auto-mode", async () => {
|
|
1593
|
+
const base = makeBase();
|
|
1594
|
+
try {
|
|
1595
|
+
execFileSync("git", ["init"], { cwd: base, stdio: "ignore" });
|
|
1596
|
+
execFileSync("git", ["config", "user.email", "test@example.com"], { cwd: base, stdio: "ignore" });
|
|
1597
|
+
execFileSync("git", ["config", "user.name", "Test User"], { cwd: base, stdio: "ignore" });
|
|
1598
|
+
const hookPath = join(base, ".git", "hooks", "pre-commit");
|
|
1599
|
+
writeFileSync(
|
|
1600
|
+
hookPath,
|
|
1601
|
+
[
|
|
1602
|
+
"#!/bin/sh",
|
|
1603
|
+
"count_file=.git/pre-commit-count",
|
|
1604
|
+
"count=0",
|
|
1605
|
+
"if [ -f \"$count_file\" ]; then count=$(cat \"$count_file\"); fi",
|
|
1606
|
+
"count=$((count + 1))",
|
|
1607
|
+
"printf \"%s\" \"$count\" > \"$count_file\"",
|
|
1608
|
+
"echo blocked by test hook >&2",
|
|
1609
|
+
"exit 1",
|
|
1610
|
+
].join("\n"),
|
|
1611
|
+
);
|
|
1612
|
+
chmodSync(hookPath, 0o755);
|
|
1613
|
+
writeFileSync(join(base, "work.txt"), "changed\n");
|
|
1614
|
+
|
|
1615
|
+
const s = new AutoSession();
|
|
1616
|
+
s.active = true;
|
|
1617
|
+
s.basePath = base;
|
|
1618
|
+
s.originalBasePath = base;
|
|
1619
|
+
s.currentUnit = { type: "execute-task", id: "M001/S01/T01", startedAt: Date.now() };
|
|
1620
|
+
|
|
1621
|
+
let pauseCalled = false;
|
|
1622
|
+
const notifications: Array<{ message: string; severity?: string }> = [];
|
|
1623
|
+
const result = await postUnitPostVerification({
|
|
1624
|
+
s,
|
|
1625
|
+
ctx: { ui: { notify: (message: string, severity?: string) => notifications.push({ message, severity }) } } as any,
|
|
1626
|
+
pi: {} as any,
|
|
1627
|
+
buildSnapshotOpts: () => ({}) as any,
|
|
1628
|
+
lockBase: () => base,
|
|
1629
|
+
stopAuto: async () => {},
|
|
1630
|
+
pauseAuto: async () => { pauseCalled = true; },
|
|
1631
|
+
updateProgressWidget: () => {},
|
|
1632
|
+
});
|
|
1633
|
+
|
|
1634
|
+
assert.equal(result, "continue");
|
|
1635
|
+
assert.equal(pauseCalled, false);
|
|
1636
|
+
assert.equal(s.lastGitActionStatus, "failed");
|
|
1637
|
+
assert.equal(readFileSync(join(base, ".git", "pre-commit-count"), "utf-8"), "3");
|
|
1638
|
+
assert.ok(
|
|
1639
|
+
notifications.some((entry) => entry.severity === "warning" && entry.message.includes("Git commit failed")),
|
|
1640
|
+
"verified task git closeout failure should warn instead of stopping auto-mode",
|
|
1641
|
+
);
|
|
1642
|
+
} finally {
|
|
1643
|
+
rmSync(base, { recursive: true, force: true });
|
|
1644
|
+
}
|
|
1645
|
+
});
|
|
1646
|
+
|
|
1590
1647
|
test("deep project setup: approval wait wins over deterministic write-gate placeholder", async () => {
|
|
1591
1648
|
const base = makeBase();
|
|
1592
1649
|
try {
|
|
@@ -118,3 +118,42 @@ describe("complete phase dispatch guard (#5683)", () => {
|
|
|
118
118
|
assert.equal(result?.reason, "All milestones complete.");
|
|
119
119
|
});
|
|
120
120
|
});
|
|
121
|
+
|
|
122
|
+
describe("complete milestone context recovery guard (#5831)", () => {
|
|
123
|
+
let base = "";
|
|
124
|
+
const executionEntryRule = DISPATCH_RULES.find(
|
|
125
|
+
(candidate) => candidate.name === "execution-entry phase (no context) → discuss-milestone",
|
|
126
|
+
);
|
|
127
|
+
const prePlanningRule = DISPATCH_RULES.find(
|
|
128
|
+
(candidate) => candidate.name === "pre-planning (no context) → discuss-milestone",
|
|
129
|
+
);
|
|
130
|
+
assert.ok(executionEntryRule, "execution-entry missing-context rule should exist");
|
|
131
|
+
assert.ok(prePlanningRule, "pre-planning missing-context rule should exist");
|
|
132
|
+
|
|
133
|
+
afterEach(() => {
|
|
134
|
+
if (base) rmSync(base, { recursive: true, force: true });
|
|
135
|
+
base = "";
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test("does not discuss a complete execution-entry milestone with no CONTEXT file", async () => {
|
|
139
|
+
base = makeBase();
|
|
140
|
+
const ctx = buildDispatchCtx(base);
|
|
141
|
+
ctx.state.registry = [{ id: "M001", title: "Milestone One", status: "complete" }];
|
|
142
|
+
ctx.state.phase = "completing-milestone";
|
|
143
|
+
|
|
144
|
+
const result = await executionEntryRule.match(ctx);
|
|
145
|
+
|
|
146
|
+
assert.equal(result, null);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("does not discuss a complete pre-planning milestone with no CONTEXT file", async () => {
|
|
150
|
+
base = makeBase();
|
|
151
|
+
const ctx = buildDispatchCtx(base);
|
|
152
|
+
ctx.state.registry = [{ id: "M001", title: "Milestone One", status: "complete" }];
|
|
153
|
+
ctx.state.phase = "pre-planning";
|
|
154
|
+
|
|
155
|
+
const result = await prePlanningRule.match(ctx);
|
|
156
|
+
|
|
157
|
+
assert.equal(result, null);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
@@ -47,6 +47,33 @@ test("dispatch guard blocks when prior milestone has incomplete slices", (t) =>
|
|
|
47
47
|
);
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
+
test("dispatch guard skips prior DB parked or deferred milestones without marker files", (t) => {
|
|
51
|
+
const repo = setupRepo();
|
|
52
|
+
t.after(() => teardownRepo(repo));
|
|
53
|
+
|
|
54
|
+
mkdirSync(join(repo, ".gsd", "milestones", "M001"), { recursive: true });
|
|
55
|
+
mkdirSync(join(repo, ".gsd", "milestones", "M002"), { recursive: true });
|
|
56
|
+
mkdirSync(join(repo, ".gsd", "milestones", "M003"), { recursive: true });
|
|
57
|
+
|
|
58
|
+
insertMilestone({ id: "M001", title: "Parked", status: "parked" });
|
|
59
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Incomplete", status: "pending", depends: [], sequence: 1 });
|
|
60
|
+
|
|
61
|
+
insertMilestone({ id: "M002", title: "Deferred", status: "deferred" });
|
|
62
|
+
insertSlice({ id: "S01", milestoneId: "M002", title: "Incomplete", status: "pending", depends: [], sequence: 1 });
|
|
63
|
+
|
|
64
|
+
insertMilestone({ id: "M003", title: "Current", status: "active" });
|
|
65
|
+
insertSlice({ id: "S01", milestoneId: "M003", title: "First", status: "pending", depends: [], sequence: 1 });
|
|
66
|
+
|
|
67
|
+
writeFileSync(join(repo, ".gsd", "milestones", "M001", "M001-ROADMAP.md"), "# M001\n");
|
|
68
|
+
writeFileSync(join(repo, ".gsd", "milestones", "M002", "M002-ROADMAP.md"), "# M002\n");
|
|
69
|
+
writeFileSync(join(repo, ".gsd", "milestones", "M003", "M003-ROADMAP.md"), "# M003\n");
|
|
70
|
+
|
|
71
|
+
assert.equal(
|
|
72
|
+
getPriorSliceCompletionBlocker(repo, "main", "plan-slice", "M003/S01"),
|
|
73
|
+
null,
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
|
|
50
77
|
test("dispatch guard blocks later slice in same milestone when earlier incomplete", (t) => {
|
|
51
78
|
const repo = setupRepo();
|
|
52
79
|
t.after(() => teardownRepo(repo));
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Tests for verification evidence cross-reference mismatch policy.
|
|
3
|
+
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
|
|
7
|
+
import { crossReferenceEvidence } from "../safety/evidence-cross-ref.ts";
|
|
8
|
+
import type { EvidenceEntry } from "../safety/evidence-collector.ts";
|
|
9
|
+
|
|
10
|
+
test("claims of passing verification become errors when recorded bash evidence failed", () => {
|
|
11
|
+
const mismatches = crossReferenceEvidence(
|
|
12
|
+
[{ command: "npm test", exitCode: 0, verdict: "passed" }],
|
|
13
|
+
[
|
|
14
|
+
{
|
|
15
|
+
kind: "bash",
|
|
16
|
+
toolCallId: "call-1",
|
|
17
|
+
command: "npm test",
|
|
18
|
+
exitCode: 1,
|
|
19
|
+
outputSnippet: "failed",
|
|
20
|
+
timestamp: Date.now(),
|
|
21
|
+
},
|
|
22
|
+
] as EvidenceEntry[],
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
assert.equal(mismatches.length, 1);
|
|
26
|
+
assert.equal(mismatches[0].severity, "error");
|
|
27
|
+
assert.match(mismatches[0].reason, /Claimed exitCode=0/);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("missing recorded bash evidence remains a warning", () => {
|
|
31
|
+
const mismatches = crossReferenceEvidence(
|
|
32
|
+
[{ command: "npm test", exitCode: 0, verdict: "passed" }],
|
|
33
|
+
[],
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
assert.equal(mismatches.length, 1);
|
|
37
|
+
assert.equal(mismatches[0].severity, "warning");
|
|
38
|
+
});
|
|
@@ -141,6 +141,14 @@ test("Feature 1: executive summary paragraph is rendered", () => {
|
|
|
141
141
|
assert.ok(html.includes("$2.50 spent"), "should contain cost");
|
|
142
142
|
});
|
|
143
143
|
|
|
144
|
+
test("report uses the shared GSD HTML shell", () => {
|
|
145
|
+
const html = generateHtmlReport(mockData(), mockOpts());
|
|
146
|
+
assert.ok(html.includes('<span class="logo">GSD</span>'), "should render shared shell logo");
|
|
147
|
+
assert.ok(html.includes('<span class="kind-chip">Report</span>'), "should render report kind chip");
|
|
148
|
+
assert.ok(html.includes('<nav class="toc" aria-label="Report sections">'), "should render shared shell TOC");
|
|
149
|
+
assert.ok(html.includes('<main>'), "should render content inside shared shell main");
|
|
150
|
+
});
|
|
151
|
+
|
|
144
152
|
test("Feature 1: executive summary includes budget context when set", () => {
|
|
145
153
|
const data = mockData({ health: { ...mockData().health, budgetCeiling: 10.00 } });
|
|
146
154
|
const html = generateHtmlReport(data, mockOpts());
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import {
|
|
15
15
|
saveDecisionToDb,
|
|
16
16
|
} from '../db-writer.ts';
|
|
17
|
+
import { getAllDecisionsFromMemories } from '../context-store.ts';
|
|
17
18
|
|
|
18
19
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
19
20
|
// Helpers
|
|
@@ -31,11 +32,14 @@ function cleanupDir(dir: string): void {
|
|
|
31
32
|
} catch { /* swallow */ }
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* Query all decisions. ADR-013 Stage 3 (PR #5755): decisions are written
|
|
37
|
+
* exclusively to memories; this helper returns the same Decision shape the
|
|
38
|
+
* previous SELECT * FROM decisions produced so the assertions below stay
|
|
39
|
+
* one-line lookups.
|
|
40
|
+
*/
|
|
35
41
|
function queryAllDecisions(): Array<Record<string, unknown>> {
|
|
36
|
-
|
|
37
|
-
if (!adapter) return [];
|
|
38
|
-
return adapter.prepare('SELECT * FROM decisions ORDER BY seq').all();
|
|
42
|
+
return getAllDecisionsFromMemories().map((d) => ({ ...d }));
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
isDbAvailable,
|
|
15
15
|
upsertRequirement,
|
|
16
16
|
getRequirementById,
|
|
17
|
-
getDecisionById,
|
|
18
17
|
_getAdapter,
|
|
19
18
|
insertArtifact,
|
|
20
19
|
} from '../gsd-db.ts';
|
|
@@ -26,6 +25,7 @@ import {
|
|
|
26
25
|
nextDecisionId,
|
|
27
26
|
nextRequirementId,
|
|
28
27
|
} from '../db-writer.ts';
|
|
28
|
+
import { getAllDecisionsFromMemories } from '../context-store.ts';
|
|
29
29
|
import type { Requirement } from '../types.ts';
|
|
30
30
|
|
|
31
31
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -73,12 +73,16 @@ describe('gsd-tools', () => {
|
|
|
73
73
|
|
|
74
74
|
assert.deepStrictEqual(result.id, 'D001', 'First decision should be D001');
|
|
75
75
|
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
assert.
|
|
80
|
-
|
|
81
|
-
assert.
|
|
76
|
+
// ADR-013 Stage 3: decisions land in memories, not the legacy decisions
|
|
77
|
+
// table. Verify the memory row carries the same content.
|
|
78
|
+
const memoryDecisions = getAllDecisionsFromMemories();
|
|
79
|
+
assert.equal(memoryDecisions.length, 1, 'one memory row exists after save');
|
|
80
|
+
const memDecision = memoryDecisions[0];
|
|
81
|
+
assert.ok(memDecision, 'memory decision exists after save');
|
|
82
|
+
assert.equal(memDecision.id, 'D001');
|
|
83
|
+
assert.deepStrictEqual(memDecision.scope, 'architecture', 'memory decision scope should match');
|
|
84
|
+
assert.deepStrictEqual(memDecision.decision, 'Use SQLite for metadata', 'memory decision text should match');
|
|
85
|
+
assert.deepStrictEqual(memDecision.choice, 'SQLite', 'memory decision choice should match');
|
|
82
86
|
|
|
83
87
|
// Verify DECISIONS.md was generated
|
|
84
88
|
const mdPath = path.join(tmpDir, '.gsd', 'DECISIONS.md');
|
|
@@ -34,6 +34,8 @@ test("guided project prompt renders compact interview and artifact guidance", as
|
|
|
34
34
|
assert.match(prompt, /depth_verification_project_confirm/);
|
|
35
35
|
assert.match(prompt, /artifact_type: "PROJECT"/);
|
|
36
36
|
assert.match(prompt, /omit `milestone_id`/);
|
|
37
|
+
assert.match(prompt, /do not write the projection directly/i);
|
|
38
|
+
assert.doesNotMatch(prompt, /then write `.gsd\/PROJECT\.md`/);
|
|
37
39
|
assert.match(prompt, /Do NOT use `artifact_type: "CONTEXT"` and do NOT pass `milestone_id: "PROJECT"`/);
|
|
38
40
|
assert.match(prompt, /\*\*Complexity:\*\* simple/);
|
|
39
41
|
assert.match(prompt, /\*\*Complexity:\*\* complex/);
|