agentic-orchestrator 0.1.28 → 0.2.1
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/.claude/settings.local.json +46 -1
- package/.cortexrc +28 -0
- package/.github/agents/copilot-instructions.md +29 -0
- package/.github/copilot-instructions.md +93 -0
- package/.vscode/settings.json +13 -0
- package/.vscode/tms.code-snippets +223 -0
- package/AGENTS.md +72 -1
- package/Agentic-Orchestrator.iml +12 -11
- package/CLAUDE.md +72 -1
- package/CONSTITUTION.md +504 -0
- package/FUTURE-ENHANCEMENTS.md +85 -0
- package/NEXT-TASKS.md +25 -0
- package/PROMPTS.md +161 -0
- package/README.md +126 -29
- package/agentic/orchestrator/agents.yaml +4 -3
- package/agentic/orchestrator/defaults/policy.defaults.yaml +39 -3
- package/agentic/orchestrator/gates.yaml +15 -3
- package/agentic/orchestrator/policy.yaml +47 -3
- package/agentic/orchestrator/prompts/builder.system.md +69 -20
- package/agentic/orchestrator/prompts/planner-intake.system.md +149 -0
- package/agentic/orchestrator/prompts/planner.system.md +113 -40
- package/agentic/orchestrator/prompts/qa.system.md +73 -18
- package/agentic/orchestrator/prompts/reconciler.system.md +119 -0
- package/agentic/orchestrator/schemas/agents.schema.json +89 -1
- package/agentic/orchestrator/schemas/execution-control.schema.json +242 -0
- package/agentic/orchestrator/schemas/index.schema.json +234 -0
- package/agentic/orchestrator/schemas/intake.review.schema.json +82 -0
- package/agentic/orchestrator/schemas/organizer-ordering-artifact.schema.json +75 -0
- package/agentic/orchestrator/schemas/plan.schema.json +44 -0
- package/agentic/orchestrator/schemas/policy.schema.json +238 -9
- package/agentic/orchestrator/schemas/policy.user.schema.json +129 -1
- package/agentic/orchestrator/schemas/spec.manifest.bootstrap.schema.json +101 -0
- package/agentic/orchestrator/schemas/spec.manifest.verified.schema.json +80 -0
- package/agentic/orchestrator/schemas/state.schema.json +298 -3
- package/agentic/orchestrator/tools/catalog.json +145 -15
- package/agentic/orchestrator/tools/schemas/input/doctor.run.input.schema.json +18 -0
- package/agentic/orchestrator/tools/schemas/input/evidence.latest.input.schema.json +4 -0
- package/agentic/orchestrator/tools/schemas/input/evidence.verify_chain.input.schema.json +13 -0
- package/agentic/orchestrator/tools/schemas/input/feature.intake_submit.input.schema.json +11 -0
- package/agentic/orchestrator/tools/schemas/input/feature.question_answer.input.schema.json +15 -0
- package/agentic/orchestrator/tools/schemas/input/feature.question_create.input.schema.json +21 -0
- package/agentic/orchestrator/tools/schemas/input/feature.question_list.input.schema.json +13 -0
- package/agentic/orchestrator/tools/schemas/input/feature.ready_to_merge.input.schema.json +5 -0
- package/agentic/orchestrator/tools/schemas/input/feature.send_message.input.schema.json +1 -1
- package/agentic/orchestrator/tools/schemas/input/replay.timeline_get.input.schema.json +32 -0
- package/agentic/orchestrator/tools/schemas/input/repo.conflict_abort.input.schema.json +16 -0
- package/agentic/orchestrator/tools/schemas/input/repo.conflict_files.input.schema.json +16 -0
- package/agentic/orchestrator/tools/schemas/input/repo.reconcile_mainline.input.schema.json +37 -0
- package/agentic/orchestrator/tools/schemas/input/repo.resolve_conflict.input.schema.json +40 -0
- package/agentic/orchestrator/tools/schemas/input/runtime.execution_request_list.input.schema.json +7 -0
- package/agentic/orchestrator/tools/schemas/input/runtime.execution_request_submit.input.schema.json +25 -0
- package/agentic/orchestrator/tools/schemas/output/doctor.run.output.schema.json +34 -0
- package/agentic/orchestrator/tools/schemas/output/evidence.verify_chain.output.schema.json +23 -0
- package/agentic/orchestrator/tools/schemas/output/feature.get_context.output.schema.json +62 -2
- package/agentic/orchestrator/tools/schemas/output/feature.intake_submit.output.schema.json +24 -0
- package/agentic/orchestrator/tools/schemas/output/feature.question_answer.output.schema.json +21 -0
- package/agentic/orchestrator/tools/schemas/output/feature.question_create.output.schema.json +12 -0
- package/agentic/orchestrator/tools/schemas/output/feature.question_list.output.schema.json +14 -0
- package/agentic/orchestrator/tools/schemas/output/feature.ready_to_merge.output.schema.json +31 -0
- package/agentic/orchestrator/tools/schemas/output/feature.send_message.output.schema.json +8 -18
- package/agentic/orchestrator/tools/schemas/output/replay.timeline_get.output.schema.json +64 -0
- package/agentic/orchestrator/tools/schemas/output/repo.conflict_abort.output.schema.json +16 -0
- package/agentic/orchestrator/tools/schemas/output/repo.conflict_files.output.schema.json +22 -0
- package/agentic/orchestrator/tools/schemas/output/repo.reconcile_mainline.output.schema.json +61 -0
- package/agentic/orchestrator/tools/schemas/output/repo.resolve_conflict.output.schema.json +19 -0
- package/agentic/orchestrator/tools/schemas/output/report.dashboard.output.schema.json +26 -0
- package/agentic/orchestrator/tools/schemas/output/runtime.execution_request_list.output.schema.json +17 -0
- package/agentic/orchestrator/tools/schemas/output/runtime.execution_request_submit.output.schema.json +24 -0
- package/agentic/orchestrator/tools.md +13 -0
- package/apps/control-plane/scripts/validate-mcp-contracts.ts +1 -1
- package/apps/control-plane/src/application/kernel-tool-wiring.ts +140 -2
- package/apps/control-plane/src/application/services/activity-monitor-service.ts +44 -1
- package/apps/control-plane/src/application/services/bootstrap-manifest-generator-service.ts +251 -0
- package/apps/control-plane/src/application/services/checkpoint-service.ts +87 -27
- package/apps/control-plane/src/application/services/collision-override-service.ts +906 -0
- package/apps/control-plane/src/application/services/collision-queue-service.ts +129 -38
- package/apps/control-plane/src/application/services/cost-tracking-service.ts +94 -0
- package/apps/control-plane/src/application/services/execution-control-service.ts +599 -0
- package/apps/control-plane/src/application/services/feature-deletion-service.ts +37 -1
- package/apps/control-plane/src/application/services/feature-lifecycle-service.ts +182 -4
- package/apps/control-plane/src/application/services/feature-send-message-service.ts +17 -8
- package/apps/control-plane/src/application/services/feature-state-service.ts +191 -6
- package/apps/control-plane/src/application/services/gate-service.ts +121 -2
- package/apps/control-plane/src/application/services/git-reconciliation-service.ts +1591 -0
- package/apps/control-plane/src/application/services/intake-service.ts +1468 -0
- package/apps/control-plane/src/application/services/merge-service.ts +308 -17
- package/apps/control-plane/src/application/services/notifier-service.ts +3 -1
- package/apps/control-plane/src/application/services/performance-analytics-service.ts +75 -0
- package/apps/control-plane/src/application/services/plan-service.ts +336 -20
- package/apps/control-plane/src/application/services/question-service.ts +693 -0
- package/apps/control-plane/src/application/services/reactions-service.ts +73 -17
- package/apps/control-plane/src/application/services/replay-timeline-service.ts +295 -0
- package/apps/control-plane/src/application/services/reporting-service.ts +194 -10
- package/apps/control-plane/src/application/services/run-lease-service.ts +121 -5
- package/apps/control-plane/src/application/services/worktree-watchdog-service.ts +95 -8
- package/apps/control-plane/src/application/tools/tool-metadata.ts +7 -0
- package/apps/control-plane/src/application/usage-types.ts +138 -0
- package/apps/control-plane/src/cli/add-command-handler.ts +162 -0
- package/apps/control-plane/src/cli/answer-command-handler.ts +113 -0
- package/apps/control-plane/src/cli/attach-command-handler.ts +12 -3
- package/apps/control-plane/src/cli/cli-argument-parser.ts +133 -11
- package/apps/control-plane/src/cli/collision-command-handler.ts +113 -0
- package/apps/control-plane/src/cli/command-catalog.ts +479 -0
- package/apps/control-plane/src/cli/complete-command-handler.ts +23 -0
- package/apps/control-plane/src/cli/completion-command-handler.ts +25 -0
- package/apps/control-plane/src/cli/completion-resolver.ts +319 -0
- package/apps/control-plane/src/cli/completion-shell-renderer.ts +58 -0
- package/apps/control-plane/src/cli/dashboard-command-handler.ts +111 -1
- package/apps/control-plane/src/cli/dashboard-runtime-runner.ts +1036 -0
- package/apps/control-plane/src/cli/dashboard-runtime.ts +31 -0
- package/apps/control-plane/src/cli/help-command-handler.ts +17 -185
- package/apps/control-plane/src/cli/init-command-handler.ts +51 -6
- package/apps/control-plane/src/cli/merge-command-handler.ts +200 -0
- package/apps/control-plane/src/cli/questions-command-handler.ts +70 -0
- package/apps/control-plane/src/cli/replay-command-handler.ts +98 -0
- package/apps/control-plane/src/cli/resume-command-handler.ts +231 -16
- package/apps/control-plane/src/cli/retry-command-handler.ts +229 -17
- package/apps/control-plane/src/cli/retry-resume-decision.ts +75 -0
- package/apps/control-plane/src/cli/rollback-command-handler.ts +4 -2
- package/apps/control-plane/src/cli/run-command-handler.ts +35 -1
- package/apps/control-plane/src/cli/spec-ingestion-service.ts +45 -55
- package/apps/control-plane/src/cli/spec-preparation.ts +114 -0
- package/apps/control-plane/src/cli/spec-utils.ts +90 -11
- package/apps/control-plane/src/cli/status-command-handler.ts +122 -0
- package/apps/control-plane/src/cli/types.ts +41 -3
- package/apps/control-plane/src/core/collisions.ts +150 -31
- package/apps/control-plane/src/core/constants.ts +18 -1
- package/apps/control-plane/src/core/error-codes.ts +39 -0
- package/apps/control-plane/src/core/execution-control.ts +56 -0
- package/apps/control-plane/src/core/feature-resume-phase.ts +118 -0
- package/apps/control-plane/src/core/gate-freshness.ts +359 -0
- package/apps/control-plane/src/core/gate-log-extractor.ts +97 -0
- package/apps/control-plane/src/core/gates.ts +90 -1
- package/apps/control-plane/src/core/intake-artifacts.ts +295 -0
- package/apps/control-plane/src/core/kernel-types.ts +11 -0
- package/apps/control-plane/src/core/kernel.ts +604 -16
- package/apps/control-plane/src/core/mainline-conflict.ts +22 -0
- package/apps/control-plane/src/core/merge-repair.ts +149 -0
- package/apps/control-plane/src/core/path-layout.ts +46 -2
- package/apps/control-plane/src/core/path-rules.ts +11 -3
- package/apps/control-plane/src/core/plan-submit-recovery.ts +130 -0
- package/apps/control-plane/src/core/questions.ts +49 -0
- package/apps/control-plane/src/core/runtime-sessions.ts +4 -0
- package/apps/control-plane/src/core/schemas.ts +40 -1
- package/apps/control-plane/src/core/tool-caller.ts +25 -1
- package/apps/control-plane/src/core/utils/index-normalizer.ts +25 -4
- package/apps/control-plane/src/core/worktree-diff.ts +66 -0
- package/apps/control-plane/src/index.ts +29 -1
- package/apps/control-plane/src/interfaces/cli/bootstrap.ts +300 -6
- package/apps/control-plane/src/mcp/kernel-tool-executor.ts +17 -0
- package/apps/control-plane/src/mcp/tool-runtime.ts +63 -4
- package/apps/control-plane/src/providers/api-worker-provider.ts +62 -15
- package/apps/control-plane/src/providers/cli-worker-provider.ts +1037 -61
- package/apps/control-plane/src/providers/output-parsers/generic-output-parser.ts +99 -1
- package/apps/control-plane/src/providers/output-parsers/types.ts +2 -0
- package/apps/control-plane/src/providers/provider-defaults.ts +116 -7
- package/apps/control-plane/src/providers/providers.ts +225 -21
- package/apps/control-plane/src/providers/worker-provider-factory.ts +26 -2
- package/apps/control-plane/src/supervisor/artifact-stager.ts +52 -0
- package/apps/control-plane/src/supervisor/build-wave-executor.ts +477 -166
- package/apps/control-plane/src/supervisor/execution-enrollment-service.ts +408 -0
- package/apps/control-plane/src/supervisor/organizer-enrollment-scheduler.ts +117 -0
- package/apps/control-plane/src/supervisor/organizer-sidecar-service.ts +394 -0
- package/apps/control-plane/src/supervisor/plan-conformance-scorer.ts +2 -5
- package/apps/control-plane/src/supervisor/planner-phase.ts +85 -0
- package/apps/control-plane/src/supervisor/planning-wave-executor.ts +993 -64
- package/apps/control-plane/src/supervisor/prompt-bundle-loader.ts +20 -1
- package/apps/control-plane/src/supervisor/qa-wave-executor.ts +384 -177
- package/apps/control-plane/src/supervisor/run-coordinator.ts +723 -20
- package/apps/control-plane/src/supervisor/runtime.ts +485 -9
- package/apps/control-plane/src/supervisor/session-orchestrator.ts +220 -1
- package/apps/control-plane/src/supervisor/types.ts +152 -1
- package/apps/control-plane/src/supervisor/worker-decision-loop.ts +1030 -92
- package/apps/control-plane/test/activity-monitor.spec.ts +76 -0
- package/apps/control-plane/test/add-command-handler.spec.ts +189 -0
- package/apps/control-plane/test/application/services/feature-state-service.spec.ts +208 -0
- package/apps/control-plane/test/artifact-stager.spec.ts +93 -0
- package/apps/control-plane/test/batch-operations.spec.ts +58 -0
- package/apps/control-plane/test/bootstrap-edge-cases.spec.ts +50 -2
- package/apps/control-plane/test/bootstrap-manifest-generator-service.spec.ts +99 -0
- package/apps/control-plane/test/bootstrap.spec.ts +177 -4
- package/apps/control-plane/test/checkpoint-service.spec.ts +977 -29
- package/apps/control-plane/test/cli-argument-parser.spec.ts +119 -0
- package/apps/control-plane/test/cli-helpers.spec.ts +1202 -12
- package/apps/control-plane/test/cli.unit.spec.ts +797 -16
- package/apps/control-plane/test/collision-command-handler.spec.ts +182 -0
- package/apps/control-plane/test/collision-override-service.spec.ts +878 -0
- package/apps/control-plane/test/collision-queue.spec.ts +430 -2
- package/apps/control-plane/test/collisions.spec.ts +209 -1
- package/apps/control-plane/test/core-utils.spec.ts +61 -0
- package/apps/control-plane/test/cost-tracking.spec.ts +224 -0
- package/apps/control-plane/test/dashboard-api.integration.spec.ts +185 -5
- package/apps/control-plane/test/dashboard-client.spec.ts +948 -0
- package/apps/control-plane/test/dashboard-command.spec.ts +138 -6
- package/apps/control-plane/test/dashboard-runtime-runner.spec.ts +1550 -0
- package/apps/control-plane/test/dashboard-runtime.spec.ts +138 -0
- package/apps/control-plane/test/dashboard-ui-utils.spec.ts +56 -12
- package/apps/control-plane/test/dependency-scheduler.spec.ts +7 -1
- package/apps/control-plane/test/env-file.spec.ts +76 -0
- package/apps/control-plane/test/execution-control-service.spec.ts +535 -0
- package/apps/control-plane/test/execution-enrollment-service.spec.ts +648 -0
- package/apps/control-plane/test/feature-lifecycle.spec.ts +126 -0
- package/apps/control-plane/test/feature-resume-phase.spec.ts +164 -0
- package/apps/control-plane/test/feature-send-message-service.spec.ts +161 -0
- package/apps/control-plane/test/feature-state-service.spec.ts +295 -0
- package/apps/control-plane/test/fs.spec.ts +80 -0
- package/apps/control-plane/test/gate-freshness.spec.ts +590 -0
- package/apps/control-plane/test/gate-log-extractor.spec.ts +170 -0
- package/apps/control-plane/test/gates.spec.ts +108 -0
- package/apps/control-plane/test/git-reconciliation-service.spec.ts +2307 -0
- package/apps/control-plane/test/helpers.ts +65 -0
- package/apps/control-plane/test/incremental-gates.spec.ts +271 -0
- package/apps/control-plane/test/index-normalizer.spec.ts +98 -0
- package/apps/control-plane/test/init-wizard.spec.ts +17 -0
- package/apps/control-plane/test/intake-artifacts.spec.ts +203 -0
- package/apps/control-plane/test/intake-service.spec.ts +3176 -0
- package/apps/control-plane/test/kernel-collision-replay.spec.ts +3 -2
- package/apps/control-plane/test/kernel-tool-executor.spec.ts +77 -0
- package/apps/control-plane/test/kernel-tool-wiring.spec.ts +279 -0
- package/apps/control-plane/test/kernel.branches.spec.ts +15 -2
- package/apps/control-plane/test/kernel.coverage.spec.ts +7 -3
- package/apps/control-plane/test/kernel.coverage2.spec.ts +731 -2
- package/apps/control-plane/test/kernel.spec.ts +464 -2
- package/apps/control-plane/test/mainline-conflict.spec.ts +66 -0
- package/apps/control-plane/test/mcp-helpers.spec.ts +79 -0
- package/apps/control-plane/test/mcp.spec.ts +177 -13
- package/apps/control-plane/test/merge-command-handler.spec.ts +531 -0
- package/apps/control-plane/test/merge-service.spec.ts +570 -4
- package/apps/control-plane/test/notifier-service.spec.ts +26 -0
- package/apps/control-plane/test/organizer-enrollment-scheduler.spec.ts +340 -0
- package/apps/control-plane/test/organizer-ordering-artifact.spec.ts +95 -0
- package/apps/control-plane/test/organizer-sidecar-service.spec.ts +468 -0
- package/apps/control-plane/test/output-loop-detector.spec.ts +6 -0
- package/apps/control-plane/test/path-layout.spec.ts +70 -0
- package/apps/control-plane/test/performance-analytics.spec.ts +124 -0
- package/apps/control-plane/test/plan-conformance-scorer.spec.ts +53 -0
- package/apps/control-plane/test/plan-service.spec.ts +686 -4
- package/apps/control-plane/test/planning-wave-executor.spec.ts +3272 -86
- package/apps/control-plane/test/policy-loader-service.spec.ts +5 -0
- package/apps/control-plane/test/prompt-overlay.spec.ts +65 -0
- package/apps/control-plane/test/provider-command-runner-epipe.spec.ts +64 -0
- package/apps/control-plane/test/providers/api-worker-provider.spec.ts +129 -0
- package/apps/control-plane/test/providers/cli-worker-provider.spec.ts +148 -0
- package/apps/control-plane/test/providers/usage-types.spec.ts +98 -0
- package/apps/control-plane/test/providers.spec.ts +293 -16
- package/apps/control-plane/test/question-command-handlers.spec.ts +156 -0
- package/apps/control-plane/test/question-service.spec.ts +1119 -0
- package/apps/control-plane/test/reactions.spec.ts +114 -0
- package/apps/control-plane/test/replay-command-handler.spec.ts +144 -0
- package/apps/control-plane/test/replay-timeline-service.spec.ts +459 -0
- package/apps/control-plane/test/response.spec.ts +31 -0
- package/apps/control-plane/test/resume-command.spec.ts +757 -9
- package/apps/control-plane/test/retry-resume-decision.spec.ts +133 -0
- package/apps/control-plane/test/rollback-command-handler.spec.ts +334 -0
- package/apps/control-plane/test/rollback-command.spec.ts +120 -0
- package/apps/control-plane/test/run-coordinator.spec.ts +3062 -404
- package/apps/control-plane/test/schemas/state.schema.spec.ts +71 -0
- package/apps/control-plane/test/service-retry-paths.spec.ts +112 -0
- package/apps/control-plane/test/services.spec.ts +472 -2
- package/apps/control-plane/test/session-management.spec.ts +346 -1
- package/apps/control-plane/test/spec-ingestion.spec.ts +102 -28
- package/apps/control-plane/test/spec-preparation.spec.ts +182 -0
- package/apps/control-plane/test/supervisor-collaborators.spec.ts +191 -3
- package/apps/control-plane/test/supervisor.calltool.spec.ts +198 -0
- package/apps/control-plane/test/supervisor.spec.ts +95 -16
- package/apps/control-plane/test/supervisor.unit.spec.ts +385 -18
- package/apps/control-plane/test/tool-runtime.spec.ts +122 -0
- package/apps/control-plane/test/worker-decision-loop.spec.ts +3479 -476
- package/apps/control-plane/test/worker-execution-policy.spec.ts +1416 -6
- package/apps/control-plane/test/worker-provider-adapters.spec.ts +1894 -37
- package/apps/control-plane/test/worker-provider-factory.spec.ts +81 -0
- package/apps/control-plane/test/worktree-watchdog-service.spec.ts +125 -0
- package/apps/control-plane/vitest.config.ts +5 -0
- package/config/agentic/orchestrator/agents.yaml +22 -1
- package/config/agentic/orchestrator/gates.yaml +24 -7
- package/config/agentic/orchestrator/policy.yaml +23 -1
- package/config/agentic/orchestrator/prompts/builder.system.md +69 -20
- package/config/agentic/orchestrator/prompts/organizer.system.md +85 -0
- package/config/agentic/orchestrator/prompts/overrides/builder.claude.md +28 -0
- package/config/agentic/orchestrator/prompts/overrides/builder.codex.md +28 -0
- package/config/agentic/orchestrator/prompts/overrides/planner.claude.md +20 -0
- package/config/agentic/orchestrator/prompts/overrides/planner.codex.md +20 -0
- package/config/agentic/orchestrator/prompts/planner-intake.system.md +149 -0
- package/config/agentic/orchestrator/prompts/planner.system.md +113 -40
- package/config/agentic/orchestrator/prompts/qa.system.md +75 -18
- package/config/agentic/orchestrator/prompts/reconciler.system.md +119 -0
- package/dist/apps/control-plane/application/kernel-tool-wiring.d.ts +26 -2
- package/dist/apps/control-plane/application/kernel-tool-wiring.js +40 -2
- package/dist/apps/control-plane/application/kernel-tool-wiring.js.map +1 -1
- package/dist/apps/control-plane/application/services/activity-monitor-service.js +37 -1
- package/dist/apps/control-plane/application/services/activity-monitor-service.js.map +1 -1
- package/dist/apps/control-plane/application/services/bootstrap-manifest-generator-service.d.ts +4 -0
- package/dist/apps/control-plane/application/services/bootstrap-manifest-generator-service.js +188 -0
- package/dist/apps/control-plane/application/services/bootstrap-manifest-generator-service.js.map +1 -0
- package/dist/apps/control-plane/application/services/checkpoint-service.d.ts +5 -0
- package/dist/apps/control-plane/application/services/checkpoint-service.js +69 -24
- package/dist/apps/control-plane/application/services/checkpoint-service.js.map +1 -1
- package/dist/apps/control-plane/application/services/collision-override-service.d.ts +139 -0
- package/dist/apps/control-plane/application/services/collision-override-service.js +568 -0
- package/dist/apps/control-plane/application/services/collision-override-service.js.map +1 -0
- package/dist/apps/control-plane/application/services/collision-queue-service.d.ts +15 -0
- package/dist/apps/control-plane/application/services/collision-queue-service.js +92 -33
- package/dist/apps/control-plane/application/services/collision-queue-service.js.map +1 -1
- package/dist/apps/control-plane/application/services/cost-tracking-service.d.ts +11 -0
- package/dist/apps/control-plane/application/services/cost-tracking-service.js +75 -0
- package/dist/apps/control-plane/application/services/cost-tracking-service.js.map +1 -1
- package/dist/apps/control-plane/application/services/execution-control-service.d.ts +75 -0
- package/dist/apps/control-plane/application/services/execution-control-service.js +421 -0
- package/dist/apps/control-plane/application/services/execution-control-service.js.map +1 -0
- package/dist/apps/control-plane/application/services/feature-deletion-service.d.ts +1 -0
- package/dist/apps/control-plane/application/services/feature-deletion-service.js +23 -1
- package/dist/apps/control-plane/application/services/feature-deletion-service.js.map +1 -1
- package/dist/apps/control-plane/application/services/feature-lifecycle-service.d.ts +24 -1
- package/dist/apps/control-plane/application/services/feature-lifecycle-service.js +132 -3
- package/dist/apps/control-plane/application/services/feature-lifecycle-service.js.map +1 -1
- package/dist/apps/control-plane/application/services/feature-send-message-service.js +16 -8
- package/dist/apps/control-plane/application/services/feature-send-message-service.js.map +1 -1
- package/dist/apps/control-plane/application/services/feature-state-service.d.ts +36 -0
- package/dist/apps/control-plane/application/services/feature-state-service.js +163 -6
- package/dist/apps/control-plane/application/services/feature-state-service.js.map +1 -1
- package/dist/apps/control-plane/application/services/gate-service.d.ts +2 -1
- package/dist/apps/control-plane/application/services/gate-service.js +95 -5
- package/dist/apps/control-plane/application/services/gate-service.js.map +1 -1
- package/dist/apps/control-plane/application/services/git-reconciliation-service.d.ts +92 -0
- package/dist/apps/control-plane/application/services/git-reconciliation-service.js +1097 -0
- package/dist/apps/control-plane/application/services/git-reconciliation-service.js.map +1 -0
- package/dist/apps/control-plane/application/services/intake-service.d.ts +63 -0
- package/dist/apps/control-plane/application/services/intake-service.js +1050 -0
- package/dist/apps/control-plane/application/services/intake-service.js.map +1 -0
- package/dist/apps/control-plane/application/services/merge-service.d.ts +5 -1
- package/dist/apps/control-plane/application/services/merge-service.js +233 -18
- package/dist/apps/control-plane/application/services/merge-service.js.map +1 -1
- package/dist/apps/control-plane/application/services/notifier-service.d.ts +1 -1
- package/dist/apps/control-plane/application/services/notifier-service.js +1 -0
- package/dist/apps/control-plane/application/services/notifier-service.js.map +1 -1
- package/dist/apps/control-plane/application/services/performance-analytics-service.d.ts +11 -0
- package/dist/apps/control-plane/application/services/performance-analytics-service.js +59 -0
- package/dist/apps/control-plane/application/services/performance-analytics-service.js.map +1 -1
- package/dist/apps/control-plane/application/services/plan-service.d.ts +5 -0
- package/dist/apps/control-plane/application/services/plan-service.js +254 -15
- package/dist/apps/control-plane/application/services/plan-service.js.map +1 -1
- package/dist/apps/control-plane/application/services/question-service.d.ts +72 -0
- package/dist/apps/control-plane/application/services/question-service.js +507 -0
- package/dist/apps/control-plane/application/services/question-service.js.map +1 -0
- package/dist/apps/control-plane/application/services/reactions-service.d.ts +2 -0
- package/dist/apps/control-plane/application/services/reactions-service.js +60 -17
- package/dist/apps/control-plane/application/services/reactions-service.js.map +1 -1
- package/dist/apps/control-plane/application/services/replay-timeline-service.d.ts +39 -0
- package/dist/apps/control-plane/application/services/replay-timeline-service.js +205 -0
- package/dist/apps/control-plane/application/services/replay-timeline-service.js.map +1 -0
- package/dist/apps/control-plane/application/services/reporting-service.d.ts +59 -0
- package/dist/apps/control-plane/application/services/reporting-service.js +121 -9
- package/dist/apps/control-plane/application/services/reporting-service.js.map +1 -1
- package/dist/apps/control-plane/application/services/run-lease-service.d.ts +20 -0
- package/dist/apps/control-plane/application/services/run-lease-service.js +81 -4
- package/dist/apps/control-plane/application/services/run-lease-service.js.map +1 -1
- package/dist/apps/control-plane/application/services/worktree-watchdog-service.d.ts +10 -0
- package/dist/apps/control-plane/application/services/worktree-watchdog-service.js +65 -8
- package/dist/apps/control-plane/application/services/worktree-watchdog-service.js.map +1 -1
- package/dist/apps/control-plane/application/tools/tool-metadata.js +7 -0
- package/dist/apps/control-plane/application/tools/tool-metadata.js.map +1 -1
- package/dist/apps/control-plane/application/usage-types.d.ts +65 -0
- package/dist/apps/control-plane/application/usage-types.js +75 -0
- package/dist/apps/control-plane/application/usage-types.js.map +1 -0
- package/dist/apps/control-plane/cli/add-command-handler.d.ts +18 -0
- package/dist/apps/control-plane/cli/add-command-handler.js +110 -0
- package/dist/apps/control-plane/cli/add-command-handler.js.map +1 -0
- package/dist/apps/control-plane/cli/answer-command-handler.d.ts +8 -0
- package/dist/apps/control-plane/cli/answer-command-handler.js +96 -0
- package/dist/apps/control-plane/cli/answer-command-handler.js.map +1 -0
- package/dist/apps/control-plane/cli/attach-command-handler.js +8 -3
- package/dist/apps/control-plane/cli/attach-command-handler.js.map +1 -1
- package/dist/apps/control-plane/cli/cli-argument-parser.js +131 -11
- package/dist/apps/control-plane/cli/cli-argument-parser.js.map +1 -1
- package/dist/apps/control-plane/cli/collision-command-handler.d.ts +8 -0
- package/dist/apps/control-plane/cli/collision-command-handler.js +90 -0
- package/dist/apps/control-plane/cli/collision-command-handler.js.map +1 -0
- package/dist/apps/control-plane/cli/command-catalog.d.ts +21 -0
- package/dist/apps/control-plane/cli/command-catalog.js +416 -0
- package/dist/apps/control-plane/cli/command-catalog.js.map +1 -0
- package/dist/apps/control-plane/cli/complete-command-handler.d.ts +15 -0
- package/dist/apps/control-plane/cli/complete-command-handler.js +26 -0
- package/dist/apps/control-plane/cli/complete-command-handler.js.map +1 -0
- package/dist/apps/control-plane/cli/completion-command-handler.d.ts +8 -0
- package/dist/apps/control-plane/cli/completion-command-handler.js +20 -0
- package/dist/apps/control-plane/cli/completion-command-handler.js.map +1 -0
- package/dist/apps/control-plane/cli/completion-resolver.d.ts +1 -0
- package/dist/apps/control-plane/cli/completion-resolver.js +250 -0
- package/dist/apps/control-plane/cli/completion-resolver.js.map +1 -0
- package/dist/apps/control-plane/cli/completion-shell-renderer.d.ts +3 -0
- package/dist/apps/control-plane/cli/completion-shell-renderer.js +53 -0
- package/dist/apps/control-plane/cli/completion-shell-renderer.js.map +1 -0
- package/dist/apps/control-plane/cli/dashboard-command-handler.d.ts +1 -0
- package/dist/apps/control-plane/cli/dashboard-command-handler.js +84 -1
- package/dist/apps/control-plane/cli/dashboard-command-handler.js.map +1 -1
- package/dist/apps/control-plane/cli/dashboard-runtime-runner.d.ts +81 -0
- package/dist/apps/control-plane/cli/dashboard-runtime-runner.js +724 -0
- package/dist/apps/control-plane/cli/dashboard-runtime-runner.js.map +1 -0
- package/dist/apps/control-plane/cli/dashboard-runtime.d.ts +1 -0
- package/dist/apps/control-plane/cli/dashboard-runtime.js +26 -0
- package/dist/apps/control-plane/cli/dashboard-runtime.js.map +1 -0
- package/dist/apps/control-plane/cli/help-command-handler.js +13 -172
- package/dist/apps/control-plane/cli/help-command-handler.js.map +1 -1
- package/dist/apps/control-plane/cli/init-command-handler.js +51 -6
- package/dist/apps/control-plane/cli/init-command-handler.js.map +1 -1
- package/dist/apps/control-plane/cli/merge-command-handler.d.ts +8 -0
- package/dist/apps/control-plane/cli/merge-command-handler.js +139 -0
- package/dist/apps/control-plane/cli/merge-command-handler.js.map +1 -0
- package/dist/apps/control-plane/cli/questions-command-handler.d.ts +8 -0
- package/dist/apps/control-plane/cli/questions-command-handler.js +59 -0
- package/dist/apps/control-plane/cli/questions-command-handler.js.map +1 -0
- package/dist/apps/control-plane/cli/replay-command-handler.d.ts +15 -0
- package/dist/apps/control-plane/cli/replay-command-handler.js +55 -0
- package/dist/apps/control-plane/cli/replay-command-handler.js.map +1 -0
- package/dist/apps/control-plane/cli/resume-command-handler.d.ts +2 -0
- package/dist/apps/control-plane/cli/resume-command-handler.js +180 -17
- package/dist/apps/control-plane/cli/resume-command-handler.js.map +1 -1
- package/dist/apps/control-plane/cli/retry-command-handler.js +202 -16
- package/dist/apps/control-plane/cli/retry-command-handler.js.map +1 -1
- package/dist/apps/control-plane/cli/retry-resume-decision.d.ts +26 -0
- package/dist/apps/control-plane/cli/retry-resume-decision.js +61 -0
- package/dist/apps/control-plane/cli/retry-resume-decision.js.map +1 -0
- package/dist/apps/control-plane/cli/rollback-command-handler.js +3 -2
- package/dist/apps/control-plane/cli/rollback-command-handler.js.map +1 -1
- package/dist/apps/control-plane/cli/run-command-handler.js +26 -2
- package/dist/apps/control-plane/cli/run-command-handler.js.map +1 -1
- package/dist/apps/control-plane/cli/spec-ingestion-service.d.ts +2 -0
- package/dist/apps/control-plane/cli/spec-ingestion-service.js +37 -48
- package/dist/apps/control-plane/cli/spec-ingestion-service.js.map +1 -1
- package/dist/apps/control-plane/cli/spec-preparation.d.ts +14 -0
- package/dist/apps/control-plane/cli/spec-preparation.js +81 -0
- package/dist/apps/control-plane/cli/spec-preparation.js.map +1 -0
- package/dist/apps/control-plane/cli/spec-utils.d.ts +4 -0
- package/dist/apps/control-plane/cli/spec-utils.js +70 -11
- package/dist/apps/control-plane/cli/spec-utils.js.map +1 -1
- package/dist/apps/control-plane/cli/status-command-handler.js +69 -0
- package/dist/apps/control-plane/cli/status-command-handler.js.map +1 -1
- package/dist/apps/control-plane/cli/types.d.ts +41 -4
- package/dist/apps/control-plane/cli/types.js +9 -1
- package/dist/apps/control-plane/cli/types.js.map +1 -1
- package/dist/apps/control-plane/core/collisions.d.ts +37 -19
- package/dist/apps/control-plane/core/collisions.js +87 -12
- package/dist/apps/control-plane/core/collisions.js.map +1 -1
- package/dist/apps/control-plane/core/constants.d.ts +17 -1
- package/dist/apps/control-plane/core/constants.js +18 -1
- package/dist/apps/control-plane/core/constants.js.map +1 -1
- package/dist/apps/control-plane/core/error-codes.d.ts +39 -0
- package/dist/apps/control-plane/core/error-codes.js +39 -0
- package/dist/apps/control-plane/core/error-codes.js.map +1 -1
- package/dist/apps/control-plane/core/execution-control.d.ts +45 -0
- package/dist/apps/control-plane/core/execution-control.js +2 -0
- package/dist/apps/control-plane/core/execution-control.js.map +1 -0
- package/dist/apps/control-plane/core/feature-resume-phase.d.ts +3 -0
- package/dist/apps/control-plane/core/feature-resume-phase.js +88 -0
- package/dist/apps/control-plane/core/feature-resume-phase.js.map +1 -0
- package/dist/apps/control-plane/core/gate-freshness.d.ts +48 -0
- package/dist/apps/control-plane/core/gate-freshness.js +267 -0
- package/dist/apps/control-plane/core/gate-freshness.js.map +1 -0
- package/dist/apps/control-plane/core/gate-log-extractor.d.ts +22 -0
- package/dist/apps/control-plane/core/gate-log-extractor.js +66 -0
- package/dist/apps/control-plane/core/gate-log-extractor.js.map +1 -0
- package/dist/apps/control-plane/core/gates.d.ts +11 -2
- package/dist/apps/control-plane/core/gates.js +67 -3
- package/dist/apps/control-plane/core/gates.js.map +1 -1
- package/dist/apps/control-plane/core/intake-artifacts.d.ts +109 -0
- package/dist/apps/control-plane/core/intake-artifacts.js +143 -0
- package/dist/apps/control-plane/core/intake-artifacts.js.map +1 -0
- package/dist/apps/control-plane/core/kernel-types.d.ts +8 -0
- package/dist/apps/control-plane/core/kernel.d.ts +256 -8
- package/dist/apps/control-plane/core/kernel.js +400 -14
- package/dist/apps/control-plane/core/kernel.js.map +1 -1
- package/dist/apps/control-plane/core/mainline-conflict.d.ts +7 -0
- package/dist/apps/control-plane/core/mainline-conflict.js +20 -0
- package/dist/apps/control-plane/core/mainline-conflict.js.map +1 -0
- package/dist/apps/control-plane/core/merge-repair.d.ts +35 -0
- package/dist/apps/control-plane/core/merge-repair.js +99 -0
- package/dist/apps/control-plane/core/merge-repair.js.map +1 -0
- package/dist/apps/control-plane/core/path-layout.d.ts +10 -0
- package/dist/apps/control-plane/core/path-layout.js +32 -2
- package/dist/apps/control-plane/core/path-layout.js.map +1 -1
- package/dist/apps/control-plane/core/path-rules.js +9 -3
- package/dist/apps/control-plane/core/path-rules.js.map +1 -1
- package/dist/apps/control-plane/core/plan-submit-recovery.d.ts +22 -0
- package/dist/apps/control-plane/core/plan-submit-recovery.js +78 -0
- package/dist/apps/control-plane/core/plan-submit-recovery.js.map +1 -0
- package/dist/apps/control-plane/core/questions.d.ts +40 -0
- package/dist/apps/control-plane/core/questions.js +2 -0
- package/dist/apps/control-plane/core/questions.js.map +1 -0
- package/dist/apps/control-plane/core/runtime-sessions.d.ts +4 -0
- package/dist/apps/control-plane/core/schemas.d.ts +2 -0
- package/dist/apps/control-plane/core/schemas.js +31 -1
- package/dist/apps/control-plane/core/schemas.js.map +1 -1
- package/dist/apps/control-plane/core/tool-caller.d.ts +18 -1
- package/dist/apps/control-plane/core/utils/index-normalizer.js +17 -4
- package/dist/apps/control-plane/core/utils/index-normalizer.js.map +1 -1
- package/dist/apps/control-plane/core/worktree-diff.d.ts +4 -0
- package/dist/apps/control-plane/core/worktree-diff.js +52 -0
- package/dist/apps/control-plane/core/worktree-diff.js.map +1 -0
- package/dist/apps/control-plane/index.d.ts +10 -2
- package/dist/apps/control-plane/index.js +9 -2
- package/dist/apps/control-plane/index.js.map +1 -1
- package/dist/apps/control-plane/interfaces/cli/bootstrap.js +236 -6
- package/dist/apps/control-plane/interfaces/cli/bootstrap.js.map +1 -1
- package/dist/apps/control-plane/mcp/kernel-tool-executor.js +16 -0
- package/dist/apps/control-plane/mcp/kernel-tool-executor.js.map +1 -1
- package/dist/apps/control-plane/mcp/tool-runtime.d.ts +5 -0
- package/dist/apps/control-plane/mcp/tool-runtime.js +40 -5
- package/dist/apps/control-plane/mcp/tool-runtime.js.map +1 -1
- package/dist/apps/control-plane/providers/api-worker-provider.d.ts +2 -2
- package/dist/apps/control-plane/providers/api-worker-provider.js +40 -9
- package/dist/apps/control-plane/providers/api-worker-provider.js.map +1 -1
- package/dist/apps/control-plane/providers/cli-worker-provider.d.ts +59 -3
- package/dist/apps/control-plane/providers/cli-worker-provider.js +758 -46
- package/dist/apps/control-plane/providers/cli-worker-provider.js.map +1 -1
- package/dist/apps/control-plane/providers/output-parsers/generic-output-parser.js +91 -1
- package/dist/apps/control-plane/providers/output-parsers/generic-output-parser.js.map +1 -1
- package/dist/apps/control-plane/providers/output-parsers/types.d.ts +2 -0
- package/dist/apps/control-plane/providers/provider-defaults.d.ts +12 -0
- package/dist/apps/control-plane/providers/provider-defaults.js +103 -7
- package/dist/apps/control-plane/providers/provider-defaults.js.map +1 -1
- package/dist/apps/control-plane/providers/providers.d.ts +50 -4
- package/dist/apps/control-plane/providers/providers.js +145 -14
- package/dist/apps/control-plane/providers/providers.js.map +1 -1
- package/dist/apps/control-plane/providers/worker-provider-factory.d.ts +2 -0
- package/dist/apps/control-plane/providers/worker-provider-factory.js +8 -1
- package/dist/apps/control-plane/providers/worker-provider-factory.js.map +1 -1
- package/dist/apps/control-plane/supervisor/artifact-stager.d.ts +5 -0
- package/dist/apps/control-plane/supervisor/artifact-stager.js +45 -0
- package/dist/apps/control-plane/supervisor/artifact-stager.js.map +1 -0
- package/dist/apps/control-plane/supervisor/build-wave-executor.d.ts +24 -1
- package/dist/apps/control-plane/supervisor/build-wave-executor.js +362 -150
- package/dist/apps/control-plane/supervisor/build-wave-executor.js.map +1 -1
- package/dist/apps/control-plane/supervisor/execution-enrollment-service.d.ts +41 -0
- package/dist/apps/control-plane/supervisor/execution-enrollment-service.js +311 -0
- package/dist/apps/control-plane/supervisor/execution-enrollment-service.js.map +1 -0
- package/dist/apps/control-plane/supervisor/organizer-enrollment-scheduler.d.ts +15 -0
- package/dist/apps/control-plane/supervisor/organizer-enrollment-scheduler.js +93 -0
- package/dist/apps/control-plane/supervisor/organizer-enrollment-scheduler.js.map +1 -0
- package/dist/apps/control-plane/supervisor/organizer-sidecar-service.d.ts +44 -0
- package/dist/apps/control-plane/supervisor/organizer-sidecar-service.js +311 -0
- package/dist/apps/control-plane/supervisor/organizer-sidecar-service.js.map +1 -0
- package/dist/apps/control-plane/supervisor/plan-conformance-scorer.js +2 -5
- package/dist/apps/control-plane/supervisor/plan-conformance-scorer.js.map +1 -1
- package/dist/apps/control-plane/supervisor/planner-phase.d.ts +3 -0
- package/dist/apps/control-plane/supervisor/planner-phase.js +70 -0
- package/dist/apps/control-plane/supervisor/planner-phase.js.map +1 -0
- package/dist/apps/control-plane/supervisor/planning-wave-executor.d.ts +42 -0
- package/dist/apps/control-plane/supervisor/planning-wave-executor.js +753 -55
- package/dist/apps/control-plane/supervisor/planning-wave-executor.js.map +1 -1
- package/dist/apps/control-plane/supervisor/prompt-bundle-loader.js +19 -1
- package/dist/apps/control-plane/supervisor/prompt-bundle-loader.js.map +1 -1
- package/dist/apps/control-plane/supervisor/qa-wave-executor.d.ts +21 -0
- package/dist/apps/control-plane/supervisor/qa-wave-executor.js +287 -156
- package/dist/apps/control-plane/supervisor/qa-wave-executor.js.map +1 -1
- package/dist/apps/control-plane/supervisor/run-coordinator.d.ts +30 -1
- package/dist/apps/control-plane/supervisor/run-coordinator.js +561 -17
- package/dist/apps/control-plane/supervisor/run-coordinator.js.map +1 -1
- package/dist/apps/control-plane/supervisor/runtime.d.ts +84 -0
- package/dist/apps/control-plane/supervisor/runtime.js +393 -3
- package/dist/apps/control-plane/supervisor/runtime.js.map +1 -1
- package/dist/apps/control-plane/supervisor/session-orchestrator.d.ts +54 -0
- package/dist/apps/control-plane/supervisor/session-orchestrator.js +176 -1
- package/dist/apps/control-plane/supervisor/session-orchestrator.js.map +1 -1
- package/dist/apps/control-plane/supervisor/types.d.ts +142 -1
- package/dist/apps/control-plane/supervisor/types.js.map +1 -1
- package/dist/apps/control-plane/supervisor/worker-decision-loop.d.ts +68 -2
- package/dist/apps/control-plane/supervisor/worker-decision-loop.js +723 -89
- package/dist/apps/control-plane/supervisor/worker-decision-loop.js.map +1 -1
- package/docs/core/ARCHITECTURE.md +227 -0
- package/docs/core/DECISIONS.md +94 -0
- package/docs/core/DOMAIN-LOGIC.md +60 -0
- package/docs/core/PATTERNS.md +201 -0
- package/docs/core/TROUBLESHOOTING.md +347 -0
- package/docs/core/intentgraph-dependencies.json +39860 -0
- package/docs/core/intentgraph.index.json +46580 -0
- package/docs/plans/2026-03-10-gate-failure-targeted-repair-design.md +224 -0
- package/docs/plans/2026-03-10-gate-failure-targeted-repair.md +1032 -0
- package/docs/superpowers/plans/2026-03-16-provider-cli-config.md +743 -0
- package/docs/superpowers/plans/2026-03-23-reconcile-divergence-fix.md +777 -0
- package/docs/superpowers/plans/2026-03-28-ordering-agent-implementation.md +1754 -0
- package/docs/superpowers/plans/2026-03-29-drop-zone-and-provider-optimization.md +1108 -0
- package/docs/superpowers/plans/2026-03-29-merge-target-feature-branch.md +685 -0
- package/docs/superpowers/plans/2026-03-29-organizer-sidecar-runtime-loop.md +1289 -0
- package/docs/superpowers/specs/2026-03-23-reconcile-divergence-fix-design.md +118 -0
- package/docs/superpowers/specs/2026-03-28-ordering-agent-spec-audit-design.md +50 -0
- package/docs/superpowers/specs/2026-03-29-drop-zone-and-provider-optimization-design.md +254 -0
- package/docs/superpowers/specs/2026-03-29-merge-target-feature-branch-design.md +152 -0
- package/docs/superpowers/specs/2026-03-29-organizer-sidecar-runtime-loop-design.md +225 -0
- package/package.json +3 -2
- package/packages/web-dashboard/package.json +2 -1
- package/packages/web-dashboard/src/app/analytics/page.tsx +36 -2
- package/packages/web-dashboard/src/app/api/actions/route.ts +274 -63
- package/packages/web-dashboard/src/app/api/actions/status/route.ts +35 -0
- package/packages/web-dashboard/src/app/api/analytics/provider/route.ts +18 -0
- package/packages/web-dashboard/src/app/api/collisions/approve/route.ts +58 -0
- package/packages/web-dashboard/src/app/api/features/[id]/checkpoint-diff/route.ts +36 -0
- package/packages/web-dashboard/src/app/api/features/[id]/checkpoints/route.ts +29 -0
- package/packages/web-dashboard/src/app/api/features/[id]/conflicts/abort/route.ts +29 -0
- package/packages/web-dashboard/src/app/api/features/[id]/conflicts/files/route.ts +30 -0
- package/packages/web-dashboard/src/app/api/features/[id]/conflicts/resolve/route.ts +51 -0
- package/packages/web-dashboard/src/app/api/features/[id]/conflicts/route.ts +75 -0
- package/packages/web-dashboard/src/app/api/features/[id]/diff/route.ts +16 -2
- package/packages/web-dashboard/src/app/api/features/[id]/files/route.ts +26 -0
- package/packages/web-dashboard/src/app/api/features/[id]/gate-history/route.ts +27 -0
- package/packages/web-dashboard/src/app/api/features/[id]/genealogy/route.ts +26 -0
- package/packages/web-dashboard/src/app/api/features/[id]/history/run/[runId]/route.ts +20 -0
- package/packages/web-dashboard/src/app/api/features/[id]/history/runs/route.ts +34 -0
- package/packages/web-dashboard/src/app/api/features/[id]/intake-workspace/route.ts +20 -0
- package/packages/web-dashboard/src/app/api/features/[id]/live-output/route.ts +74 -0
- package/packages/web-dashboard/src/app/api/features/[id]/plan/amend/route.ts +21 -0
- package/packages/web-dashboard/src/app/api/features/[id]/plan-progress/route.ts +20 -0
- package/packages/web-dashboard/src/app/api/features/[id]/planner-artifacts/[artifact]/route.ts +78 -0
- package/packages/web-dashboard/src/app/api/features/[id]/planner-lifecycle/route.ts +20 -0
- package/packages/web-dashboard/src/app/api/features/[id]/planning-workspace/route.ts +20 -0
- package/packages/web-dashboard/src/app/api/features/[id]/questions/[questionId]/answer/route.ts +27 -0
- package/packages/web-dashboard/src/app/api/features/[id]/questions/route.ts +18 -0
- package/packages/web-dashboard/src/app/api/features/[id]/review/route.ts +14 -7
- package/packages/web-dashboard/src/app/api/features/[id]/route.ts +57 -2
- package/packages/web-dashboard/src/app/api/features/[id]/spec/route.ts +30 -0
- package/packages/web-dashboard/src/app/api/features/[id]/triage/route.ts +83 -0
- package/packages/web-dashboard/src/app/api/features/[id]/worker-events/route.ts +40 -0
- package/packages/web-dashboard/src/app/api/launch/preview/route.ts +86 -0
- package/packages/web-dashboard/src/app/api/launch/submit/route.ts +180 -0
- package/packages/web-dashboard/src/app/api/mainline/status/route.ts +74 -0
- package/packages/web-dashboard/src/app/api/merge-queue/route.ts +13 -0
- package/packages/web-dashboard/src/app/api/policy/budget/route.ts +14 -0
- package/packages/web-dashboard/src/app/api/projects/route.ts +11 -7
- package/packages/web-dashboard/src/app/api/reconciler/queue/route.ts +47 -0
- package/packages/web-dashboard/src/app/api/run/route.ts +26 -2
- package/packages/web-dashboard/src/app/api/runtime/events/route.ts +227 -0
- package/packages/web-dashboard/src/app/api/runtime/operations/route.ts +269 -0
- package/packages/web-dashboard/src/app/api/runtime/questions/route.ts +11 -0
- package/packages/web-dashboard/src/app/api/runtime/runs/route.ts +80 -0
- package/packages/web-dashboard/src/app/api/status/route.ts +4 -2
- package/packages/web-dashboard/src/app/feature/[id]/page.tsx +32 -42
- package/packages/web-dashboard/src/app/globals.css +34 -3
- package/packages/web-dashboard/src/app/launch/page.tsx +362 -0
- package/packages/web-dashboard/src/app/layout.tsx +23 -1
- package/packages/web-dashboard/src/app/page.tsx +263 -272
- package/packages/web-dashboard/src/components/dashboard/attention-strip.tsx +52 -0
- package/packages/web-dashboard/src/components/dashboard/collision-approval-drawer.tsx +185 -0
- package/packages/web-dashboard/src/components/dashboard/command-center-header.tsx +102 -0
- package/packages/web-dashboard/src/components/dashboard/mainline-status-banner.tsx +84 -0
- package/packages/web-dashboard/src/components/dashboard/merged-archive.tsx +36 -0
- package/packages/web-dashboard/src/components/dashboard/prioritized-queues.tsx +98 -0
- package/packages/web-dashboard/src/components/dashboard/reconciler-queue-card.tsx +115 -0
- package/packages/web-dashboard/src/components/dashboard/secondary-diagnostics-rail.tsx +48 -0
- package/packages/web-dashboard/src/components/dashboard/task-filter-bar.tsx +74 -0
- package/packages/web-dashboard/src/components/dashboard/triage-drawer.tsx +455 -0
- package/packages/web-dashboard/src/components/diff-viewer.tsx +19 -3
- package/packages/web-dashboard/src/components/evidence-viewer.tsx +65 -51
- package/packages/web-dashboard/src/components/feature-card.tsx +90 -7
- package/packages/web-dashboard/src/components/feature-cost-panel.tsx +112 -11
- package/packages/web-dashboard/src/components/feature-list-view.tsx +25 -4
- package/packages/web-dashboard/src/components/features/runtime-inspector/EventsTimelineView.tsx +260 -0
- package/packages/web-dashboard/src/components/features/runtime-inspector/OperationsListView.tsx +172 -0
- package/packages/web-dashboard/src/components/features/runtime-inspector/RuntimeInspectorPanel.tsx +896 -0
- package/packages/web-dashboard/src/components/filter-bar.tsx +7 -39
- package/packages/web-dashboard/src/components/focus/ActionableRiskList.tsx +46 -0
- package/packages/web-dashboard/src/components/focus/AgentRolePerformanceCard.tsx +200 -0
- package/packages/web-dashboard/src/components/focus/BlockedGuidanceBanner.tsx +149 -0
- package/packages/web-dashboard/src/components/focus/CheckpointInspector.tsx +123 -0
- package/packages/web-dashboard/src/components/focus/CheckpointRail.tsx +118 -0
- package/packages/web-dashboard/src/components/focus/CheckpointScrubber.tsx +249 -0
- package/packages/web-dashboard/src/components/focus/CollisionApprovalBanner.tsx +192 -0
- package/packages/web-dashboard/src/components/focus/CollisionRadar.tsx +136 -0
- package/packages/web-dashboard/src/components/focus/ConflictStatusCard.tsx +52 -0
- package/packages/web-dashboard/src/components/focus/ContextSidebar.tsx +108 -0
- package/packages/web-dashboard/src/components/focus/DiagnosisPanel.tsx +68 -0
- package/packages/web-dashboard/src/components/focus/FeatureDecisionBanner.tsx +68 -0
- package/packages/web-dashboard/src/components/focus/FeatureQuestionAnswerPanel.tsx +167 -0
- package/packages/web-dashboard/src/components/focus/FocusHeader.tsx +54 -0
- package/packages/web-dashboard/src/components/focus/FocusLayout.tsx +283 -0
- package/packages/web-dashboard/src/components/focus/GateFlakinessSummary.tsx +144 -0
- package/packages/web-dashboard/src/components/focus/GenealogyTree.tsx +34 -0
- package/packages/web-dashboard/src/components/focus/HeroBlock.tsx +67 -0
- package/packages/web-dashboard/src/components/focus/LiveAgentConsole.tsx +277 -0
- package/packages/web-dashboard/src/components/focus/MergeQueueCard.tsx +78 -0
- package/packages/web-dashboard/src/components/focus/OperationalSummaryCard.tsx +227 -0
- package/packages/web-dashboard/src/components/focus/PinnedActions.tsx +96 -0
- package/packages/web-dashboard/src/components/focus/PlanAmendmentPanel.tsx +250 -0
- package/packages/web-dashboard/src/components/focus/PlanProgressPanel.tsx +133 -0
- package/packages/web-dashboard/src/components/focus/PlannerArtifactViewer.tsx +158 -0
- package/packages/web-dashboard/src/components/focus/PlannerLifecycleHeader.tsx +141 -0
- package/packages/web-dashboard/src/components/focus/ProgressSnapshotCard.tsx +113 -0
- package/packages/web-dashboard/src/components/focus/RecentMaterialChanges.tsx +69 -0
- package/packages/web-dashboard/src/components/focus/RoleLogViewer.tsx +436 -0
- package/packages/web-dashboard/src/components/focus/RunHistoryBrowser.tsx +62 -0
- package/packages/web-dashboard/src/components/focus/SpecViewer.tsx +172 -0
- package/packages/web-dashboard/src/components/focus/TabBar.tsx +33 -0
- package/packages/web-dashboard/src/components/focus/UsageBurnChart.tsx +212 -0
- package/packages/web-dashboard/src/components/focus/VerificationSummaryCard.tsx +122 -0
- package/packages/web-dashboard/src/components/focus/tabs/ChangesTab.tsx +325 -0
- package/packages/web-dashboard/src/components/focus/tabs/ConflictsTab.tsx +395 -0
- package/packages/web-dashboard/src/components/focus/tabs/GatesQaTab.tsx +38 -0
- package/packages/web-dashboard/src/components/focus/tabs/HistoryTab.tsx +213 -0
- package/packages/web-dashboard/src/components/focus/tabs/IntakeTab.tsx +429 -0
- package/packages/web-dashboard/src/components/focus/tabs/OverviewTab.tsx +217 -0
- package/packages/web-dashboard/src/components/focus/tabs/PlanningTab.tsx +390 -0
- package/packages/web-dashboard/src/components/focus/tabs/ReviewTab.tsx +497 -0
- package/packages/web-dashboard/src/components/focus/tabs/RuntimeTab.tsx +213 -0
- package/packages/web-dashboard/src/components/focus/tabs/TranscriptTab.tsx +315 -0
- package/packages/web-dashboard/src/components/gate-results.tsx +2 -2
- package/packages/web-dashboard/src/components/human-input-panel.tsx +33 -57
- package/packages/web-dashboard/src/components/kanban-board.tsx +4 -0
- package/packages/web-dashboard/src/components/launch/launch-draft-card.tsx +154 -0
- package/packages/web-dashboard/src/components/plan-viewer.tsx +147 -69
- package/packages/web-dashboard/src/components/quick-launch-panel.tsx +20 -47
- package/packages/web-dashboard/src/components/summary-bar.tsx +30 -76
- package/packages/web-dashboard/src/lib/aop-client.ts +2484 -36
- package/packages/web-dashboard/src/lib/blocked-state-guidance.ts +475 -0
- package/packages/web-dashboard/src/lib/collision-radar.ts +136 -0
- package/packages/web-dashboard/src/lib/dashboard-action-states.ts +204 -0
- package/packages/web-dashboard/src/lib/dashboard-runtime-client.ts +439 -0
- package/packages/web-dashboard/src/lib/dashboard-utils.ts +179 -18
- package/packages/web-dashboard/src/lib/drop-zone-utils.ts +92 -0
- package/packages/web-dashboard/src/lib/focus-detail-derivations.ts +958 -0
- package/packages/web-dashboard/src/lib/focus-view.ts +300 -0
- package/packages/web-dashboard/src/lib/health-diagnosis.ts +356 -0
- package/packages/web-dashboard/src/lib/launch-contracts.ts +77 -0
- package/packages/web-dashboard/src/lib/launch-markdown.ts +103 -0
- package/packages/web-dashboard/src/lib/launch-page-preview.ts +89 -0
- package/packages/web-dashboard/src/lib/live-feed.ts +1 -1
- package/packages/web-dashboard/src/lib/multi-project-config.ts +33 -0
- package/packages/web-dashboard/src/lib/orchestrator-tools.ts +881 -60
- package/packages/web-dashboard/src/lib/planner-workspace.ts +1285 -0
- package/packages/web-dashboard/src/lib/review-contracts.ts +5 -3
- package/packages/web-dashboard/src/lib/runtime-files.ts +285 -0
- package/packages/web-dashboard/src/lib/tool-catalog.ts +51 -0
- package/packages/web-dashboard/src/lib/types.ts +731 -3
- package/packages/web-dashboard/src/lib/usage-burn.ts +175 -0
- package/packages/web-dashboard/src/lib/worktree-diff.ts +128 -0
- package/packages/web-dashboard/src/styles/dashboard.module.css +1742 -459
- package/packages/web-dashboard/test/api/actions/route.spec.ts +675 -0
- package/packages/web-dashboard/test/api/features/diff.route.spec.ts +57 -0
- package/packages/web-dashboard/test/api/features/feature.route.spec.ts +99 -0
- package/packages/web-dashboard/test/api/features/live-output.route.spec.ts +123 -0
- package/packages/web-dashboard/test/api/features/plan-amend.route.spec.ts +95 -0
- package/packages/web-dashboard/test/api/features/planner-workspaces.route.spec.ts +162 -0
- package/packages/web-dashboard/test/api/features/question-answer.route.spec.ts +99 -0
- package/packages/web-dashboard/test/api/features/triage.route.spec.ts +195 -0
- package/packages/web-dashboard/test/api/launch/preview.route.spec.ts +149 -0
- package/packages/web-dashboard/test/api/launch/submit.route.spec.ts +382 -0
- package/packages/web-dashboard/test/api/runtime/events/route.spec.ts +164 -0
- package/packages/web-dashboard/test/api/runtime/operations/route.spec.ts +156 -0
- package/packages/web-dashboard/test/api/runtime/runs/route.spec.ts +112 -0
- package/packages/web-dashboard/test/components/changes-tab.spec.tsx +76 -0
- package/packages/web-dashboard/test/components/command-center-root.spec.tsx +87 -0
- package/packages/web-dashboard/test/components/diagnosis-panel.spec.tsx +59 -0
- package/packages/web-dashboard/test/components/feature-card.spec.tsx +45 -0
- package/packages/web-dashboard/test/components/focus-layout.spec.tsx +299 -0
- package/packages/web-dashboard/test/components/gate-results.spec.tsx +39 -0
- package/packages/web-dashboard/test/components/gates-qa-tab.spec.tsx +118 -0
- package/packages/web-dashboard/test/components/human-input-panel.spec.tsx +54 -0
- package/packages/web-dashboard/test/components/intake-tab.spec.tsx +210 -0
- package/packages/web-dashboard/test/components/kanban-board.spec.tsx +35 -0
- package/packages/web-dashboard/test/components/launch-draft-card.spec.tsx +114 -0
- package/packages/web-dashboard/test/components/launch-page.spec.tsx +79 -0
- package/packages/web-dashboard/test/components/overview-tab.spec.tsx +236 -0
- package/packages/web-dashboard/test/components/planning-tab.spec.tsx +202 -0
- package/packages/web-dashboard/test/components/review-tab.spec.tsx +169 -0
- package/packages/web-dashboard/test/components/role-log-viewer.spec.ts +42 -0
- package/packages/web-dashboard/test/components/runtime-inspector.spec.tsx +22 -0
- package/packages/web-dashboard/test/components/runtime-tab.spec.tsx +133 -0
- package/packages/web-dashboard/test/components/transcript-tab.spec.tsx +46 -0
- package/packages/web-dashboard/test/components/triage-drawer.spec.tsx +159 -0
- package/packages/web-dashboard/test/lib/aop-client.spec.ts +235 -0
- package/packages/web-dashboard/test/lib/dashboard-runtime-client.spec.ts +144 -0
- package/packages/web-dashboard/test/lib/focus-detail-derivations.spec.ts +314 -0
- package/packages/web-dashboard/test/lib/focus-view.spec.ts +248 -0
- package/packages/web-dashboard/test/lib/health-diagnosis.spec.ts +277 -0
- package/packages/web-dashboard/test/lib/launch-markdown.spec.ts +36 -0
- package/packages/web-dashboard/test/lib/multi-project-config.spec.ts +54 -0
- package/packages/web-dashboard/test/lib/orchestrator-tools.spec.ts +352 -0
- package/packages/web-dashboard/test/lib/planner-workspace.spec.ts +289 -0
- package/packages/web-dashboard/test/lib/worktree-diff.spec.ts +119 -0
- package/packages/web-dashboard/vitest.config.ts +2 -0
- package/spec-files/completed/agentic_orchestrator_add_feature_to_active_execution_spec.md +557 -0
- package/spec-files/completed/agentic_orchestrator_dashboard_command_center_redesign_spec.md +1147 -0
- package/spec-files/completed/agentic_orchestrator_execution_mode_spec.md +18 -16
- package/spec-files/completed/agentic_orchestrator_feature_focus_view_track_a_spec.md +672 -0
- package/spec-files/completed/agentic_orchestrator_feature_focus_view_track_b_spec.md +794 -0
- package/spec-files/completed/agentic_orchestrator_feature_focus_view_track_c_decision_centric_remediation_spec.md +1037 -0
- package/spec-files/completed/agentic_orchestrator_feature_focus_view_ux_redesign_spec.md +1432 -0
- package/spec-files/completed/agentic_orchestrator_focus_plan_tab_intake_planning_workspace_spec.md +921 -0
- package/spec-files/completed/agentic_orchestrator_intentional_collision_override_spec.md +584 -0
- package/spec-files/completed/agentic_orchestrator_interactive_planning_intake_and_requirements_verification_spec.md +1185 -0
- package/spec-files/completed/agentic_orchestrator_reactive_execution_enrollment_spec.md +864 -0
- package/spec-files/{outstanding → completed}/agentic_orchestrator_runtime_inspection_spec.md +92 -19
- package/spec-files/completed/agentic_orchestrator_scope_aware_run_lease_spec.md +408 -0
- package/spec-files/completed/git-reconciliation-engine.md +827 -0
- package/spec-files/outstanding/agentic_orchestrator_dashboard_quick_launch_and_control_surface_spec.md +331 -0
- package/spec-files/outstanding/agentic_orchestrator_enterprise_governance_dashboard_spec.md +16 -6
- package/spec-files/outstanding/agentic_orchestrator_evidence_integrity_doctor_spec.md +60 -9
- package/spec-files/outstanding/agentic_orchestrator_focus_plan_tab_execution_contract_workspace_spec.md +616 -0
- package/spec-files/outstanding/agentic_orchestrator_headless_standby_dashboard_runtime_spec.md +310 -0
- package/spec-files/outstanding/agentic_orchestrator_human_input_interaction_protocol_spec.md +175 -72
- package/spec-files/outstanding/agentic_orchestrator_interactive_rename_cleanup_spec.md +197 -0
- package/spec-files/outstanding/agentic_orchestrator_interactive_resume_and_reconciliation_disposition_spec.md +412 -0
- package/spec-files/outstanding/agentic_orchestrator_knowledge_canary_spec.md +166 -137
- package/spec-files/outstanding/agentic_orchestrator_observability_replay_spec.md +3 -3
- package/spec-files/outstanding/agentic_orchestrator_phase_specific_agent_profiles_and_token_telemetry_spec.md +303 -0
- package/spec-files/outstanding/agentic_orchestrator_planning_review_quality_spec.md +18 -5
- package/spec-files/outstanding/agentic_orchestrator_policy_stratification_spec.md +225 -0
- package/spec-files/outstanding/agentic_orchestrator_quality_adoption_execution_spec.md +77 -50
- package/spec-files/outstanding/agentic_orchestrator_ready_to_merge_branch_handoff_spec.md +724 -0
- package/spec-files/outstanding/agentic_orchestrator_remove_deterministic_mode_spec.md +263 -0
- package/spec-files/outstanding/agentic_orchestrator_request_more_context_and_dashboard_human_input_spec.md +456 -0
- package/spec-files/outstanding/agentic_orchestrator_spec_coverage_and_reconciliation_enforcement_spec.md +1411 -0
- package/spec-files/outstanding/agentic_orchestrator_spec_ordering_agent_spec.md +370 -0
- package/spec-files/outstanding/shadow_workspace_implementation_spec.md +1 -1
- package/spec-files/progress.md +2026 -120
- package/specs/001-runtime-inspection/checklists/requirements.md +35 -0
- package/specs/001-runtime-inspection/design.md +338 -0
- package/specs/001-runtime-inspection/spec.md +95 -0
- package/specs/002-scope-aware-lease/checklists/requirements.md +35 -0
- package/specs/002-scope-aware-lease/contracts/lease-registry.schema.json +101 -0
- package/specs/002-scope-aware-lease/data-model.md +236 -0
- package/specs/002-scope-aware-lease/plan.md +766 -0
- package/specs/002-scope-aware-lease/quickstart.md +150 -0
- package/specs/002-scope-aware-lease/research.md +135 -0
- package/specs/002-scope-aware-lease/spec.md +128 -0
- package/specs/002-scope-aware-lease/tasks.md +767 -0
- package/tsconfig.json +1 -1
- package/vitest.config.ts +28 -0
- package/ARCHITECTURE_ADHERENCE_ANALYSIS.md +0 -871
- package/packages/web-dashboard/next-env.d.ts +0 -6
- package/packages/web-dashboard/src/components/detail-panel.tsx +0 -1124
- package/packages/web-dashboard/src/components/review-workspace.tsx +0 -1162
- /package/spec-files/{outstanding → completed}/agentic_orchestrator_artifact_database_publishing_spec.md +0 -0
- /package/spec-files/{outstanding → completed}/agentic_orchestrator_cli_shell_tab_completion_spec.md +0 -0
- /package/spec-files/{outstanding → completed}/agentic_orchestrator_dashboard_diff_and_agent_console_spec.md +0 -0
- /package/spec-files/{outstanding → completed}/agentic_orchestrator_performance_improvements_spec.md +0 -0
- /package/spec-files/{outstanding → completed}/agentic_orchestrator_persistent_worker_runtime_spec.md +0 -0
- /package/spec-files/{outstanding → completed}/agentic_orchestrator_provider_auth_bootstrap_spec.md +0 -0
- /package/spec-files/{outstanding → completed}/agentic_orchestrator_real_worker_provider_execution_spec.md +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import crypto from 'node:crypto';
|
|
2
2
|
import fs from 'node:fs/promises';
|
|
3
|
+
import os from 'node:os';
|
|
3
4
|
import path from 'node:path';
|
|
4
5
|
import { ERROR_CODES } from '../core/error-codes.js';
|
|
5
6
|
import {
|
|
@@ -10,11 +11,13 @@ import {
|
|
|
10
11
|
type ProviderSelection,
|
|
11
12
|
type WorkerProviderCapabilities,
|
|
12
13
|
type WorkerRunInput,
|
|
14
|
+
type WorkerRunOutput,
|
|
13
15
|
type WorkerCapabilities,
|
|
14
16
|
type WorkerHandle,
|
|
15
17
|
type WorkerProvider,
|
|
16
18
|
type WorkerSession,
|
|
17
19
|
} from './providers.js';
|
|
20
|
+
import { unavailableUsage } from '../application/usage-types.js';
|
|
18
21
|
import { PROVIDER_CLI_DEFAULTS, type ProviderCommandTemplate } from './provider-defaults.js';
|
|
19
22
|
import type { ProviderOutputParser } from './output-parsers/types.js';
|
|
20
23
|
import { WorkerWatchdog, type WatchdogOutcome } from './worker-watchdog.js';
|
|
@@ -30,6 +33,7 @@ interface CliWorkerProviderOptions {
|
|
|
30
33
|
workerIdleTimeoutMs?: number;
|
|
31
34
|
workerWatchdogPollIntervalMs?: number;
|
|
32
35
|
workerKillGracePeriodMs?: number;
|
|
36
|
+
overlayDir?: string;
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
interface CommandTemplateValues {
|
|
@@ -38,6 +42,13 @@ interface CommandTemplateValues {
|
|
|
38
42
|
featureId: string;
|
|
39
43
|
role: string;
|
|
40
44
|
message?: string;
|
|
45
|
+
model?: string;
|
|
46
|
+
outputLastMessagePath?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface LiveAgentConsoleCapture {
|
|
50
|
+
appendChunk: (chunk: string) => void;
|
|
51
|
+
finalize: (status: 'completed' | 'failed', fallbackContent?: string) => Promise<void>;
|
|
41
52
|
}
|
|
42
53
|
|
|
43
54
|
const CLAUDE_MIN_EFFECTIVE_TIMEOUT_MS = 300_000;
|
|
@@ -55,7 +66,7 @@ const CLI_PROVIDER_CAPABILITIES: WorkerProviderCapabilities = {
|
|
|
55
66
|
supportsAcknowledgment: false,
|
|
56
67
|
};
|
|
57
68
|
|
|
58
|
-
function
|
|
69
|
+
function buildDeterministicWorkerPrompt(
|
|
59
70
|
payload: Record<string, unknown>,
|
|
60
71
|
systemPrompt: string | null,
|
|
61
72
|
): string {
|
|
@@ -67,8 +78,8 @@ function buildStructuredWorkerPrompt(
|
|
|
67
78
|
lines.push(
|
|
68
79
|
'Return exactly one JSON object and nothing else.',
|
|
69
80
|
'Allowed output object forms:',
|
|
70
|
-
'{"type":"PLAN_SUBMISSION|PATCH|NOTE|REQUEST", ...}',
|
|
71
|
-
'{"outputs":[{"type":"PLAN_SUBMISSION|PATCH|NOTE|REQUEST", ...}], ...}',
|
|
81
|
+
'{"type":"PLAN_SUBMISSION|INTAKE_SUBMISSION|PATCH|NOTE|REQUEST", ...}',
|
|
82
|
+
'{"outputs":[{"type":"PLAN_SUBMISSION|INTAKE_SUBMISSION|PATCH|NOTE|REQUEST", ...}], ...}',
|
|
72
83
|
'Do not wrap JSON in markdown code fences.',
|
|
73
84
|
'Worker input payload:',
|
|
74
85
|
JSON.stringify(payload),
|
|
@@ -76,6 +87,234 @@ function buildStructuredWorkerPrompt(
|
|
|
76
87
|
return lines.join('\n');
|
|
77
88
|
}
|
|
78
89
|
|
|
90
|
+
function buildInteractiveWorkerPrompt(
|
|
91
|
+
payload: Record<string, unknown>,
|
|
92
|
+
systemPrompt: string | null,
|
|
93
|
+
): string {
|
|
94
|
+
const lines: string[] = [];
|
|
95
|
+
if (systemPrompt) {
|
|
96
|
+
lines.push(systemPrompt);
|
|
97
|
+
lines.push('---');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const featureId = typeof payload['feature_id'] === 'string' ? payload['feature_id'] : '';
|
|
101
|
+
const repoRoot = typeof payload['repo_root'] === 'string' ? payload['repo_root'] : null;
|
|
102
|
+
const role = typeof payload['role'] === 'string' ? payload['role'] : '';
|
|
103
|
+
const workingDir =
|
|
104
|
+
typeof payload['working_directory'] === 'string' ? payload['working_directory'] : null;
|
|
105
|
+
const instructions =
|
|
106
|
+
typeof payload['instructions'] === 'string' ? payload['instructions'].trim() : '';
|
|
107
|
+
const lastToolResults = Array.isArray(payload['last_tool_results'])
|
|
108
|
+
? payload['last_tool_results']
|
|
109
|
+
: [];
|
|
110
|
+
const projectedContext = projectInteractiveContext(payload['context_bundle']);
|
|
111
|
+
const stateStatus =
|
|
112
|
+
typeof projectedContext?.state === 'object' &&
|
|
113
|
+
projectedContext.state &&
|
|
114
|
+
typeof (projectedContext.state as Record<string, unknown>).status === 'string'
|
|
115
|
+
? ((projectedContext.state as Record<string, unknown>).status as string)
|
|
116
|
+
: null;
|
|
117
|
+
const plannerPhase =
|
|
118
|
+
typeof payload['planner_phase'] === 'string'
|
|
119
|
+
? payload['planner_phase']
|
|
120
|
+
: stateStatus === 'intake'
|
|
121
|
+
? 'intake'
|
|
122
|
+
: 'planning';
|
|
123
|
+
|
|
124
|
+
lines.push(`You are the ${role} agent running in interactive mode.`);
|
|
125
|
+
lines.push(`Feature: ${featureId}`);
|
|
126
|
+
if (workingDir) {
|
|
127
|
+
lines.push(`Working directory (edit files here): ${workingDir}`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (repoRoot) {
|
|
131
|
+
const featureDir = `${repoRoot}/.aop/features/${featureId}`;
|
|
132
|
+
if (role === 'planner') {
|
|
133
|
+
if (plannerPhase === 'intake') {
|
|
134
|
+
lines.push(
|
|
135
|
+
'',
|
|
136
|
+
'Intake artifacts are on disk — use these files as the requirements workspace:',
|
|
137
|
+
` ${featureDir}/spec.md — feature specification`,
|
|
138
|
+
` ${featureDir}/spec.manifest.bootstrap.json — bootstrap requirements proposal`,
|
|
139
|
+
` ${featureDir}/spec.manifest.verified.json — current verified requirements contract`,
|
|
140
|
+
` ${featureDir}/intake.review.json — intake review and ambiguity status`,
|
|
141
|
+
` ${featureDir}/questions.json — persisted intake clarification questions and answers`,
|
|
142
|
+
` ${featureDir}/state.md — current status and front matter`,
|
|
143
|
+
` ${featureDir}/decisions.md — decision history`,
|
|
144
|
+
);
|
|
145
|
+
} else {
|
|
146
|
+
lines.push(
|
|
147
|
+
'',
|
|
148
|
+
'Planning artifacts are on disk — use these files as the execution-planning baseline:',
|
|
149
|
+
` ${featureDir}/spec.md — feature specification`,
|
|
150
|
+
` ${featureDir}/spec.manifest.verified.json — verified requirements contract`,
|
|
151
|
+
` ${featureDir}/state.md — current status and front matter`,
|
|
152
|
+
` ${featureDir}/plan.md — canonical step-by-step planning artifact`,
|
|
153
|
+
` ${featureDir}/plan.json — schema-valid planning definition`,
|
|
154
|
+
` ${featureDir}/qa_test_index.json — QA coverage and pending items`,
|
|
155
|
+
` ${featureDir}/evidence/ — gate run results`,
|
|
156
|
+
` ${featureDir}/decisions.md — decision history`,
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
} else if (role === 'builder') {
|
|
160
|
+
if (workingDir) {
|
|
161
|
+
const contextDir = `${workingDir}/.aop/context`;
|
|
162
|
+
lines.push(
|
|
163
|
+
'',
|
|
164
|
+
'Staged artifacts (read these first for context):',
|
|
165
|
+
` ${contextDir}/spec.md — original feature specification`,
|
|
166
|
+
` ${contextDir}/plan.md — human-readable implementation plan`,
|
|
167
|
+
` ${contextDir}/plan.json — structured plan with tasks and acceptance criteria`,
|
|
168
|
+
` ${contextDir}/qa_test_index.json — test expectations (if available)`,
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
lines.push(
|
|
172
|
+
'',
|
|
173
|
+
'Runtime artifacts:',
|
|
174
|
+
` ${featureDir}/state.md — current status and front matter`,
|
|
175
|
+
` ${featureDir}/evidence/ — gate run results`,
|
|
176
|
+
` ${featureDir}/decisions.md — decision history`,
|
|
177
|
+
);
|
|
178
|
+
} else if (role === 'qa') {
|
|
179
|
+
lines.push(
|
|
180
|
+
'',
|
|
181
|
+
'QA artifacts are on disk — use these files as the verification baseline:',
|
|
182
|
+
` ${featureDir}/state.md — current status and front matter`,
|
|
183
|
+
` ${featureDir}/plan.md — accepted planning baseline`,
|
|
184
|
+
` ${featureDir}/plan.json — machine-readable plan`,
|
|
185
|
+
` ${featureDir}/qa_test_index.json — QA coverage and pending items`,
|
|
186
|
+
` ${featureDir}/evidence/ — latest gate evidence`,
|
|
187
|
+
` ${featureDir}/decisions.md — decision history`,
|
|
188
|
+
);
|
|
189
|
+
} else if (role === 'reconciler') {
|
|
190
|
+
lines.push(
|
|
191
|
+
'',
|
|
192
|
+
'Reconciliation artifacts are on disk — use these files as the merge-resolution baseline:',
|
|
193
|
+
` ${featureDir}/state.md — conflict status and front matter`,
|
|
194
|
+
` ${featureDir}/spec.md — feature intent`,
|
|
195
|
+
` ${featureDir}/plan.md — accepted planning baseline`,
|
|
196
|
+
` ${featureDir}/plan.json — machine-readable plan`,
|
|
197
|
+
` ${featureDir}/decisions.md — decision history`,
|
|
198
|
+
` ${featureDir}/evidence/ — latest gate evidence`,
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (instructions.length > 0) {
|
|
204
|
+
lines.push('', 'Instructions:', instructions);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (projectedContext) {
|
|
208
|
+
lines.push('', 'Execution context summary:', JSON.stringify(projectedContext, null, 2));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (lastToolResults.length > 0) {
|
|
212
|
+
lines.push('', 'Recent tool results:', JSON.stringify(lastToolResults));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (role === 'planner') {
|
|
216
|
+
const featureDir = repoRoot ? `${repoRoot}/.aop/features/${featureId}` : null;
|
|
217
|
+
if (plannerPhase === 'intake') {
|
|
218
|
+
lines.push(
|
|
219
|
+
'',
|
|
220
|
+
'Update the intake artifacts directly in the working directory.',
|
|
221
|
+
'Return exactly one JSON object and nothing else:',
|
|
222
|
+
'{"type":"INTAKE_SUBMISSION","intake_submission":{"verified_manifest":{...},"open_ambiguities":[...],"resolved_ambiguities":[...],"requires_user_input":false}}',
|
|
223
|
+
'or {"type":"REQUEST","request":{"action":"ask_user_input","question_type":"clarification","prompt":"<blocking intake question>","details":{"ambiguity_id":"AMB-001","obligation_ids":["OBL-001"]},"expected_answer":{"kind":"free_text"},"blocking":true}}',
|
|
224
|
+
'or {"type":"NOTE","content":"<why intake remains unchanged and what intake state was observed>"}',
|
|
225
|
+
'Do not emit PLAN_SUBMISSION while operating in the intake planner phase.',
|
|
226
|
+
'If you emit REQUEST.action=ask_user_input, stop there for the turn. Do not also emit INTAKE_SUBMISSION or resolve the ambiguity yourself.',
|
|
227
|
+
'Do not claim verification_basis=human_review_confirmed unless the context already contains an answered manifest-review confirmation question.',
|
|
228
|
+
'Do not wrap JSON in markdown code fences.',
|
|
229
|
+
);
|
|
230
|
+
} else {
|
|
231
|
+
lines.push(
|
|
232
|
+
'',
|
|
233
|
+
'Update the planning artifacts directly in the working directory.',
|
|
234
|
+
featureDir
|
|
235
|
+
? `Keep ${featureDir}/plan.md aligned with the planning state and any plan_json you return.`
|
|
236
|
+
: 'Keep plan.md aligned with the planning state and any plan_json you return.',
|
|
237
|
+
'Return exactly one JSON object and nothing else:',
|
|
238
|
+
'{"type":"PLAN_SUBMISSION","plan_json":{...}}',
|
|
239
|
+
'or {"type":"REQUEST","request":{"action":"amend_plan","plan_json":{...},"expected_plan_version":<n>}}',
|
|
240
|
+
'or {"type":"NOTE","content":"<why the accepted plan remains unchanged and what state was observed>"}',
|
|
241
|
+
'Do not emit INTAKE_SUBMISSION while operating in the execution-planning phase.',
|
|
242
|
+
'Do not wrap JSON in markdown code fences.',
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
} else if (role === 'builder') {
|
|
246
|
+
lines.push(
|
|
247
|
+
'',
|
|
248
|
+
'Edit files directly in the working directory. Do not emit PATCH/unified diff output.',
|
|
249
|
+
'Use the accepted plan as your execution contract and keep changes inside planned paths.',
|
|
250
|
+
'Return NOTE only after making planned file changes.',
|
|
251
|
+
'Return REQUEST.action=more_context when the safe fix surface exceeds the accepted plan or the context is stale.',
|
|
252
|
+
'Return REQUEST.action=ask_user_input only for genuine human decisions, approvals, or policy exceptions you cannot resolve from the plan and repo.',
|
|
253
|
+
'After completing your edits, return exactly one JSON object:',
|
|
254
|
+
'{"type":"NOTE","content":"<summary of completed edits, tests updated, and remaining risks>"}',
|
|
255
|
+
'or {"type":"REQUEST","request":{"action":"more_context"}}',
|
|
256
|
+
'or {"type":"REQUEST","request":{"action":"ask_user_input","question_type":"clarification","prompt":"<question>","details":{},"expected_answer":{"kind":"free_text"},"blocking":true}}',
|
|
257
|
+
'Do not wrap JSON in markdown code fences.',
|
|
258
|
+
);
|
|
259
|
+
} else if (role === 'qa') {
|
|
260
|
+
lines.push(
|
|
261
|
+
'',
|
|
262
|
+
'Edit files directly in the working directory. Do not emit PATCH/unified diff output.',
|
|
263
|
+
'Use plan.json, qa_test_index.json, and the latest evidence as your verification contract.',
|
|
264
|
+
'Return NOTE only after making file changes that address a reproduced failure or verification gap.',
|
|
265
|
+
'Return REQUEST.action=more_context when evidence is stale or the accepted plan does not authorize the safe fix surface.',
|
|
266
|
+
'Return REQUEST.action=ask_user_input only for genuine operator decisions, approvals, or risk acknowledgements.',
|
|
267
|
+
'After completing your edits, return exactly one JSON object:',
|
|
268
|
+
'{"type":"NOTE","content":"<summary of reproduced failures, fixes applied, tests run, and remaining risks>"}',
|
|
269
|
+
'or {"type":"REQUEST","request":{"action":"more_context"}}',
|
|
270
|
+
'or {"type":"REQUEST","request":{"action":"ask_user_input","question_type":"risk_ack","prompt":"<question>","details":{},"expected_answer":{"kind":"free_text"},"blocking":true}}',
|
|
271
|
+
'Do not wrap JSON in markdown code fences.',
|
|
272
|
+
);
|
|
273
|
+
} else {
|
|
274
|
+
lines.push(
|
|
275
|
+
'',
|
|
276
|
+
'Edit files directly in the conflicted worktree. Do not emit PATCH/unified diff output.',
|
|
277
|
+
'Use spec.md, state.md, plan.json, and approved collision context as your reconciliation contract.',
|
|
278
|
+
'Return NOTE only after resolving conflicted files and performing proportionate verification.',
|
|
279
|
+
'Return REQUEST.action=more_context when the conflict snapshot or surrounding repo state is stale.',
|
|
280
|
+
'Return REQUEST.action=ask_user_input only when preserving mainline semantics and feature intent requires an operator choice.',
|
|
281
|
+
'After completing your edits, return exactly one JSON object:',
|
|
282
|
+
'{"type":"NOTE","content":"<summary of conflicts resolved, verification run, plan impacts, and residual risks>"}',
|
|
283
|
+
'or {"type":"REQUEST","request":{"action":"more_context"}}',
|
|
284
|
+
'or {"type":"REQUEST","request":{"action":"ask_user_input","question_type":"clarification","prompt":"<question>","details":{},"expected_answer":{"kind":"free_text"},"blocking":true}}',
|
|
285
|
+
'Do not wrap JSON in markdown code fences.',
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return lines.join('\n');
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function buildWorkerPrompt(
|
|
293
|
+
payload: Record<string, unknown>,
|
|
294
|
+
systemPrompt: string | null,
|
|
295
|
+
executionMode: 'deterministic' | 'interactive',
|
|
296
|
+
): string {
|
|
297
|
+
if (executionMode === 'interactive') {
|
|
298
|
+
return buildInteractiveWorkerPrompt(payload, systemPrompt);
|
|
299
|
+
}
|
|
300
|
+
return buildDeterministicWorkerPrompt(payload, systemPrompt);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export async function resolvePromptOverlay(
|
|
304
|
+
overlayDir: string,
|
|
305
|
+
role: string,
|
|
306
|
+
provider: string,
|
|
307
|
+
): Promise<string | null> {
|
|
308
|
+
const filename = `${role}.${provider}.md`;
|
|
309
|
+
const overlayPath = path.join(overlayDir, filename);
|
|
310
|
+
try {
|
|
311
|
+
const content = await fs.readFile(overlayPath, 'utf8');
|
|
312
|
+
return content.trim().length > 0 ? content : null;
|
|
313
|
+
} catch {
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
79
318
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
80
319
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
81
320
|
}
|
|
@@ -96,9 +335,109 @@ function asNonEmptyString(value: unknown): string | null {
|
|
|
96
335
|
return trimmed.length > 0 ? trimmed : null;
|
|
97
336
|
}
|
|
98
337
|
|
|
338
|
+
function projectInteractiveContext(contextBundle: unknown): Record<string, unknown> | null {
|
|
339
|
+
if (!isRecord(contextBundle)) {
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const projected: Record<string, unknown> = {};
|
|
344
|
+
const state = isRecord(contextBundle['state']) ? contextBundle['state'] : null;
|
|
345
|
+
const frontMatter = isRecord(state?.['front_matter']) ? state['front_matter'] : null;
|
|
346
|
+
if (frontMatter) {
|
|
347
|
+
projected['state'] = {
|
|
348
|
+
status: frontMatter['status'] ?? null,
|
|
349
|
+
status_reason: frontMatter['status_reason'] ?? null,
|
|
350
|
+
gate_profile: frontMatter['gate_profile'] ?? null,
|
|
351
|
+
gates: isRecord(frontMatter['gates']) ? frontMatter['gates'] : null,
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const plan = isRecord(contextBundle['plan']) ? contextBundle['plan'] : null;
|
|
356
|
+
if (plan) {
|
|
357
|
+
projected['accepted_plan'] = {
|
|
358
|
+
summary: plan['summary'] ?? null,
|
|
359
|
+
allowed_areas: Array.isArray(plan['allowed_areas']) ? plan['allowed_areas'] : [],
|
|
360
|
+
forbidden_areas: Array.isArray(plan['forbidden_areas']) ? plan['forbidden_areas'] : [],
|
|
361
|
+
files: isRecord(plan['files']) ? plan['files'] : null,
|
|
362
|
+
acceptance_criteria: Array.isArray(plan['acceptance_criteria'])
|
|
363
|
+
? plan['acceptance_criteria']
|
|
364
|
+
: [],
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const latestEvidence = isRecord(contextBundle['latest_evidence'])
|
|
369
|
+
? contextBundle['latest_evidence']
|
|
370
|
+
: null;
|
|
371
|
+
if (latestEvidence) {
|
|
372
|
+
projected['latest_evidence'] = {
|
|
373
|
+
overall: latestEvidence['overall'] ?? null,
|
|
374
|
+
mode: latestEvidence['mode'] ?? null,
|
|
375
|
+
status_reason: latestEvidence['status_reason'] ?? null,
|
|
376
|
+
failed_steps: Array.isArray(latestEvidence['failed_steps'])
|
|
377
|
+
? latestEvidence['failed_steps']
|
|
378
|
+
: [],
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
const qaIndex = isRecord(contextBundle['qa_test_index']) ? contextBundle['qa_test_index'] : null;
|
|
383
|
+
if (qaIndex) {
|
|
384
|
+
projected['qa_test_index'] = qaIndex;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const intake = isRecord(contextBundle['intake']) ? contextBundle['intake'] : null;
|
|
388
|
+
if (intake) {
|
|
389
|
+
const review = isRecord(intake['review']) ? intake['review'] : null;
|
|
390
|
+
const openAmbiguities = Array.isArray(review?.['ambiguities'])
|
|
391
|
+
? review?.['ambiguities']
|
|
392
|
+
.map((item) => (isRecord(item) ? item : null))
|
|
393
|
+
.filter(
|
|
394
|
+
(item): item is Record<string, unknown> =>
|
|
395
|
+
item !== null && asNonEmptyString(item['status']) === 'open',
|
|
396
|
+
)
|
|
397
|
+
.map((item) => ({
|
|
398
|
+
id: item['id'] ?? null,
|
|
399
|
+
summary: item['summary'] ?? null,
|
|
400
|
+
obligation_ids: Array.isArray(item['obligation_ids']) ? item['obligation_ids'] : [],
|
|
401
|
+
}))
|
|
402
|
+
: [];
|
|
403
|
+
const clarificationAnswers = Array.isArray(review?.['clarification_answers'])
|
|
404
|
+
? review?.['clarification_answers']
|
|
405
|
+
.map((item) => (isRecord(item) ? item : null))
|
|
406
|
+
.filter((item): item is Record<string, unknown> => item !== null)
|
|
407
|
+
.map((item) => ({
|
|
408
|
+
question_id: item['question_id'] ?? null,
|
|
409
|
+
ambiguity_ids: Array.isArray(item['ambiguity_ids']) ? item['ambiguity_ids'] : [],
|
|
410
|
+
answer: item['answer'] ?? null,
|
|
411
|
+
answered_at: item['answered_at'] ?? null,
|
|
412
|
+
resolution_status: item['resolution_status'] ?? null,
|
|
413
|
+
}))
|
|
414
|
+
: [];
|
|
415
|
+
projected['intake'] = {
|
|
416
|
+
summary: isRecord(intake['summary']) ? intake['summary'] : null,
|
|
417
|
+
bootstrap_manifest_version: isRecord(intake['bootstrap_manifest'])
|
|
418
|
+
? (intake['bootstrap_manifest']['manifest_version'] ?? null)
|
|
419
|
+
: null,
|
|
420
|
+
verified_manifest_version: isRecord(intake['verified_manifest'])
|
|
421
|
+
? (intake['verified_manifest']['manifest_version'] ?? null)
|
|
422
|
+
: null,
|
|
423
|
+
review: review
|
|
424
|
+
? {
|
|
425
|
+
status: review['status'] ?? null,
|
|
426
|
+
questions_open: review['questions_open'] ?? null,
|
|
427
|
+
questions_resolved: review['questions_resolved'] ?? null,
|
|
428
|
+
open_ambiguities: openAmbiguities,
|
|
429
|
+
clarification_answers: clarificationAnswers,
|
|
430
|
+
}
|
|
431
|
+
: null,
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
return Object.keys(projected).length > 0 ? projected : null;
|
|
436
|
+
}
|
|
437
|
+
|
|
99
438
|
function templateFromConfig(
|
|
100
439
|
config: Record<string, unknown> | null | undefined,
|
|
101
|
-
kind: 'run' | 'attach' | 'send',
|
|
440
|
+
kind: 'run' | 'run_resume' | 'attach' | 'send',
|
|
102
441
|
fallback: ProviderCommandTemplate | undefined,
|
|
103
442
|
): ProviderCommandTemplate | undefined {
|
|
104
443
|
const nested = isRecord(config?.[kind]) ? config?.[kind] : null;
|
|
@@ -117,33 +456,51 @@ function templateFromConfig(
|
|
|
117
456
|
return { command, args };
|
|
118
457
|
}
|
|
119
458
|
|
|
120
|
-
function
|
|
459
|
+
function appendExtraArgs(
|
|
460
|
+
template: ProviderCommandTemplate | undefined,
|
|
461
|
+
extraArgs: string[] | undefined,
|
|
462
|
+
): ProviderCommandTemplate | undefined {
|
|
463
|
+
if (!template || !extraArgs?.length) {
|
|
464
|
+
return template;
|
|
465
|
+
}
|
|
466
|
+
return { command: template.command, args: [...template.args, ...extraArgs] };
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function resolveRunTemplate(
|
|
470
|
+
selection: ProviderSelection,
|
|
471
|
+
resumeSession: boolean,
|
|
472
|
+
): ProviderCommandTemplate | undefined {
|
|
121
473
|
const topLevelCommand = asNonEmptyString(selection.agent_config?.command);
|
|
122
474
|
const topLevelArgs = readStringArray(selection.agent_config?.args);
|
|
123
475
|
const topLevelTemplate =
|
|
124
476
|
topLevelCommand && topLevelArgs ? { command: topLevelCommand, args: topLevelArgs } : undefined;
|
|
477
|
+
const defaults = PROVIDER_CLI_DEFAULTS[selection.provider];
|
|
478
|
+
const kind = resumeSession ? 'run_resume' : 'run';
|
|
125
479
|
|
|
126
|
-
|
|
480
|
+
const template = templateFromConfig(
|
|
127
481
|
selection.agent_config,
|
|
128
|
-
|
|
129
|
-
topLevelTemplate ??
|
|
482
|
+
kind,
|
|
483
|
+
topLevelTemplate ?? (resumeSession ? defaults?.run_resume : undefined) ?? defaults?.run,
|
|
130
484
|
);
|
|
485
|
+
return appendExtraArgs(template, selection.cli_extra_args);
|
|
131
486
|
}
|
|
132
487
|
|
|
133
488
|
function resolveAttachTemplate(selection: ProviderSelection): ProviderCommandTemplate | undefined {
|
|
134
|
-
|
|
489
|
+
const template = templateFromConfig(
|
|
135
490
|
selection.agent_config,
|
|
136
491
|
'attach',
|
|
137
492
|
PROVIDER_CLI_DEFAULTS[selection.provider]?.attach,
|
|
138
493
|
);
|
|
494
|
+
return appendExtraArgs(template, selection.cli_extra_args);
|
|
139
495
|
}
|
|
140
496
|
|
|
141
497
|
function resolveSendTemplate(selection: ProviderSelection): ProviderCommandTemplate | undefined {
|
|
142
|
-
|
|
498
|
+
const template = templateFromConfig(
|
|
143
499
|
selection.agent_config,
|
|
144
500
|
'send',
|
|
145
501
|
PROVIDER_CLI_DEFAULTS[selection.provider]?.send,
|
|
146
502
|
);
|
|
503
|
+
return appendExtraArgs(template, selection.cli_extra_args);
|
|
147
504
|
}
|
|
148
505
|
|
|
149
506
|
function applyTemplateArgs(args: string[], values: CommandTemplateValues): string[] {
|
|
@@ -163,6 +520,12 @@ function applyTemplateArgs(args: string[], values: CommandTemplateValues): strin
|
|
|
163
520
|
if (arg === '{message}') {
|
|
164
521
|
return values.message ?? '';
|
|
165
522
|
}
|
|
523
|
+
if (arg === '{output_last_message_path}') {
|
|
524
|
+
return values.outputLastMessagePath ?? '';
|
|
525
|
+
}
|
|
526
|
+
if (arg === '{model}') {
|
|
527
|
+
return values.model ?? '';
|
|
528
|
+
}
|
|
166
529
|
return arg;
|
|
167
530
|
});
|
|
168
531
|
}
|
|
@@ -179,6 +542,12 @@ function buildRunCommandEnv(selection: ProviderSelection): NodeJS.ProcessEnv {
|
|
|
179
542
|
if (selection.provider_config_env && selection.provider_config_ref) {
|
|
180
543
|
env[selection.provider_config_env] = selection.provider_config_ref;
|
|
181
544
|
}
|
|
545
|
+
if (selection.provider === 'claude') {
|
|
546
|
+
// Claude Code refuses to spawn inside an active Claude Code session.
|
|
547
|
+
// Both CLAUDECODE and CLAUDE_CODE_ENTRYPOINT must be absent to bypass the nested-session guard.
|
|
548
|
+
delete env['CLAUDECODE'];
|
|
549
|
+
delete env['CLAUDE_CODE_ENTRYPOINT'];
|
|
550
|
+
}
|
|
182
551
|
return env;
|
|
183
552
|
}
|
|
184
553
|
|
|
@@ -202,6 +571,206 @@ function resolveCliWorkerCapabilities(selection: ProviderSelection): WorkerCapab
|
|
|
202
571
|
};
|
|
203
572
|
}
|
|
204
573
|
|
|
574
|
+
function isRawLogRole(role: string): role is 'planner' | 'builder' | 'qa' {
|
|
575
|
+
return role === 'planner' || role === 'builder' || role === 'qa';
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
function sanitizeClaudeProjectKey(value: string): string {
|
|
579
|
+
return value.replace(/[^A-Za-z0-9]/g, '-');
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
function resolveClaudeTranscriptPath(workingDirectory: string, sessionId: string): string {
|
|
583
|
+
return path.join(
|
|
584
|
+
os.homedir(),
|
|
585
|
+
'.claude',
|
|
586
|
+
'projects',
|
|
587
|
+
sanitizeClaudeProjectKey(workingDirectory),
|
|
588
|
+
`${sessionId}.jsonl`,
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
function asNonEmptyStringOrNull(value: unknown): string | null {
|
|
593
|
+
return typeof value === 'string' && value.trim().length > 0 ? value : null;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
function collectClaudeTranscriptTextBlocks(value: unknown): string[] {
|
|
597
|
+
if (!Array.isArray(value)) {
|
|
598
|
+
return [];
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
const blocks: string[] = [];
|
|
602
|
+
for (const entry of value) {
|
|
603
|
+
if (!isRecord(entry) || entry.type !== 'text') {
|
|
604
|
+
continue;
|
|
605
|
+
}
|
|
606
|
+
const text = asNonEmptyStringOrNull(entry.text);
|
|
607
|
+
if (text) {
|
|
608
|
+
blocks.push(text);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
return blocks;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
function summarizeClaudeToolInput(input: Record<string, unknown>): string | null {
|
|
615
|
+
const description = asNonEmptyStringOrNull(input.description);
|
|
616
|
+
if (description) {
|
|
617
|
+
return description;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
const command = asNonEmptyStringOrNull(input.command);
|
|
621
|
+
if (command) {
|
|
622
|
+
return command;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
const filePath = asNonEmptyStringOrNull(input.file_path);
|
|
626
|
+
if (filePath) {
|
|
627
|
+
return filePath;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
const pattern = asNonEmptyStringOrNull(input.pattern);
|
|
631
|
+
const searchPath = asNonEmptyStringOrNull(input.path);
|
|
632
|
+
if (pattern && searchPath) {
|
|
633
|
+
return `${pattern} @ ${searchPath}`;
|
|
634
|
+
}
|
|
635
|
+
if (pattern) {
|
|
636
|
+
return pattern;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
const specs = input.specs;
|
|
640
|
+
if (Array.isArray(specs)) {
|
|
641
|
+
const renderedSpecs = specs.filter((value): value is string => typeof value === 'string');
|
|
642
|
+
if (renderedSpecs.length > 0) {
|
|
643
|
+
return renderedSpecs.join(', ');
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
return null;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
function renderClaudeTranscriptEntry(record: Record<string, unknown>): string[] {
|
|
651
|
+
const type = asNonEmptyStringOrNull(record.type);
|
|
652
|
+
if (!type) {
|
|
653
|
+
return [];
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
if (type === 'progress') {
|
|
657
|
+
const data = isRecord(record.data) ? record.data : null;
|
|
658
|
+
if (data?.type === 'hook_progress') {
|
|
659
|
+
const hookEvent = asNonEmptyStringOrNull(data.hookEvent);
|
|
660
|
+
const hookName = asNonEmptyStringOrNull(data.hookName);
|
|
661
|
+
const label = [hookEvent, hookName].filter(Boolean).join(' · ');
|
|
662
|
+
return label.length > 0 ? [`[progress] ${label}`] : [];
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
const progressType = asNonEmptyStringOrNull(data?.type);
|
|
666
|
+
return progressType ? [`[progress] ${progressType}`] : [];
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
const message = isRecord(record.message) ? record.message : null;
|
|
670
|
+
if (!message) {
|
|
671
|
+
return [];
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
if (type === 'assistant') {
|
|
675
|
+
const content = Array.isArray(message.content) ? message.content : [];
|
|
676
|
+
const rendered: string[] = [];
|
|
677
|
+
for (const entry of content) {
|
|
678
|
+
if (!isRecord(entry)) {
|
|
679
|
+
continue;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
if (entry.type === 'text') {
|
|
683
|
+
const text = asNonEmptyStringOrNull(entry.text);
|
|
684
|
+
if (text) {
|
|
685
|
+
rendered.push(text);
|
|
686
|
+
}
|
|
687
|
+
continue;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
if (entry.type === 'tool_use') {
|
|
691
|
+
const name = asNonEmptyStringOrNull(entry.name) ?? 'tool';
|
|
692
|
+
const input = isRecord(entry.input) ? entry.input : {};
|
|
693
|
+
const summary = summarizeClaudeToolInput(input);
|
|
694
|
+
rendered.push(summary ? `[tool] ${name}: ${summary}` : `[tool] ${name}`);
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
return rendered;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
if (type === 'user') {
|
|
701
|
+
const content = Array.isArray(message.content) ? message.content : [];
|
|
702
|
+
const rendered: string[] = [];
|
|
703
|
+
for (const entry of content) {
|
|
704
|
+
if (!isRecord(entry) || entry.type !== 'tool_result') {
|
|
705
|
+
continue;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
const textBlocks = collectClaudeTranscriptTextBlocks(entry.content);
|
|
709
|
+
if (textBlocks.length > 0) {
|
|
710
|
+
rendered.push(...textBlocks);
|
|
711
|
+
continue;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
const text = asNonEmptyStringOrNull(entry.content);
|
|
715
|
+
if (text) {
|
|
716
|
+
rendered.push(text);
|
|
717
|
+
continue;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
if (isRecord(record.toolUseResult)) {
|
|
721
|
+
const stdout = asNonEmptyStringOrNull(record.toolUseResult.stdout);
|
|
722
|
+
const stderr = asNonEmptyStringOrNull(record.toolUseResult.stderr);
|
|
723
|
+
if (stdout) {
|
|
724
|
+
rendered.push(stdout);
|
|
725
|
+
}
|
|
726
|
+
if (stderr) {
|
|
727
|
+
rendered.push(stderr);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
return rendered;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
return [];
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
function renderClaudeTranscript(raw: string): string {
|
|
738
|
+
const rendered: string[] = [];
|
|
739
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
740
|
+
const trimmed = line.trim();
|
|
741
|
+
if (trimmed.length === 0) {
|
|
742
|
+
continue;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
try {
|
|
746
|
+
const parsed = JSON.parse(trimmed) as unknown;
|
|
747
|
+
if (isRecord(parsed)) {
|
|
748
|
+
rendered.push(...renderClaudeTranscriptEntry(parsed));
|
|
749
|
+
}
|
|
750
|
+
} catch {
|
|
751
|
+
// Ignore malformed partial lines while the transcript is still being written.
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
return rendered.join('\n\n');
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
export const cliWorkerProviderTestExports = {
|
|
758
|
+
buildInteractiveWorkerPrompt,
|
|
759
|
+
projectInteractiveContext,
|
|
760
|
+
resolveRunTemplate,
|
|
761
|
+
resolveAttachTemplate,
|
|
762
|
+
resolveSendTemplate,
|
|
763
|
+
applyTemplateArgs,
|
|
764
|
+
buildRunCommandEnv,
|
|
765
|
+
resolveCliWorkerCapabilities,
|
|
766
|
+
sanitizeClaudeProjectKey,
|
|
767
|
+
resolveClaudeTranscriptPath,
|
|
768
|
+
collectClaudeTranscriptTextBlocks,
|
|
769
|
+
summarizeClaudeToolInput,
|
|
770
|
+
renderClaudeTranscriptEntry,
|
|
771
|
+
renderClaudeTranscript,
|
|
772
|
+
};
|
|
773
|
+
|
|
205
774
|
export class CliWorkerProvider implements WorkerProvider {
|
|
206
775
|
readonly mode = 'live' as const;
|
|
207
776
|
readonly selection: ProviderSelection;
|
|
@@ -217,14 +786,67 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
217
786
|
private readonly workerWatchdogPollIntervalMs: number;
|
|
218
787
|
private readonly workerKillGracePeriodMs: number;
|
|
219
788
|
private readonly repoRoot: string | null;
|
|
789
|
+
private readonly overlayDir: string | null;
|
|
220
790
|
private readonly rawAgentLogsEnabled: boolean;
|
|
221
791
|
private readonly rawAgentLogsRetentionDays: number;
|
|
222
792
|
private readonly workerCapabilities: WorkerCapabilities;
|
|
223
|
-
private readonly runTemplate: ProviderCommandTemplate | undefined;
|
|
224
793
|
private readonly attachTemplate: ProviderCommandTemplate | undefined;
|
|
225
794
|
private readonly sendTemplate: ProviderCommandTemplate | undefined;
|
|
226
795
|
private readonly sessionsByRoleFeature = new Map<string, string>();
|
|
227
796
|
private readonly systemPromptsBySession = new Map<string, string | null>();
|
|
797
|
+
private readonly bootstrappedSessionIds = new Set<string>();
|
|
798
|
+
private readonly overlayCache = new Map<string, string | null>();
|
|
799
|
+
|
|
800
|
+
private isMissingClaudeConversation(result: ProviderCommandResult): boolean {
|
|
801
|
+
if (this.selection.provider !== 'claude') {
|
|
802
|
+
return false;
|
|
803
|
+
}
|
|
804
|
+
const stderr = typeof result.stderr === 'string' ? result.stderr : '';
|
|
805
|
+
const stdout = typeof result.stdout === 'string' ? result.stdout : '';
|
|
806
|
+
return (
|
|
807
|
+
stderr.includes('No conversation found with session ID') ||
|
|
808
|
+
stdout.includes('No conversation found with session ID')
|
|
809
|
+
);
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
private buildBootstrapControlPrompt(sessionId: string, message: string): string {
|
|
813
|
+
const systemPrompt = this.systemPromptsBySession.get(sessionId) ?? null;
|
|
814
|
+
return systemPrompt ? `${systemPrompt}\n---\n${message}` : message;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
private async bootstrapMissingClaudeControlSession(
|
|
818
|
+
sessionId: string,
|
|
819
|
+
message: string,
|
|
820
|
+
): Promise<boolean> {
|
|
821
|
+
if (this.selection.provider !== 'claude' || message.trim().length === 0) {
|
|
822
|
+
return false;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
const runTemplate = resolveRunTemplate(this.selection, false);
|
|
826
|
+
if (!runTemplate) {
|
|
827
|
+
return false;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
const prompt = this.buildBootstrapControlPrompt(sessionId, message);
|
|
831
|
+
const args = applyTemplateArgs(runTemplate.args, {
|
|
832
|
+
sessionId,
|
|
833
|
+
prompt,
|
|
834
|
+
featureId: 'global',
|
|
835
|
+
role: 'reconciler',
|
|
836
|
+
message,
|
|
837
|
+
model: this.selection.model,
|
|
838
|
+
});
|
|
839
|
+
const result = await this.commandRunner.run(runTemplate.command, args, {
|
|
840
|
+
stdin: prompt,
|
|
841
|
+
timeoutMs: 15_000,
|
|
842
|
+
env: buildRunCommandEnv(this.selection),
|
|
843
|
+
});
|
|
844
|
+
if (result.exitCode !== 0) {
|
|
845
|
+
return false;
|
|
846
|
+
}
|
|
847
|
+
this.markSessionBootstrapped(this.selection.provider, sessionId);
|
|
848
|
+
return true;
|
|
849
|
+
}
|
|
228
850
|
|
|
229
851
|
constructor(selection: ProviderSelection, options: CliWorkerProviderOptions) {
|
|
230
852
|
this.selection = selection;
|
|
@@ -249,13 +871,13 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
249
871
|
);
|
|
250
872
|
this.repoRoot =
|
|
251
873
|
typeof options.repoRoot === 'string' && options.repoRoot.length > 0 ? options.repoRoot : null;
|
|
874
|
+
this.overlayDir = options.overlayDir ?? null;
|
|
252
875
|
this.rawAgentLogsEnabled = options.rawAgentLogsEnabled === true;
|
|
253
876
|
this.rawAgentLogsRetentionDays = asPositiveInteger(
|
|
254
877
|
options.rawAgentLogsRetentionDays,
|
|
255
878
|
DEFAULT_RAW_LOG_RETENTION_DAYS,
|
|
256
879
|
);
|
|
257
880
|
this.workerCapabilities = resolveCliWorkerCapabilities(selection);
|
|
258
|
-
this.runTemplate = resolveRunTemplate(selection);
|
|
259
881
|
this.attachTemplate = resolveAttachTemplate(selection);
|
|
260
882
|
this.sendTemplate = resolveSendTemplate(selection);
|
|
261
883
|
|
|
@@ -282,7 +904,7 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
282
904
|
featureId: string,
|
|
283
905
|
systemPrompt: string | null,
|
|
284
906
|
): Promise<WorkerSession> {
|
|
285
|
-
const sessionId =
|
|
907
|
+
const sessionId = crypto.randomUUID();
|
|
286
908
|
this.sessionsByRoleFeature.set(this.sessionKey(role, featureId), sessionId);
|
|
287
909
|
this.systemPromptsBySession.set(sessionId, systemPrompt);
|
|
288
910
|
return Promise.resolve({
|
|
@@ -311,43 +933,89 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
311
933
|
this.sessionsByRoleFeature.delete(key);
|
|
312
934
|
}
|
|
313
935
|
}
|
|
936
|
+
this.bootstrappedSessionIds.delete(sessionId);
|
|
314
937
|
this.systemPromptsBySession.delete(sessionId);
|
|
315
938
|
return Promise.resolve({ closed: true });
|
|
316
939
|
}
|
|
317
940
|
|
|
318
|
-
async runWorker(input: WorkerRunInput): Promise<
|
|
319
|
-
|
|
941
|
+
async runWorker(input: WorkerRunInput): Promise<WorkerRunOutput> {
|
|
942
|
+
const effectiveSelection = this.resolveEffectiveSelection(input.runtime_selection ?? null);
|
|
943
|
+
const sessionId = this.resolveOrCreateSessionId(input.role, input.feature_id);
|
|
944
|
+
const workingDirectory = input.working_directory ?? this.repoRoot ?? process.cwd();
|
|
945
|
+
const resumeSession = await this.shouldResumeSession(
|
|
946
|
+
effectiveSelection.provider,
|
|
947
|
+
sessionId,
|
|
948
|
+
workingDirectory,
|
|
949
|
+
);
|
|
950
|
+
const runTemplate = resolveRunTemplate(effectiveSelection, resumeSession);
|
|
951
|
+
if (!runTemplate) {
|
|
320
952
|
throw providerError(
|
|
321
953
|
ERROR_CODES.PROVIDER_RUNTIME_UNAVAILABLE,
|
|
322
954
|
'Live worker provider is missing run command configuration',
|
|
323
955
|
{
|
|
324
|
-
provider:
|
|
956
|
+
provider: effectiveSelection.provider,
|
|
325
957
|
reason: 'missing_run_command_template',
|
|
958
|
+
resume_session: resumeSession,
|
|
326
959
|
},
|
|
327
960
|
);
|
|
328
961
|
}
|
|
329
962
|
|
|
330
|
-
const
|
|
331
|
-
this.sessionsByRoleFeature.get(this.sessionKey(input.role, input.feature_id)) ??
|
|
332
|
-
`${input.role}-${input.feature_id}-unassigned`;
|
|
333
|
-
|
|
963
|
+
const executionMode = input.execution_mode ?? 'deterministic';
|
|
334
964
|
const promptPayload = {
|
|
335
965
|
role: input.role,
|
|
336
966
|
feature_id: input.feature_id,
|
|
337
|
-
|
|
967
|
+
...(typeof input.planner_phase === 'string' ? { planner_phase: input.planner_phase } : {}),
|
|
968
|
+
...(executionMode === 'interactive'
|
|
969
|
+
? {
|
|
970
|
+
repo_root: this.repoRoot ?? null,
|
|
971
|
+
context_bundle: input.context_bundle ?? {},
|
|
972
|
+
}
|
|
973
|
+
: { context_bundle: input.context_bundle ?? {} }),
|
|
338
974
|
instructions: input.instructions ?? '',
|
|
339
975
|
last_tool_results: input.last_tool_results ?? [],
|
|
340
976
|
runtime_selection: input.runtime_selection ?? null,
|
|
341
977
|
session_id: sessionId,
|
|
978
|
+
execution_mode: executionMode,
|
|
979
|
+
working_directory: input.working_directory ?? null,
|
|
342
980
|
};
|
|
343
|
-
const
|
|
344
|
-
|
|
981
|
+
const baseSystemPrompt = this.systemPromptsBySession.get(sessionId) ?? null;
|
|
982
|
+
let systemPrompt = baseSystemPrompt;
|
|
983
|
+
if (baseSystemPrompt && this.overlayDir) {
|
|
984
|
+
const cacheKey = `${input.role}.${effectiveSelection.provider}`;
|
|
985
|
+
let overlay: string | null;
|
|
986
|
+
if (this.overlayCache.has(cacheKey)) {
|
|
987
|
+
overlay = this.overlayCache.get(cacheKey) ?? null;
|
|
988
|
+
} else {
|
|
989
|
+
overlay = await resolvePromptOverlay(
|
|
990
|
+
this.overlayDir,
|
|
991
|
+
input.role,
|
|
992
|
+
effectiveSelection.provider,
|
|
993
|
+
);
|
|
994
|
+
this.overlayCache.set(cacheKey, overlay);
|
|
995
|
+
}
|
|
996
|
+
if (overlay) {
|
|
997
|
+
systemPrompt = `${baseSystemPrompt}\n\n---\n\n## Provider-Specific Instructions\n\n${overlay}`;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
const prompt = buildWorkerPrompt(promptPayload, systemPrompt, executionMode);
|
|
1001
|
+
const outputCapture = await this.createOutputCapture(runTemplate.args);
|
|
345
1002
|
|
|
346
|
-
const args = applyTemplateArgs(
|
|
1003
|
+
const args = applyTemplateArgs(runTemplate.args, {
|
|
347
1004
|
sessionId,
|
|
348
1005
|
prompt,
|
|
349
1006
|
featureId: input.feature_id,
|
|
350
1007
|
role: input.role,
|
|
1008
|
+
model: effectiveSelection.model,
|
|
1009
|
+
outputLastMessagePath: outputCapture.lastMessagePath ?? undefined,
|
|
1010
|
+
});
|
|
1011
|
+
const liveAgentConsole = await this.createLiveAgentConsoleCapture({
|
|
1012
|
+
featureId: input.feature_id,
|
|
1013
|
+
role: input.role,
|
|
1014
|
+
sessionId,
|
|
1015
|
+
provider: effectiveSelection.provider,
|
|
1016
|
+
model: effectiveSelection.model,
|
|
1017
|
+
executionMode,
|
|
1018
|
+
workingDirectory,
|
|
351
1019
|
});
|
|
352
1020
|
const effectiveTimeoutMs = this.resolveRunTimeoutMs();
|
|
353
1021
|
const runnerBackstopTimeoutMs = this.resolveRunnerBackstopTimeoutMs(effectiveTimeoutMs);
|
|
@@ -374,47 +1042,76 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
374
1042
|
};
|
|
375
1043
|
watchdog.start();
|
|
376
1044
|
|
|
377
|
-
let runResult: ProviderCommandResult;
|
|
378
1045
|
try {
|
|
379
|
-
runResult
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
1046
|
+
let runResult: ProviderCommandResult;
|
|
1047
|
+
try {
|
|
1048
|
+
runResult = await this.commandRunner.run(runTemplate.command, args, {
|
|
1049
|
+
stdin: prompt,
|
|
1050
|
+
cwd: input.working_directory,
|
|
1051
|
+
timeoutMs: runnerBackstopTimeoutMs,
|
|
1052
|
+
env: buildRunCommandEnv(effectiveSelection),
|
|
1053
|
+
onLifecycleEvent: (event) => {
|
|
1054
|
+
workerHandle.onLifecycleEvent?.(event);
|
|
1055
|
+
},
|
|
1056
|
+
registerKill: (kill) => {
|
|
1057
|
+
killRunner = kill;
|
|
1058
|
+
},
|
|
1059
|
+
onOutputChunk: (chunk) => {
|
|
1060
|
+
liveAgentConsole?.appendChunk(chunk.text);
|
|
1061
|
+
},
|
|
1062
|
+
});
|
|
1063
|
+
} catch (error) {
|
|
1064
|
+
watchdog.stop({
|
|
1065
|
+
signal: null,
|
|
1066
|
+
});
|
|
1067
|
+
await liveAgentConsole?.finalize('failed');
|
|
1068
|
+
throw error;
|
|
1069
|
+
}
|
|
1070
|
+
const watchdogOutcome = watchdog.stop({
|
|
1071
|
+
signal: runResult.signal,
|
|
1072
|
+
timedOut: runResult.timedOut ?? false,
|
|
390
1073
|
});
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
1074
|
+
|
|
1075
|
+
if (runResult.exitCode !== 0) {
|
|
1076
|
+
this.refreshSessionForRoleFeature(input.role, input.feature_id);
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
this.ensureRunSucceeded(
|
|
1080
|
+
runResult,
|
|
1081
|
+
runTemplate.command,
|
|
1082
|
+
args,
|
|
1083
|
+
effectiveTimeoutMs,
|
|
1084
|
+
watchdogOutcome,
|
|
1085
|
+
);
|
|
1086
|
+
this.markSessionBootstrapped(effectiveSelection.provider, sessionId);
|
|
1087
|
+
const preferredOutput = await this.resolvePreferredWorkerOutput(
|
|
1088
|
+
runResult.stdout ?? '',
|
|
1089
|
+
outputCapture.lastMessagePath,
|
|
1090
|
+
);
|
|
1091
|
+
await liveAgentConsole?.finalize('completed', preferredOutput);
|
|
1092
|
+
await this.persistRawAgentOutput(input.feature_id, input.role, preferredOutput);
|
|
1093
|
+
|
|
1094
|
+
const parsed = this.outputParser.parse(preferredOutput, {
|
|
1095
|
+
sessionId,
|
|
1096
|
+
role: input.role,
|
|
1097
|
+
featureId: input.feature_id,
|
|
1098
|
+
provider: this.selection.provider,
|
|
1099
|
+
model: this.selection.model,
|
|
1100
|
+
executionMode: input.execution_mode,
|
|
394
1101
|
});
|
|
1102
|
+
// CLI providers do not expose token usage; return unavailable status.
|
|
1103
|
+
parsed.usage = unavailableUsage(
|
|
1104
|
+
effectiveSelection.provider,
|
|
1105
|
+
effectiveSelection.model,
|
|
1106
|
+
input.role,
|
|
1107
|
+
);
|
|
1108
|
+
return parsed;
|
|
1109
|
+
} catch (error) {
|
|
1110
|
+
await liveAgentConsole?.finalize('failed');
|
|
395
1111
|
throw error;
|
|
1112
|
+
} finally {
|
|
1113
|
+
await this.cleanupOutputCapture(outputCapture.captureDir);
|
|
396
1114
|
}
|
|
397
|
-
const watchdogOutcome = watchdog.stop({
|
|
398
|
-
signal: runResult.signal,
|
|
399
|
-
timedOut: runResult.timedOut ?? false,
|
|
400
|
-
});
|
|
401
|
-
|
|
402
|
-
this.ensureRunSucceeded(
|
|
403
|
-
runResult,
|
|
404
|
-
this.runTemplate.command,
|
|
405
|
-
args,
|
|
406
|
-
effectiveTimeoutMs,
|
|
407
|
-
watchdogOutcome,
|
|
408
|
-
);
|
|
409
|
-
await this.persistRawAgentOutput(input.feature_id, input.role, runResult.stdout ?? '');
|
|
410
|
-
|
|
411
|
-
return this.outputParser.parse(runResult.stdout ?? '', {
|
|
412
|
-
sessionId,
|
|
413
|
-
role: input.role,
|
|
414
|
-
featureId: input.feature_id,
|
|
415
|
-
provider: this.selection.provider,
|
|
416
|
-
model: this.selection.model,
|
|
417
|
-
});
|
|
418
1115
|
}
|
|
419
1116
|
|
|
420
1117
|
getCapabilities(): WorkerProviderCapabilities {
|
|
@@ -425,6 +1122,88 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
425
1122
|
return `${role}::${featureId}`;
|
|
426
1123
|
}
|
|
427
1124
|
|
|
1125
|
+
private resolveOrCreateSessionId(role: string, featureId: string): string {
|
|
1126
|
+
const key = this.sessionKey(role, featureId);
|
|
1127
|
+
const existingSessionId = this.sessionsByRoleFeature.get(key);
|
|
1128
|
+
if (existingSessionId) {
|
|
1129
|
+
return existingSessionId;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
const sessionId = crypto.randomUUID();
|
|
1133
|
+
this.sessionsByRoleFeature.set(key, sessionId);
|
|
1134
|
+
this.systemPromptsBySession.set(sessionId, null);
|
|
1135
|
+
return sessionId;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
private refreshSessionForRoleFeature(role: string, featureId: string): void {
|
|
1139
|
+
const key = this.sessionKey(role, featureId);
|
|
1140
|
+
const oldSessionId = this.sessionsByRoleFeature.get(key);
|
|
1141
|
+
if (!oldSessionId) {
|
|
1142
|
+
return;
|
|
1143
|
+
}
|
|
1144
|
+
const systemPrompt = this.systemPromptsBySession.get(oldSessionId) ?? null;
|
|
1145
|
+
const newSessionId = crypto.randomUUID();
|
|
1146
|
+
this.sessionsByRoleFeature.set(key, newSessionId);
|
|
1147
|
+
this.bootstrappedSessionIds.delete(oldSessionId);
|
|
1148
|
+
this.systemPromptsBySession.delete(oldSessionId);
|
|
1149
|
+
this.systemPromptsBySession.set(newSessionId, systemPrompt);
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
private async shouldResumeSession(
|
|
1153
|
+
provider: string,
|
|
1154
|
+
sessionId: string,
|
|
1155
|
+
workingDirectory: string,
|
|
1156
|
+
): Promise<boolean> {
|
|
1157
|
+
if (provider !== 'claude') {
|
|
1158
|
+
return false;
|
|
1159
|
+
}
|
|
1160
|
+
if (this.bootstrappedSessionIds.has(sessionId)) {
|
|
1161
|
+
return true;
|
|
1162
|
+
}
|
|
1163
|
+
try {
|
|
1164
|
+
await fs.access(resolveClaudeTranscriptPath(workingDirectory, sessionId));
|
|
1165
|
+
this.bootstrappedSessionIds.add(sessionId);
|
|
1166
|
+
return true;
|
|
1167
|
+
} catch {
|
|
1168
|
+
return false;
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
private markSessionBootstrapped(provider: string, sessionId: string): void {
|
|
1173
|
+
if (provider === 'claude') {
|
|
1174
|
+
this.bootstrappedSessionIds.add(sessionId);
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
private resolveEffectiveSelection(
|
|
1179
|
+
runtimeSelection: WorkerRunInput['runtime_selection'] | null,
|
|
1180
|
+
): ProviderSelection {
|
|
1181
|
+
if (!runtimeSelection) {
|
|
1182
|
+
return this.selection;
|
|
1183
|
+
}
|
|
1184
|
+
if (runtimeSelection.provider !== this.selection.provider) {
|
|
1185
|
+
throw providerError(
|
|
1186
|
+
ERROR_CODES.INVALID_ARGUMENT,
|
|
1187
|
+
'Runtime selection provider override is not supported for this worker provider',
|
|
1188
|
+
{
|
|
1189
|
+
provider: this.selection.provider,
|
|
1190
|
+
runtime_provider: runtimeSelection.provider,
|
|
1191
|
+
},
|
|
1192
|
+
);
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
return {
|
|
1196
|
+
...this.selection,
|
|
1197
|
+
provider: runtimeSelection.provider,
|
|
1198
|
+
model: runtimeSelection.model,
|
|
1199
|
+
provider_config_env: runtimeSelection.provider_config_env ?? null,
|
|
1200
|
+
provider_config_ref: runtimeSelection.provider_config_ref,
|
|
1201
|
+
agent_config: isRecord(runtimeSelection.agent_config)
|
|
1202
|
+
? runtimeSelection.agent_config
|
|
1203
|
+
: this.selection.agent_config,
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1206
|
+
|
|
428
1207
|
private ensureRunSucceeded(
|
|
429
1208
|
result: ProviderCommandResult,
|
|
430
1209
|
command: string,
|
|
@@ -452,6 +1231,7 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
452
1231
|
idle_for_ms: watchdogOutcome.idleForMs,
|
|
453
1232
|
elapsed_ms: watchdogOutcome.elapsedMs,
|
|
454
1233
|
stderr: result.stderr,
|
|
1234
|
+
stdout: result.stdout ? result.stdout.slice(0, 500) : undefined,
|
|
455
1235
|
});
|
|
456
1236
|
}
|
|
457
1237
|
|
|
@@ -512,6 +1292,7 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
512
1292
|
featureId: 'global',
|
|
513
1293
|
role: 'orchestrator',
|
|
514
1294
|
message,
|
|
1295
|
+
model: this.selection.model,
|
|
515
1296
|
});
|
|
516
1297
|
|
|
517
1298
|
const result = await this.commandRunner.run(template.command, args, {
|
|
@@ -524,6 +1305,15 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
524
1305
|
return;
|
|
525
1306
|
}
|
|
526
1307
|
|
|
1308
|
+
if (
|
|
1309
|
+
kind === 'send' &&
|
|
1310
|
+
typeof message === 'string' &&
|
|
1311
|
+
this.isMissingClaudeConversation(result) &&
|
|
1312
|
+
(await this.bootstrapMissingClaudeControlSession(sessionId, message))
|
|
1313
|
+
) {
|
|
1314
|
+
return;
|
|
1315
|
+
}
|
|
1316
|
+
|
|
527
1317
|
throw providerError(
|
|
528
1318
|
result.exitCode === 127 || result.errorCode === 'ENOENT'
|
|
529
1319
|
? ERROR_CODES.UNSUPPORTED_AGENT_PROVIDER
|
|
@@ -537,10 +1327,159 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
537
1327
|
exit_code: result.exitCode,
|
|
538
1328
|
signal: result.signal,
|
|
539
1329
|
error_code: result.errorCode,
|
|
1330
|
+
timed_out: result.timedOut ?? false,
|
|
1331
|
+
stdout: result.stdout,
|
|
1332
|
+
stderr: result.stderr,
|
|
540
1333
|
},
|
|
541
1334
|
);
|
|
542
1335
|
}
|
|
543
1336
|
|
|
1337
|
+
private async createLiveAgentConsoleCapture(input: {
|
|
1338
|
+
featureId: string;
|
|
1339
|
+
role: string;
|
|
1340
|
+
sessionId: string;
|
|
1341
|
+
provider: string;
|
|
1342
|
+
model: string | null;
|
|
1343
|
+
executionMode: 'deterministic' | 'interactive';
|
|
1344
|
+
workingDirectory: string;
|
|
1345
|
+
}): Promise<LiveAgentConsoleCapture | null> {
|
|
1346
|
+
if (!this.rawAgentLogsEnabled || !this.repoRoot || !isRawLogRole(input.role)) {
|
|
1347
|
+
return null;
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
const liveDir = path.join(this.repoRoot, '.aop', 'features', input.featureId, 'logs', 'live');
|
|
1351
|
+
const contentPath = path.join(liveDir, `${input.role}.txt`);
|
|
1352
|
+
const metadataPath = path.join(liveDir, `${input.role}.json`);
|
|
1353
|
+
const startedAt = new Date().toISOString();
|
|
1354
|
+
let writeChain = Promise.resolve();
|
|
1355
|
+
let hasLiveContent = false;
|
|
1356
|
+
let finalized = false;
|
|
1357
|
+
let transcriptInterval: NodeJS.Timeout | null = null;
|
|
1358
|
+
let lastTranscriptMtimeMs = -1;
|
|
1359
|
+
let lastRenderedTranscript = '';
|
|
1360
|
+
const transcriptPath =
|
|
1361
|
+
input.provider === 'claude'
|
|
1362
|
+
? resolveClaudeTranscriptPath(input.workingDirectory, input.sessionId)
|
|
1363
|
+
: null;
|
|
1364
|
+
|
|
1365
|
+
const enqueue = (task: () => Promise<void>): void => {
|
|
1366
|
+
writeChain = writeChain.then(task).catch(() => undefined);
|
|
1367
|
+
};
|
|
1368
|
+
|
|
1369
|
+
const syncClaudeTranscript = (): void => {
|
|
1370
|
+
if (!transcriptPath || finalized) {
|
|
1371
|
+
return;
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
enqueue(async () => {
|
|
1375
|
+
try {
|
|
1376
|
+
const stats = await fs.stat(transcriptPath);
|
|
1377
|
+
if (stats.mtimeMs <= lastTranscriptMtimeMs) {
|
|
1378
|
+
return;
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
const raw = await fs.readFile(transcriptPath, 'utf8');
|
|
1382
|
+
const rendered = renderClaudeTranscript(raw);
|
|
1383
|
+
lastTranscriptMtimeMs = stats.mtimeMs;
|
|
1384
|
+
if (rendered === lastRenderedTranscript) {
|
|
1385
|
+
return;
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
lastRenderedTranscript = rendered;
|
|
1389
|
+
hasLiveContent = rendered.trim().length > 0;
|
|
1390
|
+
await fs.writeFile(contentPath, rendered, 'utf8');
|
|
1391
|
+
} catch {
|
|
1392
|
+
// Claude transcript mirroring is best-effort.
|
|
1393
|
+
}
|
|
1394
|
+
});
|
|
1395
|
+
};
|
|
1396
|
+
|
|
1397
|
+
try {
|
|
1398
|
+
await fs.mkdir(liveDir, { recursive: true });
|
|
1399
|
+
await fs.writeFile(contentPath, '', 'utf8');
|
|
1400
|
+
await fs.writeFile(
|
|
1401
|
+
metadataPath,
|
|
1402
|
+
JSON.stringify(
|
|
1403
|
+
{
|
|
1404
|
+
feature_id: input.featureId,
|
|
1405
|
+
role: input.role,
|
|
1406
|
+
session_id: input.sessionId,
|
|
1407
|
+
provider: input.provider,
|
|
1408
|
+
model: input.model,
|
|
1409
|
+
execution_mode: input.executionMode,
|
|
1410
|
+
status: 'running',
|
|
1411
|
+
started_at: startedAt,
|
|
1412
|
+
ended_at: null,
|
|
1413
|
+
},
|
|
1414
|
+
null,
|
|
1415
|
+
2,
|
|
1416
|
+
),
|
|
1417
|
+
'utf8',
|
|
1418
|
+
);
|
|
1419
|
+
} catch {
|
|
1420
|
+
return null;
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
if (transcriptPath) {
|
|
1424
|
+
syncClaudeTranscript();
|
|
1425
|
+
transcriptInterval = setInterval(() => {
|
|
1426
|
+
syncClaudeTranscript();
|
|
1427
|
+
}, 500);
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
return {
|
|
1431
|
+
appendChunk: (chunk: string) => {
|
|
1432
|
+
if (finalized || chunk.length === 0 || transcriptPath) {
|
|
1433
|
+
return;
|
|
1434
|
+
}
|
|
1435
|
+
hasLiveContent = true;
|
|
1436
|
+
enqueue(async () => {
|
|
1437
|
+
await fs.appendFile(contentPath, chunk, 'utf8');
|
|
1438
|
+
});
|
|
1439
|
+
},
|
|
1440
|
+
finalize: async (status: 'completed' | 'failed', fallbackContent?: string) => {
|
|
1441
|
+
if (finalized) {
|
|
1442
|
+
return;
|
|
1443
|
+
}
|
|
1444
|
+
finalized = true;
|
|
1445
|
+
if (transcriptInterval) {
|
|
1446
|
+
clearInterval(transcriptInterval);
|
|
1447
|
+
transcriptInterval = null;
|
|
1448
|
+
}
|
|
1449
|
+
if (transcriptPath) {
|
|
1450
|
+
syncClaudeTranscript();
|
|
1451
|
+
}
|
|
1452
|
+
if (!hasLiveContent && typeof fallbackContent === 'string' && fallbackContent.length > 0) {
|
|
1453
|
+
enqueue(async () => {
|
|
1454
|
+
await fs.writeFile(contentPath, fallbackContent, 'utf8');
|
|
1455
|
+
});
|
|
1456
|
+
}
|
|
1457
|
+
await writeChain;
|
|
1458
|
+
await fs
|
|
1459
|
+
.writeFile(
|
|
1460
|
+
metadataPath,
|
|
1461
|
+
JSON.stringify(
|
|
1462
|
+
{
|
|
1463
|
+
feature_id: input.featureId,
|
|
1464
|
+
role: input.role,
|
|
1465
|
+
session_id: input.sessionId,
|
|
1466
|
+
provider: input.provider,
|
|
1467
|
+
model: input.model,
|
|
1468
|
+
execution_mode: input.executionMode,
|
|
1469
|
+
status,
|
|
1470
|
+
started_at: startedAt,
|
|
1471
|
+
ended_at: new Date().toISOString(),
|
|
1472
|
+
},
|
|
1473
|
+
null,
|
|
1474
|
+
2,
|
|
1475
|
+
),
|
|
1476
|
+
'utf8',
|
|
1477
|
+
)
|
|
1478
|
+
.catch(() => undefined);
|
|
1479
|
+
},
|
|
1480
|
+
};
|
|
1481
|
+
}
|
|
1482
|
+
|
|
544
1483
|
private async persistRawAgentOutput(
|
|
545
1484
|
featureId: string,
|
|
546
1485
|
role: string,
|
|
@@ -552,7 +1491,7 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
552
1491
|
if (stdout.trim().length === 0) {
|
|
553
1492
|
return;
|
|
554
1493
|
}
|
|
555
|
-
if (role
|
|
1494
|
+
if (!isRawLogRole(role)) {
|
|
556
1495
|
return;
|
|
557
1496
|
}
|
|
558
1497
|
|
|
@@ -569,6 +1508,43 @@ export class CliWorkerProvider implements WorkerProvider {
|
|
|
569
1508
|
}
|
|
570
1509
|
}
|
|
571
1510
|
|
|
1511
|
+
private async createOutputCapture(
|
|
1512
|
+
args: string[],
|
|
1513
|
+
): Promise<{ captureDir: string | null; lastMessagePath: string | null }> {
|
|
1514
|
+
if (!args.includes('{output_last_message_path}')) {
|
|
1515
|
+
return { captureDir: null, lastMessagePath: null };
|
|
1516
|
+
}
|
|
1517
|
+
const captureDir = await fs.mkdtemp(path.join(os.tmpdir(), 'aop-provider-output-'));
|
|
1518
|
+
return {
|
|
1519
|
+
captureDir,
|
|
1520
|
+
lastMessagePath: path.join(captureDir, 'last-message.txt'),
|
|
1521
|
+
};
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
private async resolvePreferredWorkerOutput(
|
|
1525
|
+
stdout: string,
|
|
1526
|
+
lastMessagePath: string | null,
|
|
1527
|
+
): Promise<string> {
|
|
1528
|
+
if (lastMessagePath) {
|
|
1529
|
+
try {
|
|
1530
|
+
const lastMessage = await fs.readFile(lastMessagePath, 'utf8');
|
|
1531
|
+
if (lastMessage.trim().length > 0) {
|
|
1532
|
+
return lastMessage;
|
|
1533
|
+
}
|
|
1534
|
+
} catch {
|
|
1535
|
+
// Fall back to stdout when the provider does not materialize the capture file.
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
return stdout;
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
private async cleanupOutputCapture(captureDir: string | null): Promise<void> {
|
|
1542
|
+
if (!captureDir) {
|
|
1543
|
+
return;
|
|
1544
|
+
}
|
|
1545
|
+
await fs.rm(captureDir, { recursive: true, force: true }).catch(() => undefined);
|
|
1546
|
+
}
|
|
1547
|
+
|
|
572
1548
|
private async cleanupExpiredRawAgentLogs(logsDir: string): Promise<void> {
|
|
573
1549
|
const cutoffMs = Date.now() - this.rawAgentLogsRetentionDays * 24 * 60 * 60 * 1000;
|
|
574
1550
|
try {
|