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
|
@@ -127,6 +127,61 @@ import { b } from './b';
|
|
|
127
127
|
assert.equal(imports.length, 2);
|
|
128
128
|
});
|
|
129
129
|
|
|
130
|
+
test("ignores import-looking string literals in test fixtures", () => {
|
|
131
|
+
const source = `
|
|
132
|
+
const rewritten = source.replace(
|
|
133
|
+
'import { normalizeZagrebBusinessDeadline } from "./cutoff";',
|
|
134
|
+
'const helper = true;'
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
import realThing from "./real-thing";
|
|
138
|
+
`;
|
|
139
|
+
const imports = extractRelativeImports(source);
|
|
140
|
+
assert.deepEqual(imports, [
|
|
141
|
+
{ importPath: "./real-thing", lineNum: 7 },
|
|
142
|
+
]);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test("ignores import-looking lines inside template literals", () => {
|
|
146
|
+
const source = [
|
|
147
|
+
"const fixture = `",
|
|
148
|
+
"import missingThing from './missing-thing';",
|
|
149
|
+
"`;",
|
|
150
|
+
"",
|
|
151
|
+
"import realThing from './real-thing';",
|
|
152
|
+
].join("\n");
|
|
153
|
+
const imports = extractRelativeImports(source);
|
|
154
|
+
assert.deepEqual(imports, [
|
|
155
|
+
{ importPath: "./real-thing", lineNum: 5 },
|
|
156
|
+
]);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test("ignores require() inside string literals", () => {
|
|
160
|
+
const source = [
|
|
161
|
+
'const fixture = "const x = require(\'./missing\');";',
|
|
162
|
+
"const otherFixture = 'const y = require(\"./also-missing\");';",
|
|
163
|
+
"const real = require('./real');",
|
|
164
|
+
].join("\n");
|
|
165
|
+
const imports = extractRelativeImports(source);
|
|
166
|
+
assert.deepEqual(imports, [
|
|
167
|
+
{ importPath: "./real", lineNum: 3 },
|
|
168
|
+
]);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
test("ignores require() inside template literals", () => {
|
|
172
|
+
const source = [
|
|
173
|
+
"const fixture = `",
|
|
174
|
+
"const x = require('./missing');",
|
|
175
|
+
"`;",
|
|
176
|
+
"",
|
|
177
|
+
"const real = require('./real');",
|
|
178
|
+
].join("\n");
|
|
179
|
+
const imports = extractRelativeImports(source);
|
|
180
|
+
assert.deepEqual(imports, [
|
|
181
|
+
{ importPath: "./real", lineNum: 5 },
|
|
182
|
+
]);
|
|
183
|
+
});
|
|
184
|
+
|
|
130
185
|
test("handles empty source", () => {
|
|
131
186
|
const imports = extractRelativeImports("");
|
|
132
187
|
assert.deepEqual(imports, []);
|
|
@@ -810,6 +865,37 @@ describe("runPostExecutionChecks", () => {
|
|
|
810
865
|
}
|
|
811
866
|
});
|
|
812
867
|
|
|
868
|
+
test("does not fail on import-looking strings in task key files", () => {
|
|
869
|
+
tempDir = join(tmpdir(), `post-exec-test-${Date.now()}`);
|
|
870
|
+
mkdirSync(tempDir, { recursive: true });
|
|
871
|
+
mkdirSync(join(tempDir, "tests"), { recursive: true });
|
|
872
|
+
writeFileSync(join(tempDir, "tests", "real-thing.ts"), "export default true;");
|
|
873
|
+
writeFileSync(
|
|
874
|
+
join(tempDir, "tests", "source-verifier.test.ts"),
|
|
875
|
+
`
|
|
876
|
+
const rewritten = source.replace(
|
|
877
|
+
'import { normalizeZagrebBusinessDeadline } from "./cutoff";',
|
|
878
|
+
'const helper = true;'
|
|
879
|
+
);
|
|
880
|
+
|
|
881
|
+
import realThing from "./real-thing";
|
|
882
|
+
assert.ok(realThing);
|
|
883
|
+
`
|
|
884
|
+
);
|
|
885
|
+
|
|
886
|
+
try {
|
|
887
|
+
const task = createTask({
|
|
888
|
+
id: "T03",
|
|
889
|
+
key_files: ["tests/source-verifier.test.ts"],
|
|
890
|
+
});
|
|
891
|
+
const result = runPostExecutionChecks(task, [], tempDir);
|
|
892
|
+
assert.equal(result.status, "pass");
|
|
893
|
+
assert.deepEqual(result.checks, []);
|
|
894
|
+
} finally {
|
|
895
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
896
|
+
}
|
|
897
|
+
});
|
|
898
|
+
|
|
813
899
|
test("returns fail status when blocking failure exists", () => {
|
|
814
900
|
tempDir = join(tmpdir(), `post-exec-test-${Date.now()}`);
|
|
815
901
|
mkdirSync(tempDir, { recursive: true });
|
|
@@ -11,7 +11,7 @@ const source = readFileSync(
|
|
|
11
11
|
|
|
12
12
|
test("postUnitPreVerification blocks on git action failure", () => {
|
|
13
13
|
const failureBlock = extractSourceRegion(source, 'if (gitResult.status === "failed")');
|
|
14
|
-
assert.ok(failureBlock.includes('ctx.ui.notify(failureMsg, "error")'));
|
|
14
|
+
assert.ok(failureBlock.includes('ctx.ui.notify(failureMsg, opts?.softFailure ? "warning" : "error")'));
|
|
15
15
|
assert.ok(failureBlock.includes("await pauseAuto(ctx, pi)"));
|
|
16
16
|
assert.ok(failureBlock.includes('return "dispatched"'));
|
|
17
17
|
assert.ok(!failureBlock.includes("git-action-failed-nonblocking"));
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* 2. File path consistency — files exist vs prior expected_output
|
|
10
10
|
* 3. Task ordering — detect impossible read-before-create
|
|
11
11
|
* 4. Interface contracts — contradictory function signatures
|
|
12
|
+
* 5. Verify commands — reject unsafe or non-runnable task verification
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
import { describe, test, mock } from "node:test";
|
|
@@ -22,6 +23,7 @@ import {
|
|
|
22
23
|
checkFilePathConsistency,
|
|
23
24
|
checkTaskOrdering,
|
|
24
25
|
checkInterfaceContracts,
|
|
26
|
+
checkVerificationCommands,
|
|
25
27
|
runPreExecutionChecks,
|
|
26
28
|
normalizeFilePath,
|
|
27
29
|
type PreExecutionResult,
|
|
@@ -812,6 +814,33 @@ function process(a: number): number
|
|
|
812
814
|
});
|
|
813
815
|
});
|
|
814
816
|
|
|
817
|
+
describe("checkVerificationCommands", () => {
|
|
818
|
+
test("accepts pipe-free pytest Verify command", () => {
|
|
819
|
+
const results = checkVerificationCommands([
|
|
820
|
+
createTask({
|
|
821
|
+
id: "T01",
|
|
822
|
+
verify: "python3 -m pytest tests/ -q --tb=short",
|
|
823
|
+
}),
|
|
824
|
+
]);
|
|
825
|
+
|
|
826
|
+
assert.deepEqual(results, []);
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
test("rejects piped pytest Verify command", () => {
|
|
830
|
+
const results = checkVerificationCommands([
|
|
831
|
+
createTask({
|
|
832
|
+
id: "T01",
|
|
833
|
+
verify: "python3 -m pytest tests/ -q --tb=short 2>&1 | tail -5",
|
|
834
|
+
}),
|
|
835
|
+
]);
|
|
836
|
+
|
|
837
|
+
assert.equal(results.length, 1);
|
|
838
|
+
assert.equal(results[0]?.category, "tool");
|
|
839
|
+
assert.equal(results[0]?.blocking, true);
|
|
840
|
+
assert.match(results[0]?.message ?? "", /shell control syntax/);
|
|
841
|
+
});
|
|
842
|
+
});
|
|
843
|
+
|
|
815
844
|
// ─── runPreExecutionChecks Integration Tests ─────────────────────────────────
|
|
816
845
|
|
|
817
846
|
describe("runPreExecutionChecks", () => {
|
|
@@ -847,6 +876,30 @@ describe("runPreExecutionChecks", () => {
|
|
|
847
876
|
}
|
|
848
877
|
});
|
|
849
878
|
|
|
879
|
+
test("returns fail status for unsafe Verify command before execution", async () => {
|
|
880
|
+
tempDir = join(tmpdir(), `pre-exec-test-${Date.now()}`);
|
|
881
|
+
mkdirSync(tempDir, { recursive: true });
|
|
882
|
+
|
|
883
|
+
try {
|
|
884
|
+
const tasks = [
|
|
885
|
+
createTask({
|
|
886
|
+
id: "T01",
|
|
887
|
+
verify: "python3 -m pytest tests/ -q --tb=short 2>&1 | tail -5",
|
|
888
|
+
}),
|
|
889
|
+
];
|
|
890
|
+
|
|
891
|
+
const result = await runPreExecutionChecks(tasks, tempDir);
|
|
892
|
+
|
|
893
|
+
assert.equal(result.status, "fail");
|
|
894
|
+
assert.equal(result.checks.length, 1);
|
|
895
|
+
assert.equal(result.checks[0]?.category, "tool");
|
|
896
|
+
assert.equal(result.checks[0]?.blocking, true);
|
|
897
|
+
assert.match(result.checks[0]?.message ?? "", /Unsafe or non-runnable Verify command/);
|
|
898
|
+
} finally {
|
|
899
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
900
|
+
}
|
|
901
|
+
});
|
|
902
|
+
|
|
850
903
|
test("returns fail status when blocking failure exists", async () => {
|
|
851
904
|
tempDir = join(tmpdir(), `pre-exec-test-${Date.now()}`);
|
|
852
905
|
mkdirSync(tempDir, { recursive: true });
|
|
@@ -141,3 +141,62 @@ test("category summaries expose the wizard menu surface for configured prefs", (
|
|
|
141
141
|
assert.match(summaries.integrations, /remote: C123/);
|
|
142
142
|
assert.match(summaries.verification, /1 cmd/);
|
|
143
143
|
});
|
|
144
|
+
|
|
145
|
+
test("models wizard offers discovered models for enabled providers", async () => {
|
|
146
|
+
const dir = mkdtempSync(join(tmpdir(), "gsd-prefs-wizard-"));
|
|
147
|
+
const prefsPath = join(dir, "PREFERENCES.md");
|
|
148
|
+
const choices = [
|
|
149
|
+
"Models",
|
|
150
|
+
"local (2 models)",
|
|
151
|
+
"discovered-model",
|
|
152
|
+
"(keep current)",
|
|
153
|
+
"(keep current)",
|
|
154
|
+
"(keep current)",
|
|
155
|
+
"(keep current)",
|
|
156
|
+
"(keep current)",
|
|
157
|
+
"(keep current)",
|
|
158
|
+
"(keep current)",
|
|
159
|
+
];
|
|
160
|
+
const ctx = {
|
|
161
|
+
modelRegistry: {
|
|
162
|
+
getAvailable: () => [{ provider: "local", id: "baseline-model" }],
|
|
163
|
+
getAllWithDiscovered: () => [
|
|
164
|
+
{ provider: "local", id: "baseline-model" },
|
|
165
|
+
{ provider: "local", id: "discovered-model" },
|
|
166
|
+
{ provider: "disabled", id: "hidden-model" },
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
ui: {
|
|
170
|
+
notify() {},
|
|
171
|
+
select: async (label: string, options: string[]) => {
|
|
172
|
+
const choice = choices.shift();
|
|
173
|
+
if (!choice && label === "GSD Preferences") return "── Save & Exit ──";
|
|
174
|
+
if (!choice && options.includes("(keep current)")) return "(keep current)";
|
|
175
|
+
if (!choice && options.includes("Done")) return "Done";
|
|
176
|
+
assert.ok(choice, `Unexpected prompt: ${label}`);
|
|
177
|
+
if (choice === "Models") {
|
|
178
|
+
const modelsOption = options.find((option) => option.startsWith("Models"));
|
|
179
|
+
assert.ok(modelsOption, "Expected Models category option");
|
|
180
|
+
return modelsOption;
|
|
181
|
+
}
|
|
182
|
+
assert.ok(options.includes(choice), `"${choice}" must be offered by "${label}"`);
|
|
183
|
+
assert.ok(!options.includes("hidden-model"), "models from disabled providers must not be offered");
|
|
184
|
+
return choice;
|
|
185
|
+
},
|
|
186
|
+
input: async () => null,
|
|
187
|
+
},
|
|
188
|
+
waitForIdle: async () => {},
|
|
189
|
+
reload: async () => {},
|
|
190
|
+
} as any;
|
|
191
|
+
|
|
192
|
+
try {
|
|
193
|
+
await handlePrefsWizard(ctx, "project", {}, { pathOverride: prefsPath });
|
|
194
|
+
|
|
195
|
+
assert.equal(choices.length, 0, "Expected all queued wizard choices to be consumed");
|
|
196
|
+
const saved = readFileSync(prefsPath, "utf-8");
|
|
197
|
+
assert.match(saved, /research:\s+local\/discovered-model/);
|
|
198
|
+
assert.doesNotMatch(saved, /hidden-model/);
|
|
199
|
+
} finally {
|
|
200
|
+
rmSync(dir, { recursive: true, force: true });
|
|
201
|
+
}
|
|
202
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
|
|
4
|
+
import { loadPrompt } from "../prompt-loader.ts";
|
|
5
|
+
|
|
6
|
+
test("loadPrompt reports missing template variables with balanced braces", () => {
|
|
7
|
+
assert.throws(
|
|
8
|
+
() => loadPrompt("guided-discuss-milestone", {
|
|
9
|
+
milestoneId: "M001",
|
|
10
|
+
milestoneTitle: "Missing working directory",
|
|
11
|
+
structuredQuestionsAvailable: "false",
|
|
12
|
+
fastPathInstruction: "",
|
|
13
|
+
inlinedTemplates: "context template",
|
|
14
|
+
commitInstruction: "Do not commit during this test.",
|
|
15
|
+
}),
|
|
16
|
+
(error) => {
|
|
17
|
+
assert.ok(error instanceof Error);
|
|
18
|
+
assert.match(error.message, /template declares \{\{workingDirectory\}\} but no value was provided/);
|
|
19
|
+
assert.doesNotMatch(error.message, /\{\{workingDirectory\}\}\}/);
|
|
20
|
+
return true;
|
|
21
|
+
},
|
|
22
|
+
);
|
|
23
|
+
});
|
|
@@ -10,7 +10,12 @@ import assert from "node:assert/strict";
|
|
|
10
10
|
import { classifyError, isTransient, isTransientNetworkError } from "../error-classifier.ts";
|
|
11
11
|
import { pauseAutoForProviderError } from "../provider-error-pause.ts";
|
|
12
12
|
import { resumeAutoAfterProviderDelay } from "../bootstrap/provider-error-resume.ts";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
MAX_TRANSIENT_AUTO_RESUMES,
|
|
15
|
+
isTerminalDeletedWorktreeProviderError,
|
|
16
|
+
resetTransientRetryState,
|
|
17
|
+
shouldDeferTransientErrorToCoreRetry,
|
|
18
|
+
} from "../bootstrap/agent-end-recovery.ts";
|
|
14
19
|
import { _buildCancelledUnitStopReason } from "../auto/phases.ts";
|
|
15
20
|
import { getNextFallbackModel } from "../preferences.ts";
|
|
16
21
|
// Zero-import module — imported by path rather than through the package
|
|
@@ -399,6 +404,25 @@ test("pauseAutoForProviderError falls back to indefinite pause when not rate lim
|
|
|
399
404
|
]);
|
|
400
405
|
});
|
|
401
406
|
|
|
407
|
+
test("isTerminalDeletedWorktreeProviderError matches removed auto-worktree paths only", () => {
|
|
408
|
+
assert.equal(
|
|
409
|
+
isTerminalDeletedWorktreeProviderError('Path "/Users/dev/.gsd/projects/abc123/worktrees/M005" does not exist'),
|
|
410
|
+
true,
|
|
411
|
+
);
|
|
412
|
+
assert.equal(
|
|
413
|
+
isTerminalDeletedWorktreeProviderError('Path "/Users/dev/app/.gsd/worktrees/M005" does not exist'),
|
|
414
|
+
true,
|
|
415
|
+
);
|
|
416
|
+
assert.equal(
|
|
417
|
+
isTerminalDeletedWorktreeProviderError('Path "/Users/dev/app/src/file.ts" does not exist'),
|
|
418
|
+
false,
|
|
419
|
+
);
|
|
420
|
+
assert.equal(
|
|
421
|
+
isTerminalDeletedWorktreeProviderError('Path "/Users/dev/.gsd/projects/abc123/worktrees/M005" failed with EACCES'),
|
|
422
|
+
false,
|
|
423
|
+
);
|
|
424
|
+
});
|
|
425
|
+
|
|
402
426
|
// ── resumeAutoAfterProviderDelay ────────────────────────────────────────────
|
|
403
427
|
|
|
404
428
|
test("resumeAutoAfterProviderDelay restarts paused auto-mode from the recorded base path", async () => {
|
|
@@ -659,3 +683,15 @@ test("agent-session retryable error regex matches server_error (underscore)", ()
|
|
|
659
683
|
// "temporarily backed off" must NOT be matched (intentional exclusion #3429)
|
|
660
684
|
assert.ok(!RETRYABLE_ERROR_RE.test("temporarily backed off"));
|
|
661
685
|
});
|
|
686
|
+
|
|
687
|
+
test("exhausted retry errors are not deferred back to core retry handling", () => {
|
|
688
|
+
const cls = classifyError("Retry failed after 3 attempts: 500 empty_stream: upstream stream closed before first payload");
|
|
689
|
+
assert.equal(cls.kind, "server");
|
|
690
|
+
assert.equal(
|
|
691
|
+
shouldDeferTransientErrorToCoreRetry(
|
|
692
|
+
cls,
|
|
693
|
+
"Retry failed after 3 attempts: 500 empty_stream: upstream stream closed before first payload",
|
|
694
|
+
),
|
|
695
|
+
false,
|
|
696
|
+
);
|
|
697
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { describe, test } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
|
|
4
|
+
import { showQueueReorder } from "../queue-reorder-ui.ts";
|
|
5
|
+
|
|
6
|
+
const fakeTheme = {
|
|
7
|
+
fg: (_color: string, text: string) => text,
|
|
8
|
+
bold: (text: string) => text,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
describe("queue-reorder-ui", () => {
|
|
12
|
+
test("keeps cursor visible while scrolling long queue with arrow keys (#4656)", async () => {
|
|
13
|
+
const originalRowsDescriptor = Object.getOwnPropertyDescriptor(process.stdout, "rows");
|
|
14
|
+
Object.defineProperty(process.stdout, "rows", { value: 20, configurable: true });
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const pending = Array.from({ length: 20 }, (_, idx) => ({
|
|
18
|
+
id: `M${String(idx + 1).padStart(3, "0")}`,
|
|
19
|
+
title: `Milestone ${idx + 1}`,
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
let resolved: { order: string[]; depsToRemove: Array<{ milestone: string; dep: string }> } | null = null;
|
|
23
|
+
let lastRender: string[] = [];
|
|
24
|
+
|
|
25
|
+
const ctx = {
|
|
26
|
+
hasUI: true,
|
|
27
|
+
ui: {
|
|
28
|
+
custom: async (factory: any) => {
|
|
29
|
+
const component = factory({ requestRender() {} }, fakeTheme, null, (value: any) => {
|
|
30
|
+
resolved = value;
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
for (let i = 0; i < 15; i++) component.handleInput("\u001b[B");
|
|
34
|
+
lastRender = component.render(100);
|
|
35
|
+
component.handleInput("\r");
|
|
36
|
+
return resolved;
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
} as any;
|
|
40
|
+
|
|
41
|
+
await showQueueReorder(ctx, [], pending);
|
|
42
|
+
|
|
43
|
+
const joined = lastRender.join("\n");
|
|
44
|
+
assert.ok(joined.includes("M016"), "selected item should stay visible after scrolling");
|
|
45
|
+
assert.ok(lastRender.length <= 16, `overlay should fit terminal max-height, got ${lastRender.length}`);
|
|
46
|
+
} finally {
|
|
47
|
+
if (originalRowsDescriptor) {
|
|
48
|
+
Object.defineProperty(process.stdout, "rows", originalRowsDescriptor);
|
|
49
|
+
} else {
|
|
50
|
+
delete (process.stdout as { rows?: number }).rows;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Regression
|
|
3
|
-
* block completion when VALIDATION
|
|
2
|
+
* Regression tests for non-passing VALIDATION verdicts: completing-milestone
|
|
3
|
+
* dispatch must block completion when VALIDATION needs remediation or attention.
|
|
4
4
|
*
|
|
5
5
|
* Without this guard, needs-remediation + allSlicesDone causes a loop:
|
|
6
6
|
* complete-milestone dispatched → agent refuses (correct) → no SUMMARY
|
|
@@ -66,6 +66,93 @@ test("completing-milestone blocks when VALIDATION verdict is needs-remediation (
|
|
|
66
66
|
}
|
|
67
67
|
});
|
|
68
68
|
|
|
69
|
+
test("completing-milestone blocks when VALIDATION verdict is needs-attention (#5747)", async () => {
|
|
70
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-attention-"));
|
|
71
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
writeFileSync(
|
|
75
|
+
join(base, ".gsd", "milestones", "M001", "M001-VALIDATION.md"),
|
|
76
|
+
[
|
|
77
|
+
"---",
|
|
78
|
+
"verdict: needs-attention",
|
|
79
|
+
"remediation_round: 0",
|
|
80
|
+
"---",
|
|
81
|
+
"",
|
|
82
|
+
"# Validation Report",
|
|
83
|
+
"",
|
|
84
|
+
"Acceptance proof is incomplete and needs human attention.",
|
|
85
|
+
].join("\n"),
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const ctx = {
|
|
89
|
+
mid: "M001",
|
|
90
|
+
midTitle: "Test Milestone",
|
|
91
|
+
basePath: base,
|
|
92
|
+
state: { phase: "completing-milestone" } as any,
|
|
93
|
+
prefs: {} as any,
|
|
94
|
+
session: undefined,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const result = await completingRule!.match(ctx);
|
|
98
|
+
|
|
99
|
+
assert.ok(result !== null, "rule should match");
|
|
100
|
+
assert.equal(result!.action, "stop", "should return stop action");
|
|
101
|
+
if (result!.action === "stop") {
|
|
102
|
+
assert.equal(result!.level, "warning", "should be warning level (pausable)");
|
|
103
|
+
assert.ok(
|
|
104
|
+
result!.reason.includes("needs-attention"),
|
|
105
|
+
"reason should mention needs-attention",
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
} finally {
|
|
109
|
+
rmSync(base, { recursive: true, force: true });
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("completing-milestone blocks when VALIDATION verdict is fail (#5920)", async () => {
|
|
114
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-fail-verdict-"));
|
|
115
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
|
|
116
|
+
|
|
117
|
+
try {
|
|
118
|
+
writeFileSync(
|
|
119
|
+
join(base, ".gsd", "milestones", "M001", "M001-VALIDATION.md"),
|
|
120
|
+
[
|
|
121
|
+
"---",
|
|
122
|
+
"verdict: fail",
|
|
123
|
+
"---",
|
|
124
|
+
"",
|
|
125
|
+
"# Validation Report",
|
|
126
|
+
"",
|
|
127
|
+
"Blocking failures remain unresolved.",
|
|
128
|
+
].join("\n"),
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
const ctx = {
|
|
132
|
+
mid: "M001",
|
|
133
|
+
midTitle: "Test Milestone",
|
|
134
|
+
basePath: base,
|
|
135
|
+
state: { phase: "completing-milestone" } as any,
|
|
136
|
+
prefs: {} as any,
|
|
137
|
+
session: undefined,
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const result = await completingRule!.match(ctx);
|
|
141
|
+
|
|
142
|
+
assert.ok(result !== null, "rule should match");
|
|
143
|
+
assert.equal(result!.action, "stop", "should return stop action");
|
|
144
|
+
if (result!.action === "stop") {
|
|
145
|
+
assert.equal(result!.level, "warning", "should be warning level (pausable)");
|
|
146
|
+
assert.ok(
|
|
147
|
+
result!.reason.includes('verdict is "fail"'),
|
|
148
|
+
"reason should mention fail verdict",
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
} finally {
|
|
152
|
+
rmSync(base, { recursive: true, force: true });
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
69
156
|
test("completing-milestone proceeds normally when VALIDATION verdict is pass (#2675 guard)", async () => {
|
|
70
157
|
const base = mkdtempSync(join(tmpdir(), "gsd-remediation-"));
|
|
71
158
|
mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
|
|
@@ -36,7 +36,7 @@ function makeUatProject(): string {
|
|
|
36
36
|
return base;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
test("run-uat dispatch
|
|
39
|
+
test("run-uat dispatch skips after three attempts without a verdict", async () => {
|
|
40
40
|
const basePath = makeUatProject();
|
|
41
41
|
const rule = DISPATCH_RULES.find((r) => r.name === "run-uat (post-completion)");
|
|
42
42
|
assert.ok(rule, "run-uat dispatch rule is registered");
|
|
@@ -58,8 +58,7 @@ test("run-uat dispatch stops after three attempts without a verdict", async () =
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
const capped = await rule.match(ctx as any);
|
|
61
|
-
assert.equal(capped?.action, "
|
|
62
|
-
assert.match(capped?.reason ?? "", /dispatched 3 times/);
|
|
61
|
+
assert.equal(capped?.action, "skip");
|
|
63
62
|
assert.equal(getUatCount(basePath, "M001", "S01"), 4);
|
|
64
63
|
} finally {
|
|
65
64
|
rmSync(basePath, { recursive: true, force: true });
|
|
@@ -5,6 +5,7 @@ import test from "node:test";
|
|
|
5
5
|
import assert from "node:assert/strict";
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
+
_hasEmptyAgentEndContent,
|
|
8
9
|
_handleSessionSwitchAgentEnd,
|
|
9
10
|
isBareClaudeCodeStreamAbortPlaceholder,
|
|
10
11
|
isClaudeCodeSessionSwitchAbortMessage,
|
|
@@ -188,6 +189,15 @@ test("empty-content aborted during session-switch is silently ignored", () => {
|
|
|
188
189
|
assert.equal(cancelledWith, null);
|
|
189
190
|
});
|
|
190
191
|
|
|
192
|
+
test("missing agent_end content is classified as empty abort content", () => {
|
|
193
|
+
// Providers may omit content entirely for a late aborted agent_end. That is
|
|
194
|
+
// equivalent to empty content and must not pause/cancel the next unit.
|
|
195
|
+
assert.equal(_hasEmptyAgentEndContent(undefined), true);
|
|
196
|
+
assert.equal(_hasEmptyAgentEndContent(null), true);
|
|
197
|
+
assert.equal(_hasEmptyAgentEndContent([]), true);
|
|
198
|
+
assert.equal(_hasEmptyAgentEndContent([{ type: "text", text: "partial" }]), false);
|
|
199
|
+
});
|
|
200
|
+
|
|
191
201
|
test("completed assistant content with aborted stopReason during session-switch is ignored", () => {
|
|
192
202
|
// newSession() can abort the just-finished provider stream while the last
|
|
193
203
|
// assistant message still carries the completed unit summary. That is a
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// GSD-2 — Smart entry routing behavior tests.
|
|
2
|
+
// Verifies guided wizard choices resolve to the correct execution path.
|
|
3
|
+
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
resolveActiveTaskChoiceRoute,
|
|
9
|
+
resolveGuidedExecuteLaunchMode,
|
|
10
|
+
type ActiveTaskChoice,
|
|
11
|
+
type ActiveTaskRoute,
|
|
12
|
+
type SmartEntryIsolationMode,
|
|
13
|
+
} from "../smart-entry-routing.ts";
|
|
14
|
+
|
|
15
|
+
test("guided execute route enters auto step bootstrap only for worktree isolation", () => {
|
|
16
|
+
const cases: Array<{
|
|
17
|
+
isolationMode: SmartEntryIsolationMode;
|
|
18
|
+
expectedRoute: ActiveTaskRoute;
|
|
19
|
+
}> = [
|
|
20
|
+
{
|
|
21
|
+
isolationMode: "worktree",
|
|
22
|
+
expectedRoute: {
|
|
23
|
+
kind: "auto-bootstrap",
|
|
24
|
+
verboseMode: false,
|
|
25
|
+
options: {
|
|
26
|
+
step: true,
|
|
27
|
+
milestoneLock: "M001",
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
isolationMode: "none",
|
|
33
|
+
expectedRoute: {
|
|
34
|
+
kind: "guided-dispatch",
|
|
35
|
+
unitType: "execute-task",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
isolationMode: "branch",
|
|
40
|
+
expectedRoute: {
|
|
41
|
+
kind: "guided-dispatch",
|
|
42
|
+
unitType: "execute-task",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
for (const testCase of cases) {
|
|
48
|
+
assert.deepEqual(
|
|
49
|
+
resolveActiveTaskChoiceRoute({
|
|
50
|
+
choice: "execute",
|
|
51
|
+
isolationMode: testCase.isolationMode,
|
|
52
|
+
milestoneId: "M001",
|
|
53
|
+
}),
|
|
54
|
+
testCase.expectedRoute,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("active task smart entry choices resolve to explicit routes", () => {
|
|
60
|
+
const cases: Array<{
|
|
61
|
+
choice: ActiveTaskChoice;
|
|
62
|
+
expectedRoute: ActiveTaskRoute;
|
|
63
|
+
}> = [
|
|
64
|
+
{
|
|
65
|
+
choice: "auto",
|
|
66
|
+
expectedRoute: {
|
|
67
|
+
kind: "auto-bootstrap",
|
|
68
|
+
verboseMode: false,
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
choice: "status",
|
|
73
|
+
expectedRoute: {
|
|
74
|
+
kind: "status",
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
choice: "milestone_actions",
|
|
79
|
+
expectedRoute: {
|
|
80
|
+
kind: "milestone-actions",
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
for (const testCase of cases) {
|
|
86
|
+
assert.deepEqual(
|
|
87
|
+
resolveActiveTaskChoiceRoute({
|
|
88
|
+
choice: testCase.choice,
|
|
89
|
+
isolationMode: "worktree",
|
|
90
|
+
milestoneId: "M001",
|
|
91
|
+
}),
|
|
92
|
+
testCase.expectedRoute,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("active task route rejects invalid choices from untyped callers", () => {
|
|
98
|
+
assert.throws(
|
|
99
|
+
() =>
|
|
100
|
+
resolveActiveTaskChoiceRoute({
|
|
101
|
+
choice: "not_yet" as ActiveTaskChoice,
|
|
102
|
+
isolationMode: "worktree",
|
|
103
|
+
milestoneId: "M001",
|
|
104
|
+
}),
|
|
105
|
+
/Invalid ActiveTaskChoice: not_yet/,
|
|
106
|
+
);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("guided execute launch mode remains a small compatibility helper", () => {
|
|
110
|
+
assert.equal(resolveGuidedExecuteLaunchMode("worktree"), "auto-step");
|
|
111
|
+
assert.equal(resolveGuidedExecuteLaunchMode("none"), "guided-dispatch");
|
|
112
|
+
assert.equal(resolveGuidedExecuteLaunchMode("branch"), "guided-dispatch");
|
|
113
|
+
});
|