gsd-pi 2.82.0 → 3.0.0
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 +51 -32
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +10 -1
- package/dist/resources/extensions/browser-tools/tools/screenshot.js +1 -0
- package/dist/resources/extensions/browser-tools/tools/zoom.js +1 -0
- package/dist/resources/extensions/claude-code-cli/partial-builder.js +2 -1
- package/dist/resources/extensions/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 +19 -6
- package/dist/resources/extensions/gsd/auto/orchestrator.js +124 -6
- package/dist/resources/extensions/gsd/auto/phases.js +90 -31
- package/dist/resources/extensions/gsd/auto/session.js +4 -0
- package/dist/resources/extensions/gsd/auto/workflow-kernel.js +3 -0
- 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 +20 -19
- package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +246 -133
- package/dist/resources/extensions/gsd/auto-prompts.js +13 -5
- 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 +178 -63
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +31 -7
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +10 -9
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +9 -2
- package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +55 -12
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +17 -3
- package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
- package/dist/resources/extensions/gsd/commands/catalog.js +10 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +39 -1
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
- package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +15 -2
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +7 -2
- package/dist/resources/extensions/gsd/commands-verdict.js +139 -0
- package/dist/resources/extensions/gsd/context-store.js +112 -0
- 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/db-writer.js +150 -84
- package/dist/resources/extensions/gsd/dispatch-guard.js +2 -2
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/dist/resources/extensions/gsd/doctor-git-checks.js +87 -7
- 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/forensics.js +3 -3
- 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/knowledge-backfill.js +144 -0
- package/dist/resources/extensions/gsd/knowledge-capture.js +136 -0
- package/dist/resources/extensions/gsd/knowledge-parser.js +154 -0
- package/dist/resources/extensions/gsd/knowledge-projection.js +210 -0
- package/dist/resources/extensions/gsd/markdown-renderer.js +16 -9
- package/dist/resources/extensions/gsd/md-importer.js +1 -1
- package/dist/resources/extensions/gsd/memory-backfill.js +73 -17
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +222 -0
- package/dist/resources/extensions/gsd/migrate/command.js +5 -0
- package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
- package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
- package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
- package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
- package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
- package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
- package/dist/resources/extensions/gsd/native-git-bridge.js +48 -12
- package/dist/resources/extensions/gsd/paths.js +4 -0
- package/dist/resources/extensions/gsd/pending-auto-start.js +52 -0
- package/dist/resources/extensions/gsd/post-execution-checks.js +73 -2
- package/dist/resources/extensions/gsd/pre-execution-checks.js +28 -1
- package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
- package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
- package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
- package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
- package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/dist/resources/extensions/gsd/prompts/system.md +2 -2
- package/dist/resources/extensions/gsd/provider-switch-observer.js +146 -0
- package/dist/resources/extensions/gsd/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/state.js +3 -3
- package/dist/resources/extensions/gsd/status-guards.js +11 -0
- package/dist/resources/extensions/gsd/templates/knowledge.md +2 -2
- package/dist/resources/extensions/gsd/templates/plan.md +9 -5
- package/dist/resources/extensions/gsd/templates/task-plan.md +10 -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 +87 -14
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +119 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +32 -10
- package/dist/resources/extensions/gsd/validation.js +23 -1
- package/dist/resources/extensions/gsd/verification-gate.js +68 -7
- package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +17 -1
- package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +54 -10
- package/dist/resources/extensions/gsd/worktree-manager.js +1 -1
- 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/ttsr/ttsr-manager.js +3 -1
- 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 +9 -9
- 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 +5 -5
- 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 +9 -9
- 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.65b24fac92188a6b.js +10 -0
- package/dist/web/standalone/.next/static/chunks/9441.ff70bb53f6835771.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/layout-b23b3f6858dc6dc8.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-855d616060cb6e59.js} +1 -1
- package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
- package/package.json +6 -5
- package/packages/contracts/dist/rpc.test.js +7 -0
- package/packages/contracts/dist/rpc.test.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +21 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +24 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/src/rpc.test.ts +8 -0
- package/packages/contracts/src/workflow.ts +24 -0
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/README.md +14 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +80 -0
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/workflow-tools-parity.test.ts +244 -0
- package/packages/mcp-server/src/workflow-tools.test.ts +23 -1
- package/packages/mcp-server/src/workflow-tools.ts +168 -0
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- package/packages/native/tsconfig.json +2 -1
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/index.d.ts +2 -2
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -1
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/providers/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/dist/providers/transform-messages.d.ts +11 -0
- package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.js +20 -0
- package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/index.ts +7 -2
- package/packages/pi-ai/src/providers/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/src/providers/transform-messages.ts +24 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
- package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +44 -3
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +4 -4
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +24 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +71 -97
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js +25 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +24 -10
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js +17 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +53 -3
- package/packages/pi-coding-agent/src/core/sdk.ts +1 -1
- package/packages/pi-coding-agent/src/core/system-prompt.ts +4 -4
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +75 -102
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +30 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +29 -10
- package/packages/pi-coding-agent/src/tests/system-prompt-file-safety.test.ts +22 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__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/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +5 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/terminal.test.ts +121 -0
- package/packages/pi-tui/src/terminal.ts +11 -0
- package/packages/pi-tui/src/tui.ts +6 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +10 -1
- package/src/resources/extensions/browser-tools/tools/screenshot.ts +1 -0
- package/src/resources/extensions/browser-tools/tools/zoom.ts +1 -0
- package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
- package/src/resources/extensions/claude-code-cli/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 +59 -16
- package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
- package/src/resources/extensions/gsd/auto/loop.ts +22 -6
- package/src/resources/extensions/gsd/auto/orchestrator.ts +129 -6
- package/src/resources/extensions/gsd/auto/phases.ts +104 -38
- package/src/resources/extensions/gsd/auto/session.ts +4 -0
- package/src/resources/extensions/gsd/auto/workflow-kernel.ts +5 -1
- package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +72 -1
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +1 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +21 -19
- package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +279 -144
- package/src/resources/extensions/gsd/auto-prompts.ts +13 -5
- 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 +187 -61
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +42 -7
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +10 -9
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +10 -2
- package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +58 -15
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +20 -4
- package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
- package/src/resources/extensions/gsd/commands/catalog.ts +10 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +42 -1
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
- package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +19 -2
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +8 -3
- package/src/resources/extensions/gsd/commands-verdict.ts +202 -0
- package/src/resources/extensions/gsd/context-store.ts +120 -1
- 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/db-writer.ts +167 -84
- package/src/resources/extensions/gsd/dispatch-guard.ts +2 -2
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/src/resources/extensions/gsd/doctor-git-checks.ts +89 -7
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
- package/src/resources/extensions/gsd/doctor-types.ts +3 -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/forensics.ts +3 -3
- 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/knowledge-backfill.ts +164 -0
- package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
- package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
- package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +16 -9
- package/src/resources/extensions/gsd/md-importer.ts +1 -1
- package/src/resources/extensions/gsd/memory-backfill.ts +89 -17
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
- package/src/resources/extensions/gsd/migrate/command.ts +5 -0
- package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
- package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
- package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
- package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
- package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
- package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
- package/src/resources/extensions/gsd/native-git-bridge.ts +54 -12
- package/src/resources/extensions/gsd/paths.ts +5 -0
- package/src/resources/extensions/gsd/pending-auto-start.ts +79 -0
- package/src/resources/extensions/gsd/post-execution-checks.ts +87 -2
- package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -1
- package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
- package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
- package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
- package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
- package/src/resources/extensions/gsd/prompts/queue.md +4 -4
- package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/src/resources/extensions/gsd/prompts/system.md +2 -2
- package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
- package/src/resources/extensions/gsd/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/state.ts +3 -3
- package/src/resources/extensions/gsd/status-guards.ts +13 -0
- package/src/resources/extensions/gsd/templates/knowledge.md +2 -2
- package/src/resources/extensions/gsd/templates/plan.md +9 -5
- package/src/resources/extensions/gsd/templates/task-plan.md +10 -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 +131 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +487 -4
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +151 -12
- 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 +18 -6
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +91 -6
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/auto-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/browser-tools-compatibility-declarations.test.ts +62 -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/commands-verdict.test.ts +378 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +5 -9
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
- package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +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/db-writer.test.ts +13 -8
- package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
- package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +59 -2
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +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/freeform-decisions.test.ts +8 -4
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +11 -7
- package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +5 -2
- package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +59 -11
- package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +7 -7
- package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
- package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +112 -1
- package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +13 -5
- package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +323 -0
- package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -2
- package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
- package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +63 -2
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
- package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
- package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +29 -5
- package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +251 -2
- 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/post-unit-state-rebuild.test.ts +84 -0
- 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-contracts.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +37 -1
- package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
- package/src/resources/extensions/gsd/tests/quality-gates.test.ts +6 -0
- 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-start-footer.test.ts +16 -4
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +53 -2
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
- package/src/resources/extensions/gsd/tests/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 +103 -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-kernel.test.ts +7 -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/worktree-lifecycle.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +54 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +8 -10
- package/src/resources/extensions/gsd/tools/complete-slice.ts +6 -8
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
- package/src/resources/extensions/gsd/tools/plan-slice.ts +97 -12
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
- package/src/resources/extensions/gsd/types.ts +1 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +47 -11
- package/src/resources/extensions/gsd/validation.ts +23 -1
- package/src/resources/extensions/gsd/verification-gate.ts +78 -6
- package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +4 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +18 -1
- package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +61 -10
- package/src/resources/extensions/gsd/worktree-manager.ts +1 -1
- 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/ttsr/ttsr-manager.ts +5 -1
- 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/8359.e059d86b255fce1c.js +0 -10
- package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/layout-9ecfd95f343793f0.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/{S44UQTFCUdA44dkjfYt6S → qoMxZh-xuwuvpFW0x0k01}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{S44UQTFCUdA44dkjfYt6S → qoMxZh-xuwuvpFW0x0k01}/_ssgManifest.js +0 -0
|
@@ -4,9 +4,14 @@
|
|
|
4
4
|
import test from "node:test";
|
|
5
5
|
import assert from "node:assert/strict";
|
|
6
6
|
|
|
7
|
-
import { createAutoOrchestrator } from "../auto/orchestrator.js";
|
|
7
|
+
import { createAutoOrchestrator, STUCK_WINDOW_SIZE } from "../auto/orchestrator.js";
|
|
8
8
|
import type { AutoOrchestratorDeps } from "../auto/contracts.js";
|
|
9
9
|
import type { GSDState } from "../types.js";
|
|
10
|
+
import { createWiredDispatchAdapter } from "../auto.js";
|
|
11
|
+
import { resolveDispatch, type DispatchContext } from "../auto-dispatch.js";
|
|
12
|
+
import { RuleRegistry, setRegistry, resetRegistry } from "../rule-registry.js";
|
|
13
|
+
import type { UnifiedRule } from "../rule-types.js";
|
|
14
|
+
import { supportsStructuredQuestions } from "../workflow-mcp.js";
|
|
10
15
|
|
|
11
16
|
function makeState(): GSDState {
|
|
12
17
|
return {
|
|
@@ -62,9 +67,13 @@ function makeDeps(overrides: Partial<AutoOrchestratorDeps> = {}): { deps: AutoOr
|
|
|
62
67
|
async cleanupOnStop() { calls.push("worktree.cleanup"); },
|
|
63
68
|
},
|
|
64
69
|
health: {
|
|
70
|
+
checkResourcesStale() {
|
|
71
|
+
calls.push("health.stale");
|
|
72
|
+
return null;
|
|
73
|
+
},
|
|
65
74
|
async preAdvanceGate() {
|
|
66
75
|
calls.push("health.pre");
|
|
67
|
-
return {
|
|
76
|
+
return { kind: "pass" };
|
|
68
77
|
},
|
|
69
78
|
async postAdvanceRecord() { calls.push("health.post"); },
|
|
70
79
|
},
|
|
@@ -75,6 +84,9 @@ function makeDeps(overrides: Partial<AutoOrchestratorDeps> = {}): { deps: AutoOr
|
|
|
75
84
|
notifications: {
|
|
76
85
|
async notifyLifecycle(event) { calls.push(`notify:${event.name}`); },
|
|
77
86
|
},
|
|
87
|
+
uokGate: {
|
|
88
|
+
async emit(input) { calls.push(`gate:${input.gateId}:${input.outcome}`); },
|
|
89
|
+
},
|
|
78
90
|
};
|
|
79
91
|
|
|
80
92
|
return { deps: { ...deps, ...overrides }, calls };
|
|
@@ -87,6 +99,7 @@ test("start() advances and records active unit", async () => {
|
|
|
87
99
|
const result = await orchestrator.start({ basePath: "/tmp/project", trigger: "manual" });
|
|
88
100
|
|
|
89
101
|
assert.equal(result.kind, "advanced");
|
|
102
|
+
assert.deepEqual(result.unit, { unitType: "execute-task", unitId: "T01" });
|
|
90
103
|
const status = orchestrator.getStatus();
|
|
91
104
|
assert.equal(status.phase, "running");
|
|
92
105
|
assert.deepEqual(status.activeUnit, { unitType: "execute-task", unitId: "T01" });
|
|
@@ -95,9 +108,10 @@ test("start() advances and records active unit", async () => {
|
|
|
95
108
|
});
|
|
96
109
|
|
|
97
110
|
test("advance() returns blocked when health gate denies", async () => {
|
|
98
|
-
const { deps } = makeDeps({
|
|
111
|
+
const { deps, calls } = makeDeps({
|
|
99
112
|
health: {
|
|
100
|
-
|
|
113
|
+
checkResourcesStale: () => null,
|
|
114
|
+
async preAdvanceGate() { return { kind: "fail", reason: "doctor-block" }; },
|
|
101
115
|
async postAdvanceRecord() {},
|
|
102
116
|
},
|
|
103
117
|
});
|
|
@@ -107,6 +121,69 @@ test("advance() returns blocked when health gate denies", async () => {
|
|
|
107
121
|
|
|
108
122
|
assert.equal(result.kind, "blocked");
|
|
109
123
|
assert.equal(result.reason, "doctor-block");
|
|
124
|
+
assert.equal(result.action, "pause");
|
|
125
|
+
assert.ok(calls.includes("gate:pre-dispatch-health-gate:manual-attention"));
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test("advance() returns blocked stop when resources are stale", async () => {
|
|
129
|
+
const { deps, calls } = makeDeps({
|
|
130
|
+
health: {
|
|
131
|
+
checkResourcesStale: () => "resources changed since session start",
|
|
132
|
+
async preAdvanceGate() { return { kind: "pass" }; },
|
|
133
|
+
async postAdvanceRecord() {},
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
const orchestrator = createAutoOrchestrator(deps);
|
|
137
|
+
|
|
138
|
+
const result = await orchestrator.advance();
|
|
139
|
+
|
|
140
|
+
assert.equal(result.kind, "blocked");
|
|
141
|
+
assert.equal(result.reason, "resources changed since session start");
|
|
142
|
+
assert.equal(result.action, "stop");
|
|
143
|
+
assert.ok(calls.includes("gate:resource-version-guard:fail"));
|
|
144
|
+
assert.ok(!calls.includes("health.pre"));
|
|
145
|
+
assert.ok(!calls.includes("state.reconcile"));
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test("advance() continues past pre-dispatch health gate when it throws", async () => {
|
|
149
|
+
const { deps, calls } = makeDeps({
|
|
150
|
+
health: {
|
|
151
|
+
checkResourcesStale: () => null,
|
|
152
|
+
async preAdvanceGate() { return { kind: "threw", error: new Error("boom") }; },
|
|
153
|
+
async postAdvanceRecord() {},
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
const orchestrator = createAutoOrchestrator(deps);
|
|
157
|
+
|
|
158
|
+
const result = await orchestrator.advance();
|
|
159
|
+
|
|
160
|
+
assert.equal(result.kind, "advanced");
|
|
161
|
+
assert.ok(calls.includes("gate:pre-dispatch-health-gate:manual-attention"));
|
|
162
|
+
assert.ok(calls.includes("state.reconcile"));
|
|
163
|
+
assert.ok(calls.includes("dispatch.decide"));
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test("advance() forwards fixesApplied into pre-dispatch-health-gate pass findings", async () => {
|
|
167
|
+
let observed = "";
|
|
168
|
+
const { deps } = makeDeps({
|
|
169
|
+
health: {
|
|
170
|
+
checkResourcesStale: () => null,
|
|
171
|
+
async preAdvanceGate() { return { kind: "pass", fixesApplied: ["fix-a", "fix-b"] }; },
|
|
172
|
+
async postAdvanceRecord() {},
|
|
173
|
+
},
|
|
174
|
+
uokGate: {
|
|
175
|
+
async emit(input) {
|
|
176
|
+
if (input.gateId === "pre-dispatch-health-gate" && input.outcome === "pass") {
|
|
177
|
+
observed = input.findings ?? "";
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
const orchestrator = createAutoOrchestrator(deps);
|
|
183
|
+
|
|
184
|
+
await orchestrator.advance();
|
|
185
|
+
|
|
186
|
+
assert.equal(observed, "fix-a, fix-b");
|
|
110
187
|
});
|
|
111
188
|
|
|
112
189
|
test("advance() follows the ADR-015 invariant sequence before journaling advance", async () => {
|
|
@@ -116,9 +193,13 @@ test("advance() follows the ADR-015 invariant sequence before journaling advance
|
|
|
116
193
|
const result = await orchestrator.advance();
|
|
117
194
|
|
|
118
195
|
assert.equal(result.kind, "advanced");
|
|
196
|
+
assert.deepEqual(result.unit, { unitType: "execute-task", unitId: "T01" });
|
|
119
197
|
assert.deepEqual(calls, [
|
|
120
198
|
"runtime.lock",
|
|
199
|
+
"health.stale",
|
|
200
|
+
"gate:resource-version-guard:pass",
|
|
121
201
|
"health.pre",
|
|
202
|
+
"gate:pre-dispatch-health-gate:pass",
|
|
122
203
|
"state.reconcile",
|
|
123
204
|
"dispatch.decide",
|
|
124
205
|
"tool.compile",
|
|
@@ -144,6 +225,7 @@ test("advance() blocks before dispatch when State Reconciliation blocks", async
|
|
|
144
225
|
|
|
145
226
|
assert.equal(result.kind, "blocked");
|
|
146
227
|
assert.equal(result.reason, "state drift blocked");
|
|
228
|
+
assert.equal(result.action, "pause");
|
|
147
229
|
assert.ok(!calls.includes("dispatch.decide"));
|
|
148
230
|
assert.ok(calls.includes("journal:advance-blocked"));
|
|
149
231
|
});
|
|
@@ -163,6 +245,7 @@ test("advance() blocks before Runtime persistence when Tool Contract fails", asy
|
|
|
163
245
|
|
|
164
246
|
assert.equal(result.kind, "blocked");
|
|
165
247
|
assert.equal(result.reason, "unknown Unit");
|
|
248
|
+
assert.equal(result.action, "pause");
|
|
166
249
|
assert.ok(!calls.includes("worktree.prepare"));
|
|
167
250
|
assert.ok(!calls.includes("journal:advance"));
|
|
168
251
|
assert.ok(calls.includes("journal:advance-blocked"));
|
|
@@ -185,6 +268,7 @@ test("advance() blocks before Runtime persistence when Worktree Safety fails", a
|
|
|
185
268
|
|
|
186
269
|
assert.equal(result.kind, "blocked");
|
|
187
270
|
assert.equal(result.reason, "worktree invalid");
|
|
271
|
+
assert.equal(result.action, "pause");
|
|
188
272
|
assert.ok(!calls.includes("journal:advance"));
|
|
189
273
|
assert.ok(!calls.includes("worktree.sync"));
|
|
190
274
|
assert.ok(calls.includes("journal:advance-blocked"));
|
|
@@ -204,6 +288,51 @@ test("advance() stops when dispatch has no next unit", async () => {
|
|
|
204
288
|
assert.equal(orchestrator.getStatus().phase, "stopped");
|
|
205
289
|
});
|
|
206
290
|
|
|
291
|
+
test("advance() surfaces dispatch blocker reason instead of generic no remaining units", async () => {
|
|
292
|
+
const { deps, calls } = makeDeps({
|
|
293
|
+
dispatch: {
|
|
294
|
+
async decideNextUnit() {
|
|
295
|
+
return {
|
|
296
|
+
kind: "blocked",
|
|
297
|
+
reason: "Milestone M001 validation verdict is needs-remediation but all slices are complete.",
|
|
298
|
+
action: "pause",
|
|
299
|
+
};
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
const orchestrator = createAutoOrchestrator(deps);
|
|
304
|
+
|
|
305
|
+
const result = await orchestrator.advance();
|
|
306
|
+
|
|
307
|
+
assert.equal(result.kind, "blocked");
|
|
308
|
+
if (result.kind !== "blocked") return;
|
|
309
|
+
assert.equal(result.reason, "Milestone M001 validation verdict is needs-remediation but all slices are complete.");
|
|
310
|
+
assert.equal(result.action, "pause");
|
|
311
|
+
assert.ok(calls.includes("journal:advance-blocked"));
|
|
312
|
+
assert.ok(!calls.includes("journal:advance-stopped"));
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
test("resume() returns blocked when advance detects a dispatch blocker", async () => {
|
|
316
|
+
const { deps } = makeDeps({
|
|
317
|
+
dispatch: {
|
|
318
|
+
async decideNextUnit() {
|
|
319
|
+
return {
|
|
320
|
+
kind: "blocked",
|
|
321
|
+
reason: "remediation required",
|
|
322
|
+
action: "pause",
|
|
323
|
+
};
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
const orchestrator = createAutoOrchestrator(deps);
|
|
328
|
+
|
|
329
|
+
const result = await orchestrator.resume();
|
|
330
|
+
|
|
331
|
+
assert.equal(result.kind, "blocked");
|
|
332
|
+
if (result.kind !== "blocked") return;
|
|
333
|
+
assert.equal(result.reason, "remediation required");
|
|
334
|
+
});
|
|
335
|
+
|
|
207
336
|
test("advance() uses recovery on error", async () => {
|
|
208
337
|
const { deps, calls } = makeDeps({
|
|
209
338
|
runtime: {
|
|
@@ -232,8 +361,10 @@ test("advance() is idempotent for the same active unit", async () => {
|
|
|
232
361
|
const second = await orchestrator.advance();
|
|
233
362
|
|
|
234
363
|
assert.equal(first.kind, "advanced");
|
|
364
|
+
assert.deepEqual(first.unit, { unitType: "execute-task", unitId: "T01" });
|
|
235
365
|
assert.equal(second.kind, "blocked");
|
|
236
366
|
assert.equal(second.reason, "idempotent advance: unit already active");
|
|
367
|
+
assert.equal(second.action, "stop");
|
|
237
368
|
|
|
238
369
|
const prepareCalls = calls.filter((c) => c === "worktree.prepare").length;
|
|
239
370
|
assert.equal(prepareCalls, 1);
|
|
@@ -468,3 +599,355 @@ test("stop() cleans up worktree and transitions to stopped", async () => {
|
|
|
468
599
|
assert.ok(calls.includes("journal:stop"));
|
|
469
600
|
assert.ok(calls.includes("notify:stop"));
|
|
470
601
|
});
|
|
602
|
+
|
|
603
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
604
|
+
// Stuck-loop ring buffer (issue #5787)
|
|
605
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
606
|
+
|
|
607
|
+
test("STUCK_WINDOW_SIZE matches the legacy auto/phases.ts constant", () => {
|
|
608
|
+
assert.equal(STUCK_WINDOW_SIZE, 6);
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
test("stuck-loop: empty ring on a freshly constructed orchestrator advances normally", async () => {
|
|
612
|
+
const { deps } = makeDeps();
|
|
613
|
+
const orchestrator = createAutoOrchestrator(deps);
|
|
614
|
+
|
|
615
|
+
const result = await orchestrator.advance();
|
|
616
|
+
|
|
617
|
+
assert.equal(result.kind, "advanced");
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
test("stuck-loop: partial fill of mixed units does not block", async () => {
|
|
621
|
+
// Alternate A/B for STUCK_WINDOW_SIZE rounds. No single key saturates the
|
|
622
|
+
// window, so neither idempotency nor stuck-loop should fire.
|
|
623
|
+
let i = 0;
|
|
624
|
+
const sequence = ["A", "B", "A", "B", "A", "B"];
|
|
625
|
+
const { deps } = makeDeps({
|
|
626
|
+
dispatch: {
|
|
627
|
+
async decideNextUnit() {
|
|
628
|
+
const id = sequence[i++ % sequence.length];
|
|
629
|
+
return { unitType: "execute-task", unitId: id, reason: "ready", preconditions: [] };
|
|
630
|
+
},
|
|
631
|
+
},
|
|
632
|
+
});
|
|
633
|
+
const orchestrator = createAutoOrchestrator(deps);
|
|
634
|
+
|
|
635
|
+
for (let round = 0; round < STUCK_WINDOW_SIZE; round++) {
|
|
636
|
+
const result = await orchestrator.advance();
|
|
637
|
+
assert.equal(result.kind, "advanced", `round ${round} should advance, got ${result.kind}`);
|
|
638
|
+
}
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
test("stuck-loop: ring saturated with same unit blocks with action 'stop' and stuck-loop reason", async () => {
|
|
642
|
+
// Dispatch picks the same unit every time. The first advance succeeds.
|
|
643
|
+
// Calls 2..STUCK_WINDOW_SIZE-1 are idempotency-blocked while the ring fills.
|
|
644
|
+
// The STUCK_WINDOW_SIZE'th call sees a saturated ring and returns stuck-loop.
|
|
645
|
+
const { deps } = makeDeps();
|
|
646
|
+
const orchestrator = createAutoOrchestrator(deps);
|
|
647
|
+
|
|
648
|
+
const results: Awaited<ReturnType<typeof orchestrator.advance>>[] = [];
|
|
649
|
+
for (let i = 0; i < STUCK_WINDOW_SIZE; i++) {
|
|
650
|
+
results.push(await orchestrator.advance());
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// First call advances.
|
|
654
|
+
assert.equal(results[0].kind, "advanced");
|
|
655
|
+
|
|
656
|
+
// Intermediate calls are blocked by idempotency (not stuck-loop yet).
|
|
657
|
+
for (let i = 1; i < STUCK_WINDOW_SIZE - 1; i++) {
|
|
658
|
+
const r = results[i];
|
|
659
|
+
assert.equal(r.kind, "blocked", `round ${i} should be blocked`);
|
|
660
|
+
if (r.kind !== "blocked") return;
|
|
661
|
+
assert.equal(r.reason, "idempotent advance: unit already active");
|
|
662
|
+
assert.equal(r.action, "stop");
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// The final call (ring now holds STUCK_WINDOW_SIZE copies) returns stuck-loop.
|
|
666
|
+
const last = results[STUCK_WINDOW_SIZE - 1];
|
|
667
|
+
assert.equal(last.kind, "blocked");
|
|
668
|
+
if (last.kind !== "blocked") return;
|
|
669
|
+
assert.equal(last.action, "stop");
|
|
670
|
+
assert.equal(last.reason, `stuck-loop: execute-task:T01 picked ${STUCK_WINDOW_SIZE} times`);
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
test("stuck-loop: idempotency block continues to fire with its own reason before saturation", async () => {
|
|
674
|
+
// Two identical calls should produce idempotent (not stuck-loop). Ensures the
|
|
675
|
+
// existing idempotency block is not absorbed by the new check.
|
|
676
|
+
const { deps } = makeDeps();
|
|
677
|
+
const orchestrator = createAutoOrchestrator(deps);
|
|
678
|
+
|
|
679
|
+
const first = await orchestrator.advance();
|
|
680
|
+
const second = await orchestrator.advance();
|
|
681
|
+
|
|
682
|
+
assert.equal(first.kind, "advanced");
|
|
683
|
+
assert.equal(second.kind, "blocked");
|
|
684
|
+
assert.equal(second.reason, "idempotent advance: unit already active");
|
|
685
|
+
assert.equal(second.action, "stop");
|
|
686
|
+
});
|
|
687
|
+
|
|
688
|
+
test("stuck-loop: start() resets the ring so a fresh saturation cycle is required", async () => {
|
|
689
|
+
// Fill the ring to one short of saturation, then start() — the ring should
|
|
690
|
+
// be cleared, and the next advance must succeed instead of going stuck.
|
|
691
|
+
const { deps } = makeDeps();
|
|
692
|
+
const orchestrator = createAutoOrchestrator(deps);
|
|
693
|
+
|
|
694
|
+
for (let i = 0; i < STUCK_WINDOW_SIZE - 1; i++) {
|
|
695
|
+
await orchestrator.advance();
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
const restarted = await orchestrator.start({ basePath: "/tmp/project", trigger: "manual" });
|
|
699
|
+
assert.equal(restarted.kind, "advanced");
|
|
700
|
+
|
|
701
|
+
// Immediately after start(), the next advance is idempotent (one element in
|
|
702
|
+
// ring), not stuck-loop, confirming the ring was reset.
|
|
703
|
+
const next = await orchestrator.advance();
|
|
704
|
+
assert.equal(next.kind, "blocked");
|
|
705
|
+
assert.equal(next.reason, "idempotent advance: unit already active");
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
test("stuck-loop: resume() resets the ring", async () => {
|
|
709
|
+
const { deps } = makeDeps();
|
|
710
|
+
const orchestrator = createAutoOrchestrator(deps);
|
|
711
|
+
|
|
712
|
+
for (let i = 0; i < STUCK_WINDOW_SIZE - 1; i++) {
|
|
713
|
+
await orchestrator.advance();
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
const resumed = await orchestrator.resume();
|
|
717
|
+
assert.equal(resumed.kind, "advanced");
|
|
718
|
+
|
|
719
|
+
const next = await orchestrator.advance();
|
|
720
|
+
assert.equal(next.kind, "blocked");
|
|
721
|
+
assert.equal(next.reason, "idempotent advance: unit already active");
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
test("stuck-loop: stop() resets the ring", async () => {
|
|
725
|
+
const { deps } = makeDeps();
|
|
726
|
+
const orchestrator = createAutoOrchestrator(deps);
|
|
727
|
+
|
|
728
|
+
for (let i = 0; i < STUCK_WINDOW_SIZE - 1; i++) {
|
|
729
|
+
await orchestrator.advance();
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
const stopped = await orchestrator.stop("user-request");
|
|
733
|
+
assert.equal(stopped.kind, "stopped");
|
|
734
|
+
|
|
735
|
+
// Ring is cleared by stop(). A subsequent advance is a fresh first-touch.
|
|
736
|
+
const next = await orchestrator.advance();
|
|
737
|
+
assert.equal(next.kind, "advanced");
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
test("stuck-loop: journal records the stuck-loop reason on advance-blocked", async () => {
|
|
741
|
+
const { deps, calls } = makeDeps();
|
|
742
|
+
const orchestrator = createAutoOrchestrator(deps);
|
|
743
|
+
|
|
744
|
+
for (let i = 0; i < STUCK_WINDOW_SIZE; i++) {
|
|
745
|
+
await orchestrator.advance();
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
assert.ok(calls.includes("journal:advance-blocked"));
|
|
749
|
+
});
|
|
750
|
+
|
|
751
|
+
// ─── #5789 parity: wired dispatch adapter mirrors runDispatch's resolveDispatch call ───
|
|
752
|
+
|
|
753
|
+
test("wired DispatchAdapter forwards session-derived dispatch inputs identically to runDispatch", async () => {
|
|
754
|
+
const stateSnapshot = makeState();
|
|
755
|
+
|
|
756
|
+
// Install a capturing registry so we observe the DispatchContext both code paths
|
|
757
|
+
// build, and force a deterministic dispatch action so the parity assertion is
|
|
758
|
+
// about *inputs*, not rule evaluation.
|
|
759
|
+
const captured: DispatchContext[] = [];
|
|
760
|
+
const captureRule: UnifiedRule = {
|
|
761
|
+
name: "test-capture",
|
|
762
|
+
when: "dispatch",
|
|
763
|
+
evaluation: "first-match",
|
|
764
|
+
where: async (ctx: DispatchContext) => {
|
|
765
|
+
captured.push(ctx);
|
|
766
|
+
return {
|
|
767
|
+
action: "dispatch" as const,
|
|
768
|
+
unitType: "execute-task",
|
|
769
|
+
unitId: "T01",
|
|
770
|
+
prompt: "parity-fixture",
|
|
771
|
+
};
|
|
772
|
+
},
|
|
773
|
+
then: (r: unknown) => r,
|
|
774
|
+
};
|
|
775
|
+
setRegistry(new RuleRegistry([captureRule]));
|
|
776
|
+
|
|
777
|
+
try {
|
|
778
|
+
// Mock ExtensionContext + ExtensionAPI with the surface the wired adapter touches.
|
|
779
|
+
const fakeModelRegistry = {
|
|
780
|
+
getAll: () => [],
|
|
781
|
+
getProviderAuthMode: (_provider: string) => "apiKey" as const,
|
|
782
|
+
};
|
|
783
|
+
const ctx = {
|
|
784
|
+
model: {
|
|
785
|
+
provider: "anthropic",
|
|
786
|
+
baseUrl: "https://api.anthropic.com",
|
|
787
|
+
contextWindow: 200_000,
|
|
788
|
+
},
|
|
789
|
+
modelRegistry: fakeModelRegistry,
|
|
790
|
+
} as any;
|
|
791
|
+
const pi = {
|
|
792
|
+
getActiveTools: () => ["read_file", "write_file"],
|
|
793
|
+
} as any;
|
|
794
|
+
const basePath = "/tmp/parity-fixture";
|
|
795
|
+
|
|
796
|
+
// Path A — wired adapter (what createWiredAutoOrchestrationModule uses).
|
|
797
|
+
const adapter = createWiredDispatchAdapter(ctx, pi, basePath);
|
|
798
|
+
const adapterResult = await adapter.decideNextUnit({ stateSnapshot });
|
|
799
|
+
|
|
800
|
+
// Path B — direct resolveDispatch call mirroring phases.ts:runDispatch.
|
|
801
|
+
// Inline the same derivations runDispatch uses so any drift here is a parity break.
|
|
802
|
+
const prefs = undefined; // loadEffectiveGSDPreferences returns null for /tmp/parity-fixture.
|
|
803
|
+
const provider = ctx.model?.provider;
|
|
804
|
+
const authMode = provider && typeof ctx.modelRegistry?.getProviderAuthMode === "function"
|
|
805
|
+
? ctx.modelRegistry.getProviderAuthMode(provider)
|
|
806
|
+
: undefined;
|
|
807
|
+
const activeTools = typeof pi.getActiveTools === "function" ? pi.getActiveTools() : [];
|
|
808
|
+
const structuredQuestionsAvailable: "true" | "false" =
|
|
809
|
+
prefs !== undefined && (prefs as { planning_depth?: string }).planning_depth === "deep"
|
|
810
|
+
? "false"
|
|
811
|
+
: supportsStructuredQuestions(activeTools, {
|
|
812
|
+
authMode,
|
|
813
|
+
baseUrl: ctx.model?.baseUrl,
|
|
814
|
+
})
|
|
815
|
+
? "true"
|
|
816
|
+
: "false";
|
|
817
|
+
|
|
818
|
+
const builtDirectCtx: DispatchContext = {
|
|
819
|
+
basePath,
|
|
820
|
+
mid: stateSnapshot.activeMilestone!.id,
|
|
821
|
+
midTitle: stateSnapshot.activeMilestone!.title,
|
|
822
|
+
state: stateSnapshot,
|
|
823
|
+
prefs,
|
|
824
|
+
structuredQuestionsAvailable,
|
|
825
|
+
sessionContextWindow: ctx.model?.contextWindow,
|
|
826
|
+
sessionProvider: ctx.model?.provider,
|
|
827
|
+
modelRegistry: ctx.modelRegistry,
|
|
828
|
+
};
|
|
829
|
+
const directAction = await resolveDispatch(builtDirectCtx);
|
|
830
|
+
|
|
831
|
+
// Two contexts captured: one per resolveDispatch call.
|
|
832
|
+
assert.equal(captured.length, 2, "expected two captured dispatch contexts");
|
|
833
|
+
const [adapterCtx, directCtx] = captured;
|
|
834
|
+
|
|
835
|
+
// Parity assertion: session-derived fields are identical.
|
|
836
|
+
assert.equal(adapterCtx.structuredQuestionsAvailable, directCtx.structuredQuestionsAvailable);
|
|
837
|
+
assert.equal(adapterCtx.sessionContextWindow, directCtx.sessionContextWindow);
|
|
838
|
+
assert.equal(adapterCtx.sessionProvider, directCtx.sessionProvider);
|
|
839
|
+
assert.equal(adapterCtx.modelRegistry, directCtx.modelRegistry);
|
|
840
|
+
assert.equal(adapterCtx.basePath, directCtx.basePath);
|
|
841
|
+
assert.equal(adapterCtx.mid, directCtx.mid);
|
|
842
|
+
assert.equal(adapterCtx.midTitle, directCtx.midTitle);
|
|
843
|
+
|
|
844
|
+
// Dispatch action equality: both flows reach the same dispatch decision.
|
|
845
|
+
if (!adapterResult || !("unitType" in adapterResult)) {
|
|
846
|
+
assert.fail("expected adapter result to be a dispatch decision");
|
|
847
|
+
}
|
|
848
|
+
assert.equal(adapterResult.unitType, "execute-task");
|
|
849
|
+
assert.equal(adapterResult.unitId, "T01");
|
|
850
|
+
assert.equal(adapterResult.reason, "test-capture");
|
|
851
|
+
assert.equal(directAction.action, "dispatch");
|
|
852
|
+
if (directAction.action === "dispatch") {
|
|
853
|
+
assert.equal(directAction.unitType, adapterResult.unitType);
|
|
854
|
+
assert.equal(directAction.unitId, adapterResult.unitId);
|
|
855
|
+
assert.equal(directAction.matchedRule, adapterResult.reason);
|
|
856
|
+
}
|
|
857
|
+
} finally {
|
|
858
|
+
resetRegistry();
|
|
859
|
+
}
|
|
860
|
+
});
|
|
861
|
+
|
|
862
|
+
test("wired DispatchAdapter prefers caller-supplied dispatch inputs over ctx-derived values", async () => {
|
|
863
|
+
const stateSnapshot = makeState();
|
|
864
|
+
const captured: DispatchContext[] = [];
|
|
865
|
+
const captureRule: UnifiedRule = {
|
|
866
|
+
name: "test-capture-overrides",
|
|
867
|
+
when: "dispatch",
|
|
868
|
+
evaluation: "first-match",
|
|
869
|
+
where: async (ctx: DispatchContext) => {
|
|
870
|
+
captured.push(ctx);
|
|
871
|
+
return {
|
|
872
|
+
action: "dispatch" as const,
|
|
873
|
+
unitType: "execute-task",
|
|
874
|
+
unitId: "T01",
|
|
875
|
+
prompt: "override-fixture",
|
|
876
|
+
};
|
|
877
|
+
},
|
|
878
|
+
then: (r: unknown) => r,
|
|
879
|
+
};
|
|
880
|
+
setRegistry(new RuleRegistry([captureRule]));
|
|
881
|
+
|
|
882
|
+
try {
|
|
883
|
+
const ctxModelRegistry = {
|
|
884
|
+
getAll: () => [],
|
|
885
|
+
getProviderAuthMode: (_provider: string) => "apiKey" as const,
|
|
886
|
+
};
|
|
887
|
+
const overrideModelRegistry = {
|
|
888
|
+
getAll: () => [],
|
|
889
|
+
getProviderAuthMode: (_provider: string) => "oauth" as const,
|
|
890
|
+
};
|
|
891
|
+
const ctx = {
|
|
892
|
+
model: {
|
|
893
|
+
provider: "anthropic",
|
|
894
|
+
baseUrl: "https://api.anthropic.com",
|
|
895
|
+
contextWindow: 200_000,
|
|
896
|
+
},
|
|
897
|
+
modelRegistry: ctxModelRegistry,
|
|
898
|
+
} as any;
|
|
899
|
+
const pi = {
|
|
900
|
+
getActiveTools: () => [],
|
|
901
|
+
} as any;
|
|
902
|
+
const adapter = createWiredDispatchAdapter(ctx, pi, "/tmp/parity-fixture");
|
|
903
|
+
|
|
904
|
+
const result = await adapter.decideNextUnit({
|
|
905
|
+
stateSnapshot,
|
|
906
|
+
structuredQuestionsAvailable: "true",
|
|
907
|
+
sessionContextWindow: 500_000,
|
|
908
|
+
sessionProvider: "openai",
|
|
909
|
+
modelRegistry: overrideModelRegistry,
|
|
910
|
+
});
|
|
911
|
+
|
|
912
|
+
assert.ok(result);
|
|
913
|
+
assert.equal(captured.length, 1, "expected one captured dispatch context");
|
|
914
|
+
assert.equal(captured[0].structuredQuestionsAvailable, "true");
|
|
915
|
+
assert.equal(captured[0].sessionContextWindow, 500_000);
|
|
916
|
+
assert.equal(captured[0].sessionProvider, "openai");
|
|
917
|
+
assert.equal(captured[0].modelRegistry, overrideModelRegistry);
|
|
918
|
+
} finally {
|
|
919
|
+
resetRegistry();
|
|
920
|
+
}
|
|
921
|
+
});
|
|
922
|
+
|
|
923
|
+
test("wired DispatchAdapter preserves stop reason as a blocked decision", async () => {
|
|
924
|
+
const stateSnapshot = makeState();
|
|
925
|
+
const stopRule: UnifiedRule = {
|
|
926
|
+
name: "test-stop",
|
|
927
|
+
when: "dispatch",
|
|
928
|
+
evaluation: "first-match",
|
|
929
|
+
where: async () => ({
|
|
930
|
+
action: "stop" as const,
|
|
931
|
+
reason: "remediation blocker",
|
|
932
|
+
level: "warning" as const,
|
|
933
|
+
}),
|
|
934
|
+
then: (r: unknown) => r,
|
|
935
|
+
};
|
|
936
|
+
setRegistry(new RuleRegistry([stopRule]));
|
|
937
|
+
|
|
938
|
+
try {
|
|
939
|
+
const ctx = { model: {}, modelRegistry: { getAll: () => [] } } as any;
|
|
940
|
+
const pi = { getActiveTools: () => [] } as any;
|
|
941
|
+
const adapter = createWiredDispatchAdapter(ctx, pi, "/tmp/parity-fixture");
|
|
942
|
+
|
|
943
|
+
const result = await adapter.decideNextUnit({ stateSnapshot });
|
|
944
|
+
|
|
945
|
+
assert.deepEqual(result, {
|
|
946
|
+
kind: "blocked",
|
|
947
|
+
reason: "remediation blocker",
|
|
948
|
+
action: "pause",
|
|
949
|
+
});
|
|
950
|
+
} finally {
|
|
951
|
+
resetRegistry();
|
|
952
|
+
}
|
|
953
|
+
});
|