muonroi-cli 1.8.4 → 1.9.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/LICENSE +17 -5
- package/dist/packages/agent-harness-core/src/driver.d.ts +27 -1
- package/dist/packages/agent-harness-core/src/driver.js +46 -0
- package/dist/packages/agent-harness-core/src/event-filter.js +11 -0
- package/dist/packages/agent-harness-core/src/event-redact.js +7 -0
- package/dist/packages/agent-harness-core/src/event-tee.d.ts +64 -0
- package/dist/packages/agent-harness-core/src/event-tee.js +104 -0
- package/dist/packages/agent-harness-core/src/mcp-server.d.ts +25 -0
- package/dist/packages/agent-harness-core/src/mcp-server.js +169 -21
- package/dist/packages/agent-harness-core/src/predicate.d.ts +1 -1
- package/dist/packages/agent-harness-core/src/protocol.d.ts +90 -4
- package/dist/packages/agent-harness-core/src/protocol.js +15 -0
- package/dist/packages/agent-harness-core/src/visual-quality.d.ts +58 -0
- package/dist/packages/agent-harness-core/src/visual-quality.js +141 -0
- package/dist/packages/agent-harness-opentui/src/agent-mode.d.ts +6 -0
- package/dist/packages/agent-harness-opentui/src/agent-mode.js +14 -1
- package/dist/packages/agent-harness-opentui/src/input-bridge.d.ts +2 -10
- package/dist/packages/agent-harness-opentui/src/input-bridge.js +103 -16
- package/dist/packages/agent-harness-opentui/src/install.d.ts +8 -0
- package/dist/packages/agent-harness-opentui/src/install.js +10 -0
- package/dist/packages/agent-harness-opentui/src/semantic.js +12 -10
- package/dist/packages/agent-harness-opentui/src/visual-capture.d.ts +56 -0
- package/dist/packages/agent-harness-opentui/src/visual-capture.js +103 -0
- package/dist/src/agent-harness/mock-model.d.ts +38 -0
- package/dist/src/agent-harness/mock-model.js +69 -3
- package/dist/src/agent-harness/test-spawn.js +31 -0
- package/dist/src/chat/chat-keychain.d.ts +7 -12
- package/dist/src/chat/chat-keychain.js +19 -86
- package/dist/src/cli/config/screen-providers.js +1 -1
- package/dist/src/cli/cost-forensics.d.ts +10 -0
- package/dist/src/cli/cost-forensics.js +18 -3
- package/dist/src/cli/keys-bundle.d.ts +1 -1
- package/dist/src/cli/keys-bundle.js +1 -1
- package/dist/src/cli/keys.d.ts +10 -47
- package/dist/src/cli/keys.js +31 -399
- package/dist/src/council/clarifier.d.ts +31 -3
- package/dist/src/council/clarifier.js +220 -32
- package/dist/src/council/context.js +49 -15
- package/dist/src/council/debate-checkpoint.d.ts +129 -0
- package/dist/src/council/debate-checkpoint.js +176 -0
- package/dist/src/council/debate-planner.js +54 -5
- package/dist/src/council/debate-summary.d.ts +25 -0
- package/dist/src/council/debate-summary.js +85 -0
- package/dist/src/council/debate.d.ts +169 -2
- package/dist/src/council/debate.js +1265 -135
- package/dist/src/council/index.d.ts +108 -1
- package/dist/src/council/index.js +670 -197
- package/dist/src/council/leader.d.ts +26 -0
- package/dist/src/council/leader.js +150 -9
- package/dist/src/council/llm.d.ts +94 -0
- package/dist/src/council/llm.js +348 -55
- package/dist/src/council/panel-select.d.ts +30 -0
- package/dist/src/council/panel-select.js +82 -0
- package/dist/src/council/planner.js +40 -0
- package/dist/src/council/preflight.d.ts +17 -0
- package/dist/src/council/preflight.js +50 -2
- package/dist/src/council/prompts.d.ts +39 -4
- package/dist/src/council/prompts.js +256 -69
- package/dist/src/council/stance-recall.d.ts +42 -0
- package/dist/src/council/stance-recall.js +57 -0
- package/dist/src/council/strip-think.d.ts +17 -0
- package/dist/src/council/strip-think.js +33 -0
- package/dist/src/council/types.d.ts +138 -0
- package/dist/src/ee/artifact-cache.d.ts +16 -0
- package/dist/src/ee/artifact-cache.js +32 -0
- package/dist/src/ee/auth.d.ts +20 -0
- package/dist/src/ee/auth.js +54 -2
- package/dist/src/ee/bridge.d.ts +10 -0
- package/dist/src/ee/bridge.js +58 -0
- package/dist/src/ee/client.js +109 -21
- package/dist/src/ee/ee-onboarding.js +6 -26
- package/dist/src/ee/export-transcripts.d.ts +1 -0
- package/dist/src/ee/export-transcripts.js +8 -10
- package/dist/src/ee/extract-session.js +29 -0
- package/dist/src/ee/extract-style.d.ts +58 -0
- package/dist/src/ee/extract-style.js +270 -0
- package/dist/src/ee/recall-ledger.d.ts +9 -0
- package/dist/src/ee/recall-ledger.js +3 -0
- package/dist/src/ee/scope.d.ts +1 -0
- package/dist/src/ee/scope.js +26 -1
- package/dist/src/ee/search.d.ts +7 -0
- package/dist/src/ee/search.js +24 -0
- package/dist/src/ee/transcript-emit.js +2 -0
- package/dist/src/ee/types.d.ts +22 -0
- package/dist/src/ee/who-am-i-brain.d.ts +35 -0
- package/dist/src/ee/who-am-i-brain.js +220 -0
- package/dist/src/ee/who-am-i.d.ts +10 -3
- package/dist/src/ee/who-am-i.js +12 -0
- package/dist/src/ee/workflow-event.d.ts +48 -0
- package/dist/src/ee/workflow-event.js +81 -0
- package/dist/src/flow/compaction/compress.d.ts +3 -3
- package/dist/src/flow/compaction/compress.js +58 -8
- package/dist/src/flow/compaction/extract.d.ts +4 -7
- package/dist/src/flow/compaction/extract.js +50 -10
- package/dist/src/flow/compaction/index.d.ts +14 -1
- package/dist/src/flow/compaction/index.js +96 -3
- package/dist/src/flow/compaction/input-guard.d.ts +24 -0
- package/dist/src/flow/compaction/input-guard.js +43 -0
- package/dist/src/flow/compaction/progress.d.ts +35 -0
- package/dist/src/flow/compaction/progress.js +35 -0
- package/dist/src/flow/fold-planning.d.ts +36 -0
- package/dist/src/flow/fold-planning.js +83 -0
- package/dist/src/flow/hierarchy.d.ts +146 -0
- package/dist/src/flow/hierarchy.js +427 -0
- package/dist/src/flow/index.d.ts +1 -0
- package/dist/src/flow/index.js +2 -0
- package/dist/src/flow/run-artifacts.d.ts +102 -0
- package/dist/src/flow/run-artifacts.js +208 -0
- package/dist/src/generated/version.d.ts +1 -1
- package/dist/src/generated/version.js +1 -1
- package/dist/src/gsd/assessment-schema.d.ts +44 -0
- package/dist/src/gsd/assessment-schema.js +134 -0
- package/dist/src/gsd/capability-registry.d.ts +45 -0
- package/dist/src/gsd/capability-registry.js +337 -0
- package/dist/src/gsd/complexity-assessor.d.ts +39 -0
- package/dist/src/gsd/complexity-assessor.js +152 -0
- package/dist/src/gsd/config-bridge.d.ts +7 -0
- package/dist/src/gsd/config-bridge.js +114 -0
- package/dist/src/gsd/config-loader.d.ts +27 -0
- package/dist/src/gsd/config-loader.js +50 -0
- package/dist/src/gsd/council-context.d.ts +44 -0
- package/dist/src/gsd/council-context.js +114 -0
- package/dist/src/gsd/ee-closure.d.ts +28 -0
- package/dist/src/gsd/ee-closure.js +49 -0
- package/dist/src/gsd/flags.d.ts +66 -0
- package/dist/src/gsd/flags.js +102 -0
- package/dist/src/gsd/gsd-dispatch.d.ts +58 -0
- package/dist/src/gsd/gsd-dispatch.js +131 -0
- package/dist/src/gsd/gsd-runtime.d.ts +22 -0
- package/dist/src/gsd/gsd-runtime.js +37 -0
- package/dist/src/gsd/host-adapter.d.ts +11 -0
- package/dist/src/gsd/host-adapter.js +29 -0
- package/dist/src/gsd/index.d.ts +24 -1
- package/dist/src/gsd/index.js +27 -0
- package/dist/src/gsd/loop-host-contract.d.ts +21 -0
- package/dist/src/gsd/loop-host-contract.js +39 -0
- package/dist/src/gsd/loop-host.d.ts +69 -0
- package/dist/src/gsd/loop-host.js +245 -0
- package/dist/src/gsd/loop-resolver.d.ts +36 -0
- package/dist/src/gsd/loop-resolver.js +79 -0
- package/dist/src/gsd/model-tier.d.ts +13 -0
- package/dist/src/gsd/model-tier.js +45 -0
- package/dist/src/gsd/mutation-gate.d.ts +16 -0
- package/dist/src/gsd/mutation-gate.js +41 -0
- package/dist/src/gsd/native-roadmap.d.ts +89 -0
- package/dist/src/gsd/native-roadmap.js +343 -0
- package/dist/src/gsd/native-state.d.ts +47 -0
- package/dist/src/gsd/native-state.js +220 -0
- package/dist/src/gsd/paths.d.ts +23 -0
- package/dist/src/gsd/paths.js +66 -0
- package/dist/src/gsd/phase-dag.d.ts +12 -0
- package/dist/src/gsd/phase-dag.js +94 -0
- package/dist/src/gsd/phase-sync.d.ts +42 -0
- package/dist/src/gsd/phase-sync.js +321 -0
- package/dist/src/gsd/pil-gate-context.d.ts +13 -0
- package/dist/src/gsd/pil-gate-context.js +64 -0
- package/dist/src/gsd/pil-gate-critic.d.ts +19 -0
- package/dist/src/gsd/pil-gate-critic.js +74 -0
- package/dist/src/gsd/plan-council-prompts.d.ts +25 -0
- package/dist/src/gsd/plan-council-prompts.js +79 -0
- package/dist/src/gsd/plan-council.d.ts +44 -0
- package/dist/src/gsd/plan-council.js +283 -0
- package/dist/src/gsd/plan-gate-vocabulary.d.ts +40 -0
- package/dist/src/gsd/plan-gate-vocabulary.js +64 -0
- package/dist/src/gsd/product-workspace.d.ts +13 -0
- package/dist/src/gsd/product-workspace.js +124 -0
- package/dist/src/gsd/ship-bridge.d.ts +25 -0
- package/dist/src/gsd/ship-bridge.js +65 -0
- package/dist/src/gsd/state-document.d.ts +40 -0
- package/dist/src/gsd/state-document.js +163 -0
- package/dist/src/gsd/verdict-schema.d.ts +39 -0
- package/dist/src/gsd/verdict-schema.js +144 -0
- package/dist/src/gsd/verify-context.d.ts +22 -0
- package/dist/src/gsd/verify-context.js +27 -0
- package/dist/src/gsd/verify-council-prompts.d.ts +19 -0
- package/dist/src/gsd/verify-council-prompts.js +85 -0
- package/dist/src/gsd/verify-council.d.ts +25 -0
- package/dist/src/gsd/verify-council.js +119 -0
- package/dist/src/gsd/verify-gate-vocabulary.d.ts +25 -0
- package/dist/src/gsd/verify-gate-vocabulary.js +46 -0
- package/dist/src/gsd/workflow-engine.d.ts +60 -0
- package/dist/src/gsd/workflow-engine.js +207 -0
- package/dist/src/gsd/workflow-tools.d.ts +13 -0
- package/dist/src/gsd/workflow-tools.js +277 -0
- package/dist/src/headless/council-answers.js +4 -0
- package/dist/src/hooks/index.js +1 -1
- package/dist/src/index.js +172 -270
- package/dist/src/lsp/builtins.js +3 -1
- package/dist/src/lsp/manager.d.ts +5 -1
- package/dist/src/lsp/manager.js +249 -3
- package/dist/src/lsp/npm-cache.d.ts +11 -1
- package/dist/src/lsp/npm-cache.js +17 -1
- package/dist/src/lsp/runtime.d.ts +6 -1
- package/dist/src/lsp/runtime.js +17 -1
- package/dist/src/lsp/types.d.ts +83 -1
- package/dist/src/lsp/types.js +10 -0
- package/dist/src/maintain/pr-builder.js +23 -13
- package/dist/src/mcp/auto-setup.js +57 -32
- package/dist/src/mcp/client-pool.js +44 -16
- package/dist/src/mcp/lsp-tools.d.ts +5 -1
- package/dist/src/mcp/lsp-tools.js +93 -2
- package/dist/src/mcp/mcp-keychain.d.ts +3 -5
- package/dist/src/mcp/mcp-keychain.js +9 -49
- package/dist/src/mcp/research-onboarding.js +8 -7
- package/dist/src/mcp/runtime.js +34 -2
- package/dist/src/mcp/setup-guide-text.d.ts +1 -1
- package/dist/src/mcp/setup-guide-text.js +22 -2
- package/dist/src/mcp/tools-server.d.ts +10 -0
- package/dist/src/mcp/tools-server.js +10 -2
- package/dist/src/models/catalog-client.d.ts +87 -0
- package/dist/src/models/catalog-client.js +105 -38
- package/dist/src/models/catalog.json +528 -265
- package/dist/src/models/registry.d.ts +22 -7
- package/dist/src/models/registry.js +73 -10
- package/dist/src/ops/doctor.js +1 -1
- package/dist/src/orchestrator/ask-user.d.ts +61 -0
- package/dist/src/orchestrator/ask-user.js +65 -0
- package/dist/src/orchestrator/auto-commit.js +1 -1
- package/dist/src/orchestrator/batch-turn-runner.js +2 -2
- package/dist/src/orchestrator/cache-prefix.d.ts +67 -0
- package/dist/src/orchestrator/cache-prefix.js +83 -0
- package/dist/src/orchestrator/compact-request.d.ts +32 -0
- package/dist/src/orchestrator/compact-request.js +41 -0
- package/dist/src/orchestrator/compaction.d.ts +12 -3
- package/dist/src/orchestrator/compaction.js +35 -15
- package/dist/src/orchestrator/council-manager.d.ts +12 -3
- package/dist/src/orchestrator/council-manager.js +74 -32
- package/dist/src/orchestrator/council-request.d.ts +49 -0
- package/dist/src/orchestrator/council-request.js +62 -0
- package/dist/src/orchestrator/cross-turn-dedup.d.ts +6 -0
- package/dist/src/orchestrator/cross-turn-dedup.js +22 -1
- package/dist/src/orchestrator/error-utils.d.ts +29 -0
- package/dist/src/orchestrator/error-utils.js +132 -24
- package/dist/src/orchestrator/grounding-check.js +39 -1
- package/dist/src/orchestrator/interactive-pause.d.ts +26 -0
- package/dist/src/orchestrator/interactive-pause.js +36 -0
- package/dist/src/orchestrator/message-processor.d.ts +4 -0
- package/dist/src/orchestrator/message-processor.js +268 -41
- package/dist/src/orchestrator/orchestrator.d.ts +64 -3
- package/dist/src/orchestrator/orchestrator.js +823 -120
- package/dist/src/orchestrator/preprocessor.js +3 -3
- package/dist/src/orchestrator/proactive-compact-detector.d.ts +26 -0
- package/dist/src/orchestrator/proactive-compact-detector.js +36 -0
- package/dist/src/orchestrator/prompts.js +17 -17
- package/dist/src/orchestrator/reactive-delegation.d.ts +39 -0
- package/dist/src/orchestrator/reactive-delegation.js +59 -0
- package/dist/src/orchestrator/retry-classifier.d.ts +2 -1
- package/dist/src/orchestrator/retry-classifier.js +46 -2
- package/dist/src/orchestrator/safety-askcard.d.ts +1 -1
- package/dist/src/orchestrator/safety-askcard.js +5 -2
- package/dist/src/orchestrator/safety-intercept.d.ts +50 -0
- package/dist/src/orchestrator/safety-intercept.js +62 -0
- package/dist/src/orchestrator/scope-reminder.js +1 -1
- package/dist/src/orchestrator/session-experience.d.ts +2 -1
- package/dist/src/orchestrator/session-experience.js +2 -1
- package/dist/src/orchestrator/should-run-gate.d.ts +5 -0
- package/dist/src/orchestrator/should-run-gate.js +18 -0
- package/dist/src/orchestrator/stall-watchdog.d.ts +31 -3
- package/dist/src/orchestrator/stall-watchdog.js +65 -10
- package/dist/src/orchestrator/stream-runner.d.ts +13 -3
- package/dist/src/orchestrator/stream-runner.js +115 -49
- package/dist/src/orchestrator/sub-agent-cap.d.ts +13 -1
- package/dist/src/orchestrator/sub-agent-cap.js +16 -1
- package/dist/src/orchestrator/sub-agent-model-tier.d.ts +13 -1
- package/dist/src/orchestrator/sub-agent-model-tier.js +16 -2
- package/dist/src/orchestrator/subagent-compactor.d.ts +53 -1
- package/dist/src/orchestrator/subagent-compactor.js +126 -15
- package/dist/src/orchestrator/tool-engine.d.ts +41 -0
- package/dist/src/orchestrator/tool-engine.js +846 -66
- package/dist/src/orchestrator/tool-limit-auto-recover.d.ts +22 -0
- package/dist/src/orchestrator/tool-limit-auto-recover.js +30 -0
- package/dist/src/orchestrator/turn-runner-deps.d.ts +19 -0
- package/dist/src/orchestrator/turn-watchdog.d.ts +44 -0
- package/dist/src/orchestrator/turn-watchdog.js +84 -0
- package/dist/src/pil/agent-operating-contract.d.ts +1 -1
- package/dist/src/pil/agent-operating-contract.js +6 -4
- package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
- package/dist/src/pil/cheap-model-playbook.js +5 -1
- package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
- package/dist/src/pil/cheap-model-workbooks.js +1 -1
- package/dist/src/pil/discovery-types.d.ts +1 -0
- package/dist/src/pil/discovery.d.ts +1 -1
- package/dist/src/pil/discovery.js +18 -13
- package/dist/src/pil/layer1-intent.d.ts +18 -6
- package/dist/src/pil/layer1-intent.js +66 -757
- package/dist/src/pil/layer15-context-scan.js +15 -1
- package/dist/src/pil/layer1_5-complexity-size.d.ts +7 -0
- package/dist/src/pil/layer1_5-complexity-size.js +31 -5
- package/dist/src/pil/layer3-ee-injection.js +23 -8
- package/dist/src/pil/layer4-gsd.js +69 -16
- package/dist/src/pil/layer5-context.js +7 -3
- package/dist/src/pil/layer6-output.d.ts +23 -0
- package/dist/src/pil/layer6-output.js +5 -1
- package/dist/src/pil/llm-classify.d.ts +111 -5
- package/dist/src/pil/llm-classify.js +421 -189
- package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
- package/dist/src/pil/native-capabilities-workbook.js +8 -0
- package/dist/src/pil/pipeline.js +36 -2
- package/dist/src/pil/repo-grounding-probe.d.ts +15 -0
- package/dist/src/pil/repo-grounding-probe.js +136 -0
- package/dist/src/pil/repo-structure-hints.d.ts +7 -0
- package/dist/src/pil/repo-structure-hints.js +45 -0
- package/dist/src/pil/response-tools.js +5 -3
- package/dist/src/pil/schema.d.ts +1 -0
- package/dist/src/pil/schema.js +2 -0
- package/dist/src/pil/types.d.ts +18 -0
- package/dist/src/playbook/directives.d.ts +4 -0
- package/dist/src/playbook/directives.js +17 -5
- package/dist/src/product-loop/artifact-io.js +4 -0
- package/dist/src/product-loop/backlog-builder.d.ts +14 -1
- package/dist/src/product-loop/backlog-builder.js +30 -6
- package/dist/src/product-loop/criteria-seed.d.ts +51 -0
- package/dist/src/product-loop/criteria-seed.js +200 -0
- package/dist/src/product-loop/discovery-context-format.js +3 -1
- package/dist/src/product-loop/discovery-ecosystem.js +4 -1
- package/dist/src/product-loop/discovery-interview.d.ts +9 -0
- package/dist/src/product-loop/discovery-interview.js +60 -12
- package/dist/src/product-loop/discovery-recommender.js +2 -1
- package/dist/src/product-loop/discovery-schema.js +19 -2
- package/dist/src/product-loop/discovery-triage.d.ts +23 -0
- package/dist/src/product-loop/discovery-triage.js +109 -0
- package/dist/src/product-loop/gather.js +150 -2
- package/dist/src/product-loop/ideal-trace.d.ts +7 -0
- package/dist/src/product-loop/ideal-trace.js +64 -0
- package/dist/src/product-loop/index.d.ts +13 -1
- package/dist/src/product-loop/index.js +340 -52
- package/dist/src/product-loop/loop-driver.d.ts +7 -0
- package/dist/src/product-loop/loop-driver.js +330 -106
- package/dist/src/product-loop/phase-plan.d.ts +21 -0
- package/dist/src/product-loop/phase-plan.js +81 -6
- package/dist/src/product-loop/phase-rituals.d.ts +3 -0
- package/dist/src/product-loop/phase-rituals.js +8 -3
- package/dist/src/product-loop/phase-runner.js +39 -12
- package/dist/src/product-loop/plan-adherence-review.d.ts +26 -0
- package/dist/src/product-loop/plan-adherence-review.js +144 -0
- package/dist/src/product-loop/sprint-runner.d.ts +173 -0
- package/dist/src/product-loop/sprint-runner.js +863 -19
- package/dist/src/product-loop/types.d.ts +61 -5
- package/dist/src/providers/adapter.d.ts +1 -1
- package/dist/src/providers/adapter.js +3 -4
- package/dist/src/providers/anthropic.d.ts +9 -8
- package/dist/src/providers/anthropic.js +13 -47
- package/dist/src/providers/auth/browser-flow.d.ts +1 -1
- package/dist/src/providers/auth/browser-flow.js +1 -1
- package/dist/src/providers/auth/grok-oauth.d.ts +1 -0
- package/dist/src/providers/auth/grok-oauth.js +30 -5
- package/dist/src/providers/auth/openai-oauth.d.ts +1 -0
- package/dist/src/providers/auth/openai-oauth.js +15 -1
- package/dist/src/providers/auth/registry.js +0 -34
- package/dist/src/providers/auth/token-store.d.ts +9 -9
- package/dist/src/providers/auth/token-store.js +8 -67
- package/dist/src/providers/auth/types.d.ts +9 -1
- package/dist/src/providers/auth/types.js +1 -1
- package/dist/src/providers/capabilities.d.ts +24 -5
- package/dist/src/providers/capabilities.js +42 -24
- package/dist/src/providers/endpoints.d.ts +2 -2
- package/dist/src/providers/endpoints.js +11 -10
- package/dist/src/providers/env-store.d.ts +17 -0
- package/dist/src/providers/env-store.js +228 -0
- package/dist/src/providers/keychain.d.ts +22 -18
- package/dist/src/providers/keychain.js +127 -140
- package/dist/src/providers/mcp-vision-bridge.js +56 -146
- package/dist/src/providers/openai-compatible.js +8 -1
- package/dist/src/providers/pricing.d.ts +2 -2
- package/dist/src/providers/pricing.js +3 -13
- package/dist/src/providers/runtime.d.ts +43 -3
- package/dist/src/providers/runtime.js +88 -14
- package/dist/src/providers/strategies/base.strategy.d.ts +16 -0
- package/dist/src/providers/strategies/base.strategy.js +24 -1
- package/dist/src/providers/strategies/{siliconflow.strategy.d.ts → opencode-go.strategy.d.ts} +3 -3
- package/dist/src/providers/strategies/opencode-go.strategy.js +83 -0
- package/dist/src/providers/strategies/registry.js +4 -4
- package/dist/src/providers/strategies/thinking-mode.d.ts +109 -0
- package/dist/src/providers/strategies/thinking-mode.js +288 -1
- package/dist/src/providers/strategies/xai.strategy.js +27 -0
- package/dist/src/providers/strategies/zai.strategy.d.ts +14 -0
- package/dist/src/providers/strategies/zai.strategy.js +44 -0
- package/dist/src/providers/types.d.ts +5 -6
- package/dist/src/providers/types.js +2 -2
- package/dist/src/providers/vision-backend.d.ts +47 -0
- package/dist/src/providers/vision-backend.js +258 -0
- package/dist/src/providers/vision-proxy.d.ts +22 -9
- package/dist/src/providers/vision-proxy.js +63 -132
- package/dist/src/providers/warm.d.ts +65 -0
- package/dist/src/providers/warm.js +145 -0
- package/dist/src/providers/wire-debug.js +95 -0
- package/dist/src/router/decide.d.ts +13 -0
- package/dist/src/router/decide.js +138 -36
- package/dist/src/router/peak-hour.d.ts +38 -0
- package/dist/src/router/peak-hour.js +107 -0
- package/dist/src/router/step-router.js +3 -2
- package/dist/src/router/warm.js +4 -5
- package/dist/src/scaffold/continuation-prompt.d.ts +11 -0
- package/dist/src/scaffold/continuation-prompt.js +26 -0
- package/dist/src/scaffold/point-to-existing.d.ts +21 -0
- package/dist/src/scaffold/point-to-existing.js +25 -0
- package/dist/src/self-qa/agentic-loop.js +6 -5
- package/dist/src/{ui/state → state}/active-run.d.ts +19 -0
- package/dist/src/{ui/state → state}/active-run.js +21 -0
- package/dist/src/{ui/status-bar/store.d.ts → state/status-bar-store.d.ts} +4 -1
- package/dist/src/{ui/status-bar/store.js → state/status-bar-store.js} +12 -9
- package/dist/src/state/turn-trace.d.ts +43 -0
- package/dist/src/state/turn-trace.js +32 -0
- package/dist/src/storage/db.js +2 -1
- package/dist/src/storage/index.d.ts +1 -1
- package/dist/src/storage/index.js +1 -1
- package/dist/src/storage/interaction-log.d.ts +1 -1
- package/dist/src/storage/migrations.js +71 -1
- package/dist/src/storage/sessions.d.ts +28 -10
- package/dist/src/storage/sessions.js +78 -21
- package/dist/src/storage/transcript-view.js +1 -1
- package/dist/src/storage/transcript.d.ts +51 -0
- package/dist/src/storage/transcript.js +340 -15
- package/dist/src/tools/file.d.ts +15 -0
- package/dist/src/tools/file.js +32 -0
- package/dist/src/tools/git-safety.d.ts +19 -0
- package/dist/src/tools/git-safety.js +168 -0
- package/dist/src/tools/native-tools.d.ts +1 -1
- package/dist/src/tools/native-tools.js +81 -1
- package/dist/src/tools/registry.d.ts +20 -0
- package/dist/src/tools/registry.js +576 -23
- package/dist/src/tools/research.d.ts +29 -0
- package/dist/src/tools/research.js +233 -0
- package/dist/src/types/index.d.ts +147 -4
- package/dist/src/ui/app.js +0 -0
- package/dist/src/ui/cards/product-status-card.js +1 -1
- package/dist/src/ui/components/agent-rail-activities.d.ts +26 -0
- package/dist/src/ui/components/agent-rail-activities.js +47 -0
- package/dist/src/ui/components/bubble-body-guard.d.ts +27 -0
- package/dist/src/ui/components/bubble-body-guard.js +50 -0
- package/dist/src/ui/components/compact-progress-card.d.ts +24 -0
- package/dist/src/ui/components/compact-progress-card.js +42 -0
- package/dist/src/ui/components/context-rail.d.ts +26 -0
- package/dist/src/ui/components/context-rail.js +33 -0
- package/dist/src/ui/components/council-conclusion-card.d.ts +73 -0
- package/dist/src/ui/components/council-conclusion-card.js +420 -0
- package/dist/src/ui/components/council-debate-pill.d.ts +36 -0
- package/dist/src/ui/components/council-debate-pill.js +34 -0
- package/dist/src/ui/components/council-info-card.js +2 -2
- package/dist/src/ui/components/council-leader-bubble.d.ts +10 -3
- package/dist/src/ui/components/council-leader-bubble.js +21 -11
- package/dist/src/ui/components/council-message-bubble.d.ts +15 -2
- package/dist/src/ui/components/council-message-bubble.js +16 -15
- package/dist/src/ui/components/council-phase-timeline.d.ts +9 -1
- package/dist/src/ui/components/council-phase-timeline.js +66 -17
- package/dist/src/ui/components/council-placeholder-bubble.d.ts +16 -9
- package/dist/src/ui/components/council-placeholder-bubble.js +32 -29
- package/dist/src/ui/components/council-question-card.js +13 -12
- package/dist/src/ui/components/council-rail-rounds.d.ts +26 -0
- package/dist/src/ui/components/council-rail-rounds.js +57 -0
- package/dist/src/ui/components/council-round-group.d.ts +38 -0
- package/dist/src/ui/components/council-round-group.js +88 -0
- package/dist/src/ui/components/council-status-list.d.ts +3 -1
- package/dist/src/ui/components/council-status-list.js +36 -24
- package/dist/src/ui/components/council-synthesis-banner.d.ts +7 -2
- package/dist/src/ui/components/council-synthesis-banner.js +20 -5
- package/dist/src/ui/components/halt-recovery-card.js +9 -5
- package/dist/src/ui/components/jump-to-latest-pill.d.ts +11 -0
- package/dist/src/ui/components/jump-to-latest-pill.js +14 -0
- package/dist/src/ui/components/message-view.d.ts +15 -0
- package/dist/src/ui/components/message-view.js +50 -1
- package/dist/src/ui/components/prompt-box.js +18 -16
- package/dist/src/ui/components/session-tree-card.d.ts +14 -0
- package/dist/src/ui/components/session-tree-card.js +46 -0
- package/dist/src/ui/components/slash-inline-menu.d.ts +12 -0
- package/dist/src/ui/components/slash-inline-menu.js +26 -5
- package/dist/src/ui/components/task-list-panel.d.ts +14 -1
- package/dist/src/ui/components/task-list-panel.js +22 -2
- package/dist/src/ui/components/tool-group.d.ts +15 -3
- package/dist/src/ui/components/tool-group.js +69 -11
- package/dist/src/ui/containers/modals-layer.d.ts +4 -2
- package/dist/src/ui/containers/modals-layer.js +2 -2
- package/dist/src/ui/council-harness-event.d.ts +57 -0
- package/dist/src/ui/council-harness-event.js +46 -0
- package/dist/src/ui/heartbeat-debug.d.ts +29 -0
- package/dist/src/ui/heartbeat-debug.js +45 -0
- package/dist/src/ui/hooks/use-session-picker.d.ts +3 -3
- package/dist/src/ui/mcp-modal.js +2 -4
- package/dist/src/ui/modals/api-key-modal.js +1 -1
- package/dist/src/ui/modals/connect-modal.js +4 -3
- package/dist/src/ui/modals/model-picker-modal.d.ts +8 -18
- package/dist/src/ui/modals/model-picker-modal.js +8 -10
- package/dist/src/ui/modals/session-picker-modal.d.ts +2 -2
- package/dist/src/ui/modals/session-picker-modal.js +3 -5
- package/dist/src/ui/picker-providers.d.ts +1 -1
- package/dist/src/ui/picker-providers.js +1 -1
- package/dist/src/ui/primitives/index.d.ts +1 -0
- package/dist/src/ui/primitives/index.js +2 -0
- package/dist/src/ui/primitives/semantic-primitives.d.ts +76 -0
- package/dist/src/ui/primitives/semantic-primitives.js +81 -0
- package/dist/src/ui/slash/compact.js +5 -7
- package/dist/src/ui/slash/cost.js +1 -1
- package/dist/src/ui/slash/council.js +19 -1
- package/dist/src/ui/slash/debug.d.ts +3 -31
- package/dist/src/ui/slash/debug.js +9 -20
- package/dist/src/ui/slash/ee.js +81 -0
- package/dist/src/ui/slash/ideal.d.ts +6 -2
- package/dist/src/ui/slash/ideal.js +97 -7
- package/dist/src/ui/slash/menu-items.d.ts +7 -0
- package/dist/src/ui/slash/menu-items.js +23 -20
- package/dist/src/ui/slash/registry.d.ts +2 -0
- package/dist/src/ui/slash/registry.js +4 -0
- package/dist/src/ui/status-bar/cache-hit.d.ts +6 -0
- package/dist/src/ui/status-bar/cache-hit.js +9 -0
- package/dist/src/ui/status-bar/index.d.ts +1 -1
- package/dist/src/ui/status-bar/index.js +7 -3
- package/dist/src/ui/status-bar/usd-meter.d.ts +5 -4
- package/dist/src/ui/status-bar/usd-meter.js +6 -4
- package/dist/src/ui/theme.d.ts +1 -0
- package/dist/src/ui/theme.js +2 -0
- package/dist/src/ui/types.d.ts +7 -0
- package/dist/src/ui/use-app-logic.js +0 -0
- package/dist/src/ui/utils/agent-activities.d.ts +39 -0
- package/dist/src/ui/utils/agent-activities.js +96 -0
- package/dist/src/ui/utils/format.d.ts +14 -0
- package/dist/src/ui/utils/format.js +23 -3
- package/dist/src/ui/utils/group-tool-entries.d.ts +26 -0
- package/dist/src/ui/utils/group-tool-entries.js +111 -0
- package/dist/src/ui/utils/tool-summary.d.ts +21 -0
- package/dist/src/ui/utils/tool-summary.js +91 -0
- package/dist/src/usage/downgrade.js +2 -2
- package/dist/src/usage/product-ledger.js +2 -2
- package/dist/src/utils/event-loop-monitor.d.ts +85 -0
- package/dist/src/utils/event-loop-monitor.js +107 -0
- package/dist/src/utils/install-manager.js +2 -1
- package/dist/src/utils/llm-deadline.d.ts +14 -0
- package/dist/src/utils/llm-deadline.js +19 -0
- package/dist/src/utils/logger.js +2 -2
- package/dist/src/utils/loop-profiler.d.ts +102 -0
- package/dist/src/utils/loop-profiler.js +202 -0
- package/dist/src/utils/permission-mode.js +5 -3
- package/dist/src/utils/redactor.js +1 -1
- package/dist/src/utils/settings.d.ts +180 -5
- package/dist/src/utils/settings.js +271 -31
- package/dist/src/utils/side-question.d.ts +1 -2
- package/dist/src/utils/side-question.js +2 -2
- package/dist/src/utils/visible-retry.d.ts +11 -0
- package/dist/src/utils/visible-retry.js +10 -1
- package/dist/src/verify/entrypoint.d.ts +1 -1
- package/dist/src/verify/entrypoint.js +52 -17
- package/dist/src/verify/orchestrator.d.ts +1 -1
- package/dist/src/verify/orchestrator.js +20 -3
- package/dist/src/verify/recipes.d.ts +13 -0
- package/dist/src/verify/recipes.js +15 -0
- package/package.json +134 -132
- package/dist/src/cli/bw-vault.d.ts +0 -55
- package/dist/src/cli/bw-vault.js +0 -133
- package/dist/src/mcp/ee-tools.d.ts +0 -46
- package/dist/src/mcp/ee-tools.js +0 -193
- package/dist/src/providers/auth/gcloud.d.ts +0 -28
- package/dist/src/providers/auth/gcloud.js +0 -102
- package/dist/src/providers/auth/gemini-oauth.d.ts +0 -82
- package/dist/src/providers/auth/gemini-oauth.js +0 -472
- package/dist/src/providers/gemini.d.ts +0 -11
- package/dist/src/providers/gemini.js +0 -45
- package/dist/src/providers/siliconflow-sse-repair.d.ts +0 -58
- package/dist/src/providers/siliconflow-sse-repair.js +0 -177
- package/dist/src/providers/strategies/google.strategy.d.ts +0 -22
- package/dist/src/providers/strategies/google.strategy.js +0 -174
- package/dist/src/providers/strategies/siliconflow.strategy.js +0 -29
- package/dist/src/ui/containers/chat-feed.d.ts +0 -40
- package/dist/src/ui/containers/chat-feed.js +0 -66
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import { promises as fs } from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
+
import { readDebateCheckpoint } from "../council/debate-checkpoint.js";
|
|
3
4
|
import { resolveLeaderModel } from "../council/leader.js";
|
|
4
5
|
import { routeModel as eeRouteModel } from "../ee/bridge.js";
|
|
5
6
|
import { fireAndForgetPhaseOutcome } from "../ee/phase-outcome.js";
|
|
6
7
|
import { readArtifact } from "../flow/artifact-io.js";
|
|
8
|
+
import { parseResumeDigest, readSprintOutcomes } from "../flow/run-artifacts.js";
|
|
7
9
|
import { createRun, loadRun } from "../flow/run-manager.js";
|
|
8
10
|
import { getModelsForProvider } from "../models/registry.js";
|
|
9
11
|
import { loadKeyForProvider } from "../providers/keychain.js";
|
|
10
12
|
import { ALL_PROVIDER_IDS } from "../providers/types.js";
|
|
11
13
|
import { defaultResolveChannelId, maybeAutoFire } from "../reporter/auto-fire.js";
|
|
14
|
+
import { clearWorkspaceFocus, setWorkspaceFocus } from "../state/active-run.js";
|
|
12
15
|
import { logInteraction, logUIInteraction } from "../storage/index.js";
|
|
13
|
-
import { activeRunStore } from "../ui/state/active-run.js";
|
|
14
16
|
import { markIterationCrashed, readIterations, readManifest, writeManifest } from "./artifact-io.js";
|
|
15
17
|
import { buildBacklog } from "./backlog-builder.js";
|
|
16
18
|
import { readBacklog, writeBacklog } from "./backlog-store.js";
|
|
17
19
|
import { formatCostPreview, previewRunCost } from "./cost-preview.js";
|
|
18
|
-
import { extractRunToEE } from "./cross-run-memory.js";
|
|
20
|
+
import { composeRunTranscript, extractRunToEE } from "./cross-run-memory.js";
|
|
19
21
|
import { buildContinueFeedback } from "./feedback-routing.js";
|
|
20
22
|
import { runLoopDriver } from "./loop-driver.js";
|
|
21
23
|
import { resolveRoles } from "./role-registry.js";
|
|
@@ -38,6 +40,8 @@ export async function* runProductLoop(opts) {
|
|
|
38
40
|
switch (sub) {
|
|
39
41
|
case "status":
|
|
40
42
|
return yield* runStatus(opts);
|
|
43
|
+
case "review":
|
|
44
|
+
return yield* runReview(opts);
|
|
41
45
|
case "resume":
|
|
42
46
|
return yield* runResume(opts);
|
|
43
47
|
case "abort":
|
|
@@ -46,14 +50,30 @@ export async function* runProductLoop(opts) {
|
|
|
46
50
|
return yield* runShip(opts);
|
|
47
51
|
default: {
|
|
48
52
|
// Mode C dispatch — see .planning/MAINTAIN-MODE.md "Trigger mechanism".
|
|
49
|
-
// 1. Explicit --maintain
|
|
50
|
-
// 2. Explicit --new
|
|
51
|
-
// 3.
|
|
52
|
-
// 4.
|
|
53
|
+
// 1. Explicit --maintain → Mode C (strongest signal; wins over --force-council)
|
|
54
|
+
// 2. Explicit --new → Mode A (skip recipe detection)
|
|
55
|
+
// 3. --force-council → Mode A (user explicitly wants the full Council/loop)
|
|
56
|
+
// 4. Auto-detect: verify recipe present in cwd → Mode C
|
|
57
|
+
// 5. Otherwise → Mode A
|
|
53
58
|
if (opts.mode === "maintain") {
|
|
54
59
|
return yield* runMaintain(opts);
|
|
55
60
|
}
|
|
56
|
-
|
|
61
|
+
// `--force-council` must bypass the recipe auto-detect. Without this,
|
|
62
|
+
// ANY recipe-bearing repo (package.json/*.csproj/…) routes to runMaintain
|
|
63
|
+
// here — BEFORE the forceCouncil checks below (:189 / :197) are ever
|
|
64
|
+
// reached — so `/ideal --force-council` in an existing project was silently
|
|
65
|
+
// downgraded to maint-edit (observed: route-decision forceCouncil:false,
|
|
66
|
+
// path:maintain). Explicit --maintain above still wins over --force-council.
|
|
67
|
+
//
|
|
68
|
+
// complexity==="high" ALSO bypasses the recipe auto-detect. An
|
|
69
|
+
// architectural change (migration, SDK removal, subsystem rewrite) in a
|
|
70
|
+
// recipe-bearing repo must still earn the full Council — the very intent
|
|
71
|
+
// the complexity gate at :196-207 (and comment :188-195) documents. Before
|
|
72
|
+
// this guard, that gate was dead code for any repo with a verify recipe
|
|
73
|
+
// (real orchestrator ALWAYS wires detectVerifyRecipe), so a high-complexity
|
|
74
|
+
// /ideal was silently downgraded to maint-edit and jumped straight to Edit
|
|
75
|
+
// with no debate (observed: route-decision complexity:high path:maintain).
|
|
76
|
+
if (opts.mode !== "new" && !opts.flags.forceCouncil && opts.complexity !== "high" && opts.detectVerifyRecipe) {
|
|
57
77
|
try {
|
|
58
78
|
const recipe = await opts.detectVerifyRecipe();
|
|
59
79
|
if (recipe) {
|
|
@@ -86,10 +106,18 @@ export async function* runProductLoop(opts) {
|
|
|
86
106
|
};
|
|
87
107
|
return yield* runStart(forcedOpts);
|
|
88
108
|
}
|
|
89
|
-
// Existing repo + complexity≠high → hot-path. The leader
|
|
90
|
-
// the source instead of interviewing the user.
|
|
91
|
-
//
|
|
92
|
-
|
|
109
|
+
// Existing repo + complexity≠high + well-specified → hot-path. The leader
|
|
110
|
+
// can grep the source instead of interviewing the user. Two things still
|
|
111
|
+
// warrant the full Council/interview path: an architectural change
|
|
112
|
+
// (complexity=high / heavy), OR a request the model flagged as
|
|
113
|
+
// UNDERSPECIFIED (needsClarification) — a standard task missing a target
|
|
114
|
+
// or design decision must be clarified before code. A `quick`
|
|
115
|
+
// (complexity=low) task always hot-paths (handled below) even when
|
|
116
|
+
// underspecified: a trivial ask never earns an interview.
|
|
117
|
+
if (existingRepoBypass &&
|
|
118
|
+
opts.complexity !== "high" &&
|
|
119
|
+
!(opts.needsClarification && opts.complexity !== "low") &&
|
|
120
|
+
!opts.flags.forceCouncil) {
|
|
93
121
|
return yield* runHotPath(opts);
|
|
94
122
|
}
|
|
95
123
|
if (opts.complexity === "low" && !opts.flags.forceCouncil) {
|
|
@@ -148,6 +176,22 @@ async function* runHotPath(opts) {
|
|
|
148
176
|
stack: flags.stack,
|
|
149
177
|
createdAt: new Date(),
|
|
150
178
|
});
|
|
179
|
+
if (opts.cwd) {
|
|
180
|
+
try {
|
|
181
|
+
const { isGsdNativeEnabled } = await import("../gsd/flags.js");
|
|
182
|
+
if (isGsdNativeEnabled()) {
|
|
183
|
+
const { ensureProductPlanningWorkspace } = await import("../gsd/product-workspace.js");
|
|
184
|
+
ensureProductPlanningWorkspace(opts.cwd, {
|
|
185
|
+
idea,
|
|
186
|
+
sessionModelId: opts.sessionModelId,
|
|
187
|
+
runId,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch (err) {
|
|
192
|
+
console.error(`[ideal/hot-path] gsd product workspace bootstrap failed: ${err.message}`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
151
195
|
yield {
|
|
152
196
|
type: "content",
|
|
153
197
|
content: "\n> hot-path: complexity=low → single sprint, no council debate\n",
|
|
@@ -160,6 +204,7 @@ async function* runHotPath(opts) {
|
|
|
160
204
|
kind: "route-decision",
|
|
161
205
|
path: "hot-path",
|
|
162
206
|
complexity: opts.complexity ?? "low",
|
|
207
|
+
underspecified: !!opts.needsClarification,
|
|
163
208
|
forceCouncil: false,
|
|
164
209
|
runId,
|
|
165
210
|
});
|
|
@@ -201,7 +246,7 @@ async function* runHotPath(opts) {
|
|
|
201
246
|
try {
|
|
202
247
|
const { productSlug: deriveSlug } = await import("./product-identity.js");
|
|
203
248
|
const slug = deriveSlug(idea);
|
|
204
|
-
|
|
249
|
+
await setWorkspaceFocus(flowDir, { runId, productSlug: slug, reason: "sprint-plan-committed" });
|
|
205
250
|
fireAutoReport("sprint-plan-committed", { runId, flowDir, productSlug: slug, sprintCount: 1 });
|
|
206
251
|
}
|
|
207
252
|
catch {
|
|
@@ -233,6 +278,7 @@ async function* runHotPath(opts) {
|
|
|
233
278
|
cwd: opts.cwd,
|
|
234
279
|
sessionId: opts.sessionId,
|
|
235
280
|
processMessageFn: opts.processMessageFn,
|
|
281
|
+
runIsolatedTask: opts.runIsolatedTask,
|
|
236
282
|
detectVerifyRecipe: opts.detectVerifyRecipe,
|
|
237
283
|
skipPriorContext: opts.skipPriorContext,
|
|
238
284
|
sufficiencyMissing: opts.sufficiencyMissing,
|
|
@@ -556,6 +602,22 @@ async function* runStart(opts) {
|
|
|
556
602
|
stack: flags.stack,
|
|
557
603
|
createdAt: new Date(),
|
|
558
604
|
});
|
|
605
|
+
if (opts.cwd) {
|
|
606
|
+
try {
|
|
607
|
+
const { isGsdNativeEnabled } = await import("../gsd/flags.js");
|
|
608
|
+
if (isGsdNativeEnabled()) {
|
|
609
|
+
const { ensureProductPlanningWorkspace } = await import("../gsd/product-workspace.js");
|
|
610
|
+
ensureProductPlanningWorkspace(opts.cwd, {
|
|
611
|
+
idea,
|
|
612
|
+
sessionModelId: opts.sessionModelId,
|
|
613
|
+
runId,
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
catch (err) {
|
|
618
|
+
console.error(`[ideal] gsd product workspace bootstrap failed: ${err.message}`);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
559
621
|
// Surface a cost-vs-cap preview before the loop kicks off so $50 isn't
|
|
560
622
|
// an arbitrary number — show predicted spend per sprint × max-sprints
|
|
561
623
|
// against the configured cap, with a recommended max-sprints if it
|
|
@@ -574,6 +636,7 @@ async function* runStart(opts) {
|
|
|
574
636
|
kind: "route-decision",
|
|
575
637
|
path: "council",
|
|
576
638
|
complexity: opts.complexity ?? "unknown",
|
|
639
|
+
underspecified: !!opts.needsClarification,
|
|
577
640
|
forceCouncil: !!opts.flags.forceCouncil,
|
|
578
641
|
sufficiencyMissing: opts.sufficiencyMissing ?? [],
|
|
579
642
|
runId,
|
|
@@ -604,6 +667,7 @@ async function* runStart(opts) {
|
|
|
604
667
|
cwd: opts.cwd,
|
|
605
668
|
sessionId: opts.sessionId,
|
|
606
669
|
processMessageFn: opts.processMessageFn,
|
|
670
|
+
runIsolatedTask: opts.runIsolatedTask,
|
|
607
671
|
detectVerifyRecipe: opts.detectVerifyRecipe,
|
|
608
672
|
skipPriorContext: opts.skipPriorContext,
|
|
609
673
|
sufficiencyMissing: opts.sufficiencyMissing,
|
|
@@ -688,7 +752,7 @@ async function* runStart(opts) {
|
|
|
688
752
|
try {
|
|
689
753
|
const { productSlug: deriveSlug } = await import("./product-identity.js");
|
|
690
754
|
const slug = deriveSlug(idea);
|
|
691
|
-
|
|
755
|
+
await setWorkspaceFocus(flowDir, { runId, productSlug: slug, reason: "sprint-plan-committed" });
|
|
692
756
|
fireAutoReport("sprint-plan-committed", { runId, flowDir, productSlug: slug, sprintCount });
|
|
693
757
|
}
|
|
694
758
|
catch {
|
|
@@ -880,7 +944,7 @@ async function* drainSprints(args) {
|
|
|
880
944
|
const { productSlug: deriveSlug } = await import("./product-identity.js");
|
|
881
945
|
const slug = deriveSlug(productSpec.idea);
|
|
882
946
|
fireAutoReport("sprint-halt", { runId: ctx.runId, flowDir: ctx.flowDir, productSlug: slug, haltReason });
|
|
883
|
-
|
|
947
|
+
clearWorkspaceFocus();
|
|
884
948
|
}
|
|
885
949
|
catch {
|
|
886
950
|
/* best-effort */
|
|
@@ -934,7 +998,7 @@ async function* drainSprints(args) {
|
|
|
934
998
|
const { productSlug: deriveSlug } = await import("./product-identity.js");
|
|
935
999
|
const slug = deriveSlug(productSpec.idea);
|
|
936
1000
|
fireAutoReport("sprint-halt", { runId: ctx.runId, flowDir: ctx.flowDir, productSlug: slug, haltReason: msg });
|
|
937
|
-
|
|
1001
|
+
clearWorkspaceFocus();
|
|
938
1002
|
}
|
|
939
1003
|
catch {
|
|
940
1004
|
/* best-effort */
|
|
@@ -1028,7 +1092,7 @@ async function* drainSprints(args) {
|
|
|
1028
1092
|
}
|
|
1029
1093
|
}
|
|
1030
1094
|
// B1: clear active-run on successful ship.
|
|
1031
|
-
|
|
1095
|
+
clearWorkspaceFocus();
|
|
1032
1096
|
return {
|
|
1033
1097
|
runId: ctx.runId,
|
|
1034
1098
|
stage: "approved",
|
|
@@ -1052,7 +1116,7 @@ async function* drainSprints(args) {
|
|
|
1052
1116
|
content: `\n> Reached max-sprints (${flags.maxSprints}) without satisfying Definition-of-Done.\n`,
|
|
1053
1117
|
};
|
|
1054
1118
|
// B1: clear active-run when max-sprints reached.
|
|
1055
|
-
|
|
1119
|
+
clearWorkspaceFocus();
|
|
1056
1120
|
return {
|
|
1057
1121
|
runId: ctx.runId,
|
|
1058
1122
|
stage: "halted",
|
|
@@ -1140,6 +1204,12 @@ async function* runPhasesPath(args) {
|
|
|
1140
1204
|
currentPhaseId = sc.phaseId ?? null;
|
|
1141
1205
|
sprintHistory = [];
|
|
1142
1206
|
}
|
|
1207
|
+
// Carry the previous sprint's failure focus (unmet criteria / verify failures
|
|
1208
|
+
// / residual plan deviations) into this sprint so each iteration continues the
|
|
1209
|
+
// specific risky parts instead of restarting blind — parity with the legacy
|
|
1210
|
+
// drainSprints path. Without this the phase-orchestrated loop dropped the
|
|
1211
|
+
// feedback-routing focus between sprints.
|
|
1212
|
+
const prevSprint = sprintHistory[sprintHistory.length - 1];
|
|
1143
1213
|
const inner = runSprint({
|
|
1144
1214
|
sprintN: sc.sprintN,
|
|
1145
1215
|
ctx,
|
|
@@ -1147,6 +1217,7 @@ async function* runPhasesPath(args) {
|
|
|
1147
1217
|
roleAssignments,
|
|
1148
1218
|
history: [...sprintHistory],
|
|
1149
1219
|
phaseScope: sc.phaseScope,
|
|
1220
|
+
carryOver: prevSprint?.nextFocus ? { focus: prevSprint.nextFocus } : undefined,
|
|
1150
1221
|
});
|
|
1151
1222
|
let result;
|
|
1152
1223
|
while (true) {
|
|
@@ -1247,6 +1318,8 @@ async function* runPhasesPath(args) {
|
|
|
1247
1318
|
remainingUsd: async () => Math.max(0, manifest.capUsd - (await getProductSpentUsd(ctx.runId))),
|
|
1248
1319
|
awaitCustomerVerdict,
|
|
1249
1320
|
sprintRunner,
|
|
1321
|
+
projectCwd: ctx.cwd,
|
|
1322
|
+
idea: ctx.idea,
|
|
1250
1323
|
});
|
|
1251
1324
|
let phaseOutcome = { pass: false };
|
|
1252
1325
|
while (true) {
|
|
@@ -1384,12 +1457,27 @@ async function* runStatus(opts) {
|
|
|
1384
1457
|
return { runId: opts.runId, stage: "error", success: false, reason: "not_found" };
|
|
1385
1458
|
}
|
|
1386
1459
|
const iters = await readIterations(opts.flowDir, opts.runId);
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1460
|
+
const digest = await readResumeDigest(opts.flowDir, opts.runId);
|
|
1461
|
+
const outcomes = await readSprintOutcomes(opts.flowDir, opts.runId).catch(() => []);
|
|
1462
|
+
const lines = [
|
|
1463
|
+
`Run ${opts.runId}: ${m.idea}`,
|
|
1464
|
+
`Cap: $${m.capUsd} MaxSprints: ${m.maxSprints} DoneThreshold: ${m.doneThreshold}`,
|
|
1465
|
+
`Iterations: ${iters.length} Aborted: ${m.aborted ?? false} DoneAt: ${m.doneAt?.toISOString() ?? "—"}`,
|
|
1466
|
+
];
|
|
1467
|
+
if (digest) {
|
|
1468
|
+
lines.push("", "Resume Digest:", ` Stage: ${digest.stage}` +
|
|
1469
|
+
(typeof digest.sprintN === "number" ? ` Sprint: ${digest.sprintN}` : "") +
|
|
1470
|
+
(typeof digest.score === "number" ? ` Score: ${digest.score.toFixed(2)}` : "") +
|
|
1471
|
+
(digest.verify ? ` Verify: ${digest.verify}` : ""), ` Next: ${digest.nextAction || "—"}`);
|
|
1472
|
+
}
|
|
1473
|
+
if (outcomes.length > 0) {
|
|
1474
|
+
lines.push("", "Sprints:");
|
|
1475
|
+
for (const o of outcomes) {
|
|
1476
|
+
lines.push(` #${o.sprintN} ${o.pass ? "✓ pass" : "✗ fail"} score=${o.score.toFixed(2)} verify=${o.verify}` +
|
|
1477
|
+
(o.failedCondition ? ` (${o.failedCondition})` : ""));
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
yield { type: "content", content: `${lines.join("\n")}\n` };
|
|
1393
1481
|
return { runId: opts.runId, stage: "approved", success: true };
|
|
1394
1482
|
}
|
|
1395
1483
|
const lines = [`Active runs (${entries.length}):`];
|
|
@@ -1398,26 +1486,108 @@ async function* runStatus(opts) {
|
|
|
1398
1486
|
const iters = await readIterations(opts.flowDir, id).catch(() => []);
|
|
1399
1487
|
if (!m)
|
|
1400
1488
|
continue;
|
|
1401
|
-
|
|
1489
|
+
const digest = await readResumeDigest(opts.flowDir, id).catch(() => null);
|
|
1490
|
+
const stagePart = digest ? ` stage=${digest.stage}` : "";
|
|
1491
|
+
lines.push(` ${id} ${m.idea.slice(0, 60)} sprints=${iters.length}${stagePart} aborted=${m.aborted ?? false}`);
|
|
1402
1492
|
}
|
|
1403
1493
|
yield { type: "content", content: `${lines.join("\n")}\n` };
|
|
1404
1494
|
return { runId: "", stage: "approved", success: true };
|
|
1405
1495
|
}
|
|
1496
|
+
/**
|
|
1497
|
+
* Read + parse the structured Resume Digest from a run's top-level state.md.
|
|
1498
|
+
* Returns null when the run has no digest yet (or only a legacy one-liner).
|
|
1499
|
+
*/
|
|
1500
|
+
async function readResumeDigest(flowDir, runId) {
|
|
1501
|
+
const run = await loadRun(flowDir, runId).catch(() => null);
|
|
1502
|
+
if (!run)
|
|
1503
|
+
return null;
|
|
1504
|
+
return parseResumeDigest(run.state.sections.get("Resume Digest"));
|
|
1505
|
+
}
|
|
1506
|
+
/**
|
|
1507
|
+
* `/ideal review [runId]` — render a run's composed transcript plus a scored
|
|
1508
|
+
* sprint table. Read-only. With no runId, reviews the most recent run (any
|
|
1509
|
+
* status — review is a post-hoc lens, not restricted to incomplete runs).
|
|
1510
|
+
*/
|
|
1511
|
+
async function* runReview(opts) {
|
|
1512
|
+
let resolvedRunId = opts.runId;
|
|
1513
|
+
if (!resolvedRunId) {
|
|
1514
|
+
const runsRoot = path.join(opts.flowDir, "runs");
|
|
1515
|
+
let entries = [];
|
|
1516
|
+
try {
|
|
1517
|
+
entries = await fs.readdir(runsRoot);
|
|
1518
|
+
}
|
|
1519
|
+
catch {
|
|
1520
|
+
yield { type: "content", content: "No runs to review.\n" };
|
|
1521
|
+
return { runId: "", stage: "error", success: false, reason: "no_runs" };
|
|
1522
|
+
}
|
|
1523
|
+
const dated = [];
|
|
1524
|
+
for (const id of entries) {
|
|
1525
|
+
const m = await readManifest(opts.flowDir, id).catch(() => null);
|
|
1526
|
+
if (!m)
|
|
1527
|
+
continue;
|
|
1528
|
+
const createdAt = m.createdAt instanceof Date && !Number.isNaN(m.createdAt.getTime()) ? m.createdAt.getTime() : 0;
|
|
1529
|
+
dated.push({ id, createdAt });
|
|
1530
|
+
}
|
|
1531
|
+
if (dated.length === 0) {
|
|
1532
|
+
yield { type: "content", content: "No runs to review.\n" };
|
|
1533
|
+
return { runId: "", stage: "error", success: false, reason: "no_runs" };
|
|
1534
|
+
}
|
|
1535
|
+
dated.sort((a, b) => b.createdAt - a.createdAt);
|
|
1536
|
+
resolvedRunId = dated[0].id;
|
|
1537
|
+
}
|
|
1538
|
+
const manifest = await readManifest(opts.flowDir, resolvedRunId);
|
|
1539
|
+
if (!manifest) {
|
|
1540
|
+
yield { type: "content", content: `Run not found: ${resolvedRunId}\n` };
|
|
1541
|
+
return { runId: resolvedRunId, stage: "error", success: false, reason: "not_found" };
|
|
1542
|
+
}
|
|
1543
|
+
const header = [
|
|
1544
|
+
`# Review — run ${resolvedRunId}`,
|
|
1545
|
+
"",
|
|
1546
|
+
`Idea: ${manifest.idea}`,
|
|
1547
|
+
`Aborted: ${manifest.aborted ?? false} DoneAt: ${manifest.doneAt?.toISOString() ?? "—"}`,
|
|
1548
|
+
];
|
|
1549
|
+
const digest = await readResumeDigest(opts.flowDir, resolvedRunId);
|
|
1550
|
+
if (digest) {
|
|
1551
|
+
header.push(`Last stage: ${digest.stage} — ${digest.nextAction || "—"}`);
|
|
1552
|
+
}
|
|
1553
|
+
const outcomes = await readSprintOutcomes(opts.flowDir, resolvedRunId).catch(() => []);
|
|
1554
|
+
if (outcomes.length > 0) {
|
|
1555
|
+
header.push("", "## Sprint scores", "", "| Sprint | Result | Score | Verify | Failed condition |", "|---|---|---|---|---|");
|
|
1556
|
+
for (const o of outcomes) {
|
|
1557
|
+
header.push(`| ${o.sprintN} | ${o.pass ? "pass" : "fail"} | ${o.score.toFixed(2)} | ${o.verify} | ${o.failedCondition ?? "—"} |`);
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
yield { type: "content", content: `${header.join("\n")}\n` };
|
|
1561
|
+
// The composed transcript (manifest/roadmap/delegations/gray-areas) rounds out
|
|
1562
|
+
// the review with the actual debate + spec text. Bounded to 32KB by the composer.
|
|
1563
|
+
const transcript = await composeRunTranscript(opts.flowDir, resolvedRunId).catch(() => "");
|
|
1564
|
+
if (transcript.trim()) {
|
|
1565
|
+
yield { type: "content", content: `\n## Transcript\n${transcript}\n` };
|
|
1566
|
+
}
|
|
1567
|
+
return { runId: resolvedRunId, stage: "approved", success: true };
|
|
1568
|
+
}
|
|
1406
1569
|
async function* runAbort(opts) {
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1570
|
+
// A/B — bare `/ideal abort` (no runId, e.g. the recovery card's Abort option):
|
|
1571
|
+
// auto-detect the newest incomplete run, mirroring resume.
|
|
1572
|
+
let resolvedRunId = opts.runId;
|
|
1573
|
+
if (!resolvedRunId) {
|
|
1574
|
+
const latest = await findLatestIncompleteRun(opts.flowDir);
|
|
1575
|
+
if (!latest) {
|
|
1576
|
+
yield { type: "content", content: "No incomplete run to abort.\n" };
|
|
1577
|
+
return { runId: "", stage: "error", success: false, reason: "no_incomplete_run" };
|
|
1578
|
+
}
|
|
1579
|
+
resolvedRunId = latest.id;
|
|
1410
1580
|
}
|
|
1411
|
-
const m = await readManifest(opts.flowDir,
|
|
1581
|
+
const m = await readManifest(opts.flowDir, resolvedRunId);
|
|
1412
1582
|
if (!m) {
|
|
1413
|
-
yield { type: "content", content: `Run not found: ${
|
|
1414
|
-
return { runId:
|
|
1583
|
+
yield { type: "content", content: `Run not found: ${resolvedRunId}\n` };
|
|
1584
|
+
return { runId: resolvedRunId, stage: "error", success: false, reason: "not_found" };
|
|
1415
1585
|
}
|
|
1416
|
-
await writeManifest(opts.flowDir,
|
|
1586
|
+
await writeManifest(opts.flowDir, resolvedRunId, { ...m, aborted: true, doneAt: new Date() });
|
|
1417
1587
|
// Fire-and-forget EE phase-outcome=aborted (extension landed in 13-05).
|
|
1418
1588
|
try {
|
|
1419
1589
|
fireAndForgetPhaseOutcome({
|
|
1420
|
-
sessionId:
|
|
1590
|
+
sessionId: resolvedRunId,
|
|
1421
1591
|
phaseName: "product-loop",
|
|
1422
1592
|
outcome: "aborted",
|
|
1423
1593
|
});
|
|
@@ -1431,9 +1601,9 @@ async function* runAbort(opts) {
|
|
|
1431
1601
|
// EE client is non-fatal (offline queue absorbs transport failures).
|
|
1432
1602
|
// P1.6: log telemetry for the extract outcome.
|
|
1433
1603
|
{
|
|
1434
|
-
const eeResult = await extractRunToEE(opts.flowDir,
|
|
1604
|
+
const eeResult = await extractRunToEE(opts.flowDir, resolvedRunId, opts.cwd ?? process.cwd());
|
|
1435
1605
|
try {
|
|
1436
|
-
logInteraction(opts.sessionId ??
|
|
1606
|
+
logInteraction(opts.sessionId ?? resolvedRunId ?? "abort", "ee_injection", {
|
|
1437
1607
|
eventSubtype: "extract",
|
|
1438
1608
|
durationMs: Math.round(eeResult.durationMs),
|
|
1439
1609
|
data: {
|
|
@@ -1447,39 +1617,106 @@ async function* runAbort(opts) {
|
|
|
1447
1617
|
// DB errors must not break /ideal
|
|
1448
1618
|
}
|
|
1449
1619
|
}
|
|
1450
|
-
yield { type: "content", content: `Aborted run ${
|
|
1451
|
-
return { runId:
|
|
1620
|
+
yield { type: "content", content: `Aborted run ${resolvedRunId}.\n` };
|
|
1621
|
+
return { runId: resolvedRunId, stage: "halted", success: false, reason: "aborted" };
|
|
1622
|
+
}
|
|
1623
|
+
/**
|
|
1624
|
+
* B — Auto-detect the newest resumable run.
|
|
1625
|
+
*
|
|
1626
|
+
* "Resumable" = a run that has a manifest (early pre-manifest crashes are not
|
|
1627
|
+
* replayable) AND is neither aborted nor terminal (`doneAt` is set on done-gate
|
|
1628
|
+
* pass / ship / abort). Sorted by manifest `createdAt` descending so a bare
|
|
1629
|
+
* `/ideal resume` continues the most recent incomplete run without the user
|
|
1630
|
+
* having to remember (or type) the runId.
|
|
1631
|
+
*/
|
|
1632
|
+
async function findLatestIncompleteRun(flowDir) {
|
|
1633
|
+
const runsRoot = path.join(flowDir, "runs");
|
|
1634
|
+
let entries;
|
|
1635
|
+
try {
|
|
1636
|
+
entries = await fs.readdir(runsRoot);
|
|
1637
|
+
}
|
|
1638
|
+
catch (err) {
|
|
1639
|
+
// No runs directory yet → nothing to resume. Not an error worth surfacing.
|
|
1640
|
+
if (err?.code !== "ENOENT") {
|
|
1641
|
+
console.error(`[product-loop] findLatestIncompleteRun: readdir failed: ${err?.message}`);
|
|
1642
|
+
}
|
|
1643
|
+
return null;
|
|
1644
|
+
}
|
|
1645
|
+
const candidates = [];
|
|
1646
|
+
for (const id of entries) {
|
|
1647
|
+
const m = await readManifest(flowDir, id).catch((e) => {
|
|
1648
|
+
console.error(`[product-loop] findLatestIncompleteRun: manifest read failed for ${id}: ${e?.message}`);
|
|
1649
|
+
return null;
|
|
1650
|
+
});
|
|
1651
|
+
if (!m)
|
|
1652
|
+
continue; // no manifest → not resumable
|
|
1653
|
+
if (m.aborted)
|
|
1654
|
+
continue; // hard-killed
|
|
1655
|
+
if (m.doneAt)
|
|
1656
|
+
continue; // terminal (done / shipped)
|
|
1657
|
+
const createdAt = m.createdAt instanceof Date && !Number.isNaN(m.createdAt.getTime()) ? m.createdAt.getTime() : 0;
|
|
1658
|
+
candidates.push({ id, idea: m.idea, createdAt });
|
|
1659
|
+
}
|
|
1660
|
+
if (candidates.length === 0)
|
|
1661
|
+
return null;
|
|
1662
|
+
candidates.sort((a, b) => b.createdAt - a.createdAt);
|
|
1663
|
+
const top = candidates[0];
|
|
1664
|
+
return { id: top.id, idea: top.idea };
|
|
1452
1665
|
}
|
|
1453
1666
|
async function* runResume(opts) {
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1667
|
+
// B — bare `/ideal resume` (no runId): auto-detect the newest incomplete run.
|
|
1668
|
+
let resolvedRunId = opts.runId;
|
|
1669
|
+
if (!resolvedRunId) {
|
|
1670
|
+
const latest = await findLatestIncompleteRun(opts.flowDir);
|
|
1671
|
+
if (!latest) {
|
|
1672
|
+
yield {
|
|
1673
|
+
type: "content",
|
|
1674
|
+
content: 'No incomplete run to resume. Start one with /ideal "<idea>".\n',
|
|
1675
|
+
};
|
|
1676
|
+
return { runId: "", stage: "error", success: false, reason: "no_incomplete_run" };
|
|
1677
|
+
}
|
|
1678
|
+
resolvedRunId = latest.id;
|
|
1679
|
+
yield {
|
|
1680
|
+
type: "content",
|
|
1681
|
+
content: `Resuming latest incomplete run ${resolvedRunId}: ${latest.idea.slice(0, 60)}\n`,
|
|
1682
|
+
};
|
|
1457
1683
|
}
|
|
1458
|
-
const run = await loadRun(opts.flowDir,
|
|
1684
|
+
const run = await loadRun(opts.flowDir, resolvedRunId);
|
|
1459
1685
|
if (!run) {
|
|
1460
|
-
yield { type: "content", content: `Run not found: ${
|
|
1461
|
-
return { runId:
|
|
1686
|
+
yield { type: "content", content: `Run not found: ${resolvedRunId}\n` };
|
|
1687
|
+
return { runId: resolvedRunId, stage: "error", success: false, reason: "not_found" };
|
|
1462
1688
|
}
|
|
1463
|
-
const manifest = await readManifest(opts.flowDir,
|
|
1689
|
+
const manifest = await readManifest(opts.flowDir, resolvedRunId);
|
|
1464
1690
|
if (!manifest) {
|
|
1465
|
-
yield { type: "content", content: `Manifest missing for ${
|
|
1466
|
-
return { runId:
|
|
1691
|
+
yield { type: "content", content: `Manifest missing for ${resolvedRunId}\n` };
|
|
1692
|
+
return { runId: resolvedRunId, stage: "error", success: false, reason: "manifest_missing" };
|
|
1467
1693
|
}
|
|
1468
1694
|
if (manifest.aborted) {
|
|
1469
|
-
yield { type: "content", content: `Run ${
|
|
1470
|
-
return { runId:
|
|
1695
|
+
yield { type: "content", content: `Run ${resolvedRunId} was aborted; cannot resume.\n` };
|
|
1696
|
+
return { runId: resolvedRunId, stage: "halted", success: false, reason: "aborted" };
|
|
1697
|
+
}
|
|
1698
|
+
// Surface the Resume Digest so the user sees where the run stopped and what
|
|
1699
|
+
// resuming will do — the whole point of giving the digest real content.
|
|
1700
|
+
{
|
|
1701
|
+
const digest = parseResumeDigest(run.state.sections.get("Resume Digest"));
|
|
1702
|
+
if (digest) {
|
|
1703
|
+
yield {
|
|
1704
|
+
type: "content",
|
|
1705
|
+
content: `> Resume Digest — stage: ${digest.stage}${typeof digest.sprintN === "number" ? ` (sprint ${digest.sprintN})` : ""} · next: ${digest.nextAction || "—"}\n`,
|
|
1706
|
+
};
|
|
1707
|
+
}
|
|
1471
1708
|
}
|
|
1472
1709
|
// Detect crashed in-flight sprint: an iterations.md entry without a closing
|
|
1473
1710
|
// Verify line is treated as crashed. Our schema always writes the Verify line
|
|
1474
1711
|
// before returning, so an iteration is "in-flight" iff the file has a Sprint
|
|
1475
1712
|
// heading but no matching Verify field. readIterations skips malformed
|
|
1476
1713
|
// entries — so we mark the highest sprint number as crashed regardless.
|
|
1477
|
-
const iters = await readIterations(opts.flowDir,
|
|
1714
|
+
const iters = await readIterations(opts.flowDir, resolvedRunId);
|
|
1478
1715
|
let nextSprint = iters.length + 1;
|
|
1479
1716
|
if (iters.length > 0) {
|
|
1480
1717
|
const last = iters[iters.length - 1];
|
|
1481
1718
|
if (!last.lastVerifyResult || last.lastVerifyResult === "UNKNOWN") {
|
|
1482
|
-
await markIterationCrashed(opts.flowDir,
|
|
1719
|
+
await markIterationCrashed(opts.flowDir, resolvedRunId, last.sprintN);
|
|
1483
1720
|
nextSprint = last.sprintN; // retry with retryOf metadata
|
|
1484
1721
|
yield {
|
|
1485
1722
|
type: "content",
|
|
@@ -1490,7 +1727,7 @@ async function* runResume(opts) {
|
|
|
1490
1727
|
// Fire EE phase-outcome=resumed (extension landed in 13-05).
|
|
1491
1728
|
try {
|
|
1492
1729
|
fireAndForgetPhaseOutcome({
|
|
1493
|
-
sessionId:
|
|
1730
|
+
sessionId: resolvedRunId,
|
|
1494
1731
|
phaseName: `sprint-${Math.max(1, nextSprint - 1)}`,
|
|
1495
1732
|
outcome: "resumed",
|
|
1496
1733
|
});
|
|
@@ -1499,9 +1736,8 @@ async function* runResume(opts) {
|
|
|
1499
1736
|
/* non-fatal */
|
|
1500
1737
|
}
|
|
1501
1738
|
// Resume into sprint loop with reconstructed history + manifest flags.
|
|
1502
|
-
const productSpec = await loadProductSpec(opts.flowDir, opts.runId, manifest.idea, manifest.stack);
|
|
1503
1739
|
const ctx = {
|
|
1504
|
-
runId:
|
|
1740
|
+
runId: resolvedRunId,
|
|
1505
1741
|
flowDir: opts.flowDir,
|
|
1506
1742
|
idea: manifest.idea,
|
|
1507
1743
|
sessionModelId: opts.sessionModelId,
|
|
@@ -1512,8 +1748,60 @@ async function* runResume(opts) {
|
|
|
1512
1748
|
cwd: opts.cwd,
|
|
1513
1749
|
sessionId: opts.sessionId,
|
|
1514
1750
|
processMessageFn: opts.processMessageFn,
|
|
1751
|
+
runIsolatedTask: opts.runIsolatedTask,
|
|
1515
1752
|
detectVerifyRecipe: opts.detectVerifyRecipe,
|
|
1516
1753
|
};
|
|
1754
|
+
// C-v2 cross-session debate resume — a persisted debate checkpoint means the
|
|
1755
|
+
// council debate was interrupted before it ever produced a spec, so the run
|
|
1756
|
+
// cannot go straight to sprints (loadProductSpec would return an empty stub).
|
|
1757
|
+
// Re-run the council FSM: loop-driver's resume entry skips discovery + the
|
|
1758
|
+
// interview and restores the debate from its checkpoint, then scoping writes
|
|
1759
|
+
// the spec. This mirrors runStart's phase-1 → phase-2 handoff.
|
|
1760
|
+
const runDir = path.join(opts.flowDir, "runs", resolvedRunId);
|
|
1761
|
+
const interruptedDebate = await readDebateCheckpoint(runDir);
|
|
1762
|
+
if (interruptedDebate) {
|
|
1763
|
+
yield {
|
|
1764
|
+
type: "content",
|
|
1765
|
+
content: `\n> Detected an interrupted council debate (round ${interruptedDebate.roundCount + 1}); resuming it before sprints.\n`,
|
|
1766
|
+
};
|
|
1767
|
+
const driverGen = runLoopDriver(ctx);
|
|
1768
|
+
let driverResult;
|
|
1769
|
+
try {
|
|
1770
|
+
while (true) {
|
|
1771
|
+
const { value, done } = await driverGen.next();
|
|
1772
|
+
if (done) {
|
|
1773
|
+
driverResult = value;
|
|
1774
|
+
break;
|
|
1775
|
+
}
|
|
1776
|
+
yield value;
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
catch (err) {
|
|
1780
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1781
|
+
yield { type: "error", error: true, content: msg };
|
|
1782
|
+
return { runId: resolvedRunId, stage: "error", success: false, reason: msg };
|
|
1783
|
+
}
|
|
1784
|
+
if (!driverResult?.success || driverResult.stage !== "approved") {
|
|
1785
|
+
return { ...driverResult, runId: resolvedRunId };
|
|
1786
|
+
}
|
|
1787
|
+
// Build the sprint plan now that the spec exists (idempotent — skips when
|
|
1788
|
+
// backlog.json / sprint-plan.json already exist).
|
|
1789
|
+
const resumedSpec = await loadProductSpec(opts.flowDir, resolvedRunId, manifest.idea, manifest.stack);
|
|
1790
|
+
const { sprintCount } = await buildBacklogAndSprintPlan({
|
|
1791
|
+
flowDir: opts.flowDir,
|
|
1792
|
+
runId: resolvedRunId,
|
|
1793
|
+
productSpec: resumedSpec,
|
|
1794
|
+
ctx,
|
|
1795
|
+
sessionModelId: opts.sessionModelId,
|
|
1796
|
+
maxSprints: opts.flags.maxSprints,
|
|
1797
|
+
onChunk: (chunk) => void chunk,
|
|
1798
|
+
});
|
|
1799
|
+
yield {
|
|
1800
|
+
type: "content",
|
|
1801
|
+
content: `\n> Committed: ${sprintCount} sprint${sprintCount === 1 ? "" : "s"} planned. Sprint 1 active.\n`,
|
|
1802
|
+
};
|
|
1803
|
+
}
|
|
1804
|
+
const productSpec = await loadProductSpec(opts.flowDir, resolvedRunId, manifest.idea, manifest.stack);
|
|
1517
1805
|
const roleAssignments = opts.roleAssignments ?? (await resolveRoleAssignments(opts.sessionModelId));
|
|
1518
1806
|
// Subsystem E: phase-orchestrated path (default ON; set MUONROI_PHASE_MODE=0 for legacy).
|
|
1519
1807
|
if (process.env.MUONROI_PHASE_MODE !== "0") {
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import type { StreamChunk } from "../types/index.js";
|
|
2
2
|
import type { DriverContext, DriverResult, Stage } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Clamp a title for the milestone/phase index (F12): truncate at a word
|
|
5
|
+
* boundary when possible and strip trailing punctuation/whitespace so a raw
|
|
6
|
+
* slice can't leave a dangling "(" or a half word. Falls back to a hard slice
|
|
7
|
+
* for a single long token.
|
|
8
|
+
*/
|
|
9
|
+
export declare function clampTitle(raw: string, max: number): string;
|
|
3
10
|
export declare function runLoopDriver(ctx: DriverContext): AsyncGenerator<StreamChunk, DriverResult, unknown>;
|
|
4
11
|
export type { DriverContext, DriverResult, Stage };
|