gsd-pi 2.82.0-dev.ed17d078d → 3.0.0-dev.04f5ccf82
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 +93 -18
- package/dist/cli.js +20 -9
- package/dist/headless-ui.js +13 -6
- package/dist/headless.js +9 -2
- 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 +44 -6
- package/dist/resources/extensions/cmux/index.js +5 -0
- package/dist/resources/extensions/gsd/auto/detect-stuck.js +1 -1
- package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
- package/dist/resources/extensions/gsd/auto/loop.js +122 -40
- package/dist/resources/extensions/gsd/auto/orchestrator.js +15 -4
- package/dist/resources/extensions/gsd/auto/phases.js +146 -49
- package/dist/resources/extensions/gsd/auto/session.js +6 -0
- package/dist/resources/extensions/gsd/auto/unit-runner-events.js +7 -1
- 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-budget.js +9 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +72 -5
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +1 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +185 -30
- package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +329 -137
- package/dist/resources/extensions/gsd/auto-prompts.js +36 -10
- package/dist/resources/extensions/gsd/auto-recovery.js +82 -16
- package/dist/resources/extensions/gsd/auto-start.js +99 -16
- package/dist/resources/extensions/gsd/auto-timers.js +11 -3
- package/dist/resources/extensions/gsd/auto-verification.js +146 -34
- package/dist/resources/extensions/gsd/auto-worktree.js +185 -26
- package/dist/resources/extensions/gsd/auto.js +135 -74
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +65 -10
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +13 -10
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +14 -4
- package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +24 -9
- package/dist/resources/extensions/gsd/clean-root-preflight.js +267 -8
- package/dist/resources/extensions/gsd/commands/catalog.js +10 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +38 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +20 -0
- package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +2 -0
- package/dist/resources/extensions/gsd/commands-mcp-status.js +9 -0
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +16 -4
- package/dist/resources/extensions/gsd/commands-verdict.js +139 -0
- package/dist/resources/extensions/gsd/crash-recovery.js +55 -7
- package/dist/resources/extensions/gsd/db/auto-workers.js +30 -0
- 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-base-schema.js +2 -0
- package/dist/resources/extensions/gsd/db-migration-steps.js +4 -0
- package/dist/resources/extensions/gsd/db-task-slice-rows.js +2 -0
- package/dist/resources/extensions/gsd/dispatch-guard.js +46 -2
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +10 -0
- package/dist/resources/extensions/gsd/doctor-git-checks.js +74 -3
- package/dist/resources/extensions/gsd/doctor-proactive.js +14 -2
- 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 +10 -3
- package/dist/resources/extensions/gsd/git-conflict-state.js +21 -0
- package/dist/resources/extensions/gsd/git-service.js +152 -15
- package/dist/resources/extensions/gsd/gsd-db.js +76 -33
- package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -3
- package/dist/resources/extensions/gsd/guided-flow.js +110 -117
- package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
- package/dist/resources/extensions/gsd/init-wizard.js +17 -2
- package/dist/resources/extensions/gsd/markdown-renderer.js +14 -11
- package/dist/resources/extensions/gsd/mcp-filter.js +58 -0
- package/dist/resources/extensions/gsd/migrate/parsers.js +121 -2
- 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 +57 -14
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -0
- 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/planning-path-scope.js +9 -3
- package/dist/resources/extensions/gsd/post-execution-checks.js +73 -9
- package/dist/resources/extensions/gsd/pre-execution-checks.js +54 -19
- package/dist/resources/extensions/gsd/preferences-mcp.js +19 -0
- package/dist/resources/extensions/gsd/preferences-models.js +6 -4
- package/dist/resources/extensions/gsd/preferences-types.js +3 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +147 -0
- package/dist/resources/extensions/gsd/preferences.js +35 -0
- 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/forensics.md +3 -3
- 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/reactive-execute.md +1 -1
- 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/repo-identity.js +39 -22
- package/dist/resources/extensions/gsd/repository-registry.js +44 -0
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +2 -0
- package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +42 -18
- package/dist/resources/extensions/gsd/session-lock.js +15 -2
- package/dist/resources/extensions/gsd/slice-parallel-conflict.js +2 -2
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +84 -5
- 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 +28 -7
- package/dist/resources/extensions/gsd/status-guards.js +14 -2
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- 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 +15 -9
- package/dist/resources/extensions/gsd/tools/complete-slice.js +56 -10
- package/dist/resources/extensions/gsd/tools/exec-tool.js +87 -5
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
- package/dist/resources/extensions/gsd/tools/plan-slice.js +151 -15
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +32 -1
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +185 -40
- package/dist/resources/extensions/gsd/tui/render-kit.js +33 -0
- package/dist/resources/extensions/gsd/unit-context-composer.js +2 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +69 -17
- package/dist/resources/extensions/gsd/validation.js +23 -1
- package/dist/resources/extensions/gsd/verification-gate.js +142 -7
- package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
- package/dist/resources/extensions/gsd/watch/header-renderer.js +34 -25
- package/dist/resources/extensions/gsd/workflow-manifest.js +2 -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 +86 -19
- package/dist/resources/extensions/gsd/worktree-manager.js +11 -2
- package/dist/resources/extensions/gsd/worktree-safety.js +43 -4
- package/dist/resources/extensions/gsd/worktree-state-projection.js +31 -0
- package/dist/resources/extensions/gsd/worktree-telemetry.js +32 -0
- package/dist/resources/extensions/shared/html-shell.js +388 -0
- package/dist/resources/extensions/shared/interview-ui.js +6 -4
- package/dist/resources/extensions/shared/next-action-ui.js +13 -5
- 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/resources/skills/forensics/SKILL.md +1 -1
- 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 +8 -8
- 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/required-server-files.json +1 -1
- 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 +8 -8
- 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-8c10ec293ae0f1d5.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/dist/web/standalone/server.js +1 -1
- package/dist/welcome-screen.js +7 -8
- package/package.json +4 -4
- 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 +13 -4
- 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.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/src/__tests__/stream-process.test.mjs +32 -12
- 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-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/package.json +1 -1
- 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/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/compaction/compaction.d.ts +6 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js +7 -2
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +14 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.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/modes/interactive/components/__tests__/tool-execution.test.js +8 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +16 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.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/components/tool-execution.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.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 +82 -97
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +7 -7
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +11 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.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/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/compaction/compaction.test.ts +23 -1
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +7 -2
- package/packages/pi-coding-agent/src/core/sdk.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +17 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +20 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +3 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +91 -102
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +15 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +9 -9
- 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/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/loader.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/loader.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/loader.test.js +24 -0
- package/packages/pi-tui/dist/__tests__/loader.test.js.map +1 -0
- 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/__tests__/tui.test.js +72 -4
- package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
- package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/loader.js +3 -0
- package/packages/pi-tui/dist/components/loader.js.map +1 -1
- 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 +1 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +117 -33
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/loader.test.ts +30 -0
- package/packages/pi-tui/src/__tests__/terminal.test.ts +121 -0
- package/packages/pi-tui/src/__tests__/tui.test.ts +90 -4
- package/packages/pi-tui/src/components/loader.ts +3 -0
- package/packages/pi-tui/src/terminal.ts +11 -0
- package/packages/pi-tui/src/tui.ts +116 -33
- 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/claude-code-cli/partial-builder.ts +2 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +52 -6
- 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 +49 -2
- package/src/resources/extensions/cmux/index.ts +6 -0
- package/src/resources/extensions/gsd/auto/contracts.ts +19 -6
- package/src/resources/extensions/gsd/auto/detect-stuck.ts +1 -0
- package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
- package/src/resources/extensions/gsd/auto/loop.ts +123 -40
- package/src/resources/extensions/gsd/auto/orchestrator.ts +15 -4
- package/src/resources/extensions/gsd/auto/phases.ts +172 -60
- package/src/resources/extensions/gsd/auto/session.ts +16 -0
- package/src/resources/extensions/gsd/auto/types.ts +3 -0
- package/src/resources/extensions/gsd/auto/unit-runner-events.ts +6 -2
- 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-budget.ts +11 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +78 -5
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +1 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +208 -29
- package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +369 -148
- package/src/resources/extensions/gsd/auto-prompts.ts +36 -13
- package/src/resources/extensions/gsd/auto-recovery.ts +86 -13
- package/src/resources/extensions/gsd/auto-start.ts +109 -14
- package/src/resources/extensions/gsd/auto-timers.ts +10 -3
- package/src/resources/extensions/gsd/auto-verification.ts +174 -42
- package/src/resources/extensions/gsd/auto-worktree.ts +202 -30
- package/src/resources/extensions/gsd/auto.ts +172 -81
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +66 -10
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +13 -10
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +13 -4
- package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +27 -10
- package/src/resources/extensions/gsd/clean-root-preflight.ts +284 -8
- package/src/resources/extensions/gsd/commands/catalog.ts +10 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +41 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +21 -0
- package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +2 -0
- package/src/resources/extensions/gsd/commands-mcp-status.ts +8 -0
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +17 -4
- package/src/resources/extensions/gsd/commands-verdict.ts +202 -0
- package/src/resources/extensions/gsd/crash-recovery.ts +55 -6
- package/src/resources/extensions/gsd/db/auto-workers.ts +37 -0
- 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-base-schema.ts +2 -0
- package/src/resources/extensions/gsd/db-migration-steps.ts +5 -0
- package/src/resources/extensions/gsd/db-task-slice-rows.ts +4 -0
- package/src/resources/extensions/gsd/dispatch-guard.ts +60 -2
- package/src/resources/extensions/gsd/docs/preferences-reference.md +10 -0
- package/src/resources/extensions/gsd/doctor-git-checks.ts +73 -3
- package/src/resources/extensions/gsd/doctor-proactive.ts +18 -2
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
- package/src/resources/extensions/gsd/doctor-types.ts +2 -0
- package/src/resources/extensions/gsd/doctor.ts +2 -27
- package/src/resources/extensions/gsd/export-html.ts +27 -427
- package/src/resources/extensions/gsd/forensics.ts +9 -3
- package/src/resources/extensions/gsd/git-conflict-state.ts +23 -0
- package/src/resources/extensions/gsd/git-service.ts +182 -16
- package/src/resources/extensions/gsd/gsd-db.ts +80 -31
- package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -3
- package/src/resources/extensions/gsd/guided-flow.ts +142 -134
- package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
- package/src/resources/extensions/gsd/init-wizard.ts +17 -2
- package/src/resources/extensions/gsd/journal.ts +8 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +14 -11
- package/src/resources/extensions/gsd/mcp-filter.ts +80 -0
- package/src/resources/extensions/gsd/migrate/parsers.ts +139 -2
- 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 +63 -14
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +3 -0
- 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/planning-path-scope.ts +10 -2
- package/src/resources/extensions/gsd/post-execution-checks.ts +87 -12
- package/src/resources/extensions/gsd/pre-execution-checks.ts +67 -19
- package/src/resources/extensions/gsd/preferences-mcp.ts +27 -0
- package/src/resources/extensions/gsd/preferences-models.ts +6 -4
- package/src/resources/extensions/gsd/preferences-types.ts +35 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +154 -0
- package/src/resources/extensions/gsd/preferences.ts +39 -0
- 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/forensics.md +3 -3
- 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/reactive-execute.md +1 -1
- 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/repo-identity.ts +45 -25
- package/src/resources/extensions/gsd/repository-registry.ts +77 -0
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +2 -0
- package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +54 -19
- package/src/resources/extensions/gsd/session-lock.ts +15 -2
- package/src/resources/extensions/gsd/slice-parallel-conflict.ts +2 -2
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +75 -3
- 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 +33 -7
- package/src/resources/extensions/gsd/status-guards.ts +16 -2
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- 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/artifact-retry-cap.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +10 -1
- 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 +775 -34
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +245 -28
- 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 +136 -13
- package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +12 -0
- 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-workers.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
- package/src/resources/extensions/gsd/tests/autocomplete-regressions-1675.test.ts +21 -0
- 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 +170 -3
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +32 -4
- 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 +55 -2
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +60 -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 +104 -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-task-slice-rows.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +61 -2
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +139 -1
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +68 -1
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +140 -1
- package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +99 -1
- package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +15 -1
- package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +28 -0
- 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/init-prefs-routing.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +36 -1
- package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +226 -2
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +5 -21
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/interrupted-session-auto.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +49 -3
- package/src/resources/extensions/gsd/tests/journal.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +287 -0
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +21 -40
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +59 -1
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
- package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +60 -0
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +80 -2
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
- package/src/resources/extensions/gsd/tests/parallel-orchestrator-zombie-cleanup.test.ts +55 -0
- 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.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 +343 -3
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +18 -1
- 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 +105 -3
- package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +8 -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 +147 -0
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/preferences-mcp.test.ts +128 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/prefs-missing-models-crash.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +42 -1
- 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/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/repo-identity-worktree.test.ts +28 -1
- package/src/resources/extensions/gsd/tests/repository-registry.test.ts +52 -0
- package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +2 -3
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +59 -1
- package/src/resources/extensions/gsd/tests/slice-parallel-conflict.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +112 -1
- package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +94 -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 +17 -1
- package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +131 -9
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +111 -1
- package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +29 -2
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +42 -1
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +188 -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 +153 -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 +73 -2
- package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +59 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +18 -10
- package/src/resources/extensions/gsd/tools/complete-slice.ts +57 -10
- package/src/resources/extensions/gsd/tools/exec-tool.ts +98 -5
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
- package/src/resources/extensions/gsd/tools/plan-slice.ts +172 -12
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +31 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +166 -17
- package/src/resources/extensions/gsd/tui/render-kit.ts +44 -0
- package/src/resources/extensions/gsd/types.ts +1 -1
- package/src/resources/extensions/gsd/unit-context-composer.ts +3 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +86 -19
- package/src/resources/extensions/gsd/validation.ts +23 -1
- package/src/resources/extensions/gsd/verification-gate.ts +170 -6
- package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
- package/src/resources/extensions/gsd/watch/header-renderer.ts +35 -24
- package/src/resources/extensions/gsd/workflow-manifest.ts +2 -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 +98 -20
- package/src/resources/extensions/gsd/worktree-manager.ts +14 -2
- package/src/resources/extensions/gsd/worktree-safety.ts +57 -10
- package/src/resources/extensions/gsd/worktree-state-projection.ts +43 -0
- package/src/resources/extensions/gsd/worktree-telemetry.ts +39 -0
- package/src/resources/extensions/shared/html-shell.ts +412 -0
- package/src/resources/extensions/shared/interview-ui.ts +6 -4
- package/src/resources/extensions/shared/next-action-ui.ts +11 -5
- package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +15 -0
- package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +32 -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/src/resources/skills/forensics/SKILL.md +1 -1
- 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-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/{YEvjuT-fsFfYQhDSWtueS → w_ikFkx_-OHxisG9xjz4u}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{YEvjuT-fsFfYQhDSWtueS → w_ikFkx_-OHxisG9xjz4u}/_ssgManifest.js +0 -0
|
@@ -38,6 +38,25 @@ import { registerWorker, updateWorker } from "./worker-registry.js";
|
|
|
38
38
|
import { loadEffectiveGSDPreferences } from "../gsd/preferences.js";
|
|
39
39
|
import { emitJournalEvent } from "../gsd/journal.js";
|
|
40
40
|
import { CmuxClient, shellEscape } from "../cmux/index.js";
|
|
41
|
+
import {
|
|
42
|
+
buildShellEnvAssignments,
|
|
43
|
+
buildSubagentProcessArgs,
|
|
44
|
+
createSubagentLaunchPlan,
|
|
45
|
+
isSubagentChildProcess,
|
|
46
|
+
type SubagentContextMode,
|
|
47
|
+
type SubagentSessionArgs,
|
|
48
|
+
} from "./launch.js";
|
|
49
|
+
import {
|
|
50
|
+
SubagentRunStore,
|
|
51
|
+
createInitialRunRecord,
|
|
52
|
+
createSubagentTrackingName,
|
|
53
|
+
deriveRunStatus,
|
|
54
|
+
type SubagentChildArtifact,
|
|
55
|
+
type SubagentRunMode,
|
|
56
|
+
type SubagentRunStatus,
|
|
57
|
+
} from "./run-store.js";
|
|
58
|
+
|
|
59
|
+
export { buildSubagentProcessArgs } from "./launch.js";
|
|
41
60
|
|
|
42
61
|
const MAX_PARALLEL_TASKS = 8;
|
|
43
62
|
const MAX_CONCURRENCY = 4;
|
|
@@ -187,15 +206,19 @@ interface UsageStats {
|
|
|
187
206
|
|
|
188
207
|
interface SingleResult {
|
|
189
208
|
agent: string;
|
|
209
|
+
trackingName?: string;
|
|
190
210
|
agentSource: "user" | "project" | "unknown";
|
|
191
211
|
task: string;
|
|
192
212
|
exitCode: number;
|
|
213
|
+
running?: boolean;
|
|
193
214
|
messages: Message[];
|
|
194
215
|
stderr: string;
|
|
195
216
|
usage: UsageStats;
|
|
196
217
|
model?: string;
|
|
197
218
|
stopReason?: string;
|
|
198
219
|
errorMessage?: string;
|
|
220
|
+
sessionFile?: string;
|
|
221
|
+
mergeResult?: MergeResult;
|
|
199
222
|
step?: number;
|
|
200
223
|
}
|
|
201
224
|
|
|
@@ -261,21 +284,6 @@ function writePromptToTempFile(agentName: string, prompt: string): { dir: string
|
|
|
261
284
|
return { dir: tmpDir, filePath };
|
|
262
285
|
}
|
|
263
286
|
|
|
264
|
-
export function buildSubagentProcessArgs(
|
|
265
|
-
agent: AgentConfig,
|
|
266
|
-
task: string,
|
|
267
|
-
tmpPromptPath: string | null,
|
|
268
|
-
modelOverride?: string,
|
|
269
|
-
): string[] {
|
|
270
|
-
const args: string[] = ["--mode", "json", "-p", "--no-session"];
|
|
271
|
-
const effectiveModel = modelOverride ?? agent.model;
|
|
272
|
-
if (effectiveModel) args.push("--model", effectiveModel);
|
|
273
|
-
if (agent.tools && agent.tools.length > 0) args.push("--tools", agent.tools.join(","));
|
|
274
|
-
if (tmpPromptPath) args.push("--append-system-prompt", tmpPromptPath);
|
|
275
|
-
args.push(`Task: ${task}`);
|
|
276
|
-
return args;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
287
|
function processSubagentEventLine(
|
|
280
288
|
line: string,
|
|
281
289
|
currentResult: SingleResult,
|
|
@@ -329,6 +337,71 @@ async function waitForFile(filePath: string, signal: AbortSignal | undefined, ti
|
|
|
329
337
|
|
|
330
338
|
type OnUpdateCallback = (partial: AgentToolResult<SubagentDetails>) => void;
|
|
331
339
|
|
|
340
|
+
interface TaskParam {
|
|
341
|
+
agent: string;
|
|
342
|
+
task: string;
|
|
343
|
+
cwd?: string;
|
|
344
|
+
model?: string;
|
|
345
|
+
context?: SubagentContextMode;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
interface ChainParam extends TaskParam {}
|
|
349
|
+
|
|
350
|
+
function resultStatus(result: SingleResult): SubagentRunStatus {
|
|
351
|
+
if (result.stopReason === "aborted") return "interrupted";
|
|
352
|
+
return result.exitCode === 0 ? "succeeded" : "failed";
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function resultToChildArtifact(result: SingleResult, index: number, cwd?: string): SubagentChildArtifact {
|
|
356
|
+
const running = result.running === true || result.exitCode === -1;
|
|
357
|
+
return {
|
|
358
|
+
index,
|
|
359
|
+
agent: result.agent,
|
|
360
|
+
trackingName: result.trackingName,
|
|
361
|
+
task: result.task,
|
|
362
|
+
status: running ? "running" : resultStatus(result),
|
|
363
|
+
exitCode: result.exitCode,
|
|
364
|
+
cwd,
|
|
365
|
+
sessionFile: result.sessionFile,
|
|
366
|
+
completedAt: running ? undefined : new Date().toISOString(),
|
|
367
|
+
output: getFinalOutput(result.messages),
|
|
368
|
+
stderr: result.stderr || undefined,
|
|
369
|
+
errorMessage: result.errorMessage,
|
|
370
|
+
stopReason: result.stopReason,
|
|
371
|
+
model: result.model,
|
|
372
|
+
usage: result.usage,
|
|
373
|
+
merge: result.mergeResult
|
|
374
|
+
? {
|
|
375
|
+
success: result.mergeResult.success,
|
|
376
|
+
appliedPatches: result.mergeResult.appliedPatches,
|
|
377
|
+
failedPatches: result.mergeResult.failedPatches,
|
|
378
|
+
error: result.mergeResult.error,
|
|
379
|
+
}
|
|
380
|
+
: undefined,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function formatAgentLabel(agent: string, trackingName?: string): string {
|
|
385
|
+
return trackingName ? `${trackingName} / ${agent}` : agent;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function formatRunRecord(record: ReturnType<SubagentRunStore["get"]>): string {
|
|
389
|
+
if (!record) return "Subagent run not found.";
|
|
390
|
+
const lines = [
|
|
391
|
+
`Run ${record.runId}: ${record.status}`,
|
|
392
|
+
`Mode: ${record.mode}`,
|
|
393
|
+
`Context: ${record.contextMode}`,
|
|
394
|
+
`Updated: ${record.updatedAt}`,
|
|
395
|
+
];
|
|
396
|
+
for (const child of record.children) {
|
|
397
|
+
const exit = child.exitCode === undefined ? "" : ` (exit ${child.exitCode})`;
|
|
398
|
+
lines.push(`- [${child.status}] ${formatAgentLabel(child.agent, child.trackingName)}${exit}: ${child.output || child.errorMessage || child.stderr || child.task}`);
|
|
399
|
+
if (child.sessionFile) lines.push(` session: ${child.sessionFile}`);
|
|
400
|
+
}
|
|
401
|
+
if (record.failure) lines.push(`Failure: ${record.failure.message}`);
|
|
402
|
+
return lines.join("\n");
|
|
403
|
+
}
|
|
404
|
+
|
|
332
405
|
async function runSingleAgent(
|
|
333
406
|
defaultCwd: string,
|
|
334
407
|
agents: AgentConfig[],
|
|
@@ -340,6 +413,10 @@ async function runSingleAgent(
|
|
|
340
413
|
onUpdate: OnUpdateCallback | undefined,
|
|
341
414
|
makeDetails: (results: SingleResult[]) => SubagentDetails,
|
|
342
415
|
modelOverride?: string,
|
|
416
|
+
contextMode: SubagentContextMode = "fresh",
|
|
417
|
+
parentSessionManager?: Parameters<typeof createSubagentLaunchPlan>[0]["parentSessionManager"],
|
|
418
|
+
sessionOverride?: SubagentSessionArgs,
|
|
419
|
+
trackingName?: string,
|
|
343
420
|
): Promise<SingleResult> {
|
|
344
421
|
const agent = agents.find((a) => a.name === agentName);
|
|
345
422
|
|
|
@@ -347,6 +424,7 @@ async function runSingleAgent(
|
|
|
347
424
|
const available = agents.map((a) => `"${a.name}"`).join(", ") || "none";
|
|
348
425
|
return {
|
|
349
426
|
agent: agentName,
|
|
427
|
+
trackingName,
|
|
350
428
|
agentSource: "unknown",
|
|
351
429
|
task,
|
|
352
430
|
exitCode: 1,
|
|
@@ -363,6 +441,7 @@ async function runSingleAgent(
|
|
|
363
441
|
if (activePhase && agent.conflictsWith.includes(activePhase)) {
|
|
364
442
|
return {
|
|
365
443
|
agent: agentName,
|
|
444
|
+
trackingName,
|
|
366
445
|
agentSource: agent.source,
|
|
367
446
|
task,
|
|
368
447
|
exitCode: 1,
|
|
@@ -379,9 +458,11 @@ async function runSingleAgent(
|
|
|
379
458
|
|
|
380
459
|
const currentResult: SingleResult = {
|
|
381
460
|
agent: agentName,
|
|
461
|
+
trackingName,
|
|
382
462
|
agentSource: agent.source,
|
|
383
463
|
task,
|
|
384
|
-
exitCode:
|
|
464
|
+
exitCode: -1,
|
|
465
|
+
running: true,
|
|
385
466
|
messages: [],
|
|
386
467
|
stderr: "",
|
|
387
468
|
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, contextTokens: 0, turns: 0 },
|
|
@@ -404,7 +485,18 @@ async function runSingleAgent(
|
|
|
404
485
|
tmpPromptDir = tmp.dir;
|
|
405
486
|
tmpPromptPath = tmp.filePath;
|
|
406
487
|
}
|
|
407
|
-
const
|
|
488
|
+
const launch = createSubagentLaunchPlan({
|
|
489
|
+
agent,
|
|
490
|
+
task,
|
|
491
|
+
tmpPromptPath,
|
|
492
|
+
modelOverride,
|
|
493
|
+
contextMode,
|
|
494
|
+
parentSessionManager,
|
|
495
|
+
session: sessionOverride,
|
|
496
|
+
cwd,
|
|
497
|
+
defaultCwd,
|
|
498
|
+
});
|
|
499
|
+
if (launch.session.mode === "fork") currentResult.sessionFile = launch.session.sessionFile;
|
|
408
500
|
let wasAborted = false;
|
|
409
501
|
|
|
410
502
|
const exitCode = await new Promise<number>((resolve) => {
|
|
@@ -412,8 +504,8 @@ async function runSingleAgent(
|
|
|
412
504
|
const extensionArgs = bundledPaths.flatMap(p => ["--extension", p]);
|
|
413
505
|
const proc = spawn(
|
|
414
506
|
process.execPath,
|
|
415
|
-
[process.env.GSD_BIN_PATH!, ...extensionArgs, ...args],
|
|
416
|
-
{ cwd: cwd
|
|
507
|
+
[process.env.GSD_BIN_PATH!, ...extensionArgs, ...launch.args],
|
|
508
|
+
{ cwd: launch.cwd, env: launch.env, shell: false, stdio: ["ignore", "pipe", "pipe"] },
|
|
417
509
|
);
|
|
418
510
|
liveSubagentProcesses.add(proc);
|
|
419
511
|
let buffer = "";
|
|
@@ -454,6 +546,7 @@ async function runSingleAgent(
|
|
|
454
546
|
});
|
|
455
547
|
|
|
456
548
|
currentResult.exitCode = exitCode;
|
|
549
|
+
currentResult.running = false;
|
|
457
550
|
if (wasAborted) throw new Error("Subagent was aborted");
|
|
458
551
|
return currentResult;
|
|
459
552
|
} finally {
|
|
@@ -485,10 +578,14 @@ async function runSingleAgentInCmuxSplit(
|
|
|
485
578
|
onUpdate: OnUpdateCallback | undefined,
|
|
486
579
|
makeDetails: (results: SingleResult[]) => SubagentDetails,
|
|
487
580
|
modelOverride?: string,
|
|
581
|
+
contextMode: SubagentContextMode = "fresh",
|
|
582
|
+
parentSessionManager?: Parameters<typeof createSubagentLaunchPlan>[0]["parentSessionManager"],
|
|
583
|
+
sessionOverride?: SubagentSessionArgs,
|
|
584
|
+
trackingName?: string,
|
|
488
585
|
): Promise<SingleResult> {
|
|
489
586
|
const agent = agents.find((a) => a.name === agentName);
|
|
490
587
|
if (!agent) {
|
|
491
|
-
return runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, signal, onUpdate, makeDetails, modelOverride);
|
|
588
|
+
return runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, signal, onUpdate, makeDetails, modelOverride, contextMode, parentSessionManager, sessionOverride, trackingName);
|
|
492
589
|
}
|
|
493
590
|
|
|
494
591
|
let tmpPromptDir: string | null = null;
|
|
@@ -497,9 +594,11 @@ async function runSingleAgentInCmuxSplit(
|
|
|
497
594
|
|
|
498
595
|
const currentResult: SingleResult = {
|
|
499
596
|
agent: agentName,
|
|
597
|
+
trackingName,
|
|
500
598
|
agentSource: agent.source,
|
|
501
599
|
task,
|
|
502
|
-
exitCode:
|
|
600
|
+
exitCode: -1,
|
|
601
|
+
running: true,
|
|
503
602
|
messages: [],
|
|
504
603
|
stderr: "",
|
|
505
604
|
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, contextTokens: 0, turns: 0 },
|
|
@@ -533,33 +632,64 @@ async function runSingleAgentInCmuxSplit(
|
|
|
533
632
|
? await cmuxClient.createSplit(directionOrSurfaceId as "right" | "down" | "left" | "up")
|
|
534
633
|
: directionOrSurfaceId;
|
|
535
634
|
if (!cmuxSurfaceId) {
|
|
536
|
-
return runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, signal, onUpdate, makeDetails, modelOverride);
|
|
635
|
+
return runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, signal, onUpdate, makeDetails, modelOverride, contextMode, parentSessionManager, sessionOverride, trackingName);
|
|
537
636
|
}
|
|
538
637
|
|
|
539
638
|
const bundledPaths = (process.env.GSD_BUNDLED_EXTENSION_PATHS ?? "").split(path.delimiter).map((s) => s.trim()).filter(Boolean);
|
|
540
639
|
const extensionArgs = bundledPaths.flatMap((p) => ["--extension", p]);
|
|
541
|
-
const
|
|
640
|
+
const launch = createSubagentLaunchPlan({
|
|
641
|
+
agent,
|
|
642
|
+
task,
|
|
643
|
+
tmpPromptPath,
|
|
644
|
+
modelOverride,
|
|
645
|
+
contextMode,
|
|
646
|
+
parentSessionManager,
|
|
647
|
+
session: sessionOverride,
|
|
648
|
+
cwd,
|
|
649
|
+
defaultCwd,
|
|
650
|
+
});
|
|
651
|
+
if (launch.session.mode === "fork") currentResult.sessionFile = launch.session.sessionFile;
|
|
652
|
+
const processArgs = [process.env.GSD_BIN_PATH!, ...extensionArgs, ...launch.args];
|
|
542
653
|
// Normalize all paths to forward slashes before embedding in bash strings.
|
|
543
654
|
// On Windows, backslashes are interpreted as escape characters by bash,
|
|
544
655
|
// mangling paths like C:\Users\user into C:Useruser (#1436).
|
|
545
656
|
const bashPath = (p: string) => shellEscape(p.replaceAll("\\", "/"));
|
|
657
|
+
const envPrefix = buildShellEnvAssignments(launch.env).join(" ");
|
|
658
|
+
const commandPrefix = envPrefix ? `${envPrefix} ` : "";
|
|
546
659
|
const innerScript = [
|
|
547
|
-
`cd ${bashPath(cwd
|
|
660
|
+
`cd ${bashPath(launch.cwd)}`,
|
|
548
661
|
"set -o pipefail",
|
|
549
|
-
`${bashPath(process.execPath)} ${processArgs.map(a => bashPath(a)).join(" ")} 2> >(tee ${bashPath(stderrPath)} >&2) | tee ${bashPath(stdoutPath)}`,
|
|
662
|
+
`${commandPrefix}${bashPath(process.execPath)} ${processArgs.map(a => bashPath(a)).join(" ")} 2> >(tee ${bashPath(stderrPath)} >&2) | tee ${bashPath(stdoutPath)}`,
|
|
550
663
|
"status=${PIPESTATUS[0]}",
|
|
551
664
|
`printf '%s' "$status" > ${bashPath(exitPath)}`,
|
|
552
665
|
].join("; ");
|
|
553
666
|
|
|
554
667
|
const sent = await cmuxClient.sendSurface(cmuxSurfaceId, `bash -lc ${shellEscape(innerScript)}`);
|
|
555
668
|
if (!sent) {
|
|
556
|
-
return runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, signal, onUpdate, makeDetails, modelOverride);
|
|
669
|
+
return runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, signal, onUpdate, makeDetails, modelOverride, contextMode, parentSessionManager, sessionOverride, trackingName);
|
|
557
670
|
}
|
|
558
671
|
|
|
559
672
|
const finished = await waitForFile(exitPath, signal);
|
|
560
673
|
if (!finished) {
|
|
674
|
+
// Terminate the child running inside the cmux split: send Ctrl-C
|
|
675
|
+
// so bash interrupts the pipeline and writes the exit code, instead
|
|
676
|
+
// of leaving an orphaned subagent that can keep editing after cancel.
|
|
677
|
+
try {
|
|
678
|
+
await cmuxClient.sendInterrupt(cmuxSurfaceId);
|
|
679
|
+
} catch {
|
|
680
|
+
/* ignore — best-effort */
|
|
681
|
+
}
|
|
682
|
+
// Give the shell a brief window to reap the killed child and write exit.code.
|
|
683
|
+
await waitForFile(exitPath, undefined, 5000);
|
|
561
684
|
currentResult.exitCode = 1;
|
|
685
|
+
currentResult.running = false;
|
|
562
686
|
currentResult.stderr = "cmux split execution timed out or was aborted";
|
|
687
|
+
if (fs.existsSync(stdoutPath)) {
|
|
688
|
+
const stdout = fs.readFileSync(stdoutPath, "utf-8");
|
|
689
|
+
for (const line of stdout.split("\n")) {
|
|
690
|
+
processSubagentEventLine(line, currentResult, emitUpdate);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
563
693
|
return currentResult;
|
|
564
694
|
}
|
|
565
695
|
|
|
@@ -573,6 +703,7 @@ async function runSingleAgentInCmuxSplit(
|
|
|
573
703
|
currentResult.stderr = fs.readFileSync(stderrPath, "utf-8");
|
|
574
704
|
}
|
|
575
705
|
currentResult.exitCode = Number.parseInt(fs.readFileSync(exitPath, "utf-8").trim() || "1", 10) || 0;
|
|
706
|
+
currentResult.running = false;
|
|
576
707
|
return currentResult;
|
|
577
708
|
} finally {
|
|
578
709
|
if (tmpPromptPath)
|
|
@@ -601,6 +732,10 @@ const TaskItem = Type.Object({
|
|
|
601
732
|
task: Type.String({ description: "Task to delegate to the agent" }),
|
|
602
733
|
cwd: Type.Optional(Type.String({ description: "Working directory for the agent process" })),
|
|
603
734
|
model: Type.Optional(Type.String({ description: "Model override for this task (e.g. 'claude-sonnet-4-6')" })),
|
|
735
|
+
context: Type.Optional(StringEnum(["fresh", "fork"] as const, {
|
|
736
|
+
description: 'Context mode for this task. "fresh" keeps the existing isolated context behavior; "fork" branches the parent session.',
|
|
737
|
+
default: "fresh",
|
|
738
|
+
})),
|
|
604
739
|
});
|
|
605
740
|
|
|
606
741
|
const ChainItem = Type.Object({
|
|
@@ -608,6 +743,10 @@ const ChainItem = Type.Object({
|
|
|
608
743
|
task: Type.String({ description: "Task with optional {previous} placeholder for prior output" }),
|
|
609
744
|
cwd: Type.Optional(Type.String({ description: "Working directory for the agent process" })),
|
|
610
745
|
model: Type.Optional(Type.String({ description: "Model override for this step (e.g. 'claude-sonnet-4-6')" })),
|
|
746
|
+
context: Type.Optional(StringEnum(["fresh", "fork"] as const, {
|
|
747
|
+
description: 'Context mode for this step. "fresh" keeps the existing isolated context behavior; "fork" branches the parent session.',
|
|
748
|
+
default: "fresh",
|
|
749
|
+
})),
|
|
611
750
|
});
|
|
612
751
|
|
|
613
752
|
const AgentScopeSchema = StringEnum(["user", "project", "both"] as const, {
|
|
@@ -615,12 +754,27 @@ const AgentScopeSchema = StringEnum(["user", "project", "both"] as const, {
|
|
|
615
754
|
default: "both",
|
|
616
755
|
});
|
|
617
756
|
|
|
757
|
+
const ContextModeSchema = StringEnum(["fresh", "fork"] as const, {
|
|
758
|
+
description: 'Context mode for delegated work. "fresh" is the default existing behavior; "fork" branches the parent session.',
|
|
759
|
+
default: "fresh",
|
|
760
|
+
});
|
|
761
|
+
|
|
762
|
+
const SubagentActionSchema = StringEnum(["launch", "status", "resume"] as const, {
|
|
763
|
+
description: 'Run action. "launch" starts delegated work, "status" inspects a persisted run, and "resume" follows up a child session from a run.',
|
|
764
|
+
default: "launch",
|
|
765
|
+
});
|
|
766
|
+
|
|
618
767
|
const SubagentParams = Type.Object({
|
|
768
|
+
action: Type.Optional(SubagentActionSchema),
|
|
769
|
+
runId: Type.Optional(Type.String({ description: "Persisted subagent run id for status or resume actions" })),
|
|
619
770
|
agent: Type.Optional(Type.String({ description: "Name of the agent to invoke (for single mode)" })),
|
|
620
771
|
task: Type.Optional(Type.String({ description: "Task to delegate (for single mode)" })),
|
|
621
772
|
tasks: Type.Optional(Type.Array(TaskItem, { description: "Array of {agent, task} for parallel execution" })),
|
|
622
773
|
chain: Type.Optional(Type.Array(ChainItem, { description: "Array of {agent, task} for sequential execution" })),
|
|
623
774
|
agentScope: Type.Optional(AgentScopeSchema),
|
|
775
|
+
context: Type.Optional(ContextModeSchema),
|
|
776
|
+
background: Type.Optional(Type.Boolean({ description: "Return after starting the run and keep status in the persisted run record. Default: false.", default: false })),
|
|
777
|
+
followUp: Type.Optional(Type.String({ description: "Follow-up instruction for resume action. Falls back to task when omitted." })),
|
|
624
778
|
confirmProjectAgents: Type.Optional(
|
|
625
779
|
Type.Boolean({ description: "Prompt before running project-local agents. Default: false.", default: false }),
|
|
626
780
|
),
|
|
@@ -638,6 +792,8 @@ const SubagentParams = Type.Object({
|
|
|
638
792
|
});
|
|
639
793
|
|
|
640
794
|
export default function (pi: ExtensionAPI) {
|
|
795
|
+
if (isSubagentChildProcess()) return;
|
|
796
|
+
|
|
641
797
|
pi.on("session_shutdown", async () => {
|
|
642
798
|
await stopLiveSubagents();
|
|
643
799
|
});
|
|
@@ -687,13 +843,18 @@ export default function (pi: ExtensionAPI) {
|
|
|
687
843
|
const confirmProjectAgents = params.confirmProjectAgents ?? false;
|
|
688
844
|
const cmuxClient = CmuxClient.fromPreferences(loadEffectiveGSDPreferences()?.preferences);
|
|
689
845
|
const cmuxSplitsEnabled = cmuxClient.getConfig().splits;
|
|
846
|
+
const runStore = new SubagentRunStore();
|
|
847
|
+
const action = params.action ?? "launch";
|
|
848
|
+
const contextMode: SubagentContextMode = params.context ?? "fresh";
|
|
849
|
+
const taskParams: TaskParam[] = Array.isArray(params.tasks) ? params.tasks as TaskParam[] : [];
|
|
850
|
+
const chainParams: ChainParam[] = Array.isArray(params.chain) ? params.chain as ChainParam[] : [];
|
|
690
851
|
|
|
691
852
|
// Resolve isolation mode
|
|
692
853
|
const isolationMode = readIsolationMode();
|
|
693
854
|
const useIsolation = Boolean(params.isolated) && isolationMode !== "none";
|
|
694
855
|
|
|
695
|
-
const hasChain =
|
|
696
|
-
const hasTasks =
|
|
856
|
+
const hasChain = chainParams.length > 0;
|
|
857
|
+
const hasTasks = taskParams.length > 0;
|
|
697
858
|
const hasSingle = Boolean(params.agent && params.task);
|
|
698
859
|
const modeCount = Number(hasChain) + Number(hasTasks) + Number(hasSingle);
|
|
699
860
|
|
|
@@ -706,6 +867,85 @@ export default function (pi: ExtensionAPI) {
|
|
|
706
867
|
results,
|
|
707
868
|
});
|
|
708
869
|
|
|
870
|
+
if (action === "status") {
|
|
871
|
+
if (!params.runId) {
|
|
872
|
+
return {
|
|
873
|
+
content: [{ type: "text", text: "Status requires runId." }],
|
|
874
|
+
details: makeDetails("single")([]),
|
|
875
|
+
isError: true,
|
|
876
|
+
};
|
|
877
|
+
}
|
|
878
|
+
const record = runStore.get(params.runId);
|
|
879
|
+
return {
|
|
880
|
+
content: [{ type: "text", text: formatRunRecord(record) }],
|
|
881
|
+
details: makeDetails("single")([]),
|
|
882
|
+
...(record ? {} : { isError: true }),
|
|
883
|
+
};
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
if (action === "resume") {
|
|
887
|
+
if (!params.runId) {
|
|
888
|
+
return {
|
|
889
|
+
content: [{ type: "text", text: "Resume requires runId." }],
|
|
890
|
+
details: makeDetails("single")([]),
|
|
891
|
+
isError: true,
|
|
892
|
+
};
|
|
893
|
+
}
|
|
894
|
+
const record = runStore.get(params.runId);
|
|
895
|
+
if (!record) {
|
|
896
|
+
return {
|
|
897
|
+
content: [{ type: "text", text: `Subagent run not found: ${params.runId}` }],
|
|
898
|
+
details: makeDetails("single")([]),
|
|
899
|
+
isError: true,
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
const followUp = params.followUp ?? params.task;
|
|
903
|
+
if (!followUp) {
|
|
904
|
+
return {
|
|
905
|
+
content: [{ type: "text", text: "Resume requires followUp or task." }],
|
|
906
|
+
details: makeDetails("single")([]),
|
|
907
|
+
isError: true,
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
const sessionChildren = record.children.filter((child) => child.sessionFile);
|
|
911
|
+
const matches = params.agent
|
|
912
|
+
? sessionChildren.filter((child) => child.agent === params.agent)
|
|
913
|
+
: sessionChildren;
|
|
914
|
+
const selected = matches.length === 1 ? matches[0] : undefined;
|
|
915
|
+
if (!selected?.sessionFile) {
|
|
916
|
+
const available = sessionChildren.map((child) => formatAgentLabel(child.agent, child.trackingName)).join(", ") || "none";
|
|
917
|
+
return {
|
|
918
|
+
content: [{
|
|
919
|
+
type: "text",
|
|
920
|
+
text: `Resume requires exactly one child session or an agent selector. Available resumable agents: ${available}`,
|
|
921
|
+
}],
|
|
922
|
+
details: makeDetails("single")([]),
|
|
923
|
+
isError: true,
|
|
924
|
+
};
|
|
925
|
+
}
|
|
926
|
+
const result = await runSingleAgent(
|
|
927
|
+
ctx.cwd,
|
|
928
|
+
agents,
|
|
929
|
+
selected.agent,
|
|
930
|
+
followUp,
|
|
931
|
+
selected.cwd,
|
|
932
|
+
undefined,
|
|
933
|
+
signal,
|
|
934
|
+
onUpdate,
|
|
935
|
+
makeDetails("single"),
|
|
936
|
+
params.model,
|
|
937
|
+
"fresh",
|
|
938
|
+
ctx.sessionManager,
|
|
939
|
+
{ mode: "fork", sessionFile: selected.sessionFile, sessionDir: path.dirname(selected.sessionFile) },
|
|
940
|
+
selected.trackingName,
|
|
941
|
+
);
|
|
942
|
+
return {
|
|
943
|
+
content: [{ type: "text", text: getFinalOutput(result.messages) || result.errorMessage || result.stderr || "(no output)" }],
|
|
944
|
+
details: makeDetails("single")([result]),
|
|
945
|
+
...(result.exitCode === 0 ? {} : { isError: true }),
|
|
946
|
+
};
|
|
947
|
+
}
|
|
948
|
+
|
|
709
949
|
if (modeCount !== 1) {
|
|
710
950
|
const available = agents.map((a) => `${a.name} (${a.source})`).join(", ") || "none";
|
|
711
951
|
return {
|
|
@@ -724,16 +964,16 @@ export default function (pi: ExtensionAPI) {
|
|
|
724
964
|
// auto-mode flowId; per-dispatch ids still let us measure frequency, batch size, mode).
|
|
725
965
|
const dispatchMode: "single" | "parallel" | "chain" = hasChain ? "chain" : hasTasks ? "parallel" : "single";
|
|
726
966
|
const dispatchAgents = hasChain
|
|
727
|
-
?
|
|
967
|
+
? chainParams.map((s) => s.agent)
|
|
728
968
|
: hasTasks
|
|
729
|
-
?
|
|
969
|
+
? taskParams.map((t) => t.agent)
|
|
730
970
|
: params.agent
|
|
731
971
|
? [params.agent]
|
|
732
972
|
: [];
|
|
733
973
|
const dispatchTasks = hasChain
|
|
734
|
-
?
|
|
974
|
+
? chainParams.map((s) => s.task)
|
|
735
975
|
: hasTasks
|
|
736
|
-
?
|
|
976
|
+
? taskParams.map((t) => t.task)
|
|
737
977
|
: params.task
|
|
738
978
|
? [params.task]
|
|
739
979
|
: [];
|
|
@@ -741,6 +981,84 @@ export default function (pi: ExtensionAPI) {
|
|
|
741
981
|
const dispatchStartMs = Date.now();
|
|
742
982
|
let finalResults: SingleResult[] = [];
|
|
743
983
|
let dispatchCompletedEmitted = false;
|
|
984
|
+
const usedTrackingNames = new Set<string>();
|
|
985
|
+
const dispatchTrackingNames = dispatchAgents.map(() => {
|
|
986
|
+
const trackingName = createSubagentTrackingName(usedTrackingNames);
|
|
987
|
+
usedTrackingNames.add(trackingName);
|
|
988
|
+
return trackingName;
|
|
989
|
+
});
|
|
990
|
+
const dispatchContextMode: SubagentContextMode =
|
|
991
|
+
hasChain && chainParams.some((step) => (step.context ?? contextMode) === "fork")
|
|
992
|
+
? "fork"
|
|
993
|
+
: hasTasks && taskParams.some((task) => (task.context ?? contextMode) === "fork")
|
|
994
|
+
? "fork"
|
|
995
|
+
: contextMode;
|
|
996
|
+
const dispatchChildren = dispatchAgents.map((agent, index) => ({
|
|
997
|
+
agent,
|
|
998
|
+
trackingName: dispatchTrackingNames[index],
|
|
999
|
+
task: dispatchTasks[index] ?? "",
|
|
1000
|
+
cwd: hasChain
|
|
1001
|
+
? chainParams[index]?.cwd
|
|
1002
|
+
: hasTasks
|
|
1003
|
+
? taskParams[index]?.cwd
|
|
1004
|
+
: params.cwd,
|
|
1005
|
+
}));
|
|
1006
|
+
try {
|
|
1007
|
+
runStore.create(createInitialRunRecord({
|
|
1008
|
+
runId: dispatchId,
|
|
1009
|
+
mode: dispatchMode as SubagentRunMode,
|
|
1010
|
+
contextMode: dispatchContextMode,
|
|
1011
|
+
cwd: ctx.cwd,
|
|
1012
|
+
children: dispatchChildren,
|
|
1013
|
+
}));
|
|
1014
|
+
} catch {
|
|
1015
|
+
// Persistence is observability; execution remains authoritative.
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
const persistRunResults = (results: SingleResult[], completed = false): void => {
|
|
1019
|
+
try {
|
|
1020
|
+
runStore.update(dispatchId, (record) => {
|
|
1021
|
+
const children = [...record.children];
|
|
1022
|
+
for (let index = 0; index < results.length; index++) {
|
|
1023
|
+
const result = results[index];
|
|
1024
|
+
if (!result) continue;
|
|
1025
|
+
children[index] = {
|
|
1026
|
+
...children[index],
|
|
1027
|
+
...resultToChildArtifact(result, index, children[index]?.cwd),
|
|
1028
|
+
};
|
|
1029
|
+
}
|
|
1030
|
+
if (completed) {
|
|
1031
|
+
for (let index = 0; index < children.length; index++) {
|
|
1032
|
+
const child = children[index];
|
|
1033
|
+
if (child.status === "queued" || child.status === "running") {
|
|
1034
|
+
children[index] = {
|
|
1035
|
+
...child,
|
|
1036
|
+
status: "failed",
|
|
1037
|
+
completedAt: new Date().toISOString(),
|
|
1038
|
+
errorMessage: "Subagent run ended before this child completed.",
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
const status = completed ? deriveRunStatus(children) : "running";
|
|
1044
|
+
const failed = children.find((child) => child.status === "failed");
|
|
1045
|
+
const interrupted = children.find((child) => child.status === "interrupted");
|
|
1046
|
+
return {
|
|
1047
|
+
...record,
|
|
1048
|
+
children,
|
|
1049
|
+
status,
|
|
1050
|
+
...(completed && status !== "running" ? { completedAt: new Date().toISOString() } : {}),
|
|
1051
|
+
...(interrupted
|
|
1052
|
+
? { failure: { type: "interrupted" as const, message: interrupted.errorMessage || interrupted.stderr || "Subagent run was interrupted" } }
|
|
1053
|
+
: failed
|
|
1054
|
+
? { failure: { type: failed.merge?.success === false ? "merge-failed" as const : "child-failed" as const, message: failed.errorMessage || failed.stderr || `Subagent ${failed.agent} failed` } }
|
|
1055
|
+
: {}),
|
|
1056
|
+
};
|
|
1057
|
+
});
|
|
1058
|
+
} catch {
|
|
1059
|
+
// Persistence is observability; execution remains authoritative.
|
|
1060
|
+
}
|
|
1061
|
+
};
|
|
744
1062
|
|
|
745
1063
|
emitJournalEvent(ctx.cwd, {
|
|
746
1064
|
ts: new Date().toISOString(),
|
|
@@ -768,10 +1086,20 @@ export default function (pi: ExtensionAPI) {
|
|
|
768
1086
|
});
|
|
769
1087
|
const errorMessageFor = (err: unknown): string =>
|
|
770
1088
|
err instanceof Error ? err.message : String(err || "subagent dispatch failed");
|
|
771
|
-
const makeFailureResult = (
|
|
1089
|
+
const makeFailureResult = (
|
|
1090
|
+
err: unknown,
|
|
1091
|
+
agent: string,
|
|
1092
|
+
task: string,
|
|
1093
|
+
step?: number,
|
|
1094
|
+
trackingName?: string,
|
|
1095
|
+
): SingleResult => {
|
|
772
1096
|
const message = errorMessageFor(err);
|
|
1097
|
+
const dispatchIndex = dispatchAgents.findIndex((dispatchAgent, index) =>
|
|
1098
|
+
dispatchAgent === agent && dispatchTasks[index] === task
|
|
1099
|
+
);
|
|
773
1100
|
return {
|
|
774
1101
|
agent,
|
|
1102
|
+
trackingName: trackingName ?? (dispatchIndex >= 0 ? dispatchTrackingNames[dispatchIndex] : undefined),
|
|
775
1103
|
agentSource: "unknown",
|
|
776
1104
|
task,
|
|
777
1105
|
exitCode: 1,
|
|
@@ -810,6 +1138,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
810
1138
|
dispatchAgents[nextIndex] ?? "unknown",
|
|
811
1139
|
dispatchTasks[nextIndex] ?? "",
|
|
812
1140
|
dispatchMode === "chain" ? nextIndex + 1 : undefined,
|
|
1141
|
+
dispatchTrackingNames[nextIndex],
|
|
813
1142
|
),
|
|
814
1143
|
];
|
|
815
1144
|
}
|
|
@@ -822,6 +1151,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
822
1151
|
agent,
|
|
823
1152
|
dispatchTasks[index] ?? "",
|
|
824
1153
|
dispatchMode === "chain" ? index + 1 : undefined,
|
|
1154
|
+
dispatchTrackingNames[index],
|
|
825
1155
|
),
|
|
826
1156
|
);
|
|
827
1157
|
};
|
|
@@ -829,6 +1159,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
829
1159
|
if (dispatchCompletedEmitted) return;
|
|
830
1160
|
finalResults = results;
|
|
831
1161
|
dispatchCompletedEmitted = true;
|
|
1162
|
+
persistRunResults(results, true);
|
|
832
1163
|
const successCount = results.filter((r) => r.exitCode === 0).length;
|
|
833
1164
|
const failureCount = results.filter((r) => r.exitCode !== 0).length;
|
|
834
1165
|
const totalCost = results.reduce((s, r) => s + (r.usage?.cost ?? 0), 0);
|
|
@@ -856,8 +1187,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
856
1187
|
try {
|
|
857
1188
|
if ((agentScope === "project" || agentScope === "both") && confirmProjectAgents && ctx.hasUI) {
|
|
858
1189
|
const requestedAgentNames = new Set<string>();
|
|
859
|
-
if (
|
|
860
|
-
if (
|
|
1190
|
+
if (hasChain) for (const step of chainParams) requestedAgentNames.add(step.agent);
|
|
1191
|
+
if (hasTasks) for (const t of taskParams) requestedAgentNames.add(t.agent);
|
|
861
1192
|
if (params.agent) requestedAgentNames.add(params.agent);
|
|
862
1193
|
|
|
863
1194
|
const projectAgentsRequested = Array.from(requestedAgentNames)
|
|
@@ -881,29 +1212,103 @@ export default function (pi: ExtensionAPI) {
|
|
|
881
1212
|
}
|
|
882
1213
|
}
|
|
883
1214
|
|
|
884
|
-
if (params.
|
|
1215
|
+
if (params.background) {
|
|
1216
|
+
if (!params.agent || !params.task || hasTasks || hasChain) {
|
|
1217
|
+
const failure = makeFailureResult(
|
|
1218
|
+
new Error("Background launch currently requires single mode with agent and task."),
|
|
1219
|
+
params.agent ?? "unknown",
|
|
1220
|
+
params.task ?? "",
|
|
1221
|
+
);
|
|
1222
|
+
finishDispatch([failure]);
|
|
1223
|
+
return {
|
|
1224
|
+
content: [{ type: "text", text: failure.errorMessage ?? failure.stderr }],
|
|
1225
|
+
details: makeDetails("single")([failure]),
|
|
1226
|
+
isError: true,
|
|
1227
|
+
};
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
void (async () => {
|
|
1231
|
+
let isolation: IsolationEnvironment | null = null;
|
|
1232
|
+
try {
|
|
1233
|
+
const effectiveCwd = params.cwd ?? ctx.cwd;
|
|
1234
|
+
if (useIsolation) {
|
|
1235
|
+
const taskId = crypto.randomUUID();
|
|
1236
|
+
isolation = await createIsolation(effectiveCwd, taskId, isolationMode);
|
|
1237
|
+
}
|
|
1238
|
+
const result = await runSingleAgent(
|
|
1239
|
+
ctx.cwd,
|
|
1240
|
+
agents,
|
|
1241
|
+
params.agent!,
|
|
1242
|
+
params.task!,
|
|
1243
|
+
isolation ? isolation.workDir : params.cwd,
|
|
1244
|
+
undefined,
|
|
1245
|
+
undefined,
|
|
1246
|
+
(partial) => {
|
|
1247
|
+
if (partial.details?.results[0]) persistRunResults([partial.details.results[0]]);
|
|
1248
|
+
},
|
|
1249
|
+
makeDetails("single"),
|
|
1250
|
+
params.model,
|
|
1251
|
+
contextMode,
|
|
1252
|
+
ctx.sessionManager,
|
|
1253
|
+
undefined,
|
|
1254
|
+
dispatchTrackingNames[0],
|
|
1255
|
+
);
|
|
1256
|
+
if (isolation && result.exitCode === 0) {
|
|
1257
|
+
const patches = await isolation.captureDelta();
|
|
1258
|
+
if (patches.length > 0) {
|
|
1259
|
+
const mergeResult = await mergeDeltaPatches(effectiveCwd, patches);
|
|
1260
|
+
result.mergeResult = mergeResult;
|
|
1261
|
+
if (!mergeResult.success) {
|
|
1262
|
+
result.exitCode = 1;
|
|
1263
|
+
result.stopReason = "error";
|
|
1264
|
+
result.errorMessage = `Patch merge failed: ${mergeResult.error || "unknown error"}`;
|
|
1265
|
+
result.stderr = result.stderr || result.errorMessage;
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
finalResults = [result];
|
|
1270
|
+
finishDispatch([result]);
|
|
1271
|
+
} catch (err) {
|
|
1272
|
+
finalResults = synthesizeFailureResults(err);
|
|
1273
|
+
finishDispatch(finalResults);
|
|
1274
|
+
} finally {
|
|
1275
|
+
if (isolation) await isolation.cleanup();
|
|
1276
|
+
}
|
|
1277
|
+
})();
|
|
1278
|
+
|
|
1279
|
+
return {
|
|
1280
|
+
content: [{
|
|
1281
|
+
type: "text",
|
|
1282
|
+
text: `Started background subagent run ${dispatchId}. Use action: "status" with runId: "${dispatchId}" to inspect it.`,
|
|
1283
|
+
}],
|
|
1284
|
+
details: makeDetails("single")([]),
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
if (chainParams.length > 0) {
|
|
885
1289
|
const results: SingleResult[] = [];
|
|
886
1290
|
finalResults = results;
|
|
887
1291
|
let previousOutput = "";
|
|
888
1292
|
|
|
889
|
-
for (let i = 0; i <
|
|
890
|
-
const step =
|
|
1293
|
+
for (let i = 0; i < chainParams.length; i++) {
|
|
1294
|
+
const step = chainParams[i];
|
|
891
1295
|
const taskWithContext = step.task.replace(/\{previous\}/g, previousOutput);
|
|
892
1296
|
|
|
893
1297
|
// Create update callback that includes all previous results
|
|
894
|
-
const chainUpdate: OnUpdateCallback
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
}
|
|
1298
|
+
const chainUpdate: OnUpdateCallback = (partial) => {
|
|
1299
|
+
// Combine completed results with current streaming result
|
|
1300
|
+
const currentResult = partial.details?.results[0];
|
|
1301
|
+
if (currentResult) {
|
|
1302
|
+
const allResults = [...results, currentResult];
|
|
1303
|
+
persistRunResults(allResults);
|
|
1304
|
+
if (onUpdate) {
|
|
1305
|
+
onUpdate({
|
|
1306
|
+
content: partial.content,
|
|
1307
|
+
details: makeDetails("chain")(allResults),
|
|
1308
|
+
});
|
|
905
1309
|
}
|
|
906
|
-
|
|
1310
|
+
}
|
|
1311
|
+
};
|
|
907
1312
|
|
|
908
1313
|
const result = await runSingleAgent(
|
|
909
1314
|
ctx.cwd,
|
|
@@ -916,8 +1321,13 @@ export default function (pi: ExtensionAPI) {
|
|
|
916
1321
|
chainUpdate,
|
|
917
1322
|
makeDetails("chain"),
|
|
918
1323
|
step.model || params.model,
|
|
1324
|
+
step.context ?? contextMode,
|
|
1325
|
+
ctx.sessionManager,
|
|
1326
|
+
undefined,
|
|
1327
|
+
dispatchTrackingNames[i],
|
|
919
1328
|
);
|
|
920
1329
|
results.push(result);
|
|
1330
|
+
persistRunResults(results);
|
|
921
1331
|
|
|
922
1332
|
const isError =
|
|
923
1333
|
result.exitCode !== 0 || result.stopReason === "error" || result.stopReason === "aborted";
|
|
@@ -940,14 +1350,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
940
1350
|
};
|
|
941
1351
|
}
|
|
942
1352
|
|
|
943
|
-
if (
|
|
944
|
-
if (
|
|
1353
|
+
if (taskParams.length > 0) {
|
|
1354
|
+
if (taskParams.length > MAX_PARALLEL_TASKS) {
|
|
945
1355
|
finishDispatch([]);
|
|
946
1356
|
return {
|
|
947
1357
|
content: [
|
|
948
1358
|
{
|
|
949
1359
|
type: "text",
|
|
950
|
-
text: `Too many parallel tasks (${
|
|
1360
|
+
text: `Too many parallel tasks (${taskParams.length}). Max is ${MAX_PARALLEL_TASKS}.`,
|
|
951
1361
|
},
|
|
952
1362
|
],
|
|
953
1363
|
details: makeDetails("parallel")([]),
|
|
@@ -955,14 +1365,15 @@ export default function (pi: ExtensionAPI) {
|
|
|
955
1365
|
}
|
|
956
1366
|
|
|
957
1367
|
// Track all results for streaming updates
|
|
958
|
-
const allResults: SingleResult[] = new Array(
|
|
1368
|
+
const allResults: SingleResult[] = new Array(taskParams.length);
|
|
959
1369
|
|
|
960
1370
|
// Initialize placeholder results
|
|
961
|
-
for (let i = 0; i <
|
|
1371
|
+
for (let i = 0; i < taskParams.length; i++) {
|
|
962
1372
|
allResults[i] = {
|
|
963
|
-
agent:
|
|
1373
|
+
agent: taskParams[i].agent,
|
|
1374
|
+
trackingName: dispatchTrackingNames[i],
|
|
964
1375
|
agentSource: "unknown",
|
|
965
|
-
task:
|
|
1376
|
+
task: taskParams[i].task,
|
|
966
1377
|
exitCode: -1, // -1 = still running
|
|
967
1378
|
messages: [],
|
|
968
1379
|
stderr: "",
|
|
@@ -986,51 +1397,84 @@ export default function (pi: ExtensionAPI) {
|
|
|
986
1397
|
|
|
987
1398
|
const MAX_RETRIES = 1; // Retry failed tasks once
|
|
988
1399
|
const batchId = crypto.randomUUID();
|
|
989
|
-
const batchSize =
|
|
1400
|
+
const batchSize = taskParams.length;
|
|
990
1401
|
// Pre-create a grid layout for cmux splits so agents get a clean tiled arrangement
|
|
991
1402
|
const gridSurfaces = cmuxSplitsEnabled
|
|
992
1403
|
? await cmuxClient.createGridLayout(Math.min(batchSize, MAX_CONCURRENCY))
|
|
993
1404
|
: [];
|
|
994
|
-
const results = await mapWithConcurrencyLimit(
|
|
1405
|
+
const results = await mapWithConcurrencyLimit(taskParams, MAX_CONCURRENCY, async (t, index) => {
|
|
995
1406
|
const workerId = registerWorker(t.agent, t.task, index, batchSize, batchId);
|
|
996
1407
|
const taskModel = t.model || params.model;
|
|
997
|
-
const
|
|
1408
|
+
const updateParallelResult = (partial: AgentToolResult<SubagentDetails>) => {
|
|
1409
|
+
if (partial.details?.results[0]) {
|
|
1410
|
+
allResults[index] = partial.details.results[0];
|
|
1411
|
+
persistRunResults([...allResults]);
|
|
1412
|
+
emitParallelUpdate();
|
|
1413
|
+
}
|
|
1414
|
+
};
|
|
1415
|
+
const executeOnce = (runCwd: string | undefined) => cmuxSplitsEnabled
|
|
998
1416
|
? runSingleAgentInCmuxSplit(
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
)
|
|
1417
|
+
cmuxClient,
|
|
1418
|
+
gridSurfaces[index] ?? (index % 2 === 0 ? "right" : "down"),
|
|
1419
|
+
ctx.cwd,
|
|
1420
|
+
agents,
|
|
1421
|
+
t.agent,
|
|
1422
|
+
t.task,
|
|
1423
|
+
runCwd,
|
|
1424
|
+
undefined,
|
|
1425
|
+
signal,
|
|
1426
|
+
updateParallelResult,
|
|
1427
|
+
makeDetails("parallel"),
|
|
1428
|
+
taskModel,
|
|
1429
|
+
t.context ?? contextMode,
|
|
1430
|
+
ctx.sessionManager,
|
|
1431
|
+
undefined,
|
|
1432
|
+
dispatchTrackingNames[index],
|
|
1433
|
+
)
|
|
1017
1434
|
: runSingleAgent(
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1435
|
+
ctx.cwd,
|
|
1436
|
+
agents,
|
|
1437
|
+
t.agent,
|
|
1438
|
+
t.task,
|
|
1439
|
+
runCwd,
|
|
1440
|
+
undefined,
|
|
1441
|
+
signal,
|
|
1442
|
+
updateParallelResult,
|
|
1443
|
+
makeDetails("parallel"),
|
|
1444
|
+
taskModel,
|
|
1445
|
+
t.context ?? contextMode,
|
|
1446
|
+
ctx.sessionManager,
|
|
1447
|
+
undefined,
|
|
1448
|
+
dispatchTrackingNames[index],
|
|
1449
|
+
);
|
|
1450
|
+
const runTask = async () => {
|
|
1451
|
+
let isolation: IsolationEnvironment | null = null;
|
|
1452
|
+
const effectiveCwd = t.cwd ?? ctx.cwd;
|
|
1453
|
+
try {
|
|
1454
|
+
if (useIsolation) {
|
|
1455
|
+
const taskId = crypto.randomUUID();
|
|
1456
|
+
isolation = await createIsolation(effectiveCwd, taskId, isolationMode);
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
const result = await executeOnce(isolation ? isolation.workDir : t.cwd);
|
|
1460
|
+
if (isolation && result.exitCode === 0) {
|
|
1461
|
+
const patches = await isolation.captureDelta();
|
|
1462
|
+
const mergeResult = patches.length > 0
|
|
1463
|
+
? await mergeDeltaPatches(effectiveCwd, patches)
|
|
1464
|
+
: { success: true, appliedPatches: [], failedPatches: [] };
|
|
1465
|
+
result.mergeResult = mergeResult;
|
|
1466
|
+
if (!mergeResult.success) {
|
|
1467
|
+
result.exitCode = 1;
|
|
1468
|
+
result.stopReason = "error";
|
|
1469
|
+
result.errorMessage = `Patch merge failed: ${mergeResult.error || "unknown error"}`;
|
|
1470
|
+
result.stderr = result.stderr || result.errorMessage;
|
|
1029
1471
|
}
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1472
|
+
}
|
|
1473
|
+
return result;
|
|
1474
|
+
} finally {
|
|
1475
|
+
if (isolation) await isolation.cleanup();
|
|
1476
|
+
}
|
|
1477
|
+
};
|
|
1034
1478
|
let result = await runTask();
|
|
1035
1479
|
|
|
1036
1480
|
// Auto-retry failed tasks (likely API rate limit or transient error)
|
|
@@ -1041,6 +1485,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1041
1485
|
|
|
1042
1486
|
updateWorker(workerId, result.exitCode === 0 ? "completed" : "failed");
|
|
1043
1487
|
allResults[index] = result;
|
|
1488
|
+
persistRunResults([...allResults]);
|
|
1044
1489
|
emitParallelUpdate();
|
|
1045
1490
|
return result;
|
|
1046
1491
|
});
|
|
@@ -1052,7 +1497,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1052
1497
|
const output = isError
|
|
1053
1498
|
? (r.errorMessage || r.stderr || getFinalOutput(r.messages) || "(no output)")
|
|
1054
1499
|
: getFinalOutput(r.messages);
|
|
1055
|
-
return `[${r.agent}] ${r.exitCode === 0 ? "completed" : `failed (exit ${r.exitCode})`}: ${output || "(no output)"}`;
|
|
1500
|
+
return `[${formatAgentLabel(r.agent, r.trackingName)}] ${r.exitCode === 0 ? "completed" : `failed (exit ${r.exitCode})`}: ${output || "(no output)"}`;
|
|
1056
1501
|
});
|
|
1057
1502
|
finishDispatch(results);
|
|
1058
1503
|
return {
|
|
@@ -1077,6 +1522,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
1077
1522
|
isolation = await createIsolation(effectiveCwd, taskId, isolationMode);
|
|
1078
1523
|
}
|
|
1079
1524
|
|
|
1525
|
+
const singleUpdate: OnUpdateCallback = (partial) => {
|
|
1526
|
+
if (partial.details?.results[0]) persistRunResults([partial.details.results[0]]);
|
|
1527
|
+
if (onUpdate) onUpdate(partial);
|
|
1528
|
+
};
|
|
1080
1529
|
const result = cmuxSplitsEnabled
|
|
1081
1530
|
? await runSingleAgentInCmuxSplit(
|
|
1082
1531
|
cmuxClient,
|
|
@@ -1088,9 +1537,13 @@ export default function (pi: ExtensionAPI) {
|
|
|
1088
1537
|
isolation ? isolation.workDir : params.cwd,
|
|
1089
1538
|
undefined,
|
|
1090
1539
|
signal,
|
|
1091
|
-
|
|
1540
|
+
singleUpdate,
|
|
1092
1541
|
makeDetails("single"),
|
|
1093
1542
|
params.model,
|
|
1543
|
+
contextMode,
|
|
1544
|
+
ctx.sessionManager,
|
|
1545
|
+
undefined,
|
|
1546
|
+
dispatchTrackingNames[0],
|
|
1094
1547
|
)
|
|
1095
1548
|
: await runSingleAgent(
|
|
1096
1549
|
ctx.cwd,
|
|
@@ -1100,9 +1553,13 @@ export default function (pi: ExtensionAPI) {
|
|
|
1100
1553
|
isolation ? isolation.workDir : params.cwd,
|
|
1101
1554
|
undefined,
|
|
1102
1555
|
signal,
|
|
1103
|
-
|
|
1556
|
+
singleUpdate,
|
|
1104
1557
|
makeDetails("single"),
|
|
1105
1558
|
params.model,
|
|
1559
|
+
contextMode,
|
|
1560
|
+
ctx.sessionManager,
|
|
1561
|
+
undefined,
|
|
1562
|
+
dispatchTrackingNames[0],
|
|
1106
1563
|
);
|
|
1107
1564
|
finalResults = [result];
|
|
1108
1565
|
|
|
@@ -1111,6 +1568,13 @@ export default function (pi: ExtensionAPI) {
|
|
|
1111
1568
|
const patches = await isolation.captureDelta();
|
|
1112
1569
|
if (patches.length > 0) {
|
|
1113
1570
|
mergeResult = await mergeDeltaPatches(effectiveCwd, patches);
|
|
1571
|
+
result.mergeResult = mergeResult;
|
|
1572
|
+
if (!mergeResult.success) {
|
|
1573
|
+
result.exitCode = 1;
|
|
1574
|
+
result.stopReason = "error";
|
|
1575
|
+
result.errorMessage = `Patch merge failed: ${mergeResult.error || "unknown error"}`;
|
|
1576
|
+
result.stderr = result.stderr || result.errorMessage;
|
|
1577
|
+
}
|
|
1114
1578
|
}
|
|
1115
1579
|
}
|
|
1116
1580
|
|
|
@@ -1152,7 +1616,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1152
1616
|
if (!dispatchCompletedEmitted) finalResults = synthesizeFailureResults(err);
|
|
1153
1617
|
throw err;
|
|
1154
1618
|
} finally {
|
|
1155
|
-
finishDispatch(finalResults);
|
|
1619
|
+
if (!params.background) finishDispatch(finalResults);
|
|
1156
1620
|
}
|
|
1157
1621
|
},
|
|
1158
1622
|
|
|
@@ -1234,7 +1698,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1234
1698
|
|
|
1235
1699
|
if (expanded) {
|
|
1236
1700
|
const container = new Container();
|
|
1237
|
-
let header = `${icon} ${theme.fg("toolTitle", theme.bold(r.agent))}${theme.fg("muted", ` (${r.agentSource})`)}`;
|
|
1701
|
+
let header = `${icon} ${theme.fg("toolTitle", theme.bold(formatAgentLabel(r.agent, r.trackingName)))}${theme.fg("muted", ` (${r.agentSource})`)}`;
|
|
1238
1702
|
if (isError && r.stopReason) header += ` ${theme.fg("error", `[${r.stopReason}]`)}`;
|
|
1239
1703
|
container.addChild(new Text(header, 0, 0));
|
|
1240
1704
|
if (isError && r.errorMessage)
|
|
@@ -1270,7 +1734,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1270
1734
|
return container;
|
|
1271
1735
|
}
|
|
1272
1736
|
|
|
1273
|
-
let text = `${icon} ${theme.fg("toolTitle", theme.bold(r.agent))}${theme.fg("muted", ` (${r.agentSource})`)}`;
|
|
1737
|
+
let text = `${icon} ${theme.fg("toolTitle", theme.bold(formatAgentLabel(r.agent, r.trackingName)))}${theme.fg("muted", ` (${r.agentSource})`)}`;
|
|
1274
1738
|
if (isError && r.stopReason) text += ` ${theme.fg("error", `[${r.stopReason}]`)}`;
|
|
1275
1739
|
if (isError && r.errorMessage) text += `\n${theme.fg("error", `Error: ${r.errorMessage}`)}`;
|
|
1276
1740
|
else if (displayItems.length === 0) text += `\n${theme.fg("muted", "(no output)")}`;
|
|
@@ -1321,7 +1785,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1321
1785
|
container.addChild(new Spacer(1));
|
|
1322
1786
|
container.addChild(
|
|
1323
1787
|
new Text(
|
|
1324
|
-
`${theme.fg("muted", `─── Step ${r.step}: `) + theme.fg("accent", r.agent)} ${rIcon}`,
|
|
1788
|
+
`${theme.fg("muted", `─── Step ${r.step}: `) + theme.fg("accent", formatAgentLabel(r.agent, r.trackingName))} ${rIcon}`,
|
|
1325
1789
|
0,
|
|
1326
1790
|
0,
|
|
1327
1791
|
),
|
|
@@ -1368,7 +1832,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1368
1832
|
for (const r of details.results) {
|
|
1369
1833
|
const rIcon = r.exitCode === 0 ? theme.fg("success", "✓") : theme.fg("error", "✗");
|
|
1370
1834
|
const displayItems = getDisplayItems(r.messages);
|
|
1371
|
-
text += `\n\n${theme.fg("muted", `─── Step ${r.step}: `)}${theme.fg("accent", r.agent)} ${rIcon}`;
|
|
1835
|
+
text += `\n\n${theme.fg("muted", `─── Step ${r.step}: `)}${theme.fg("accent", formatAgentLabel(r.agent, r.trackingName))} ${rIcon}`;
|
|
1372
1836
|
if (displayItems.length === 0) text += `\n${theme.fg("muted", "(no output)")}`;
|
|
1373
1837
|
else text += `\n${renderDisplayItems(displayItems, 5)}`;
|
|
1374
1838
|
}
|
|
@@ -1409,7 +1873,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1409
1873
|
|
|
1410
1874
|
container.addChild(new Spacer(1));
|
|
1411
1875
|
container.addChild(
|
|
1412
|
-
new Text(`${theme.fg("muted", "─── ") + theme.fg("accent", r.agent)} ${rIcon}`, 0, 0),
|
|
1876
|
+
new Text(`${theme.fg("muted", "─── ") + theme.fg("accent", formatAgentLabel(r.agent, r.trackingName))} ${rIcon}`, 0, 0),
|
|
1413
1877
|
);
|
|
1414
1878
|
container.addChild(new Text(theme.fg("muted", "Task: ") + theme.fg("dim", r.task), 0, 0));
|
|
1415
1879
|
|
|
@@ -1454,7 +1918,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1454
1918
|
? theme.fg("success", "✓")
|
|
1455
1919
|
: theme.fg("error", "✗");
|
|
1456
1920
|
const displayItems = getDisplayItems(r.messages);
|
|
1457
|
-
text += `\n\n${theme.fg("muted", "─── ")}${theme.fg("accent", r.agent)} ${rIcon}`;
|
|
1921
|
+
text += `\n\n${theme.fg("muted", "─── ")}${theme.fg("accent", formatAgentLabel(r.agent, r.trackingName))} ${rIcon}`;
|
|
1458
1922
|
if (displayItems.length === 0)
|
|
1459
1923
|
text += `\n${theme.fg("muted", r.exitCode === -1 ? "(running...)" : "(no output)")}`;
|
|
1460
1924
|
else text += `\n${renderDisplayItems(displayItems, 5)}`;
|