gsd-pi 2.82.0-dev.c22380fc3 → 2.82.0-dev.e7a7f1ed5
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 +5 -4
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +10 -1
- package/dist/resources/extensions/claude-code-cli/partial-builder.js +2 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +1 -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 +11 -0
- package/dist/resources/extensions/gsd/auto/phases.js +81 -31
- 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-direct-dispatch.js +1 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +18 -17
- 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 +2 -2
- package/dist/resources/extensions/gsd/auto-recovery.js +71 -14
- package/dist/resources/extensions/gsd/auto-start.js +87 -14
- package/dist/resources/extensions/gsd/auto-verification.js +45 -26
- package/dist/resources/extensions/gsd/auto-worktree.js +176 -10
- package/dist/resources/extensions/gsd/auto.js +37 -5
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +31 -7
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +9 -8
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +4 -2
- package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
- 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 +37 -0
- package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +7 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +43 -5
- package/dist/resources/extensions/gsd/db/milestone-leases.js +24 -0
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
- package/dist/resources/extensions/gsd/dispatch-guard.js +2 -2
- package/dist/resources/extensions/gsd/doctor-git-checks.js +46 -1
- 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 +45 -3
- package/dist/resources/extensions/gsd/gsd-db.js +21 -6
- package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -3
- package/dist/resources/extensions/gsd/guided-flow.js +101 -116
- package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
- package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
- 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/queue-reorder-ui.js +30 -13
- 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 +11 -0
- 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/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-mcp.js +17 -1
- package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +33 -8
- 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 +13 -13
- 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/browse-directories/route.js +1 -1
- 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 +13 -13
- 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 +4 -4
- package/packages/mcp-server/src/workflow-tools.test.ts +1 -1
- package/packages/native/tsconfig.json +2 -1
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/google-gemini-cli.js +5 -0
- package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/google-gemini-cli.test.js +41 -0
- package/packages/pi-ai/dist/providers/google-gemini-cli.test.js.map +1 -0
- 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/src/providers/google-gemini-cli.test.ts +49 -0
- package/packages/pi-ai/src/providers/google-gemini-cli.ts +7 -0
- 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/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/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/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/modes/interactive/components/footer.ts +23 -7
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/terminal.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/terminal.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/terminal.test.js +103 -0
- package/packages/pi-tui/dist/__tests__/terminal.test.js.map +1 -0
- package/packages/pi-tui/dist/terminal.d.ts +2 -0
- package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal.js +12 -0
- package/packages/pi-tui/dist/terminal.js.map +1 -1
- package/packages/pi-tui/src/__tests__/terminal.test.ts +121 -0
- package/packages/pi-tui/src/terminal.ts +11 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/src/resources/GSD-WORKFLOW.md +10 -1
- package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +1 -1
- package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +9 -0
- package/src/resources/extensions/cmux/index.ts +6 -0
- package/src/resources/extensions/gsd/auto/contracts.ts +14 -6
- 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 +11 -0
- package/src/resources/extensions/gsd/auto/phases.ts +90 -38
- 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-direct-dispatch.ts +1 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +19 -17
- 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 +2 -2
- package/src/resources/extensions/gsd/auto-recovery.ts +74 -11
- package/src/resources/extensions/gsd/auto-start.ts +94 -12
- package/src/resources/extensions/gsd/auto-verification.ts +58 -36
- package/src/resources/extensions/gsd/auto-worktree.ts +193 -10
- package/src/resources/extensions/gsd/auto.ts +40 -5
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +42 -7
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +9 -8
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +4 -2
- package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
- 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 +40 -0
- package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +8 -3
- package/src/resources/extensions/gsd/crash-recovery.ts +44 -4
- package/src/resources/extensions/gsd/db/milestone-leases.ts +26 -0
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
- package/src/resources/extensions/gsd/dispatch-guard.ts +2 -2
- package/src/resources/extensions/gsd/doctor-git-checks.ts +45 -1
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
- package/src/resources/extensions/gsd/doctor-types.ts +1 -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 +51 -4
- package/src/resources/extensions/gsd/gsd-db.ts +21 -6
- package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -3
- package/src/resources/extensions/gsd/guided-flow.ts +134 -133
- package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
- package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
- 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/queue-reorder-ui.ts +31 -13
- 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 +13 -0
- 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 +56 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +80 -1
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +35 -7
- 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 +91 -6
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/auto-stop-notification.test.ts +20 -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/checkout-branch-stash-guard.test.ts +87 -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/crash-recovery-via-db.test.ts +86 -2
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -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 +66 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +65 -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/gsd-db.test.ts +11 -0
- 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-runtime.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +112 -1
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -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.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/prefs-wizard-coverage.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +37 -1
- package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +89 -2
- package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +2 -3
- 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-reconciliation-drift.test.ts +119 -23
- package/src/resources/extensions/gsd/tests/status-guards.test.ts +13 -1
- 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/validate-milestone-stuck-guard.test.ts +29 -2
- 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 +19 -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/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/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-mcp.ts +18 -1
- package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +41 -8
- 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/{Wop3A7KRGyR06H3rla_1- → 4dSwdrs__8NwCZggxP9KF}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{Wop3A7KRGyR06H3rla_1- → 4dSwdrs__8NwCZggxP9KF}/_ssgManifest.js +0 -0
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
checkpointDatabase,
|
|
38
38
|
refreshOpenDatabaseFromDisk,
|
|
39
39
|
tryCreateMemoriesFts,
|
|
40
|
+
_isLikelyWslDrvFsPathForTest,
|
|
40
41
|
} from '../gsd-db.ts';
|
|
41
42
|
import { _resetLogs, peekLogs, setStderrLoggingEnabled } from '../workflow-logger.ts';
|
|
42
43
|
|
|
@@ -345,6 +346,16 @@ describe('gsd-db', () => {
|
|
|
345
346
|
});
|
|
346
347
|
});
|
|
347
348
|
|
|
349
|
+
test('gsd-db: detects WSL DrvFs mount paths for conservative pragmas', () => {
|
|
350
|
+
withPlatform('linux', () => {
|
|
351
|
+
assert.equal(_isLikelyWslDrvFsPathForTest('/mnt/d/code/project/.gsd/gsd.db'), true);
|
|
352
|
+
assert.equal(_isLikelyWslDrvFsPathForTest('/tmp/gsd.db'), false);
|
|
353
|
+
});
|
|
354
|
+
withPlatform('darwin', () => {
|
|
355
|
+
assert.equal(_isLikelyWslDrvFsPathForTest('/mnt/d/code/project/.gsd/gsd.db'), false);
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
|
|
348
359
|
test('gsd-db: transaction rollback on error', () => {
|
|
349
360
|
openDatabase(':memory:');
|
|
350
361
|
|
|
@@ -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/);
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// GSD-2 — Guided workflow dispatch project-root tests.
|
|
2
|
+
// Verifies smart entry dispatch uses the explicit project root instead of cwd.
|
|
3
|
+
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
7
|
+
import { tmpdir } from "node:os";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
_dispatchWorkflowForTest,
|
|
12
|
+
resolveGuidedDispatchProjectRoot,
|
|
13
|
+
} from "../guided-flow.ts";
|
|
14
|
+
|
|
15
|
+
test("guided dispatch falls back to cwd only when no project root is supplied", () => {
|
|
16
|
+
const cwd = process.cwd();
|
|
17
|
+
assert.equal(resolveGuidedDispatchProjectRoot(), cwd);
|
|
18
|
+
assert.equal(resolveGuidedDispatchProjectRoot("/tmp/explicit-root"), "/tmp/explicit-root");
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("guided dispatch passes the explicit project root through model and compatibility checks", async () => {
|
|
22
|
+
const explicitRoot = mkdtempSync(join(tmpdir(), "gsd-guided-root-explicit-"));
|
|
23
|
+
const otherRoot = mkdtempSync(join(tmpdir(), "gsd-guided-root-cwd-"));
|
|
24
|
+
const workflowPath = join(explicitRoot, "GSD-WORKFLOW.md");
|
|
25
|
+
const originalWorkflowPath = process.env.GSD_WORKFLOW_PATH;
|
|
26
|
+
const originalCwd = process.cwd();
|
|
27
|
+
const seen = {
|
|
28
|
+
prefsRoot: "",
|
|
29
|
+
modelRoot: "",
|
|
30
|
+
compatibilityRoot: "",
|
|
31
|
+
sent: false,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const ctx = {
|
|
35
|
+
model: { provider: "local-provider" },
|
|
36
|
+
modelRegistry: {
|
|
37
|
+
getProviderAuthMode: () => "apiKey",
|
|
38
|
+
},
|
|
39
|
+
ui: {
|
|
40
|
+
notify: () => {},
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const pi = {
|
|
45
|
+
getActiveTools: () => ["gsd_plan_slice"],
|
|
46
|
+
setActiveTools: () => {},
|
|
47
|
+
sendMessage: () => {
|
|
48
|
+
seen.sent = true;
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
writeFileSync(workflowPath, "# Workflow\n", "utf-8");
|
|
54
|
+
process.env.GSD_WORKFLOW_PATH = workflowPath;
|
|
55
|
+
process.chdir(otherRoot);
|
|
56
|
+
|
|
57
|
+
await _dispatchWorkflowForTest(
|
|
58
|
+
pi as any,
|
|
59
|
+
"Plan the slice.",
|
|
60
|
+
"gsd-run",
|
|
61
|
+
ctx as any,
|
|
62
|
+
"plan-slice",
|
|
63
|
+
{
|
|
64
|
+
basePath: explicitRoot,
|
|
65
|
+
deps: {
|
|
66
|
+
loadPreferences: (projectRoot?: string) => {
|
|
67
|
+
seen.prefsRoot = projectRoot ?? "";
|
|
68
|
+
return { preferences: {} } as any;
|
|
69
|
+
},
|
|
70
|
+
selectModel: async (
|
|
71
|
+
_ctx: unknown,
|
|
72
|
+
_pi: unknown,
|
|
73
|
+
_unitType: string,
|
|
74
|
+
_unitId: string,
|
|
75
|
+
projectRoot: string,
|
|
76
|
+
) => {
|
|
77
|
+
seen.modelRoot = projectRoot;
|
|
78
|
+
return { routing: null, appliedModel: null };
|
|
79
|
+
},
|
|
80
|
+
getTransportSupportError: (
|
|
81
|
+
_provider: string | undefined,
|
|
82
|
+
_requiredTools: string[],
|
|
83
|
+
options?: { projectRoot?: string },
|
|
84
|
+
) => {
|
|
85
|
+
seen.compatibilityRoot = options?.projectRoot ?? "";
|
|
86
|
+
return null;
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
assert.equal(seen.prefsRoot, explicitRoot);
|
|
93
|
+
assert.equal(seen.modelRoot, explicitRoot);
|
|
94
|
+
assert.equal(seen.compatibilityRoot, explicitRoot);
|
|
95
|
+
assert.equal(seen.sent, true);
|
|
96
|
+
} finally {
|
|
97
|
+
process.chdir(originalCwd);
|
|
98
|
+
if (originalWorkflowPath === undefined) {
|
|
99
|
+
delete process.env.GSD_WORKFLOW_PATH;
|
|
100
|
+
} else {
|
|
101
|
+
process.env.GSD_WORKFLOW_PATH = originalWorkflowPath;
|
|
102
|
+
}
|
|
103
|
+
rmSync(explicitRoot, { recursive: true, force: true });
|
|
104
|
+
rmSync(otherRoot, { recursive: true, force: true });
|
|
105
|
+
}
|
|
106
|
+
});
|
|
@@ -21,6 +21,15 @@ import {
|
|
|
21
21
|
checkAutoStartAfterDiscuss,
|
|
22
22
|
} from "../guided-flow.ts";
|
|
23
23
|
|
|
24
|
+
function pendingInput(basePath: string, milestoneId: string) {
|
|
25
|
+
return {
|
|
26
|
+
basePath,
|
|
27
|
+
milestoneId,
|
|
28
|
+
ctx: { ui: { notify: () => undefined } } as any,
|
|
29
|
+
pi: { setActiveTools: () => undefined, getActiveTools: () => [] } as any,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
24
33
|
// ─── Tests ─────────────────────────────────────────────────────────────────
|
|
25
34
|
|
|
26
35
|
describe("#2985 Bug 3 — concurrent discuss sessions must be independent", () => {
|
|
@@ -34,13 +43,11 @@ describe("#2985 Bug 3 — concurrent discuss sessions must be independent", () =
|
|
|
34
43
|
const projectB = "/projects/beta";
|
|
35
44
|
|
|
36
45
|
setPendingAutoStart(projectA, {
|
|
37
|
-
|
|
38
|
-
milestoneId: "M001-aaa111",
|
|
46
|
+
...pendingInput(projectA, "M001-aaa111"),
|
|
39
47
|
});
|
|
40
48
|
|
|
41
49
|
setPendingAutoStart(projectB, {
|
|
42
|
-
|
|
43
|
-
milestoneId: "M002-bbb222",
|
|
50
|
+
...pendingInput(projectB, "M002-bbb222"),
|
|
44
51
|
});
|
|
45
52
|
|
|
46
53
|
// Both sessions should be retrievable
|
|
@@ -55,8 +62,8 @@ describe("#2985 Bug 3 — concurrent discuss sessions must be independent", () =
|
|
|
55
62
|
const projectA = "/projects/alpha";
|
|
56
63
|
const projectB = "/projects/beta";
|
|
57
64
|
|
|
58
|
-
setPendingAutoStart(projectA,
|
|
59
|
-
setPendingAutoStart(projectB,
|
|
65
|
+
setPendingAutoStart(projectA, pendingInput(projectA, "M001-aaa111"));
|
|
66
|
+
setPendingAutoStart(projectB, pendingInput(projectB, "M002-bbb222"));
|
|
60
67
|
|
|
61
68
|
// Clear only projectA
|
|
62
69
|
clearPendingAutoStart(projectA);
|
|
@@ -72,8 +79,8 @@ describe("#2985 Bug 4 — getDiscussionMilestoneId must be keyed by basePath", (
|
|
|
72
79
|
});
|
|
73
80
|
|
|
74
81
|
test("getDiscussionMilestoneId(basePath) returns correct milestone for each project", () => {
|
|
75
|
-
setPendingAutoStart("/proj/a",
|
|
76
|
-
setPendingAutoStart("/proj/b",
|
|
82
|
+
setPendingAutoStart("/proj/a", pendingInput("/proj/a", "M001"));
|
|
83
|
+
setPendingAutoStart("/proj/b", pendingInput("/proj/b", "M002"));
|
|
77
84
|
|
|
78
85
|
assert.equal(getDiscussionMilestoneId("/proj/a"), "M001");
|
|
79
86
|
assert.equal(getDiscussionMilestoneId("/proj/b"), "M002");
|
|
@@ -81,8 +88,8 @@ describe("#2985 Bug 4 — getDiscussionMilestoneId must be keyed by basePath", (
|
|
|
81
88
|
});
|
|
82
89
|
|
|
83
90
|
test("getDiscussionMilestoneId() without basePath returns null when multiple sessions exist", () => {
|
|
84
|
-
setPendingAutoStart("/proj/a",
|
|
85
|
-
setPendingAutoStart("/proj/b",
|
|
91
|
+
setPendingAutoStart("/proj/a", pendingInput("/proj/a", "M001"));
|
|
92
|
+
setPendingAutoStart("/proj/b", pendingInput("/proj/b", "M002"));
|
|
86
93
|
|
|
87
94
|
// Without a key, the function should not blindly return the first entry
|
|
88
95
|
const result = getDiscussionMilestoneId();
|
|
@@ -92,7 +99,7 @@ describe("#2985 Bug 4 — getDiscussionMilestoneId must be keyed by basePath", (
|
|
|
92
99
|
});
|
|
93
100
|
|
|
94
101
|
test("getDiscussionMilestoneId() without basePath returns the milestone when only one session", () => {
|
|
95
|
-
setPendingAutoStart("/proj/a",
|
|
102
|
+
setPendingAutoStart("/proj/a", pendingInput("/proj/a", "M001"));
|
|
96
103
|
|
|
97
104
|
// With only one session, backward compat — return it
|
|
98
105
|
const result = getDiscussionMilestoneId();
|
|
@@ -129,3 +136,44 @@ test("checkAutoStartAfterDiscuss ignores missing manifest for single-milestone d
|
|
|
129
136
|
rmSync(base, { recursive: true, force: true });
|
|
130
137
|
}
|
|
131
138
|
});
|
|
139
|
+
|
|
140
|
+
test("checkAutoStartAfterDiscuss(basePath) selects the matching pending entry when multiple sessions exist", () => {
|
|
141
|
+
const projectA = mkdtempSync(join(tmpdir(), "gsd-auto-start-project-a-"));
|
|
142
|
+
const projectB = mkdtempSync(join(tmpdir(), "gsd-auto-start-project-b-"));
|
|
143
|
+
|
|
144
|
+
function writeReadyArtifacts(base: string, milestoneId: string): void {
|
|
145
|
+
const gsdDir = join(base, ".gsd");
|
|
146
|
+
const milestoneDir = join(gsdDir, "milestones", milestoneId);
|
|
147
|
+
mkdirSync(milestoneDir, { recursive: true });
|
|
148
|
+
writeFileSync(join(gsdDir, "PROJECT.md"), `# Project\n\n| ${milestoneId} | Milestone | active |\n`);
|
|
149
|
+
writeFileSync(join(gsdDir, "STATE.md"), "# State\n");
|
|
150
|
+
writeFileSync(join(milestoneDir, `${milestoneId}-CONTEXT.md`), "# Context\n");
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
clearPendingAutoStart();
|
|
155
|
+
writeReadyArtifacts(projectA, "M001");
|
|
156
|
+
writeReadyArtifacts(projectB, "M002");
|
|
157
|
+
setPendingAutoStart(projectA, {
|
|
158
|
+
basePath: projectA,
|
|
159
|
+
milestoneId: "M001",
|
|
160
|
+
ctx: { ui: { notify: () => undefined } } as any,
|
|
161
|
+
pi: { setActiveTools: () => undefined, getActiveTools: () => [] } as any,
|
|
162
|
+
});
|
|
163
|
+
setPendingAutoStart(projectB, {
|
|
164
|
+
basePath: projectB,
|
|
165
|
+
milestoneId: "M002",
|
|
166
|
+
ctx: { ui: { notify: () => undefined } } as any,
|
|
167
|
+
pi: { setActiveTools: () => undefined, getActiveTools: () => [] } as any,
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
assert.equal(checkAutoStartAfterDiscuss(), false, "ambiguous pending sessions should not auto-start");
|
|
171
|
+
assert.equal(checkAutoStartAfterDiscuss(projectB), true, "explicit basePath should select projectB");
|
|
172
|
+
assert.equal(getDiscussionMilestoneId(projectA), "M001", "projectA should remain pending");
|
|
173
|
+
assert.equal(getDiscussionMilestoneId(projectB), null, "projectB should be cleared after start");
|
|
174
|
+
} finally {
|
|
175
|
+
clearPendingAutoStart();
|
|
176
|
+
rmSync(projectA, { recursive: true, force: true });
|
|
177
|
+
rmSync(projectB, { recursive: true, force: true });
|
|
178
|
+
}
|
|
179
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
|
|
9
|
+
test("guided milestone discussion callsites pass workingDirectory to loadPrompt", () => {
|
|
10
|
+
const source = readFileSync(join(__dirname, "..", "guided-flow.ts"), "utf-8");
|
|
11
|
+
const calls = [...source.matchAll(/loadPrompt\("guided-discuss-milestone",\s*\{([\s\S]*?)\}\)/g)];
|
|
12
|
+
|
|
13
|
+
assert.equal(calls.length, 6, "all guided-flow guided-discuss-milestone callsites should be covered");
|
|
14
|
+
for (const call of calls) {
|
|
15
|
+
assert.match(
|
|
16
|
+
call[1] ?? "",
|
|
17
|
+
/\bworkingDirectory:\s*basePath\b/,
|
|
18
|
+
"guided-discuss-milestone prompts need workingDirectory so template validation does not crash",
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// GSD-2 — Guided Unit Tool Contract tests.
|
|
2
|
+
// Verifies guided workflow turns use manifest tool policy without auto-mode state.
|
|
3
|
+
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
7
|
+
import { tmpdir } from "node:os";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
|
|
10
|
+
import { registerHooks } from "../bootstrap/register-hooks.ts";
|
|
11
|
+
import {
|
|
12
|
+
clearGuidedUnitContext,
|
|
13
|
+
getGuidedUnitContext,
|
|
14
|
+
setGuidedUnitContext,
|
|
15
|
+
} from "../guided-unit-context.ts";
|
|
16
|
+
|
|
17
|
+
test("guided Unit context applies Tool Contract policy when auto-mode has no current Unit", async () => {
|
|
18
|
+
const basePath = mkdtempSync(join(tmpdir(), "gsd-guided-tool-contract-"));
|
|
19
|
+
const handlers = new Map<string, Array<(event: any, ctx?: any) => Promise<any> | any>>();
|
|
20
|
+
const pi = {
|
|
21
|
+
on(event: string, handler: (event: any, ctx?: any) => Promise<any> | any) {
|
|
22
|
+
const existing = handlers.get(event) ?? [];
|
|
23
|
+
existing.push(handler);
|
|
24
|
+
handlers.set(event, existing);
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
clearGuidedUnitContext();
|
|
30
|
+
registerHooks(pi as any, []);
|
|
31
|
+
setGuidedUnitContext(basePath, "plan-slice");
|
|
32
|
+
|
|
33
|
+
let blockResult: { block?: boolean; reason?: string } | undefined;
|
|
34
|
+
for (const handler of handlers.get("tool_call") ?? []) {
|
|
35
|
+
const result = await handler({
|
|
36
|
+
toolName: "edit",
|
|
37
|
+
input: {
|
|
38
|
+
path: join(basePath, "src", "main.ts"),
|
|
39
|
+
},
|
|
40
|
+
}, { cwd: basePath });
|
|
41
|
+
if (result?.block) {
|
|
42
|
+
blockResult = result;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
assert.equal(blockResult?.block, true);
|
|
48
|
+
assert.match(blockResult?.reason ?? "", /plan-slice|ToolsPolicy|not allowed|blocked/i);
|
|
49
|
+
} finally {
|
|
50
|
+
clearGuidedUnitContext();
|
|
51
|
+
rmSync(basePath, { recursive: true, force: true });
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("guided Unit context can be cleared by project root", () => {
|
|
56
|
+
clearGuidedUnitContext();
|
|
57
|
+
setGuidedUnitContext("/project/a", "plan-slice");
|
|
58
|
+
setGuidedUnitContext("/project/b", "complete-slice");
|
|
59
|
+
|
|
60
|
+
clearGuidedUnitContext("/project/a");
|
|
61
|
+
|
|
62
|
+
assert.equal(getGuidedUnitContext("/project/a"), null);
|
|
63
|
+
assert.equal(getGuidedUnitContext("/project/b")?.unitType, "complete-slice");
|
|
64
|
+
clearGuidedUnitContext();
|
|
65
|
+
});
|
|
@@ -45,7 +45,7 @@ describe("headless milestone bootstrap — parity with interactive flow", () =>
|
|
|
45
45
|
|
|
46
46
|
// Match only the actual dispatchWorkflow call — comments in the body
|
|
47
47
|
// may mention "plan-milestone" as part of the fix rationale.
|
|
48
|
-
const dispatchMatches = [...fnBody.matchAll(/dispatchWorkflow\([
|
|
48
|
+
const dispatchMatches = [...fnBody.matchAll(/dispatchWorkflow\([\s\S]*?,\s*"([^"]+)"\s*,\s*\{\s*basePath\s*\}\s*\)/g)];
|
|
49
49
|
assert.strictEqual(
|
|
50
50
|
dispatchMatches.length,
|
|
51
51
|
1,
|
|
@@ -65,15 +65,15 @@ describe("headless milestone bootstrap — parity with interactive flow", () =>
|
|
|
65
65
|
/### Ready-phrase pre-condition \(NON-BYPASSABLE\)/.test(section),
|
|
66
66
|
"single-milestone ready-phrase section must be present",
|
|
67
67
|
);
|
|
68
|
-
// All four required
|
|
68
|
+
// All four required outcomes must appear as checkboxes, not a prose list.
|
|
69
69
|
for (const artifact of [
|
|
70
|
-
"
|
|
71
|
-
"
|
|
70
|
+
"PROJECT artifact",
|
|
71
|
+
"REQUIREMENTS artifact",
|
|
72
72
|
"`{{contextPath}}`",
|
|
73
73
|
"`gsd_plan_milestone`",
|
|
74
74
|
]) {
|
|
75
75
|
assert.ok(
|
|
76
|
-
new RegExp(`- \\[ \\] [
|
|
76
|
+
new RegExp(`- \\[ \\] [^\\n]*${artifact.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`).test(section),
|
|
77
77
|
`single-milestone pre-condition must include a checkbox for ${artifact}`,
|
|
78
78
|
);
|
|
79
79
|
}
|
|
@@ -103,8 +103,8 @@ describe("headless milestone bootstrap — parity with interactive flow", () =>
|
|
|
103
103
|
"multi-milestone ready-phrase section must be present",
|
|
104
104
|
);
|
|
105
105
|
for (const artifact of [
|
|
106
|
-
"
|
|
107
|
-
"
|
|
106
|
+
"PROJECT artifact",
|
|
107
|
+
"REQUIREMENTS artifact",
|
|
108
108
|
"`gsd_plan_milestone`",
|
|
109
109
|
"`.gsd/DISCUSSION-MANIFEST.json`",
|
|
110
110
|
]) {
|
|
@@ -92,6 +92,11 @@ test("resolveModelId: returns undefined for unknown model", () => {
|
|
|
92
92
|
assert.equal(match, undefined);
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
+
test("resolveModelId: returns undefined for missing model ID", () => {
|
|
96
|
+
const match = resolveModelId(undefined, AVAILABLE_MODELS, "anthropic");
|
|
97
|
+
assert.equal(match, undefined);
|
|
98
|
+
});
|
|
99
|
+
|
|
95
100
|
test("resolveModelId: returns undefined for unknown provider/model combo", () => {
|
|
96
101
|
const match = resolveModelId("fakeprovider/fake-model", AVAILABLE_MODELS, undefined);
|
|
97
102
|
assert.equal(match, undefined);
|
|
@@ -9,11 +9,11 @@ import { isInfrastructureError, INFRA_ERROR_CODES } from "../auto/infra-errors.j
|
|
|
9
9
|
test("INFRA_ERROR_CODES contains the expected codes", () => {
|
|
10
10
|
for (const code of [
|
|
11
11
|
"ENOSPC", "ENOMEM", "EROFS", "EDQUOT", "EMFILE", "ENFILE",
|
|
12
|
-
"EAGAIN", "ECONNREFUSED", "ENOTFOUND", "ENETUNREACH",
|
|
12
|
+
"EAGAIN", "ENOBUFS", "ECONNREFUSED", "ENOTFOUND", "ENETUNREACH",
|
|
13
13
|
]) {
|
|
14
14
|
assert.ok(INFRA_ERROR_CODES.has(code), `missing ${code}`);
|
|
15
15
|
}
|
|
16
|
-
assert.equal(INFRA_ERROR_CODES.size,
|
|
16
|
+
assert.equal(INFRA_ERROR_CODES.size, 11, "unexpected extra codes");
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
// ── isInfrastructureError: code property detection ───────────────────────────
|
|
@@ -5,6 +5,8 @@ import test, { describe } from "node:test";
|
|
|
5
5
|
import assert from "node:assert/strict";
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
+
INFRA_ERROR_CODES,
|
|
9
|
+
isInfrastructureError,
|
|
8
10
|
isTransientCooldownError,
|
|
9
11
|
getCooldownRetryAfterMs,
|
|
10
12
|
MAX_COOLDOWN_RETRIES,
|
|
@@ -13,6 +15,13 @@ import {
|
|
|
13
15
|
|
|
14
16
|
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
15
17
|
|
|
18
|
+
describe("infra error classification", () => {
|
|
19
|
+
test("ENOBUFS is treated as infrastructure exhaustion", () => {
|
|
20
|
+
assert.equal(INFRA_ERROR_CODES.has("ENOBUFS"), true);
|
|
21
|
+
assert.equal(isInfrastructureError(Object.assign(new Error("spawnSync git ENOBUFS"), { code: "ENOBUFS" })), "ENOBUFS");
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
16
25
|
describe("infra-errors cooldown constants", () => {
|
|
17
26
|
test("COOLDOWN_FALLBACK_WAIT_MS is a positive number greater than the 30s rate-limit backoff", () => {
|
|
18
27
|
assert.ok(typeof COOLDOWN_FALLBACK_WAIT_MS === "number");
|
|
@@ -446,6 +446,26 @@ node_modules/
|
|
|
446
446
|
const strandedIssues = detect.issues.filter(i => i.code === "stranded_lock_directory");
|
|
447
447
|
assert.deepStrictEqual(strandedIssues.length, 0, "live lock holder: stranded_lock_directory NOT detected");
|
|
448
448
|
});
|
|
449
|
+
|
|
450
|
+
test('stranded_lock_directory still reports when worker lookup fails', async () => {
|
|
451
|
+
const dir = createMinimalProject();
|
|
452
|
+
cleanups.push(dir);
|
|
453
|
+
|
|
454
|
+
const lockDir = join(dir, ".gsd.lock");
|
|
455
|
+
mkdirSync(lockDir, { recursive: true });
|
|
456
|
+
const { openDatabase, _getAdapter, closeDatabase } = await import("../../gsd-db.ts");
|
|
457
|
+
openDatabase(join(dir, ".gsd", "gsd.db"));
|
|
458
|
+
const db = _getAdapter()!;
|
|
459
|
+
db.exec("DROP TABLE workers");
|
|
460
|
+
|
|
461
|
+
try {
|
|
462
|
+
const detect = await runGSDDoctor(dir);
|
|
463
|
+
const strandedIssues = detect.issues.filter(i => i.code === "stranded_lock_directory");
|
|
464
|
+
assert.ok(strandedIssues.length > 0, "reports stranded lock directory even when active worker lookup fails");
|
|
465
|
+
} finally {
|
|
466
|
+
closeDatabase();
|
|
467
|
+
}
|
|
468
|
+
});
|
|
449
469
|
} else {
|
|
450
470
|
}
|
|
451
471
|
|
|
@@ -5,7 +5,7 @@ import assert from 'node:assert/strict';
|
|
|
5
5
|
import { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync, symlinkSync, readFileSync } from "node:fs";
|
|
6
6
|
import { join, dirname } from "node:path";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
8
|
-
import { execSync } from "node:child_process";
|
|
8
|
+
import { execFileSync, execSync } from "node:child_process";
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
11
|
inferCommitType,
|
|
@@ -371,6 +371,18 @@ describe('git-service', async () => {
|
|
|
371
371
|
return dir;
|
|
372
372
|
}
|
|
373
373
|
|
|
374
|
+
function gitRun(args: string[], cwd: string): string {
|
|
375
|
+
return execFileSync("git", args, {
|
|
376
|
+
cwd,
|
|
377
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
378
|
+
encoding: "utf-8",
|
|
379
|
+
env: {
|
|
380
|
+
...process.env,
|
|
381
|
+
GIT_ALLOW_PROTOCOL: "file",
|
|
382
|
+
},
|
|
383
|
+
}).trim();
|
|
384
|
+
}
|
|
385
|
+
|
|
374
386
|
// ─── GitServiceImpl: smart staging ─────────────────────────────────────
|
|
375
387
|
|
|
376
388
|
test('GitServiceImpl: smart staging', () => {
|
|
@@ -413,6 +425,96 @@ describe('git-service', async () => {
|
|
|
413
425
|
rmSync(repo, { recursive: true, force: true });
|
|
414
426
|
});
|
|
415
427
|
|
|
428
|
+
test('GitServiceImpl: task autoCommit skips keyFiles inside submodules', () => {
|
|
429
|
+
const repo = initTempRepo();
|
|
430
|
+
const subSrc = mkdtempSync(join(tmpdir(), "gsd-git-submodule-src-"));
|
|
431
|
+
|
|
432
|
+
try {
|
|
433
|
+
gitRun(["init", "-b", "main"], subSrc);
|
|
434
|
+
gitRun(["config", "user.name", "Pi Test"], subSrc);
|
|
435
|
+
gitRun(["config", "user.email", "pi@example.com"], subSrc);
|
|
436
|
+
createFile(subSrc, "tracked.txt", "initial\n");
|
|
437
|
+
gitRun(["add", "-A"], subSrc);
|
|
438
|
+
gitRun(["commit", "-m", "init submodule"], subSrc);
|
|
439
|
+
|
|
440
|
+
gitRun(["-c", "protocol.file.allow=always", "submodule", "add", `file://${subSrc}`, "sub"], repo);
|
|
441
|
+
gitRun(["commit", "-m", "add submodule"], repo);
|
|
442
|
+
|
|
443
|
+
createFile(repo, "sub/copied.txt", "copied from source\n");
|
|
444
|
+
createFile(repo, "src/feature.ts", "export const feature = true;\n");
|
|
445
|
+
createFile(repo, "src/unrelated.ts", "export const unrelated = true;\n");
|
|
446
|
+
|
|
447
|
+
const svc = new GitServiceImpl(repo);
|
|
448
|
+
const taskContext: TaskCommitContext = {
|
|
449
|
+
taskId: "S01/T01",
|
|
450
|
+
taskDisplayId: "T01",
|
|
451
|
+
taskTitle: "fix submodule staging",
|
|
452
|
+
milestoneId: "M001",
|
|
453
|
+
milestoneTitle: "Submodule auto commit",
|
|
454
|
+
sliceId: "S01",
|
|
455
|
+
sliceTitle: "Commit scoped files",
|
|
456
|
+
oneLiner: "Fixed auto commit when key files include submodule paths",
|
|
457
|
+
keyFiles: ["sub/copied.txt", "src/feature.ts"],
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
const result = svc.autoCommit("execute-task", "M001/S01/T01", [], taskContext);
|
|
461
|
+
|
|
462
|
+
assert.ok(result !== null, "autoCommit should commit non-submodule changes");
|
|
463
|
+
const committed = gitRun(["show", "--name-only", "--format=", "HEAD"], repo);
|
|
464
|
+
assert.ok(committed.includes("src/feature.ts"), "non-submodule keyFile is committed");
|
|
465
|
+
assert.ok(!committed.includes("sub/copied.txt"), "submodule inner keyFile is not pathspec-staged");
|
|
466
|
+
assert.ok(!committed.includes("src/unrelated.ts"), "scoped staging does not fall back to smartStage");
|
|
467
|
+
} finally {
|
|
468
|
+
rmSync(repo, { recursive: true, force: true });
|
|
469
|
+
rmSync(subSrc, { recursive: true, force: true });
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
test('GitServiceImpl: all keyFiles inside submodules falls back to smartStage', () => {
|
|
474
|
+
const repo = initTempRepo();
|
|
475
|
+
const subSrc = mkdtempSync(join(tmpdir(), "gsd-git-all-submodule-src-"));
|
|
476
|
+
|
|
477
|
+
try {
|
|
478
|
+
gitRun(["init", "-b", "main"], subSrc);
|
|
479
|
+
gitRun(["config", "user.name", "Pi Test"], subSrc);
|
|
480
|
+
gitRun(["config", "user.email", "pi@example.com"], subSrc);
|
|
481
|
+
createFile(subSrc, "tracked.txt", "initial\n");
|
|
482
|
+
gitRun(["add", "-A"], subSrc);
|
|
483
|
+
gitRun(["commit", "-m", "init submodule"], subSrc);
|
|
484
|
+
|
|
485
|
+
gitRun(["-c", "protocol.file.allow=always", "submodule", "add", `file://${subSrc}`, "sub"], repo);
|
|
486
|
+
gitRun(["commit", "-m", "add submodule"], repo);
|
|
487
|
+
|
|
488
|
+
createFile(repo, "sub/file1.txt", "inside submodule\n");
|
|
489
|
+
createFile(repo, "sub/file2.txt", "also inside\n");
|
|
490
|
+
createFile(repo, "src/real.ts", "export const real = true;\n");
|
|
491
|
+
|
|
492
|
+
const svc = new GitServiceImpl(repo);
|
|
493
|
+
const taskContext: TaskCommitContext = {
|
|
494
|
+
taskId: "S01/T02",
|
|
495
|
+
taskDisplayId: "T02",
|
|
496
|
+
taskTitle: "all keyFiles inside submodule",
|
|
497
|
+
milestoneId: "M001",
|
|
498
|
+
milestoneTitle: "Submodule auto commit",
|
|
499
|
+
sliceId: "S01",
|
|
500
|
+
sliceTitle: "Commit scoped files",
|
|
501
|
+
oneLiner: "Fell back when all key files are inside submodules",
|
|
502
|
+
keyFiles: ["sub", "sub/file1.txt", "sub/file2.txt"],
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
const result = svc.autoCommit("execute-task", "M001/S01/T02", [], taskContext);
|
|
506
|
+
|
|
507
|
+
assert.ok(result !== null, "autoCommit falls back to smartStage when all keyFiles are filtered");
|
|
508
|
+
const committed = gitRun(["show", "--name-only", "--format=", "HEAD"], repo);
|
|
509
|
+
assert.ok(!committed.includes("sub/file1.txt"), "submodule keyFile is not committed");
|
|
510
|
+
assert.ok(!committed.includes("sub/file2.txt"), "submodule keyFile is not committed");
|
|
511
|
+
assert.ok(committed.includes("src/real.ts"), "smartStage fallback commits other dirty files");
|
|
512
|
+
} finally {
|
|
513
|
+
rmSync(repo, { recursive: true, force: true });
|
|
514
|
+
rmSync(subSrc, { recursive: true, force: true });
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
|
|
416
518
|
// ─── GitServiceImpl: smart staging excludes tracked runtime files ──────
|
|
417
519
|
|
|
418
520
|
test('GitServiceImpl: smart staging excludes tracked runtime files', () => {
|
|
@@ -1066,6 +1168,15 @@ describe('git-service', async () => {
|
|
|
1066
1168
|
rmSync(repo, { recursive: true, force: true });
|
|
1067
1169
|
});
|
|
1068
1170
|
|
|
1171
|
+
test('Integration branch: rejects milestone branches', () => {
|
|
1172
|
+
const repo = initBranchTestRepo();
|
|
1173
|
+
|
|
1174
|
+
writeIntegrationBranch(repo, "M001", "milestone/M001");
|
|
1175
|
+
assert.deepStrictEqual(readIntegrationBranch(repo, "M001"), null, "milestone branches are not recorded as integration branch");
|
|
1176
|
+
|
|
1177
|
+
rmSync(repo, { recursive: true, force: true });
|
|
1178
|
+
});
|
|
1179
|
+
|
|
1069
1180
|
// ─── writeIntegrationBranch: still records legitimate branches ────────
|
|
1070
1181
|
|
|
1071
1182
|
test('Integration branch: records non-ephemeral gsd branches', () => {
|
package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts
CHANGED
|
@@ -195,6 +195,11 @@ describe("infrastructure error detection", () => {
|
|
|
195
195
|
assert.equal(isInfrastructureError(err), "EAGAIN");
|
|
196
196
|
});
|
|
197
197
|
|
|
198
|
+
test("ENOBUFS (no buffer space available) is detected", () => {
|
|
199
|
+
const err = Object.assign(new Error("spawnSync git ENOBUFS"), { code: "ENOBUFS" });
|
|
200
|
+
assert.equal(isInfrastructureError(err), "ENOBUFS");
|
|
201
|
+
});
|
|
202
|
+
|
|
198
203
|
test("SQLite WAL corruption is detected via message scan", () => {
|
|
199
204
|
const err = new Error("database disk image is malformed");
|
|
200
205
|
assert.equal(isInfrastructureError(err), "SQLITE_CORRUPT");
|
|
@@ -223,7 +228,7 @@ describe("infrastructure error detection", () => {
|
|
|
223
228
|
test("all INFRA_ERROR_CODES are covered", () => {
|
|
224
229
|
const expectedCodes = [
|
|
225
230
|
"ENOSPC", "ENOMEM", "EROFS", "EDQUOT", "EMFILE",
|
|
226
|
-
"ENFILE", "EAGAIN", "ECONNREFUSED", "ENOTFOUND", "ENETUNREACH",
|
|
231
|
+
"ENFILE", "EAGAIN", "ENOBUFS", "ECONNREFUSED", "ENOTFOUND", "ENETUNREACH",
|
|
227
232
|
];
|
|
228
233
|
for (const code of expectedCodes) {
|
|
229
234
|
assert.ok(INFRA_ERROR_CODES.has(code), `${code} should be in INFRA_ERROR_CODES`);
|