agentic-orchestrator 0.1.27 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.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 +110 -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 +252 -18
- 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 +801 -43
- 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/path-normalizers.spec.ts +41 -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 +786 -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 +3141 -364
- 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 +23 -2
- 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 +83 -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 +196 -19
- 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 +33 -1
- package/dist/apps/control-plane/supervisor/run-coordinator.js +631 -39
- 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 +357 -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 +131 -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 +107 -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 +845 -59
- 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 +54 -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 +2045 -87
- 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,6 +1,22 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
1
3
|
import { STATUS, TOOLS } from '../core/constants.js';
|
|
2
4
|
import { ERROR_CODES } from '../core/error-codes.js';
|
|
5
|
+
import {
|
|
6
|
+
normalizeManifestConfidence,
|
|
7
|
+
obligationsMeetConfidenceThreshold,
|
|
8
|
+
validatePlanTraceAgainstObligationIds,
|
|
9
|
+
type PlanTraceContractValidation,
|
|
10
|
+
} from '../core/intake-artifacts.js';
|
|
11
|
+
import type { FeatureStatePayload } from '../core/tool-caller.js';
|
|
12
|
+
import {
|
|
13
|
+
assessGateFreshness,
|
|
14
|
+
readCheckpointValidity,
|
|
15
|
+
readGateEvidenceByMode,
|
|
16
|
+
} from '../core/gate-freshness.js';
|
|
17
|
+
import { extractGateLog, type GateLogExtraction } from '../core/gate-log-extractor.js';
|
|
3
18
|
import type { FeatureContextPayload, InitialPlanGenerator, SupervisorToolCaller } from './types.js';
|
|
19
|
+
import { resolvePlannerPhaseFromContext } from './planner-phase.js';
|
|
4
20
|
import {
|
|
5
21
|
NOOP_WORKER_DECISION_RUNNER,
|
|
6
22
|
type WorkerDecisionResult,
|
|
@@ -21,6 +37,9 @@ type AnyRecord = Record<string, unknown>;
|
|
|
21
37
|
interface PlanningWaveExecutorDependencies {
|
|
22
38
|
toolCaller: SupervisorToolCaller;
|
|
23
39
|
planGenerator: InitialPlanGenerator;
|
|
40
|
+
plannerSessionSync?: {
|
|
41
|
+
syncPlannerSessions(featureIds: string[]): Promise<void>;
|
|
42
|
+
};
|
|
24
43
|
workerDecisionRunner?: WorkerDecisionRunner;
|
|
25
44
|
providerMode?: WorkerProviderMode;
|
|
26
45
|
outputLoopDetector?: OutputLoopDetector;
|
|
@@ -35,10 +54,22 @@ interface PlanningWaveExecutorDependencies {
|
|
|
35
54
|
runId?: string | (() => string);
|
|
36
55
|
providerName?: string;
|
|
37
56
|
modelName?: string;
|
|
57
|
+
safeCheckpointHook?: () => Promise<void>;
|
|
58
|
+
getPolicySnapshot?: () => Record<string, unknown>;
|
|
38
59
|
}
|
|
39
60
|
|
|
40
61
|
interface ReconciliationDecision {
|
|
41
|
-
|
|
62
|
+
planDecision: 'update_required' | 'unchanged';
|
|
63
|
+
executionDisposition:
|
|
64
|
+
| 'converged'
|
|
65
|
+
| 'retry_build'
|
|
66
|
+
| 'retry_qa'
|
|
67
|
+
| 'rerun_fast_gate'
|
|
68
|
+
| 'rerun_full_gate'
|
|
69
|
+
| 'blocked_checkpoint_invalid'
|
|
70
|
+
| 'blocked_provider_failure'
|
|
71
|
+
| 'blocked_stale_evidence'
|
|
72
|
+
| 'blocked_other';
|
|
42
73
|
reasons: string[];
|
|
43
74
|
acceptanceCriteriaAdditions: string[];
|
|
44
75
|
edgeCaseChecklist: string[];
|
|
@@ -48,6 +79,10 @@ interface ReconciliationDecision {
|
|
|
48
79
|
running: number;
|
|
49
80
|
};
|
|
50
81
|
latestGateOverall: string | null;
|
|
82
|
+
gateEvidenceFreshness: string;
|
|
83
|
+
checkpointValidity: string;
|
|
84
|
+
gateFailureContext: Record<string, unknown> | null;
|
|
85
|
+
planTraceContract: PlanTraceContractValidation | null;
|
|
51
86
|
}
|
|
52
87
|
|
|
53
88
|
function asRecord(value: unknown): AnyRecord {
|
|
@@ -85,6 +120,14 @@ function normalizeList(values: string[]): string[] {
|
|
|
85
120
|
return normalized;
|
|
86
121
|
}
|
|
87
122
|
|
|
123
|
+
function asString(value: unknown): string | null {
|
|
124
|
+
return typeof value === 'string' && value.length > 0 ? value : null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function asNumber(value: unknown): number | null {
|
|
128
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : null;
|
|
129
|
+
}
|
|
130
|
+
|
|
88
131
|
function readCount(summary: AnyRecord, key: string): number {
|
|
89
132
|
const raw = summary[key];
|
|
90
133
|
if (typeof raw !== 'number' || !Number.isFinite(raw) || raw < 0) {
|
|
@@ -97,6 +140,53 @@ function readStatus(value: unknown): string {
|
|
|
97
140
|
return typeof value === 'string' ? value : 'unknown';
|
|
98
141
|
}
|
|
99
142
|
|
|
143
|
+
function readVerifiedManifestObligations(context: FeatureContextPayload): AnyRecord[] {
|
|
144
|
+
const intake = asRecord(context.intake);
|
|
145
|
+
const verifiedManifest = asRecord(intake.verified_manifest);
|
|
146
|
+
return Array.isArray(verifiedManifest.obligations)
|
|
147
|
+
? verifiedManifest.obligations.map((item) => asRecord(item))
|
|
148
|
+
: [];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function readVerifiedManifestObligationIds(context: FeatureContextPayload): string[] {
|
|
152
|
+
const obligations = readVerifiedManifestObligations(context);
|
|
153
|
+
return normalizeList(
|
|
154
|
+
obligations
|
|
155
|
+
.map((item) => asString(item.obligation_id))
|
|
156
|
+
.filter((item): item is string => item !== null),
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function readPlanTraceContractValidation(
|
|
161
|
+
context: FeatureContextPayload,
|
|
162
|
+
plan: AnyRecord,
|
|
163
|
+
): PlanTraceContractValidation | null {
|
|
164
|
+
const verifiedObligationIds = readVerifiedManifestObligationIds(context);
|
|
165
|
+
if (verifiedObligationIds.length === 0) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
return validatePlanTraceAgainstObligationIds(plan, verifiedObligationIds);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function hasInvalidPlanTraceContract(
|
|
172
|
+
validation: PlanTraceContractValidation | null,
|
|
173
|
+
): validation is PlanTraceContractValidation {
|
|
174
|
+
return validation !== null && !validation.valid;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
interface IntakeRecoveryAmbiguity {
|
|
178
|
+
id: string;
|
|
179
|
+
summary: string;
|
|
180
|
+
obligationIds: string[];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
interface IntakeRecoveryAnswer {
|
|
184
|
+
questionId: string;
|
|
185
|
+
ambiguityIds: string[];
|
|
186
|
+
answer: string;
|
|
187
|
+
answeredAt: string | null;
|
|
188
|
+
}
|
|
189
|
+
|
|
100
190
|
function deriveEdgeCaseChecklist(specText: string): string[] {
|
|
101
191
|
const checklist = [
|
|
102
192
|
'Edge-case: boundary values and size limits are covered.',
|
|
@@ -121,6 +211,39 @@ function deriveEdgeCaseChecklist(specText: string): string[] {
|
|
|
121
211
|
return normalizeList(checklist);
|
|
122
212
|
}
|
|
123
213
|
|
|
214
|
+
function deriveEdgeCaseChecklistFromVerifiedManifest(obligations: AnyRecord[]): string[] {
|
|
215
|
+
const checklist: string[] = [];
|
|
216
|
+
const kinds = new Set(
|
|
217
|
+
obligations
|
|
218
|
+
.map((obligation) => asString(obligation.kind))
|
|
219
|
+
.filter((item): item is string => item !== null),
|
|
220
|
+
);
|
|
221
|
+
const verificationHints = new Set(
|
|
222
|
+
obligations
|
|
223
|
+
.map((obligation) => asString(obligation.verification_hint))
|
|
224
|
+
.filter((item): item is string => item !== null),
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
if (kinds.has('artifact') || kinds.has('workflow') || kinds.has('behavior')) {
|
|
228
|
+
checklist.push(
|
|
229
|
+
'Verified workflow and artifact obligations cover boundary values and phase transitions.',
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
if (kinds.has('endpoint') || kinds.has('contract')) {
|
|
233
|
+
checklist.push(
|
|
234
|
+
'Verified endpoint and contract obligations cover payload validation and negative-path handling.',
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
if (kinds.has('integration')) {
|
|
238
|
+
checklist.push('Verified integration obligations cover dependency failure and retry behavior.');
|
|
239
|
+
}
|
|
240
|
+
if (verificationHints.has('required') || kinds.has('verification')) {
|
|
241
|
+
checklist.push('Required verified-manifest obligations have explicit verification coverage.');
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return normalizeList(checklist);
|
|
245
|
+
}
|
|
246
|
+
|
|
124
247
|
function readPlanVersion(plan: AnyRecord): number | null {
|
|
125
248
|
const raw = plan.plan_version;
|
|
126
249
|
if (typeof raw !== 'number' || !Number.isFinite(raw) || raw < 1) {
|
|
@@ -129,6 +252,14 @@ function readPlanVersion(plan: AnyRecord): number | null {
|
|
|
129
252
|
return Math.floor(raw);
|
|
130
253
|
}
|
|
131
254
|
|
|
255
|
+
function readStateVersion(frontMatter: AnyRecord): number | null {
|
|
256
|
+
const raw = frontMatter.version;
|
|
257
|
+
if (typeof raw !== 'number' || !Number.isFinite(raw) || raw < 1) {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
return Math.floor(raw);
|
|
261
|
+
}
|
|
262
|
+
|
|
132
263
|
function isPostQaStatus(status: string): boolean {
|
|
133
264
|
return status === STATUS.QA || status === STATUS.READY_TO_MERGE || status === STATUS.BLOCKED;
|
|
134
265
|
}
|
|
@@ -143,9 +274,19 @@ const TIMEOUT_RUNTIME_ERROR_CODES = new Set<string>([
|
|
|
143
274
|
* @fileoverview Planning phase wave executor.
|
|
144
275
|
*/
|
|
145
276
|
|
|
277
|
+
/**
|
|
278
|
+
* Executes the planning phase for one supervisor iteration wave.
|
|
279
|
+
* Handles intake verification, plan generation, worker decision dispatch,
|
|
280
|
+
* and post-QA reconciliation of accepted plans.
|
|
281
|
+
*/
|
|
146
282
|
export class PlanningWaveExecutor {
|
|
147
283
|
private readonly toolCaller: SupervisorToolCaller;
|
|
148
284
|
private readonly planGenerator: InitialPlanGenerator;
|
|
285
|
+
private readonly plannerSessionSync:
|
|
286
|
+
| {
|
|
287
|
+
syncPlannerSessions(featureIds: string[]): Promise<void>;
|
|
288
|
+
}
|
|
289
|
+
| undefined;
|
|
149
290
|
private readonly workerDecisionRunner: WorkerDecisionRunner;
|
|
150
291
|
private readonly providerMode: WorkerProviderMode;
|
|
151
292
|
private readonly outputLoopDetector: OutputLoopDetector | undefined;
|
|
@@ -160,12 +301,15 @@ export class PlanningWaveExecutor {
|
|
|
160
301
|
private readonly runId: string | (() => string) | null;
|
|
161
302
|
private readonly providerName: string;
|
|
162
303
|
private readonly modelName: string;
|
|
304
|
+
private readonly safeCheckpointHook: (() => Promise<void>) | undefined;
|
|
305
|
+
private readonly getPolicySnapshot: (() => Record<string, unknown>) | undefined;
|
|
163
306
|
private readonly noProgressByFeature = new Map<string, number>();
|
|
164
307
|
private readonly lastStatusByFeature = new Map<string, string>();
|
|
165
308
|
|
|
166
309
|
constructor(dependencies: PlanningWaveExecutorDependencies) {
|
|
167
310
|
this.toolCaller = dependencies.toolCaller;
|
|
168
311
|
this.planGenerator = dependencies.planGenerator;
|
|
312
|
+
this.plannerSessionSync = dependencies.plannerSessionSync;
|
|
169
313
|
this.workerDecisionRunner = dependencies.workerDecisionRunner ?? NOOP_WORKER_DECISION_RUNNER;
|
|
170
314
|
this.providerMode = dependencies.providerMode ?? 'stub';
|
|
171
315
|
this.outputLoopDetector = dependencies.outputLoopDetector;
|
|
@@ -183,78 +327,262 @@ export class PlanningWaveExecutor {
|
|
|
183
327
|
this.runId = dependencies.runId ?? null;
|
|
184
328
|
this.providerName = dependencies.providerName ?? 'unknown';
|
|
185
329
|
this.modelName = dependencies.modelName ?? 'unknown';
|
|
330
|
+
this.safeCheckpointHook = dependencies.safeCheckpointHook;
|
|
331
|
+
this.getPolicySnapshot = dependencies.getPolicySnapshot;
|
|
186
332
|
}
|
|
187
333
|
|
|
334
|
+
/**
|
|
335
|
+
* Runs a single planning wave: resolves planner phase (intake vs. planning), invokes workers,
|
|
336
|
+
* normalizes accepted plan state, and falls back to stub plan generation when not in live mode.
|
|
337
|
+
* @param featureIds Feature IDs eligible for planning in this wave.
|
|
338
|
+
*/
|
|
188
339
|
async run(featureIds: string[]): Promise<void> {
|
|
340
|
+
await this.plannerSessionSync?.syncPlannerSessions(featureIds);
|
|
189
341
|
for (const featureId of featureIds) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
342
|
+
try {
|
|
343
|
+
const context = await this.toolCaller.callTool<FeatureContextPayload>(
|
|
344
|
+
'planner',
|
|
345
|
+
TOOLS.FEATURE_GET_CONTEXT,
|
|
346
|
+
{
|
|
347
|
+
feature_id: featureId,
|
|
348
|
+
},
|
|
349
|
+
);
|
|
197
350
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
351
|
+
const state = context.data.state.front_matter;
|
|
352
|
+
const plannerPhase = resolvePlannerPhaseFromContext(context.data);
|
|
353
|
+
const previousStatus = this.lastStatusByFeature.get(featureId);
|
|
354
|
+
if (previousStatus === STATUS.BLOCKED && state.status === STATUS.PLANNING) {
|
|
355
|
+
this.noProgressByFeature.delete(featureId);
|
|
356
|
+
this.outputLoopDetector?.reset(featureId);
|
|
357
|
+
}
|
|
358
|
+
this.lastStatusByFeature.set(featureId, state.status);
|
|
359
|
+
if (
|
|
360
|
+
state.status !== STATUS.INTAKE &&
|
|
361
|
+
state.status !== STATUS.PLANNING &&
|
|
362
|
+
state.status !== STATUS.BLOCKED
|
|
363
|
+
) {
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
208
366
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
} catch (error) {
|
|
220
|
-
const handledRuntimeFailure = await this.handleRuntimeFailure(error, featureId);
|
|
221
|
-
if (handledRuntimeFailure) {
|
|
367
|
+
const existingPlan = asRecord(context.data.plan);
|
|
368
|
+
const planTraceContract = readPlanTraceContractValidation(context.data, existingPlan);
|
|
369
|
+
if (
|
|
370
|
+
await this.normalizeAcceptedPlanState(
|
|
371
|
+
featureId,
|
|
372
|
+
asRecord(state),
|
|
373
|
+
existingPlan,
|
|
374
|
+
planTraceContract,
|
|
375
|
+
)
|
|
376
|
+
) {
|
|
222
377
|
continue;
|
|
223
378
|
}
|
|
224
|
-
|
|
225
|
-
|
|
379
|
+
if (
|
|
380
|
+
state.status === STATUS.BLOCKED &&
|
|
381
|
+
plannerPhase === 'planning' &&
|
|
382
|
+
readPlanVersion(existingPlan) !== null &&
|
|
383
|
+
!hasInvalidPlanTraceContract(planTraceContract)
|
|
384
|
+
) {
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
let decision: WorkerDecisionResult;
|
|
388
|
+
try {
|
|
389
|
+
decision = await this.workerDecisionRunner.execute({
|
|
390
|
+
role: 'planner',
|
|
391
|
+
featureId,
|
|
392
|
+
contextBundle: asRecord(context.data),
|
|
393
|
+
instructions: this.instructionsForPlannerState(asRecord(context.data)),
|
|
394
|
+
});
|
|
395
|
+
} catch (error) {
|
|
396
|
+
const handledRuntimeFailure = await this.handleRuntimeFailure(error, featureId);
|
|
397
|
+
if (handledRuntimeFailure) {
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
throw error;
|
|
401
|
+
}
|
|
226
402
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
403
|
+
const loopStalled = await this.enforceOutputLoopPolicy(featureId, decision);
|
|
404
|
+
if (loopStalled) {
|
|
405
|
+
continue;
|
|
406
|
+
}
|
|
231
407
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
408
|
+
if (decision.questionRequested) {
|
|
409
|
+
this.noProgressByFeature.delete(featureId);
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
if (decision.intakeSubmission) {
|
|
413
|
+
this.noProgressByFeature.delete(featureId);
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
236
416
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
417
|
+
const shouldSkip = await this.enforceWorkerExecutionPolicy(featureId, decision);
|
|
418
|
+
if (shouldSkip) {
|
|
419
|
+
continue;
|
|
420
|
+
}
|
|
240
421
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
422
|
+
if (
|
|
423
|
+
decision.planSubmission ||
|
|
424
|
+
(readPlanVersion(existingPlan) !== null &&
|
|
425
|
+
!hasInvalidPlanTraceContract(planTraceContract))
|
|
426
|
+
) {
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
if (this.providerMode === 'stub') {
|
|
431
|
+
if (plannerPhase === 'intake') {
|
|
432
|
+
const intake = asRecord(asRecord(context.data).intake);
|
|
433
|
+
const verifiedManifest = asRecord(intake.verified_manifest);
|
|
434
|
+
const bootstrapManifest = asRecord(intake.bootstrap_manifest);
|
|
435
|
+
if (
|
|
436
|
+
Object.keys(verifiedManifest).length === 0 &&
|
|
437
|
+
this.policyAllowsStubAutoPromotion(bootstrapManifest)
|
|
438
|
+
) {
|
|
439
|
+
await this.toolCaller.callTool('planner', TOOLS.FEATURE_INTAKE_SUBMIT, {
|
|
440
|
+
feature_id: featureId,
|
|
441
|
+
intake_submission: {
|
|
442
|
+
verified_manifest: {
|
|
443
|
+
...bootstrapManifest,
|
|
444
|
+
artifact_type: 'verified',
|
|
445
|
+
verification_basis: 'policy_approved_auto_promotion',
|
|
446
|
+
verified_at: new Date().toISOString(),
|
|
447
|
+
source_bootstrap_version:
|
|
448
|
+
typeof bootstrapManifest.manifest_version === 'number'
|
|
449
|
+
? bootstrapManifest.manifest_version
|
|
450
|
+
: null,
|
|
451
|
+
},
|
|
452
|
+
open_ambiguities: [],
|
|
453
|
+
resolved_ambiguities: [],
|
|
454
|
+
requires_user_input: false,
|
|
455
|
+
},
|
|
456
|
+
});
|
|
457
|
+
continue;
|
|
458
|
+
}
|
|
459
|
+
if (Object.keys(verifiedManifest).length === 0) {
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
const plan = await this.planGenerator.generateInitialPlan(featureId);
|
|
464
|
+
await this.toolCaller.callTool('planner', TOOLS.PLAN_SUBMIT, {
|
|
465
|
+
feature_id: featureId,
|
|
466
|
+
plan_json: plan,
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
} finally {
|
|
470
|
+
if (this.safeCheckpointHook) {
|
|
471
|
+
await this.safeCheckpointHook();
|
|
472
|
+
}
|
|
247
473
|
}
|
|
248
474
|
}
|
|
249
475
|
}
|
|
250
476
|
|
|
477
|
+
/**
|
|
478
|
+
* Clears all per-feature tracking state (progress counters, status cache, loop detector).
|
|
479
|
+
* Called when a feature is removed from the active execution set.
|
|
480
|
+
* @param featureId The feature whose tracking data should be purged.
|
|
481
|
+
*/
|
|
251
482
|
clearFeatureTracking(featureId: string): void {
|
|
252
483
|
this.noProgressByFeature.delete(featureId);
|
|
253
484
|
this.lastStatusByFeature.delete(featureId);
|
|
254
485
|
this.outputLoopDetector?.delete(featureId);
|
|
255
486
|
}
|
|
256
487
|
|
|
488
|
+
private instructionsForPlannerState(contextBundle: AnyRecord): string {
|
|
489
|
+
if (resolvePlannerPhaseFromContext(contextBundle) === 'intake') {
|
|
490
|
+
return [
|
|
491
|
+
'Review spec.md, the bootstrap manifest, verified manifest state, and intake review artifacts.',
|
|
492
|
+
'In intake mode, form or verify the requirements contract before execution planning begins.',
|
|
493
|
+
'Emit INTAKE_SUBMISSION when the verified manifest is ready.',
|
|
494
|
+
'Emit REQUEST action=ask_user_input only for blocking requirement clarification.',
|
|
495
|
+
'If you emit ask_user_input, stop there for the turn and wait for the persisted human answer before promoting intake.',
|
|
496
|
+
'Do not emit PLAN_SUBMISSION while the feature remains in intake.',
|
|
497
|
+
].join(' ');
|
|
498
|
+
}
|
|
499
|
+
return 'Review the feature artifacts on disk, update plan.md so it reflects the current planning state and step-by-step implementation plan, and emit PLAN_SUBMISSION/REQUEST/NOTE outputs to advance planning.';
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
private policyAllowsStubAutoPromotion(bootstrapManifest: AnyRecord): boolean {
|
|
503
|
+
if (Object.keys(bootstrapManifest).length === 0) {
|
|
504
|
+
return false;
|
|
505
|
+
}
|
|
506
|
+
const planning = asRecord(this.getPolicySnapshot?.().planning);
|
|
507
|
+
const intake = asRecord(planning.intake);
|
|
508
|
+
if (intake.allow_auto_promotion !== true) {
|
|
509
|
+
return false;
|
|
510
|
+
}
|
|
511
|
+
const ambiguities = Array.isArray(bootstrapManifest.ambiguities)
|
|
512
|
+
? bootstrapManifest.ambiguities
|
|
513
|
+
: [];
|
|
514
|
+
if (ambiguities.length > 0) {
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
const minimumConfidence =
|
|
518
|
+
normalizeManifestConfidence(intake.auto_promotion_min_confidence) ?? 'high';
|
|
519
|
+
const obligations = Array.isArray(bootstrapManifest.obligations)
|
|
520
|
+
? bootstrapManifest.obligations.map((item) => asRecord(item))
|
|
521
|
+
: [];
|
|
522
|
+
return obligationsMeetConfidenceThreshold(
|
|
523
|
+
obligations
|
|
524
|
+
.map((obligation) => normalizeManifestConfidence(obligation.confidence))
|
|
525
|
+
.filter((confidence): confidence is 'high' | 'medium' | 'low' => confidence !== null)
|
|
526
|
+
.map((confidence) => ({ confidence })),
|
|
527
|
+
minimumConfidence,
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
private async normalizeAcceptedPlanState(
|
|
532
|
+
featureId: string,
|
|
533
|
+
frontMatter: AnyRecord,
|
|
534
|
+
plan: AnyRecord,
|
|
535
|
+
planTraceContract: PlanTraceContractValidation | null = null,
|
|
536
|
+
): Promise<boolean> {
|
|
537
|
+
const planVersion = readPlanVersion(plan);
|
|
538
|
+
if (planVersion == null || hasInvalidPlanTraceContract(planTraceContract)) {
|
|
539
|
+
return false;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
const status = readStatus(frontMatter.status);
|
|
543
|
+
const gates = asRecord(frontMatter.gates);
|
|
544
|
+
const needsStatusHeal = status === STATUS.PLANNING;
|
|
545
|
+
const needsPlanGateHeal = gates.plan !== 'pass';
|
|
546
|
+
if (!needsStatusHeal && !needsPlanGateHeal) {
|
|
547
|
+
return false;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const expectedVersion = readStateVersion(frontMatter);
|
|
551
|
+
if (expectedVersion == null) {
|
|
552
|
+
return false;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
const nextFrontMatter: AnyRecord = {
|
|
556
|
+
gates: {
|
|
557
|
+
...gates,
|
|
558
|
+
plan: 'pass',
|
|
559
|
+
},
|
|
560
|
+
};
|
|
561
|
+
if (needsStatusHeal) {
|
|
562
|
+
nextFrontMatter.status = STATUS.BUILDING;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_STATE_PATCH, {
|
|
566
|
+
feature_id: featureId,
|
|
567
|
+
expected_version: expectedVersion,
|
|
568
|
+
patch: {
|
|
569
|
+
front_matter: nextFrontMatter,
|
|
570
|
+
},
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
this.lastStatusByFeature.set(featureId, needsStatusHeal ? STATUS.BUILDING : status);
|
|
574
|
+
return true;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Reconciles accepted plans against QA/gate findings after the QA wave completes.
|
|
579
|
+
* Evaluates gate freshness, plan-trace contract validity, and QA test summaries,
|
|
580
|
+
* then emits plan updates or invokes the planner worker for revisions when needed.
|
|
581
|
+
* @param featureIds Feature IDs in post-QA status to reconcile.
|
|
582
|
+
* @param iteration Current supervisor iteration number (used for decision logging).
|
|
583
|
+
*/
|
|
257
584
|
async runPostQaReconciliation(featureIds: string[], iteration: number): Promise<void> {
|
|
585
|
+
await this.plannerSessionSync?.syncPlannerSessions(featureIds);
|
|
258
586
|
for (const featureId of featureIds) {
|
|
259
587
|
const context = await this.toolCaller.callTool<FeatureContextPayload>(
|
|
260
588
|
'planner',
|
|
@@ -269,13 +597,17 @@ export class PlanningWaveExecutor {
|
|
|
269
597
|
if (!isPostQaStatus(status)) {
|
|
270
598
|
continue;
|
|
271
599
|
}
|
|
600
|
+
if (status === STATUS.BLOCKED && resolvePlannerPhaseFromContext(context.data) === 'intake') {
|
|
601
|
+
continue;
|
|
602
|
+
}
|
|
272
603
|
|
|
273
604
|
const existingPlan = asRecord(context.data.plan);
|
|
274
605
|
if (Object.keys(existingPlan).length === 0) {
|
|
275
606
|
await this.appendDecisionLog(featureId, {
|
|
276
607
|
phase: 'post_qa_reconciliation',
|
|
277
608
|
iteration,
|
|
278
|
-
|
|
609
|
+
plan_decision: 'unchanged',
|
|
610
|
+
execution_disposition: 'blocked_other',
|
|
279
611
|
reasons: ['missing_plan'],
|
|
280
612
|
status,
|
|
281
613
|
});
|
|
@@ -287,24 +619,118 @@ export class PlanningWaveExecutor {
|
|
|
287
619
|
await this.appendDecisionLog(featureId, {
|
|
288
620
|
phase: 'post_qa_reconciliation',
|
|
289
621
|
iteration,
|
|
290
|
-
|
|
622
|
+
plan_decision: 'unchanged',
|
|
623
|
+
execution_disposition: 'blocked_other',
|
|
291
624
|
reasons: ['existing_plan_version_invalid'],
|
|
292
625
|
status,
|
|
293
626
|
});
|
|
294
627
|
continue;
|
|
295
628
|
}
|
|
296
629
|
|
|
297
|
-
const decision = this.evaluateReconciliationDecision(
|
|
298
|
-
|
|
630
|
+
const decision = await this.evaluateReconciliationDecision(
|
|
631
|
+
context.data,
|
|
632
|
+
existingPlan,
|
|
633
|
+
status,
|
|
634
|
+
);
|
|
635
|
+
if (this.shouldInvokePlannerForPlanTraceContract(decision)) {
|
|
636
|
+
const plannerDecision = await this.workerDecisionRunner.execute({
|
|
637
|
+
role: 'planner',
|
|
638
|
+
featureId,
|
|
639
|
+
contextBundle: {
|
|
640
|
+
...asRecord(context.data),
|
|
641
|
+
plan_trace_contract: structuredClone(decision.planTraceContract),
|
|
642
|
+
},
|
|
643
|
+
instructions:
|
|
644
|
+
'The accepted plan_trace no longer matches the verified manifest contract. Review plan_trace_contract, revise the accepted plan so every verified manifest obligation is correctly traced, remove obsolete obligation mappings, and emit PLAN_SUBMISSION or REQUEST.action=amend_plan. Do not leave the stale plan_trace unchanged.',
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
await this.appendDecisionLog(featureId, {
|
|
648
|
+
phase: 'post_qa_reconciliation',
|
|
649
|
+
iteration,
|
|
650
|
+
plan_decision:
|
|
651
|
+
plannerDecision.planSubmission || plannerDecision.requestHandled
|
|
652
|
+
? 'update_required'
|
|
653
|
+
: 'unchanged',
|
|
654
|
+
execution_disposition:
|
|
655
|
+
plannerDecision.planSubmission || plannerDecision.requestHandled
|
|
656
|
+
? 'retry_build'
|
|
657
|
+
: decision.executionDisposition,
|
|
658
|
+
status,
|
|
659
|
+
reasons:
|
|
660
|
+
plannerDecision.planSubmission || plannerDecision.requestHandled
|
|
661
|
+
? normalizeList([
|
|
662
|
+
...decision.reasons,
|
|
663
|
+
'planner_verified_manifest_trace_revision_requested',
|
|
664
|
+
])
|
|
665
|
+
: decision.reasons,
|
|
666
|
+
qa_summary: decision.qaSummary,
|
|
667
|
+
latest_gate_overall: decision.latestGateOverall,
|
|
668
|
+
gate_evidence_freshness: decision.gateEvidenceFreshness,
|
|
669
|
+
checkpoint_validity: decision.checkpointValidity,
|
|
670
|
+
gate_failure_context: decision.gateFailureContext,
|
|
671
|
+
edge_case_checklist: decision.edgeCaseChecklist,
|
|
672
|
+
plan_trace_contract: decision.planTraceContract,
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
continue;
|
|
676
|
+
}
|
|
677
|
+
if (this.shouldInvokePlannerForGateFailure(decision)) {
|
|
678
|
+
const plannerDecision = await this.workerDecisionRunner.execute({
|
|
679
|
+
role: 'planner',
|
|
680
|
+
featureId,
|
|
681
|
+
contextBundle: {
|
|
682
|
+
...asRecord(context.data),
|
|
683
|
+
gate_failure_context: structuredClone(decision.gateFailureContext),
|
|
684
|
+
},
|
|
685
|
+
instructions:
|
|
686
|
+
'A required gate is currently failing with fresh evidence. Review gate_failure_context, revise the accepted plan as needed so the builder can legally investigate and fix the failure, and emit PLAN_SUBMISSION or REQUEST.action=amend_plan when a plan revision is required.',
|
|
687
|
+
});
|
|
688
|
+
|
|
299
689
|
await this.appendDecisionLog(featureId, {
|
|
300
690
|
phase: 'post_qa_reconciliation',
|
|
301
691
|
iteration,
|
|
302
|
-
|
|
692
|
+
plan_decision:
|
|
693
|
+
plannerDecision.planSubmission || plannerDecision.requestHandled
|
|
694
|
+
? 'update_required'
|
|
695
|
+
: 'unchanged',
|
|
696
|
+
execution_disposition:
|
|
697
|
+
plannerDecision.planSubmission || plannerDecision.requestHandled
|
|
698
|
+
? 'retry_build'
|
|
699
|
+
: decision.executionDisposition,
|
|
700
|
+
status,
|
|
701
|
+
reasons:
|
|
702
|
+
plannerDecision.planSubmission || plannerDecision.requestHandled
|
|
703
|
+
? normalizeList([...decision.reasons, 'planner_gate_failure_revision_requested'])
|
|
704
|
+
: decision.reasons,
|
|
705
|
+
qa_summary: decision.qaSummary,
|
|
706
|
+
latest_gate_overall: decision.latestGateOverall,
|
|
707
|
+
gate_evidence_freshness: decision.gateEvidenceFreshness,
|
|
708
|
+
checkpoint_validity: decision.checkpointValidity,
|
|
709
|
+
gate_failure_context: decision.gateFailureContext,
|
|
710
|
+
edge_case_checklist: decision.edgeCaseChecklist,
|
|
711
|
+
plan_trace_contract: decision.planTraceContract,
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
if (plannerDecision.planSubmission || plannerDecision.requestHandled) {
|
|
715
|
+
continue;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
if (decision.planDecision === 'unchanged') {
|
|
720
|
+
await this.appendDecisionLog(featureId, {
|
|
721
|
+
phase: 'post_qa_reconciliation',
|
|
722
|
+
iteration,
|
|
723
|
+
plan_decision: decision.planDecision,
|
|
724
|
+
execution_disposition: decision.executionDisposition,
|
|
303
725
|
status,
|
|
304
726
|
reasons: decision.reasons,
|
|
305
727
|
qa_summary: decision.qaSummary,
|
|
306
728
|
latest_gate_overall: decision.latestGateOverall,
|
|
729
|
+
gate_evidence_freshness: decision.gateEvidenceFreshness,
|
|
730
|
+
checkpoint_validity: decision.checkpointValidity,
|
|
731
|
+
gate_failure_context: decision.gateFailureContext,
|
|
307
732
|
edge_case_checklist: decision.edgeCaseChecklist,
|
|
733
|
+
plan_trace_contract: decision.planTraceContract,
|
|
308
734
|
});
|
|
309
735
|
continue;
|
|
310
736
|
}
|
|
@@ -319,7 +745,8 @@ export class PlanningWaveExecutor {
|
|
|
319
745
|
await this.appendDecisionLog(featureId, {
|
|
320
746
|
phase: 'post_qa_reconciliation',
|
|
321
747
|
iteration,
|
|
322
|
-
|
|
748
|
+
plan_decision: decision.planDecision,
|
|
749
|
+
execution_disposition: decision.executionDisposition,
|
|
323
750
|
status,
|
|
324
751
|
expected_plan_version: planVersion,
|
|
325
752
|
next_plan_version: nextPlan.plan_version,
|
|
@@ -327,20 +754,29 @@ export class PlanningWaveExecutor {
|
|
|
327
754
|
reasons: decision.reasons,
|
|
328
755
|
qa_summary: decision.qaSummary,
|
|
329
756
|
latest_gate_overall: decision.latestGateOverall,
|
|
757
|
+
gate_evidence_freshness: decision.gateEvidenceFreshness,
|
|
758
|
+
checkpoint_validity: decision.checkpointValidity,
|
|
759
|
+
gate_failure_context: decision.gateFailureContext,
|
|
330
760
|
edge_case_checklist: decision.edgeCaseChecklist,
|
|
761
|
+
plan_trace_contract: decision.planTraceContract,
|
|
331
762
|
});
|
|
332
763
|
}
|
|
333
764
|
}
|
|
334
765
|
|
|
335
|
-
private evaluateReconciliationDecision(
|
|
766
|
+
private async evaluateReconciliationDecision(
|
|
336
767
|
context: FeatureContextPayload,
|
|
337
768
|
plan: AnyRecord,
|
|
338
769
|
status: string,
|
|
339
|
-
): ReconciliationDecision {
|
|
770
|
+
): Promise<ReconciliationDecision> {
|
|
340
771
|
const acceptanceCriteria = asStringArray(plan.acceptance_criteria);
|
|
341
772
|
const riskItems = asStringArray(plan.risk);
|
|
773
|
+
const verifiedObligations = readVerifiedManifestObligations(context);
|
|
774
|
+
const planTraceContract = readPlanTraceContractValidation(context, plan);
|
|
342
775
|
const specText = typeof context.spec === 'string' ? context.spec : '';
|
|
343
|
-
const edgeCaseChecklist =
|
|
776
|
+
const edgeCaseChecklist =
|
|
777
|
+
verifiedObligations.length > 0
|
|
778
|
+
? deriveEdgeCaseChecklistFromVerifiedManifest(verifiedObligations)
|
|
779
|
+
: deriveEdgeCaseChecklist(specText);
|
|
344
780
|
const qaSummary = asRecord(asRecord(context.qa_test_index).summary);
|
|
345
781
|
const pending = readCount(qaSummary, 'pending');
|
|
346
782
|
const failed = readCount(qaSummary, 'failed');
|
|
@@ -349,32 +785,146 @@ export class PlanningWaveExecutor {
|
|
|
349
785
|
typeof asRecord(context.latest_evidence).overall === 'string'
|
|
350
786
|
? String(asRecord(context.latest_evidence).overall)
|
|
351
787
|
: null;
|
|
788
|
+
const frontMatter = asRecord(asRecord(context.state).front_matter);
|
|
789
|
+
const statusReason =
|
|
790
|
+
typeof frontMatter.status_reason === 'string' ? frontMatter.status_reason : '';
|
|
791
|
+
const lastGateMode =
|
|
792
|
+
typeof asRecord(frontMatter.evidence).last_gate_mode === 'string'
|
|
793
|
+
? String(asRecord(frontMatter.evidence).last_gate_mode)
|
|
794
|
+
: null;
|
|
795
|
+
const fastFreshness = assessGateFreshness({
|
|
796
|
+
frontMatter,
|
|
797
|
+
mode: 'fast',
|
|
798
|
+
gateEvidenceByMode: readGateEvidenceByMode(context),
|
|
799
|
+
latestEvidence: context.latest_evidence,
|
|
800
|
+
});
|
|
801
|
+
const fullFreshness = assessGateFreshness({
|
|
802
|
+
frontMatter,
|
|
803
|
+
mode: 'full',
|
|
804
|
+
gateEvidenceByMode: readGateEvidenceByMode(context),
|
|
805
|
+
latestEvidence: context.latest_evidence,
|
|
806
|
+
});
|
|
807
|
+
const checkpointValidity = readCheckpointValidity(frontMatter);
|
|
808
|
+
const gateEvidenceFreshness =
|
|
809
|
+
lastGateMode === 'full'
|
|
810
|
+
? fullFreshness.freshness
|
|
811
|
+
: status === STATUS.BLOCKED || status === STATUS.BUILDING
|
|
812
|
+
? fastFreshness.freshness
|
|
813
|
+
: fullFreshness.freshness;
|
|
814
|
+
let executionDisposition: ReconciliationDecision['executionDisposition'] =
|
|
815
|
+
status === STATUS.READY_TO_MERGE ? 'converged' : 'retry_qa';
|
|
816
|
+
const gateFailureContext = await this.extractGateFailureContext(context);
|
|
352
817
|
|
|
353
|
-
const
|
|
818
|
+
const planReasons: string[] = [];
|
|
819
|
+
const executionReasons: string[] = [];
|
|
354
820
|
const acceptanceCriteriaAdditions: string[] = [];
|
|
355
821
|
|
|
356
822
|
const missingEdgeCases = edgeCaseChecklist.filter((item) => !riskItems.includes(item));
|
|
357
823
|
if (missingEdgeCases.length > 0) {
|
|
358
|
-
|
|
824
|
+
planReasons.push(`edge_case_checklist_missing:${missingEdgeCases.length}`);
|
|
359
825
|
acceptanceCriteriaAdditions.push(
|
|
360
826
|
'Planner edge-case checklist has been reviewed and incorporated into the execution plan.',
|
|
361
827
|
);
|
|
362
828
|
}
|
|
363
829
|
|
|
830
|
+
const planTraceRequiresRevision = hasInvalidPlanTraceContract(planTraceContract);
|
|
831
|
+
if (planTraceContract?.missing_obligation_ids.length) {
|
|
832
|
+
planReasons.push(
|
|
833
|
+
`verified_manifest_trace_missing:${planTraceContract.missing_obligation_ids.length}`,
|
|
834
|
+
);
|
|
835
|
+
}
|
|
836
|
+
if (planTraceContract?.unknown_obligation_ids.length) {
|
|
837
|
+
planReasons.push(
|
|
838
|
+
`verified_manifest_trace_unknown:${planTraceContract.unknown_obligation_ids.length}`,
|
|
839
|
+
);
|
|
840
|
+
}
|
|
841
|
+
if (planTraceContract?.duplicate_obligation_ids.length) {
|
|
842
|
+
planReasons.push(
|
|
843
|
+
`verified_manifest_trace_duplicate:${planTraceContract.duplicate_obligation_ids.length}`,
|
|
844
|
+
);
|
|
845
|
+
}
|
|
846
|
+
if (planTraceContract?.invalid_mappings.length) {
|
|
847
|
+
planReasons.push(
|
|
848
|
+
`verified_manifest_trace_invalid_mapping:${planTraceContract.invalid_mappings.length}`,
|
|
849
|
+
);
|
|
850
|
+
}
|
|
851
|
+
if (planTraceRequiresRevision) {
|
|
852
|
+
acceptanceCriteriaAdditions.push(
|
|
853
|
+
'plan_trace maps every verified manifest obligation_id into planned implementation and verification work.',
|
|
854
|
+
);
|
|
855
|
+
}
|
|
856
|
+
|
|
364
857
|
const hasQaSignals =
|
|
365
858
|
status === STATUS.BLOCKED || failed > 0 || pending > 0 || latestGateOverall === 'fail';
|
|
366
859
|
const qaCheckpoint = `Planner reconciliation checkpoint [status=${status};failed=${failed};pending=${pending};latest=${latestGateOverall ?? 'unknown'}]`;
|
|
367
860
|
if (hasQaSignals && !acceptanceCriteria.includes(qaCheckpoint)) {
|
|
368
|
-
|
|
861
|
+
planReasons.push(`qa_signals_detected:${status}:failed=${failed}:pending=${pending}`);
|
|
369
862
|
acceptanceCriteriaAdditions.push(
|
|
370
863
|
'Reconcile QA/gate findings against plan scope and apply corrective updates before merge.',
|
|
371
864
|
);
|
|
372
865
|
acceptanceCriteriaAdditions.push(qaCheckpoint);
|
|
373
866
|
}
|
|
374
867
|
|
|
868
|
+
if (status === STATUS.BLOCKED) {
|
|
869
|
+
if (statusReason.includes(ERROR_CODES.PROVIDER_OUTPUT_INVALID)) {
|
|
870
|
+
executionReasons.push('provider_output_invalid');
|
|
871
|
+
executionDisposition = 'blocked_provider_failure';
|
|
872
|
+
} else if (
|
|
873
|
+
lastGateMode === 'full' &&
|
|
874
|
+
latestGateOverall === 'fail' &&
|
|
875
|
+
fullFreshness.freshness === 'current'
|
|
876
|
+
) {
|
|
877
|
+
executionDisposition = 'blocked_other';
|
|
878
|
+
} else if (
|
|
879
|
+
lastGateMode === 'fast' &&
|
|
880
|
+
latestGateOverall === 'fail' &&
|
|
881
|
+
fastFreshness.freshness === 'current'
|
|
882
|
+
) {
|
|
883
|
+
executionDisposition = 'blocked_other';
|
|
884
|
+
} else if (lastGateMode === 'full' && fullFreshness.shouldRerunGate) {
|
|
885
|
+
executionReasons.push(...fullFreshness.reasons);
|
|
886
|
+
executionDisposition =
|
|
887
|
+
latestGateOverall === 'pass' ? 'rerun_full_gate' : 'blocked_stale_evidence';
|
|
888
|
+
} else if (fastFreshness.shouldRerunGate) {
|
|
889
|
+
executionReasons.push(...fastFreshness.reasons);
|
|
890
|
+
executionDisposition = latestGateOverall === 'pass' ? 'retry_qa' : 'blocked_stale_evidence';
|
|
891
|
+
} else if (fullFreshness.shouldRerunGate) {
|
|
892
|
+
executionReasons.push(...fullFreshness.reasons);
|
|
893
|
+
executionDisposition =
|
|
894
|
+
latestGateOverall === 'pass' ? 'rerun_full_gate' : 'blocked_stale_evidence';
|
|
895
|
+
} else if (latestGateOverall === 'fail') {
|
|
896
|
+
executionDisposition = 'blocked_other';
|
|
897
|
+
}
|
|
898
|
+
} else if (status === STATUS.QA) {
|
|
899
|
+
if (fullFreshness.shouldRerunGate) {
|
|
900
|
+
executionReasons.push(...fullFreshness.reasons);
|
|
901
|
+
executionDisposition = 'rerun_full_gate';
|
|
902
|
+
} else if (failed > 0 || pending > 0 || running > 0) {
|
|
903
|
+
executionDisposition = 'retry_qa';
|
|
904
|
+
} else if (latestGateOverall === 'pass' && fullFreshness.freshness === 'current') {
|
|
905
|
+
executionDisposition = 'converged';
|
|
906
|
+
}
|
|
907
|
+
} else if (status === STATUS.READY_TO_MERGE) {
|
|
908
|
+
if (fullFreshness.shouldRerunGate) {
|
|
909
|
+
executionReasons.push(...fullFreshness.reasons);
|
|
910
|
+
executionDisposition = 'rerun_full_gate';
|
|
911
|
+
} else if (latestGateOverall !== 'pass' || fullFreshness.freshness !== 'current') {
|
|
912
|
+
executionReasons.push(...fullFreshness.reasons);
|
|
913
|
+
executionDisposition = 'blocked_stale_evidence';
|
|
914
|
+
} else {
|
|
915
|
+
executionDisposition = 'converged';
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
if (planTraceRequiresRevision && executionDisposition === 'converged') {
|
|
920
|
+
executionDisposition = 'retry_build';
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
const reasons = normalizeList([...planReasons, ...executionReasons]);
|
|
375
924
|
if (reasons.length === 0) {
|
|
376
925
|
return {
|
|
377
|
-
|
|
926
|
+
planDecision: 'unchanged',
|
|
927
|
+
executionDisposition,
|
|
378
928
|
reasons: ['reconciled_no_gaps'],
|
|
379
929
|
acceptanceCriteriaAdditions: [],
|
|
380
930
|
edgeCaseChecklist,
|
|
@@ -384,11 +934,16 @@ export class PlanningWaveExecutor {
|
|
|
384
934
|
running,
|
|
385
935
|
},
|
|
386
936
|
latestGateOverall,
|
|
937
|
+
gateEvidenceFreshness,
|
|
938
|
+
checkpointValidity,
|
|
939
|
+
gateFailureContext,
|
|
940
|
+
planTraceContract,
|
|
387
941
|
};
|
|
388
942
|
}
|
|
389
943
|
|
|
390
944
|
return {
|
|
391
|
-
|
|
945
|
+
planDecision: acceptanceCriteriaAdditions.length > 0 ? 'update_required' : 'unchanged',
|
|
946
|
+
executionDisposition,
|
|
392
947
|
reasons,
|
|
393
948
|
acceptanceCriteriaAdditions: normalizeList(acceptanceCriteriaAdditions),
|
|
394
949
|
edgeCaseChecklist,
|
|
@@ -398,6 +953,10 @@ export class PlanningWaveExecutor {
|
|
|
398
953
|
running,
|
|
399
954
|
},
|
|
400
955
|
latestGateOverall,
|
|
956
|
+
gateEvidenceFreshness,
|
|
957
|
+
checkpointValidity,
|
|
958
|
+
gateFailureContext,
|
|
959
|
+
planTraceContract,
|
|
401
960
|
};
|
|
402
961
|
}
|
|
403
962
|
|
|
@@ -421,6 +980,88 @@ export class PlanningWaveExecutor {
|
|
|
421
980
|
return nextPlan;
|
|
422
981
|
}
|
|
423
982
|
|
|
983
|
+
private shouldInvokePlannerForGateFailure(decision: ReconciliationDecision): boolean {
|
|
984
|
+
return (
|
|
985
|
+
decision.gateFailureContext !== null &&
|
|
986
|
+
decision.latestGateOverall === 'fail' &&
|
|
987
|
+
decision.gateEvidenceFreshness === 'current' &&
|
|
988
|
+
decision.checkpointValidity !== 'invalid' &&
|
|
989
|
+
(decision.executionDisposition === 'blocked_other' ||
|
|
990
|
+
decision.executionDisposition === 'retry_qa')
|
|
991
|
+
);
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
private shouldInvokePlannerForPlanTraceContract(decision: ReconciliationDecision): boolean {
|
|
995
|
+
return hasInvalidPlanTraceContract(decision.planTraceContract);
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
private async extractGateFailureContext(
|
|
999
|
+
context: FeatureContextPayload,
|
|
1000
|
+
): Promise<Record<string, unknown> | null> {
|
|
1001
|
+
const latestEvidence = asRecord(context.latest_evidence);
|
|
1002
|
+
const stepResultsRaw = Array.isArray(latestEvidence.step_results)
|
|
1003
|
+
? latestEvidence.step_results
|
|
1004
|
+
: [];
|
|
1005
|
+
const stepResults = (stepResultsRaw as unknown[])
|
|
1006
|
+
.map((item) => asRecord(item))
|
|
1007
|
+
.filter((item): item is AnyRecord => Object.keys(item).length > 0);
|
|
1008
|
+
|
|
1009
|
+
const failingStep =
|
|
1010
|
+
stepResults.find((item) => (asNumber(item.exit_code) ?? 0) !== 0 || item.timeout === true) ??
|
|
1011
|
+
(typeof latestEvidence.overall === 'string' && latestEvidence.overall === 'fail'
|
|
1012
|
+
? (stepResults[0] ?? null)
|
|
1013
|
+
: null);
|
|
1014
|
+
|
|
1015
|
+
if (!failingStep) {
|
|
1016
|
+
return null;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
const stepName = asString(failingStep.name) ?? 'unknown';
|
|
1020
|
+
const stepCmd = Array.isArray(failingStep.cmd)
|
|
1021
|
+
? (failingStep.cmd as unknown[]).map((value) => String(value))
|
|
1022
|
+
: [];
|
|
1023
|
+
const exitCode = asNumber(failingStep.exit_code) ?? 1;
|
|
1024
|
+
const rawLogPath = asString(failingStep.log_path);
|
|
1025
|
+
const notes = Array.isArray(latestEvidence.notes)
|
|
1026
|
+
? latestEvidence.notes.filter((item): item is string => typeof item === 'string')
|
|
1027
|
+
: [];
|
|
1028
|
+
|
|
1029
|
+
let failureAnalysis: GateLogExtraction | null = null;
|
|
1030
|
+
if (rawLogPath) {
|
|
1031
|
+
const logPath = path.isAbsolute(rawLogPath)
|
|
1032
|
+
? rawLogPath
|
|
1033
|
+
: this.repoRoot
|
|
1034
|
+
? path.join(this.repoRoot, rawLogPath)
|
|
1035
|
+
: rawLogPath;
|
|
1036
|
+
try {
|
|
1037
|
+
const logContent = await fs.readFile(logPath, 'utf8');
|
|
1038
|
+
failureAnalysis = extractGateLog({
|
|
1039
|
+
stepName,
|
|
1040
|
+
cmd: stepCmd,
|
|
1041
|
+
exitCode,
|
|
1042
|
+
logContent,
|
|
1043
|
+
});
|
|
1044
|
+
} catch {
|
|
1045
|
+
failureAnalysis = null;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
return {
|
|
1050
|
+
gate_name: asString(latestEvidence.mode) ?? 'unknown',
|
|
1051
|
+
step_name: stepName,
|
|
1052
|
+
cmd: stepCmd,
|
|
1053
|
+
exit_code: exitCode,
|
|
1054
|
+
timeout: failingStep.timeout === true,
|
|
1055
|
+
affected_files: failureAnalysis?.affectedFiles ?? [],
|
|
1056
|
+
error_lines: failureAnalysis?.errorLines ?? [],
|
|
1057
|
+
summary_lines: failureAnalysis?.summaryLines ?? [],
|
|
1058
|
+
error_count: failureAnalysis?.errorCount ?? null,
|
|
1059
|
+
log_tail: failureAnalysis?.logTail ?? '',
|
|
1060
|
+
notes,
|
|
1061
|
+
evidence_overall: asString(latestEvidence.overall) ?? null,
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
|
|
424
1065
|
private async appendDecisionLog(featureId: string, note: AnyRecord): Promise<void> {
|
|
425
1066
|
await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_LOG_APPEND, {
|
|
426
1067
|
feature_id: featureId,
|
|
@@ -568,6 +1209,10 @@ export class PlanningWaveExecutor {
|
|
|
568
1209
|
decision: {
|
|
569
1210
|
invalidOutput: boolean;
|
|
570
1211
|
noProgress: boolean;
|
|
1212
|
+
contextStall?: boolean;
|
|
1213
|
+
contextRequestCount?: number;
|
|
1214
|
+
lastContextRequestAt?: string | null;
|
|
1215
|
+
lastContextRequestRole?: string | null;
|
|
571
1216
|
},
|
|
572
1217
|
): Promise<boolean> {
|
|
573
1218
|
if (this.providerMode !== 'live') {
|
|
@@ -575,7 +1220,24 @@ export class PlanningWaveExecutor {
|
|
|
575
1220
|
return false;
|
|
576
1221
|
}
|
|
577
1222
|
|
|
1223
|
+
const context = await this.toolCaller.callTool<FeatureContextPayload>(
|
|
1224
|
+
'planner',
|
|
1225
|
+
TOOLS.FEATURE_GET_CONTEXT,
|
|
1226
|
+
{
|
|
1227
|
+
feature_id: featureId,
|
|
1228
|
+
},
|
|
1229
|
+
);
|
|
1230
|
+
|
|
578
1231
|
if (decision.invalidOutput) {
|
|
1232
|
+
if (
|
|
1233
|
+
await this.requestIntakeClarificationFallback(
|
|
1234
|
+
featureId,
|
|
1235
|
+
asRecord(context.data),
|
|
1236
|
+
ERROR_CODES.PROVIDER_OUTPUT_INVALID,
|
|
1237
|
+
)
|
|
1238
|
+
) {
|
|
1239
|
+
return true;
|
|
1240
|
+
}
|
|
579
1241
|
await this.applyWorkerPolicyAction(
|
|
580
1242
|
featureId,
|
|
581
1243
|
this.malformedOutputAction,
|
|
@@ -585,6 +1247,75 @@ export class PlanningWaveExecutor {
|
|
|
585
1247
|
return true;
|
|
586
1248
|
}
|
|
587
1249
|
|
|
1250
|
+
if (decision.contextStall) {
|
|
1251
|
+
if (
|
|
1252
|
+
await this.requestIntakeClarificationFallback(
|
|
1253
|
+
featureId,
|
|
1254
|
+
asRecord(context.data),
|
|
1255
|
+
ERROR_CODES.PROVIDER_CONTEXT_STALL,
|
|
1256
|
+
)
|
|
1257
|
+
) {
|
|
1258
|
+
return true;
|
|
1259
|
+
}
|
|
1260
|
+
const state = await this.toolCaller.callTool<FeatureStatePayload>(
|
|
1261
|
+
'orchestrator',
|
|
1262
|
+
TOOLS.FEATURE_STATE_GET,
|
|
1263
|
+
{ feature_id: featureId },
|
|
1264
|
+
);
|
|
1265
|
+
const frontMatter = asRecord(state.data.front_matter);
|
|
1266
|
+
const expectedVersion =
|
|
1267
|
+
typeof frontMatter.version === 'number' && Number.isFinite(frontMatter.version)
|
|
1268
|
+
? Math.floor(frontMatter.version)
|
|
1269
|
+
: null;
|
|
1270
|
+
const recovery = this.buildPlannerRecoveryFrontMatter(
|
|
1271
|
+
frontMatter,
|
|
1272
|
+
ERROR_CODES.PROVIDER_CONTEXT_STALL,
|
|
1273
|
+
'planning',
|
|
1274
|
+
);
|
|
1275
|
+
await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_STATE_PATCH, {
|
|
1276
|
+
feature_id: featureId,
|
|
1277
|
+
expected_version: expectedVersion,
|
|
1278
|
+
patch: {
|
|
1279
|
+
front_matter: {
|
|
1280
|
+
status: STATUS.BLOCKED,
|
|
1281
|
+
status_reason: `${ERROR_CODES.PROVIDER_CONTEXT_STALL}: repeated context refresh with no progress`,
|
|
1282
|
+
recovery,
|
|
1283
|
+
context_request_count: decision.contextRequestCount ?? 0,
|
|
1284
|
+
last_context_request_at: decision.lastContextRequestAt ?? null,
|
|
1285
|
+
last_context_request_role: decision.lastContextRequestRole ?? 'planner',
|
|
1286
|
+
},
|
|
1287
|
+
},
|
|
1288
|
+
});
|
|
1289
|
+
this.lastStatusByFeature.set(featureId, STATUS.BLOCKED);
|
|
1290
|
+
await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_LOG_APPEND, {
|
|
1291
|
+
feature_id: featureId,
|
|
1292
|
+
note: JSON.stringify({
|
|
1293
|
+
phase: 'planning',
|
|
1294
|
+
decision: 'blocked',
|
|
1295
|
+
error_code: ERROR_CODES.PROVIDER_CONTEXT_STALL,
|
|
1296
|
+
reason: 'repeated context refresh with no progress',
|
|
1297
|
+
recovery_state: recovery.state,
|
|
1298
|
+
recovery_attempt: recovery.attempt,
|
|
1299
|
+
context_request_count: decision.contextRequestCount ?? 0,
|
|
1300
|
+
last_context_request_at: decision.lastContextRequestAt ?? null,
|
|
1301
|
+
last_context_request_role: decision.lastContextRequestRole ?? 'planner',
|
|
1302
|
+
}),
|
|
1303
|
+
});
|
|
1304
|
+
return true;
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
if (
|
|
1308
|
+
decision.noProgress &&
|
|
1309
|
+
(await this.requestIntakeClarificationFallback(
|
|
1310
|
+
featureId,
|
|
1311
|
+
asRecord(context.data),
|
|
1312
|
+
ERROR_CODES.PROVIDER_NO_PROGRESS,
|
|
1313
|
+
))
|
|
1314
|
+
) {
|
|
1315
|
+
this.noProgressByFeature.delete(featureId);
|
|
1316
|
+
return true;
|
|
1317
|
+
}
|
|
1318
|
+
|
|
588
1319
|
if (!decision.noProgress) {
|
|
589
1320
|
this.noProgressByFeature.delete(featureId);
|
|
590
1321
|
return false;
|
|
@@ -605,6 +1336,200 @@ export class PlanningWaveExecutor {
|
|
|
605
1336
|
return true;
|
|
606
1337
|
}
|
|
607
1338
|
|
|
1339
|
+
private readOpenIntakeAmbiguities(context: AnyRecord): IntakeRecoveryAmbiguity[] {
|
|
1340
|
+
const review = asRecord(asRecord(context.intake).review);
|
|
1341
|
+
const ambiguities = Array.isArray(review.ambiguities) ? review.ambiguities : [];
|
|
1342
|
+
return ambiguities
|
|
1343
|
+
.map((item) => asRecord(item))
|
|
1344
|
+
.filter((item) => asString(item.status) === 'open')
|
|
1345
|
+
.map((item) => ({
|
|
1346
|
+
id: asString(item.id) ?? 'AMB-UNKNOWN',
|
|
1347
|
+
summary: asString(item.summary) ?? 'Clarify the remaining intake ambiguity.',
|
|
1348
|
+
obligationIds: asStringArray(item.obligation_ids),
|
|
1349
|
+
}));
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
private async readAnsweredIntakeAmbiguityIds(featureId: string): Promise<Set<string>> {
|
|
1353
|
+
const response = await this.toolCaller.callTool<{ items?: unknown[] }>(
|
|
1354
|
+
'orchestrator',
|
|
1355
|
+
TOOLS.FEATURE_QUESTION_LIST,
|
|
1356
|
+
{
|
|
1357
|
+
feature_id: featureId,
|
|
1358
|
+
status: 'all',
|
|
1359
|
+
},
|
|
1360
|
+
);
|
|
1361
|
+
const items = Array.isArray(response.data.items) ? response.data.items : [];
|
|
1362
|
+
const ambiguityIds = items
|
|
1363
|
+
.map((item) => asRecord(item))
|
|
1364
|
+
.filter(
|
|
1365
|
+
(item) =>
|
|
1366
|
+
asString(item.status) === 'answered' &&
|
|
1367
|
+
(asString(item.resume_status) === STATUS.INTAKE ||
|
|
1368
|
+
asString(item.resume_phase) === STATUS.INTAKE ||
|
|
1369
|
+
asString(item.phase) === STATUS.INTAKE),
|
|
1370
|
+
)
|
|
1371
|
+
.flatMap((item) => {
|
|
1372
|
+
const details = asRecord(item.details);
|
|
1373
|
+
const direct = asString(details.ambiguity_id);
|
|
1374
|
+
const grouped = asStringArray(details.ambiguity_ids);
|
|
1375
|
+
return direct ? [direct, ...grouped] : grouped;
|
|
1376
|
+
});
|
|
1377
|
+
return new Set(normalizeList(ambiguityIds));
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
private readAnsweredIntakeClarifications(context: AnyRecord): IntakeRecoveryAnswer[] {
|
|
1381
|
+
const review = asRecord(asRecord(context.intake).review);
|
|
1382
|
+
const answers = Array.isArray(review.clarification_answers) ? review.clarification_answers : [];
|
|
1383
|
+
return answers
|
|
1384
|
+
.map((item) => asRecord(item))
|
|
1385
|
+
.filter((item) => asStringArray(item.ambiguity_ids).length > 0)
|
|
1386
|
+
.map((item) => ({
|
|
1387
|
+
questionId: asString(item.question_id) ?? 'unknown',
|
|
1388
|
+
ambiguityIds: asStringArray(item.ambiguity_ids),
|
|
1389
|
+
answer:
|
|
1390
|
+
typeof item.answer === 'string'
|
|
1391
|
+
? item.answer
|
|
1392
|
+
: JSON.stringify(asRecord(item.answer) ?? {}, null, 2),
|
|
1393
|
+
answeredAt: asString(item.answered_at),
|
|
1394
|
+
}));
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
private buildIntakeClarificationPrompt(
|
|
1398
|
+
ambiguities: IntakeRecoveryAmbiguity[],
|
|
1399
|
+
followUpAmbiguityIds: Set<string>,
|
|
1400
|
+
priorAnswers: IntakeRecoveryAnswer[],
|
|
1401
|
+
): string {
|
|
1402
|
+
const needsFollowUp = ambiguities.some((ambiguity) => followUpAmbiguityIds.has(ambiguity.id));
|
|
1403
|
+
const intro =
|
|
1404
|
+
needsFollowUp && ambiguities.length === 1
|
|
1405
|
+
? 'Planning still cannot continue because this intake ambiguity remains unresolved after the previous answer:'
|
|
1406
|
+
: needsFollowUp
|
|
1407
|
+
? 'Planning still cannot continue because these intake ambiguities remain unresolved after the previous answer:'
|
|
1408
|
+
: ambiguities.length === 1
|
|
1409
|
+
? 'Planning cannot continue until this remaining intake ambiguity is clarified:'
|
|
1410
|
+
: 'Planning cannot continue until these remaining intake ambiguities are clarified:';
|
|
1411
|
+
const items = ambiguities.map((ambiguity) => `- ${ambiguity.id}: ${ambiguity.summary}`);
|
|
1412
|
+
const priorAnswerLines = ambiguities.flatMap((ambiguity) =>
|
|
1413
|
+
priorAnswers
|
|
1414
|
+
.filter((answer) => answer.ambiguityIds.includes(ambiguity.id))
|
|
1415
|
+
.map(
|
|
1416
|
+
(answer) =>
|
|
1417
|
+
`- ${ambiguity.id} via ${answer.questionId}${
|
|
1418
|
+
answer.answeredAt ? ` at ${answer.answeredAt}` : ''
|
|
1419
|
+
}: ${answer.answer}`,
|
|
1420
|
+
),
|
|
1421
|
+
);
|
|
1422
|
+
const priorAnswersBlock =
|
|
1423
|
+
priorAnswerLines.length > 0
|
|
1424
|
+
? `\nPrior answered clarification evidence:\n${priorAnswerLines.join('\n')}\nUse this prior answer evidence. Only ask a narrower follow-up if it is still insufficient to resolve the ambiguity.`
|
|
1425
|
+
: '';
|
|
1426
|
+
return `${intro}\n${items.join('\n')}${priorAnswersBlock}\nRespond in free text and explicitly address each ambiguity ID.`;
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
private async requestIntakeClarificationFallback(
|
|
1430
|
+
featureId: string,
|
|
1431
|
+
context: AnyRecord,
|
|
1432
|
+
recoveryReason: string,
|
|
1433
|
+
): Promise<boolean> {
|
|
1434
|
+
if (resolvePlannerPhaseFromContext(context) !== 'intake') {
|
|
1435
|
+
return false;
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
const intake = asRecord(context.intake);
|
|
1439
|
+
const verifiedManifest = asRecord(intake.verified_manifest);
|
|
1440
|
+
if (Object.keys(verifiedManifest).length > 0) {
|
|
1441
|
+
return false;
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
const humanInput = asRecord(context.human_input);
|
|
1445
|
+
const openQuestions = Array.isArray(humanInput.open_questions) ? humanInput.open_questions : [];
|
|
1446
|
+
if (openQuestions.length > 0) {
|
|
1447
|
+
return false;
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
const ambiguities = this.readOpenIntakeAmbiguities(context);
|
|
1451
|
+
const answeredAmbiguityIds = await this.readAnsweredIntakeAmbiguityIds(featureId);
|
|
1452
|
+
const priorAnswers = this.readAnsweredIntakeClarifications(context);
|
|
1453
|
+
if (ambiguities.length === 0) {
|
|
1454
|
+
return false;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
const frontMatter = asRecord(asRecord(context.state).front_matter);
|
|
1458
|
+
const cluster = asRecord(frontMatter.cluster);
|
|
1459
|
+
const question = await this.toolCaller.callTool<{ question_id?: string }>(
|
|
1460
|
+
'orchestrator',
|
|
1461
|
+
TOOLS.FEATURE_QUESTION_CREATE,
|
|
1462
|
+
{
|
|
1463
|
+
feature_id: featureId,
|
|
1464
|
+
role: 'planner',
|
|
1465
|
+
session_id: asString(cluster.planner_session_id) ?? `planner:intake-recovery:${featureId}`,
|
|
1466
|
+
question_type: 'clarification',
|
|
1467
|
+
prompt: this.buildIntakeClarificationPrompt(
|
|
1468
|
+
ambiguities,
|
|
1469
|
+
answeredAmbiguityIds,
|
|
1470
|
+
priorAnswers,
|
|
1471
|
+
),
|
|
1472
|
+
details: {
|
|
1473
|
+
ambiguity_ids: ambiguities.map((ambiguity) => ambiguity.id),
|
|
1474
|
+
obligation_ids: normalizeList(
|
|
1475
|
+
ambiguities.flatMap((ambiguity) => ambiguity.obligationIds),
|
|
1476
|
+
),
|
|
1477
|
+
prior_answered_ambiguity_ids: ambiguities
|
|
1478
|
+
.filter((ambiguity) => answeredAmbiguityIds.has(ambiguity.id))
|
|
1479
|
+
.map((ambiguity) => ambiguity.id),
|
|
1480
|
+
recovery_reason: recoveryReason,
|
|
1481
|
+
recovery_source: 'planning_wave_executor',
|
|
1482
|
+
},
|
|
1483
|
+
expected_answer: {
|
|
1484
|
+
kind: 'free_text',
|
|
1485
|
+
},
|
|
1486
|
+
blocking: true,
|
|
1487
|
+
phase: STATUS.INTAKE,
|
|
1488
|
+
request_action: 'ask_user_input',
|
|
1489
|
+
resume_status: STATUS.INTAKE,
|
|
1490
|
+
resume_phase: STATUS.INTAKE,
|
|
1491
|
+
},
|
|
1492
|
+
);
|
|
1493
|
+
|
|
1494
|
+
this.noProgressByFeature.delete(featureId);
|
|
1495
|
+
this.lastStatusByFeature.set(featureId, STATUS.AWAITING_INPUT);
|
|
1496
|
+
await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_LOG_APPEND, {
|
|
1497
|
+
feature_id: featureId,
|
|
1498
|
+
note: JSON.stringify({
|
|
1499
|
+
phase: 'planning',
|
|
1500
|
+
action: 'ask_user_input',
|
|
1501
|
+
decision: 'awaiting_input',
|
|
1502
|
+
question_id: asRecord(question.data).question_id ?? null,
|
|
1503
|
+
recovery_reason: recoveryReason,
|
|
1504
|
+
ambiguity_ids: ambiguities.map((ambiguity) => ambiguity.id),
|
|
1505
|
+
}),
|
|
1506
|
+
});
|
|
1507
|
+
return true;
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
private buildPlannerRecoveryFrontMatter(
|
|
1511
|
+
frontMatter: AnyRecord,
|
|
1512
|
+
errorCode: string,
|
|
1513
|
+
phase: 'planning',
|
|
1514
|
+
): AnyRecord {
|
|
1515
|
+
const existingRecovery = asRecord(frontMatter.recovery);
|
|
1516
|
+
const nextAttempt =
|
|
1517
|
+
(typeof existingRecovery.attempt === 'number' && Number.isFinite(existingRecovery.attempt)
|
|
1518
|
+
? Math.max(0, Math.floor(existingRecovery.attempt))
|
|
1519
|
+
: 0) + 1;
|
|
1520
|
+
const now = new Date().toISOString();
|
|
1521
|
+
return {
|
|
1522
|
+
state: 'retrying',
|
|
1523
|
+
cause: errorCode,
|
|
1524
|
+
role: 'planner',
|
|
1525
|
+
resume_phase: phase,
|
|
1526
|
+
attempt: nextAttempt,
|
|
1527
|
+
run_id: this.resolveRunId(),
|
|
1528
|
+
started_at: asString(existingRecovery.started_at) ?? now,
|
|
1529
|
+
last_attempt_at: now,
|
|
1530
|
+
};
|
|
1531
|
+
}
|
|
1532
|
+
|
|
608
1533
|
private async applyWorkerPolicyAction(
|
|
609
1534
|
featureId: string,
|
|
610
1535
|
action:
|
|
@@ -638,6 +1563,7 @@ export class PlanningWaveExecutor {
|
|
|
638
1563
|
typeof frontMatter.version === 'number' && Number.isFinite(frontMatter.version)
|
|
639
1564
|
? Math.floor(frontMatter.version)
|
|
640
1565
|
: null;
|
|
1566
|
+
const recovery = this.buildPlannerRecoveryFrontMatter(frontMatter, errorCode, phase);
|
|
641
1567
|
await this.toolCaller.callTool('orchestrator', TOOLS.FEATURE_STATE_PATCH, {
|
|
642
1568
|
feature_id: featureId,
|
|
643
1569
|
expected_version: expectedVersion,
|
|
@@ -645,6 +1571,7 @@ export class PlanningWaveExecutor {
|
|
|
645
1571
|
front_matter: {
|
|
646
1572
|
status: STATUS.BLOCKED,
|
|
647
1573
|
status_reason: `${errorCode}: ${message}`,
|
|
1574
|
+
recovery,
|
|
648
1575
|
},
|
|
649
1576
|
},
|
|
650
1577
|
});
|
|
@@ -656,6 +1583,8 @@ export class PlanningWaveExecutor {
|
|
|
656
1583
|
decision: 'blocked',
|
|
657
1584
|
error_code: errorCode,
|
|
658
1585
|
reason: message,
|
|
1586
|
+
recovery_state: recovery.state,
|
|
1587
|
+
recovery_attempt: recovery.attempt,
|
|
659
1588
|
}),
|
|
660
1589
|
});
|
|
661
1590
|
}
|