muonroi-cli 1.8.3 → 1.8.5
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 +21 -21
- package/README.md +133 -122
- 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-tee.d.ts +48 -0
- package/dist/packages/agent-harness-core/src/event-tee.js +77 -0
- package/dist/packages/agent-harness-core/src/mcp-server.d.ts +11 -0
- package/dist/packages/agent-harness-core/src/mcp-server.js +87 -15
- package/dist/packages/agent-harness-core/src/protocol.d.ts +66 -2
- 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 +28 -0
- package/dist/src/agent-harness/mock-model.js +63 -1
- package/dist/src/agent-harness/test-spawn.js +31 -0
- 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 +30 -15
- 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 +2 -2
- package/dist/src/cli/keys.js +19 -81
- package/dist/src/council/clarifier.d.ts +28 -2
- package/dist/src/council/clarifier.js +81 -15
- 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 +51 -3
- 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 +1210 -134
- package/dist/src/council/index.d.ts +85 -1
- package/dist/src/council/index.js +634 -196
- package/dist/src/council/leader.d.ts +26 -0
- package/dist/src/council/leader.js +150 -9
- package/dist/src/council/llm.d.ts +32 -0
- package/dist/src/council/llm.js +231 -38
- package/dist/src/council/panel-select.d.ts +30 -0
- package/dist/src/council/panel-select.js +72 -0
- package/dist/src/council/planner.js +23 -0
- package/dist/src/council/preflight.d.ts +7 -0
- package/dist/src/council/preflight.js +14 -2
- package/dist/src/council/prompts.d.ts +30 -3
- package/dist/src/council/prompts.js +254 -84
- 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 +128 -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 +1 -0
- package/dist/src/ee/auth.js +15 -2
- package/dist/src/ee/bridge.d.ts +10 -0
- package/dist/src/ee/bridge.js +58 -0
- package/dist/src/ee/client.js +81 -18
- 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 +45 -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 +13 -1
- package/dist/src/flow/compaction/index.js +70 -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/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 +55 -0
- package/dist/src/gsd/flags.js +83 -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 +251 -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/hooks/index.js +1 -1
- package/dist/src/index.js +44 -11
- 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 +1 -1
- package/dist/src/mcp/ee-tools.js +1 -0
- package/dist/src/mcp/oauth-callback.js +2 -2
- 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 +77 -76
- 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 +8 -8
- 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 +10 -0
- package/dist/src/orchestrator/compaction.js +27 -7
- package/dist/src/orchestrator/council-manager.d.ts +12 -3
- package/dist/src/orchestrator/council-manager.js +65 -24
- 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/message-processor.js +242 -33
- package/dist/src/orchestrator/orchestrator.d.ts +39 -3
- package/dist/src/orchestrator/orchestrator.js +651 -102
- package/dist/src/orchestrator/preprocessor.js +1 -1
- 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 +159 -159
- 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-intercept.d.ts +45 -0
- package/dist/src/orchestrator/safety-intercept.js +55 -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 +24 -3
- package/dist/src/orchestrator/stall-watchdog.js +47 -13
- package/dist/src/orchestrator/stream-runner.js +62 -29
- 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 +26 -0
- package/dist/src/orchestrator/tool-engine.js +669 -56
- 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 +37 -0
- package/dist/src/orchestrator/turn-watchdog.js +55 -0
- package/dist/src/pil/agent-operating-contract.d.ts +1 -1
- package/dist/src/pil/agent-operating-contract.js +1 -1
- 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.js +16 -11
- 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/layer2_5-ponytail.js +8 -8
- 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 +33 -2
- package/dist/src/pil/llm-classify.js +123 -131
- package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
- package/dist/src/pil/native-capabilities-workbook.js +1 -0
- package/dist/src/pil/pipeline.js +34 -2
- 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/backlog-builder.d.ts +14 -1
- package/dist/src/product-loop/backlog-builder.js +30 -6
- 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.js +32 -3
- package/dist/src/product-loop/discovery-schema.js +5 -1
- package/dist/src/product-loop/done-gate.js +3 -3
- 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 +333 -52
- package/dist/src/product-loop/loop-driver.d.ts +7 -0
- package/dist/src/product-loop/loop-driver.js +327 -116
- package/dist/src/product-loop/phase-plan.d.ts +5 -0
- package/dist/src/product-loop/phase-plan.js +39 -2
- package/dist/src/product-loop/phase-runner.js +9 -1
- package/dist/src/product-loop/progress-snapshot.js +4 -4
- package/dist/src/product-loop/sprint-runner.d.ts +111 -0
- package/dist/src/product-loop/sprint-runner.js +559 -16
- package/dist/src/product-loop/types.d.ts +36 -5
- package/dist/src/providers/adapter.d.ts +1 -1
- package/dist/src/providers/adapter.js +3 -4
- 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/openai-oauth.js +1 -1
- package/dist/src/providers/auth/registry.js +0 -34
- package/dist/src/providers/auth/token-store.js +4 -1
- package/dist/src/providers/auth/types.d.ts +1 -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/keychain.d.ts +1 -1
- package/dist/src/providers/keychain.js +7 -9
- package/dist/src/providers/mcp-vision-bridge.js +82 -172
- 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 +27 -2
- package/dist/src/providers/runtime.js +78 -15
- 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 +280 -1
- 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/wire-debug.js +95 -0
- package/dist/src/reporter/index.js +1 -1
- 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/bb-ecosystem-apply.js +47 -47
- package/dist/src/scaffold/bb-quality-gate.js +5 -5
- package/dist/src/scaffold/continuation-prompt.d.ts +11 -0
- package/dist/src/scaffold/continuation-prompt.js +86 -60
- package/dist/src/scaffold/init-new.js +453 -453
- 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 +22 -22
- 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/interaction-log.js +5 -5
- package/dist/src/storage/migrations.js +196 -126
- package/dist/src/storage/session-experience-store.js +4 -4
- package/dist/src/storage/sessions.d.ts +28 -10
- package/dist/src/storage/sessions.js +112 -55
- package/dist/src/storage/transcript-view.js +1 -1
- package/dist/src/storage/transcript.d.ts +51 -0
- package/dist/src/storage/transcript.js +383 -112
- package/dist/src/storage/usage.js +14 -14
- package/dist/src/storage/workspaces.js +12 -12
- package/dist/src/tools/file.d.ts +15 -0
- package/dist/src/tools/file.js +32 -0
- package/dist/src/tools/native-tools.js +5 -0
- package/dist/src/tools/registry.d.ts +3 -0
- package/dist/src/tools/registry.js +460 -22
- package/dist/src/tools/research.d.ts +29 -0
- package/dist/src/tools/research.js +233 -0
- package/dist/src/types/index.d.ts +118 -3
- package/dist/src/ui/app.js +0 -0
- package/dist/src/ui/cards/product-status-card.js +1 -1
- 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/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 +49 -15
- 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 +12 -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/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/containers/modals-layer.d.ts +2 -1
- 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/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-inspect.js +4 -4
- 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/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 +12 -18
- 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/format.d.ts +14 -0
- package/dist/src/ui/utils/format.js +23 -3
- package/dist/src/usage/downgrade.js +2 -2
- package/dist/src/usage/product-ledger.js +2 -2
- package/dist/src/utils/clipboard-image.js +23 -23
- package/dist/src/utils/install-manager.js +14 -11
- package/dist/src/utils/logger.js +2 -2
- package/dist/src/utils/permission-mode.js +5 -3
- package/dist/src/utils/redactor.js +1 -1
- package/dist/src/utils/settings.d.ts +153 -5
- package/dist/src/utils/settings.js +233 -29
- package/dist/src/utils/side-question.js +2 -2
- package/dist/src/utils/skills.js +3 -3
- 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 +1 -1
- package/dist/src/verify/recipes.d.ts +13 -0
- package/dist/src/verify/recipes.js +15 -0
- package/package.json +135 -132
- 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
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Milestone → Phase → Run hierarchy for the Product Ideal Loop.
|
|
3
|
+
*
|
|
4
|
+
* Sprint-2 Part A (full plan, item 2 of the deferred list). Built as an ADDITIVE
|
|
5
|
+
* INDEX LAYER on top of `runs/<runId>/` (per REV-3 Kill B / REV-2 Kill #7): it
|
|
6
|
+
* groups runs under phases under milestones for navigation and cross-run memory,
|
|
7
|
+
* but does NOT reroute the numeric ROADMAP phases that phase-sync depends on. A
|
|
8
|
+
* phase here simply *references* the run IDs executed under it; the run
|
|
9
|
+
* artifacts remain the source of truth for sprint/verify state.
|
|
10
|
+
*
|
|
11
|
+
* .muonroi-flow/milestones/<mid>/milestone.json ← canonical record (read)
|
|
12
|
+
* .muonroi-flow/milestones/<mid>/milestone.md ← human-reviewable render
|
|
13
|
+
* .muonroi-flow/milestones/<mid>/phases/<pid>/phase.json
|
|
14
|
+
* .muonroi-flow/milestones/<mid>/phases/<pid>/phase.md
|
|
15
|
+
*
|
|
16
|
+
* The active milestone/phase pointers live in the top-level `state.md`
|
|
17
|
+
* ("Active Milestone" / "Active Phase" sections), alongside "Active Run".
|
|
18
|
+
*
|
|
19
|
+
* Records are JSON for reliable machine reads; the paired `.md` is a rendered
|
|
20
|
+
* summary only (never parsed back). Writes are atomic. Reads are tolerant: a
|
|
21
|
+
* missing/corrupt record returns null, never throws.
|
|
22
|
+
*/
|
|
23
|
+
import { promises as fs } from "node:fs";
|
|
24
|
+
import * as path from "node:path";
|
|
25
|
+
import { atomicWriteJSON, atomicWriteText } from "../storage/atomic-io.js";
|
|
26
|
+
import { readArtifact, writeArtifact } from "./artifact-io.js";
|
|
27
|
+
import { getActiveRunId, setActiveRunId } from "./run-manager.js";
|
|
28
|
+
// ─── Paths ──────────────────────────────────────────────────────────────────
|
|
29
|
+
export const MILESTONES_DIR = "milestones";
|
|
30
|
+
function milestonesRoot(flowDir) {
|
|
31
|
+
return path.join(flowDir, MILESTONES_DIR);
|
|
32
|
+
}
|
|
33
|
+
function milestoneDir(flowDir, milestoneId) {
|
|
34
|
+
return path.join(milestonesRoot(flowDir), milestoneId);
|
|
35
|
+
}
|
|
36
|
+
function phaseDir(flowDir, milestoneId, phaseId) {
|
|
37
|
+
return path.join(milestoneDir(flowDir, milestoneId), "phases", phaseId);
|
|
38
|
+
}
|
|
39
|
+
// ─── Slug generation ─────────────────────────────────────────────────────────
|
|
40
|
+
/** kebab-case a title into a slug body (no ordinal prefix). */
|
|
41
|
+
function slugBody(title) {
|
|
42
|
+
const s = title
|
|
43
|
+
.toLowerCase()
|
|
44
|
+
.normalize("NFKD")
|
|
45
|
+
.replace(/[\u0300-\u036f]/g, "")
|
|
46
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
47
|
+
.replace(/^-+|-+$/g, "")
|
|
48
|
+
.slice(0, 40)
|
|
49
|
+
.replace(/-+$/g, "");
|
|
50
|
+
return s || "untitled";
|
|
51
|
+
}
|
|
52
|
+
function pad2(n) {
|
|
53
|
+
return n < 10 ? `0${n}` : String(n);
|
|
54
|
+
}
|
|
55
|
+
/** `m01-native-state` from ordinal 1 + title. */
|
|
56
|
+
function milestoneSlug(ordinal, title) {
|
|
57
|
+
return `m${pad2(ordinal)}-${slugBody(title)}`;
|
|
58
|
+
}
|
|
59
|
+
/** `p01-scoping` from ordinal 1 + title. */
|
|
60
|
+
function phaseSlug(ordinal, title) {
|
|
61
|
+
return `p${pad2(ordinal)}-${slugBody(title)}`;
|
|
62
|
+
}
|
|
63
|
+
// ─── Rendering (human .md summaries) ─────────────────────────────────────────
|
|
64
|
+
function renderMilestoneMd(m, phases) {
|
|
65
|
+
const lines = [
|
|
66
|
+
`# Milestone: ${m.title}`,
|
|
67
|
+
"",
|
|
68
|
+
`- Id: ${m.id}`,
|
|
69
|
+
`- Status: ${m.status}`,
|
|
70
|
+
`- Goal: ${m.goal || "(none)"}`,
|
|
71
|
+
`- Created: ${m.createdAt}`,
|
|
72
|
+
`- Updated: ${m.updatedAt}`,
|
|
73
|
+
"",
|
|
74
|
+
"## Phases",
|
|
75
|
+
"",
|
|
76
|
+
];
|
|
77
|
+
if (phases.length === 0) {
|
|
78
|
+
lines.push("_(no phases yet)_");
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
for (const p of phases) {
|
|
82
|
+
const runs = p.runIds.length > 0 ? ` — runs: ${p.runIds.join(", ")}` : "";
|
|
83
|
+
lines.push(`- [${p.status === "done" ? "x" : " "}] ${p.id}: ${p.title}${runs}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return `${lines.join("\n")}\n`;
|
|
87
|
+
}
|
|
88
|
+
function renderPhaseMd(p) {
|
|
89
|
+
const lines = [
|
|
90
|
+
`# Phase: ${p.title}`,
|
|
91
|
+
"",
|
|
92
|
+
`- Id: ${p.id}`,
|
|
93
|
+
`- Milestone: ${p.milestoneId}`,
|
|
94
|
+
`- Status: ${p.status}`,
|
|
95
|
+
`- Goal: ${p.goal || "(none)"}`,
|
|
96
|
+
`- Created: ${p.createdAt}`,
|
|
97
|
+
`- Updated: ${p.updatedAt}`,
|
|
98
|
+
"",
|
|
99
|
+
"## Runs",
|
|
100
|
+
"",
|
|
101
|
+
];
|
|
102
|
+
if (p.runIds.length === 0) {
|
|
103
|
+
lines.push("_(no runs yet)_");
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
for (const r of p.runIds)
|
|
107
|
+
lines.push(`- ${r}`);
|
|
108
|
+
}
|
|
109
|
+
return `${lines.join("\n")}\n`;
|
|
110
|
+
}
|
|
111
|
+
// ─── Milestone CRUD ──────────────────────────────────────────────────────────
|
|
112
|
+
async function readMilestoneRecord(flowDir, milestoneId) {
|
|
113
|
+
try {
|
|
114
|
+
const raw = await fs.readFile(path.join(milestoneDir(flowDir, milestoneId), "milestone.json"), "utf8");
|
|
115
|
+
return JSON.parse(raw);
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
if (err.code === "ENOENT")
|
|
119
|
+
return null;
|
|
120
|
+
return null; // tolerant: corrupt record → null, never throw
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async function persistMilestone(flowDir, m) {
|
|
124
|
+
const dir = milestoneDir(flowDir, m.id);
|
|
125
|
+
await fs.mkdir(dir, { recursive: true });
|
|
126
|
+
await atomicWriteJSON(path.join(dir, "milestone.json"), m);
|
|
127
|
+
const phases = await listPhases(flowDir, m.id);
|
|
128
|
+
await atomicWriteText(path.join(dir, "milestone.md"), renderMilestoneMd(m, phases));
|
|
129
|
+
}
|
|
130
|
+
/** List all milestones, sorted by ordinal ascending. */
|
|
131
|
+
export async function listMilestones(flowDir) {
|
|
132
|
+
let ids;
|
|
133
|
+
try {
|
|
134
|
+
ids = await fs.readdir(milestonesRoot(flowDir));
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
if (err.code === "ENOENT")
|
|
138
|
+
return [];
|
|
139
|
+
throw err;
|
|
140
|
+
}
|
|
141
|
+
const out = [];
|
|
142
|
+
for (const id of ids) {
|
|
143
|
+
if (id.startsWith("."))
|
|
144
|
+
continue;
|
|
145
|
+
const m = await readMilestoneRecord(flowDir, id);
|
|
146
|
+
if (m)
|
|
147
|
+
out.push(m);
|
|
148
|
+
}
|
|
149
|
+
out.sort((a, b) => a.ordinal - b.ordinal);
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
export async function loadMilestone(flowDir, milestoneId) {
|
|
153
|
+
return readMilestoneRecord(flowDir, milestoneId);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Create a milestone. `nowIso` is injected (never Date.now here) so callers
|
|
157
|
+
* control the clock and tests stay deterministic. Ordinal is next-highest+1.
|
|
158
|
+
*/
|
|
159
|
+
export async function createMilestone(flowDir, input, nowIso) {
|
|
160
|
+
const existing = await listMilestones(flowDir);
|
|
161
|
+
const ordinal = existing.reduce((max, m) => Math.max(max, m.ordinal), 0) + 1;
|
|
162
|
+
const m = {
|
|
163
|
+
id: milestoneSlug(ordinal, input.title),
|
|
164
|
+
title: input.title,
|
|
165
|
+
goal: input.goal ?? "",
|
|
166
|
+
ordinal,
|
|
167
|
+
status: "active",
|
|
168
|
+
createdAt: nowIso,
|
|
169
|
+
updatedAt: nowIso,
|
|
170
|
+
};
|
|
171
|
+
await persistMilestone(flowDir, m);
|
|
172
|
+
return m;
|
|
173
|
+
}
|
|
174
|
+
export async function updateMilestone(flowDir, milestoneId, patch, nowIso) {
|
|
175
|
+
const m = await readMilestoneRecord(flowDir, milestoneId);
|
|
176
|
+
if (!m)
|
|
177
|
+
return null;
|
|
178
|
+
const next = { ...m, ...patch, updatedAt: nowIso };
|
|
179
|
+
await persistMilestone(flowDir, next);
|
|
180
|
+
return next;
|
|
181
|
+
}
|
|
182
|
+
// ─── Phase CRUD ──────────────────────────────────────────────────────────────
|
|
183
|
+
async function readPhaseRecord(flowDir, milestoneId, phaseId) {
|
|
184
|
+
try {
|
|
185
|
+
const raw = await fs.readFile(path.join(phaseDir(flowDir, milestoneId, phaseId), "phase.json"), "utf8");
|
|
186
|
+
return JSON.parse(raw);
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
return null; // tolerant
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async function persistPhase(flowDir, p) {
|
|
193
|
+
const dir = phaseDir(flowDir, p.milestoneId, p.id);
|
|
194
|
+
await fs.mkdir(dir, { recursive: true });
|
|
195
|
+
await atomicWriteJSON(path.join(dir, "phase.json"), p);
|
|
196
|
+
await atomicWriteText(path.join(dir, "phase.md"), renderPhaseMd(p));
|
|
197
|
+
// Refresh the parent milestone.md so its phase list stays current.
|
|
198
|
+
const m = await readMilestoneRecord(flowDir, p.milestoneId);
|
|
199
|
+
if (m)
|
|
200
|
+
await persistMilestone(flowDir, m);
|
|
201
|
+
}
|
|
202
|
+
/** List phases under a milestone, sorted by ordinal ascending. */
|
|
203
|
+
export async function listPhases(flowDir, milestoneId) {
|
|
204
|
+
let ids;
|
|
205
|
+
try {
|
|
206
|
+
ids = await fs.readdir(path.join(milestoneDir(flowDir, milestoneId), "phases"));
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
if (err.code === "ENOENT")
|
|
210
|
+
return [];
|
|
211
|
+
throw err;
|
|
212
|
+
}
|
|
213
|
+
const out = [];
|
|
214
|
+
for (const id of ids) {
|
|
215
|
+
if (id.startsWith("."))
|
|
216
|
+
continue;
|
|
217
|
+
const p = await readPhaseRecord(flowDir, milestoneId, id);
|
|
218
|
+
if (p)
|
|
219
|
+
out.push(p);
|
|
220
|
+
}
|
|
221
|
+
out.sort((a, b) => a.ordinal - b.ordinal);
|
|
222
|
+
return out;
|
|
223
|
+
}
|
|
224
|
+
export async function loadPhase(flowDir, milestoneId, phaseId) {
|
|
225
|
+
return readPhaseRecord(flowDir, milestoneId, phaseId);
|
|
226
|
+
}
|
|
227
|
+
export async function createPhase(flowDir, milestoneId, input, nowIso) {
|
|
228
|
+
const existing = await listPhases(flowDir, milestoneId);
|
|
229
|
+
const ordinal = existing.reduce((max, p) => Math.max(max, p.ordinal), 0) + 1;
|
|
230
|
+
const p = {
|
|
231
|
+
id: phaseSlug(ordinal, input.title),
|
|
232
|
+
milestoneId,
|
|
233
|
+
title: input.title,
|
|
234
|
+
goal: input.goal ?? "",
|
|
235
|
+
ordinal,
|
|
236
|
+
status: "active",
|
|
237
|
+
runIds: input.runId ? [input.runId] : [],
|
|
238
|
+
createdAt: nowIso,
|
|
239
|
+
updatedAt: nowIso,
|
|
240
|
+
};
|
|
241
|
+
await persistPhase(flowDir, p);
|
|
242
|
+
return p;
|
|
243
|
+
}
|
|
244
|
+
export async function updatePhase(flowDir, milestoneId, phaseId, patch, nowIso) {
|
|
245
|
+
const p = await readPhaseRecord(flowDir, milestoneId, phaseId);
|
|
246
|
+
if (!p)
|
|
247
|
+
return null;
|
|
248
|
+
const next = { ...p, ...patch, updatedAt: nowIso };
|
|
249
|
+
await persistPhase(flowDir, next);
|
|
250
|
+
return next;
|
|
251
|
+
}
|
|
252
|
+
/** Link a run to a phase (idempotent — no duplicate run ids). */
|
|
253
|
+
export async function attachRunToPhase(flowDir, milestoneId, phaseId, runId, nowIso) {
|
|
254
|
+
const p = await readPhaseRecord(flowDir, milestoneId, phaseId);
|
|
255
|
+
if (!p)
|
|
256
|
+
return null;
|
|
257
|
+
if (p.runIds.includes(runId))
|
|
258
|
+
return p;
|
|
259
|
+
const next = { ...p, runIds: [...p.runIds, runId], updatedAt: nowIso };
|
|
260
|
+
await persistPhase(flowDir, next);
|
|
261
|
+
return next;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* A run is "substantive" once it has progressed past the boot skeleton — i.e.
|
|
265
|
+
* it carries research (`research.md`), a scoped spec (`tasks.json`, or a
|
|
266
|
+
* `Product Specification` section in `roadmap.md`), or context (`context.md`).
|
|
267
|
+
* The eager on-boot run has only the six empty base `.md` files, so it fails
|
|
268
|
+
* every check. Tolerant: any read error → treat as non-substantive.
|
|
269
|
+
*/
|
|
270
|
+
async function isSubstantiveRun(flowDir, runId) {
|
|
271
|
+
const runDir = path.join(flowDir, "runs", runId);
|
|
272
|
+
for (const marker of ["research.md", "tasks.json", "context.md"]) {
|
|
273
|
+
if (await fs.stat(path.join(runDir, marker)).then(() => true, () => false))
|
|
274
|
+
return true;
|
|
275
|
+
}
|
|
276
|
+
try {
|
|
277
|
+
const roadmap = await fs.readFile(path.join(runDir, "roadmap.md"), "utf8");
|
|
278
|
+
if (roadmap.includes("Product Specification"))
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
/* no roadmap → not substantive via this marker */
|
|
283
|
+
}
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
// ─── High-level wiring ───────────────────────────────────────────────────────
|
|
287
|
+
/**
|
|
288
|
+
* Find the milestone+phase a run is already indexed under, scanning every
|
|
289
|
+
* milestone. Returns null when the run is not yet linked anywhere. Used to keep
|
|
290
|
+
* scoping wiring idempotent across `/ideal resume` (the scoping stage re-runs).
|
|
291
|
+
*/
|
|
292
|
+
export async function findPhaseForRun(flowDir, runId) {
|
|
293
|
+
for (const m of await listMilestones(flowDir)) {
|
|
294
|
+
for (const p of await listPhases(flowDir, m.id)) {
|
|
295
|
+
if (p.runIds.includes(runId))
|
|
296
|
+
return { milestoneId: m.id, phaseId: p.id };
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Idempotently place a run in the hierarchy and mark it active. First call for a
|
|
303
|
+
* run creates (or reuses the active) milestone, opens a phase for the run, links
|
|
304
|
+
* it, and points the active-milestone/active-phase pointers at it. Subsequent
|
|
305
|
+
* calls (resume) are no-ops that just re-assert the pointers.
|
|
306
|
+
*
|
|
307
|
+
* The milestone groups an idea/product; the phase is one scoped iteration under
|
|
308
|
+
* it. This is purely an INDEX over `runs/<runId>/` — it never moves or rewrites
|
|
309
|
+
* run artifacts, and the numeric ROADMAP phases that phase-sync reads are
|
|
310
|
+
* untouched.
|
|
311
|
+
*/
|
|
312
|
+
export async function ensureRunScoped(flowDir, input, nowIso) {
|
|
313
|
+
// Reuse the active run's milestone when the current focus resolves to one
|
|
314
|
+
// (a prior product run in this session), computed BEFORE we repoint focus.
|
|
315
|
+
const priorMilestoneId = (await getActivePointer(flowDir)).milestoneId;
|
|
316
|
+
const existing = await findPhaseForRun(flowDir, input.runId);
|
|
317
|
+
if (existing) {
|
|
318
|
+
// Make this run the single canonical focus — the active milestone/phase are
|
|
319
|
+
// derived from it, ending the old Active-Run-vs-Active-Phase drift (F8).
|
|
320
|
+
await setActiveRunId(flowDir, input.runId);
|
|
321
|
+
await clearLegacyActivePointerSections(flowDir);
|
|
322
|
+
return existing;
|
|
323
|
+
}
|
|
324
|
+
let milestoneId = priorMilestoneId;
|
|
325
|
+
if (!milestoneId || !(await loadMilestone(flowDir, milestoneId))) {
|
|
326
|
+
const m = await createMilestone(flowDir, { title: input.milestoneTitle, goal: input.milestoneGoal }, nowIso);
|
|
327
|
+
milestoneId = m.id;
|
|
328
|
+
}
|
|
329
|
+
const phase = await createPhase(flowDir, milestoneId, { title: input.phaseTitle, goal: input.phaseGoal, runId: input.runId }, nowIso);
|
|
330
|
+
await setActiveRunId(flowDir, input.runId);
|
|
331
|
+
await clearLegacyActivePointerSections(flowDir);
|
|
332
|
+
return { milestoneId, phaseId: phase.id };
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* One-time backfill: index any `runs/<id>/` not yet linked to a phase under a
|
|
336
|
+
* synthetic `m00-legacy` milestone (one phase per orphan run). Idempotent — runs
|
|
337
|
+
* already indexed are skipped, and re-running adds only newly-orphaned runs.
|
|
338
|
+
* Returns the number of runs newly indexed.
|
|
339
|
+
*
|
|
340
|
+
* `m00` (ordinal 0) sorts before any real milestone so legacy work stays visible
|
|
341
|
+
* but out of the way. The clock is injected for deterministic tests.
|
|
342
|
+
*/
|
|
343
|
+
export async function migrateLegacyRuns(flowDir, nowIso) {
|
|
344
|
+
let runIds;
|
|
345
|
+
try {
|
|
346
|
+
runIds = await fs.readdir(path.join(flowDir, "runs"));
|
|
347
|
+
}
|
|
348
|
+
catch (err) {
|
|
349
|
+
if (err.code === "ENOENT")
|
|
350
|
+
return 0;
|
|
351
|
+
throw err;
|
|
352
|
+
}
|
|
353
|
+
runIds.sort(); // run ids are time-sortable; keep phase ordinals chronological.
|
|
354
|
+
const orphans = [];
|
|
355
|
+
for (const runId of runIds) {
|
|
356
|
+
if (runId.startsWith("."))
|
|
357
|
+
continue;
|
|
358
|
+
const stat = await fs.stat(path.join(flowDir, "runs", runId)).catch(() => null);
|
|
359
|
+
if (!stat?.isDirectory())
|
|
360
|
+
continue;
|
|
361
|
+
if (await findPhaseForRun(flowDir, runId))
|
|
362
|
+
continue;
|
|
363
|
+
// F1 — skip skeleton runs: the TUI eagerly creates an empty run on boot
|
|
364
|
+
// (only the base .md files, no ProductSpec / research). Indexing those as
|
|
365
|
+
// "legacy" clutters the hierarchy with runs the user never actually used.
|
|
366
|
+
if (!(await isSubstantiveRun(flowDir, runId)))
|
|
367
|
+
continue;
|
|
368
|
+
orphans.push(runId);
|
|
369
|
+
}
|
|
370
|
+
if (orphans.length === 0)
|
|
371
|
+
return 0;
|
|
372
|
+
const LEGACY_ID = "m00-legacy";
|
|
373
|
+
if (!(await loadMilestone(flowDir, LEGACY_ID))) {
|
|
374
|
+
const m = {
|
|
375
|
+
id: LEGACY_ID,
|
|
376
|
+
title: "Legacy runs",
|
|
377
|
+
goal: "Runs created before the milestone/phase hierarchy existed.",
|
|
378
|
+
ordinal: 0,
|
|
379
|
+
status: "archived",
|
|
380
|
+
createdAt: nowIso,
|
|
381
|
+
updatedAt: nowIso,
|
|
382
|
+
};
|
|
383
|
+
await persistMilestone(flowDir, m);
|
|
384
|
+
}
|
|
385
|
+
for (const runId of orphans) {
|
|
386
|
+
await createPhase(flowDir, LEGACY_ID, { title: `run ${runId}`, runId }, nowIso);
|
|
387
|
+
}
|
|
388
|
+
return orphans.length;
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* F8 — the active milestone/phase are DERIVED from the single canonical focus,
|
|
392
|
+
* the active run, via the hierarchy index; they are NOT separately persisted.
|
|
393
|
+
*
|
|
394
|
+
* Previously `state.md` carried independent `Active Run` (set for chat-runs) and
|
|
395
|
+
* `Active Milestone`/`Active Phase` (set by `ensureRunScoped` for product-runs)
|
|
396
|
+
* pointers that routinely drifted out of sync — `/ideal` never updated `Active
|
|
397
|
+
* Run`, so it pointed at a stale skeleton run while the milestone/phase pointed
|
|
398
|
+
* at the product run. Council decision (5/5): collapse to one truth. Whatever run
|
|
399
|
+
* is active, its phase (and that phase's milestone) is the active one; a
|
|
400
|
+
* chat/skeleton run that was never indexed resolves to nulls.
|
|
401
|
+
*/
|
|
402
|
+
export async function getActivePointer(flowDir) {
|
|
403
|
+
const runId = await getActiveRunId(flowDir);
|
|
404
|
+
if (!runId)
|
|
405
|
+
return { milestoneId: null, phaseId: null };
|
|
406
|
+
const hit = await findPhaseForRun(flowDir, runId);
|
|
407
|
+
return { milestoneId: hit?.milestoneId ?? null, phaseId: hit?.phaseId ?? null };
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Blank the legacy `Active Milestone`/`Active Phase` sections if an old
|
|
411
|
+
* `state.md` still carries them, so a stale value can never be mistaken for the
|
|
412
|
+
* (now derived) truth. One-time, idempotent; no-op when the sections are absent
|
|
413
|
+
* or already empty. Legacy files are otherwise read-as-junk — never migrated.
|
|
414
|
+
*/
|
|
415
|
+
export async function clearLegacyActivePointerSections(flowDir) {
|
|
416
|
+
const stateMap = await readArtifact(flowDir, "state.md");
|
|
417
|
+
if (!stateMap)
|
|
418
|
+
return;
|
|
419
|
+
const hadM = stateMap.sections.get("Active Milestone")?.trim();
|
|
420
|
+
const hadP = stateMap.sections.get("Active Phase")?.trim();
|
|
421
|
+
if (!hadM && !hadP)
|
|
422
|
+
return;
|
|
423
|
+
stateMap.sections.set("Active Milestone", "");
|
|
424
|
+
stateMap.sections.set("Active Phase", "");
|
|
425
|
+
await writeArtifact(flowDir, "state.md", stateMap);
|
|
426
|
+
}
|
|
427
|
+
//# sourceMappingURL=hierarchy.js.map
|
package/dist/src/flow/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Re-exports public API from parser, scaffold, artifact-io, run-manager, migration.
|
|
5
5
|
*/
|
|
6
6
|
export { readArtifact, writeArtifact } from "./artifact-io.js";
|
|
7
|
+
export { type ActivePointer, attachRunToPhase, clearLegacyActivePointerSections, createMilestone, createPhase, ensureRunScoped, findPhaseForRun, getActivePointer, listMilestones, listPhases, loadMilestone, loadPhase, MILESTONES_DIR, type MilestoneRecord, migrateLegacyRuns, type PhaseRecord, updateMilestone, updatePhase, } from "./hierarchy.js";
|
|
7
8
|
export { detectLegacyFlow, migrateQuickCodexFlow } from "./migration.js";
|
|
8
9
|
export type { SectionMap } from "./parser.js";
|
|
9
10
|
export { getSection, parseSections, serializeSections } from "./parser.js";
|
package/dist/src/flow/index.js
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
// Artifact I/O
|
|
7
7
|
export { readArtifact, writeArtifact } from "./artifact-io.js";
|
|
8
|
+
// Hierarchy (milestone → phase → run index layer)
|
|
9
|
+
export { attachRunToPhase, clearLegacyActivePointerSections, createMilestone, createPhase, ensureRunScoped, findPhaseForRun, getActivePointer, listMilestones, listPhases, loadMilestone, loadPhase, MILESTONES_DIR, migrateLegacyRuns, updateMilestone, updatePhase, } from "./hierarchy.js";
|
|
8
10
|
// Migration
|
|
9
11
|
export { detectLegacyFlow, migrateQuickCodexFlow } from "./migration.js";
|
|
10
12
|
// Parser
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* First-class run artifacts for the Product Ideal Loop.
|
|
3
|
+
*
|
|
4
|
+
* Sprint-2 MVP (Part A core, run-centric — hierarchy deferred per REV-3 Kill B):
|
|
5
|
+
* promotes the debate research summary and the prior-run context out of buried
|
|
6
|
+
* `delegations.md` sections into dedicated `research.md` / `context.md` files,
|
|
7
|
+
* gives the Resume Digest structured, parseable content (the empty digest was
|
|
8
|
+
* the root cause of "resume blindness"), and persists per-sprint outcome JSON so
|
|
9
|
+
* `/ideal review` and cross-run memory can render real history.
|
|
10
|
+
*
|
|
11
|
+
* All artifacts live under `.muonroi-flow/runs/<runId>/`. Writes are atomic.
|
|
12
|
+
* Reads are tolerant: a missing file returns null, never throws.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Structured resume state written to the `## Resume Digest` section of a run's
|
|
16
|
+
* top-level `state.md`. Replaces the previous one-line "Stage: X" string so a
|
|
17
|
+
* fresh session (or the user) can see exactly where the run stopped and what
|
|
18
|
+
* comes next without replaying the whole FSM.
|
|
19
|
+
*/
|
|
20
|
+
export interface ResumeDigest {
|
|
21
|
+
/** FSM stage or sprint phase the run last entered (e.g. "research", "sprint-3"). */
|
|
22
|
+
stage: string;
|
|
23
|
+
/** The stage that last completed successfully (blank at the very start). */
|
|
24
|
+
lastCompleted?: string;
|
|
25
|
+
/** One-line human hint for what resuming will do next. */
|
|
26
|
+
nextAction: string;
|
|
27
|
+
/** Sprint number when the digest is written mid-sprint-loop. */
|
|
28
|
+
sprintN?: number;
|
|
29
|
+
/** Latest done-gate score (0..1) when known. */
|
|
30
|
+
score?: number;
|
|
31
|
+
/** Latest verify verdict string (PASS/FAIL/UNKNOWN) when known. */
|
|
32
|
+
verify?: string;
|
|
33
|
+
/** Open questions / unresolved gray areas the next stage should address. */
|
|
34
|
+
openQuestions?: string[];
|
|
35
|
+
/** Short EE recall snapshot (top lessons) surfaced for the next stage. */
|
|
36
|
+
eeSnapshot?: string;
|
|
37
|
+
/** ISO timestamp of the digest write. */
|
|
38
|
+
updatedAt?: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Render a ResumeDigest as markdown for the `## Resume Digest` section body.
|
|
42
|
+
* Deterministic field order so diffs stay minimal.
|
|
43
|
+
*/
|
|
44
|
+
export declare function renderResumeDigest(d: ResumeDigest): string;
|
|
45
|
+
/**
|
|
46
|
+
* Parse a `## Resume Digest` section body back into a ResumeDigest. Tolerant:
|
|
47
|
+
* returns null when the body has no recognizable `Stage:` line (e.g. the old
|
|
48
|
+
* empty digest or a legacy one-line string).
|
|
49
|
+
*/
|
|
50
|
+
export declare function parseResumeDigest(body: string | undefined): ResumeDigest | null;
|
|
51
|
+
export interface ResearchDoc {
|
|
52
|
+
/** Council debate running summary. */
|
|
53
|
+
summary: string;
|
|
54
|
+
/** Structured research findings (evidence table / bullets), if any. */
|
|
55
|
+
findings?: string;
|
|
56
|
+
/** EE recall seed surfaced before the debate, if any. */
|
|
57
|
+
eeSeed?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Part E — web-research confidence for this run. "native" = a model with
|
|
60
|
+
* native online web research drove the Researcher stance; "degraded" = no
|
|
61
|
+
* web-native model was reachable, so online facts fall back to the (untrusted)
|
|
62
|
+
* add-in path. Recorded so `/ideal review` surfaces research trustworthiness.
|
|
63
|
+
*/
|
|
64
|
+
webResearch?: {
|
|
65
|
+
confidence: "native" | "degraded";
|
|
66
|
+
model?: string;
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Write `research.md` — the first-class home for the debate output. Previously
|
|
71
|
+
* this lived only in `delegations.md` sections; callers still write those for
|
|
72
|
+
* back-compat, but `research.md` is now the canonical, reviewable surface.
|
|
73
|
+
*/
|
|
74
|
+
export declare function writeResearchDoc(flowDir: string, runId: string, doc: ResearchDoc): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Write `context.md` — the prior-run digest + project context carried into a
|
|
77
|
+
* run. Prior context was previously computed then discarded (loop-driver noted
|
|
78
|
+
* it was dropped from the system prompt); persisting it here makes it a
|
|
79
|
+
* reviewable, resumable surface without re-bloating the live prompt.
|
|
80
|
+
*/
|
|
81
|
+
export declare function writeContextDoc(flowDir: string, runId: string, content: string): Promise<void>;
|
|
82
|
+
/** Read a whole-file run doc (research.md / context.md). Null when absent. */
|
|
83
|
+
export declare function readRunDoc(flowDir: string, runId: string, filename: string): Promise<string | null>;
|
|
84
|
+
export interface SprintOutcome {
|
|
85
|
+
sprintN: number;
|
|
86
|
+
pass: boolean;
|
|
87
|
+
score: number;
|
|
88
|
+
verify: string;
|
|
89
|
+
failedCondition?: string;
|
|
90
|
+
criteriaMet: number;
|
|
91
|
+
criteriaPartial: number;
|
|
92
|
+
criteriaUnmet: number;
|
|
93
|
+
finishedAt: string;
|
|
94
|
+
}
|
|
95
|
+
/** Absolute path to a run's `sprints/` directory. */
|
|
96
|
+
export declare function sprintsDir(flowDir: string, runId: string): string;
|
|
97
|
+
/** Persist a per-sprint outcome record as `sprints/<n>-outcome.json`. */
|
|
98
|
+
export declare function writeSprintOutcome(flowDir: string, runId: string, outcome: SprintOutcome): Promise<void>;
|
|
99
|
+
/** Persist a per-sprint verify report as `sprints/<n>-verify.md`. */
|
|
100
|
+
export declare function writeSprintVerify(flowDir: string, runId: string, sprintN: number, markdown: string): Promise<void>;
|
|
101
|
+
/** Read all sprint outcomes for a run, sorted by sprint number ascending. */
|
|
102
|
+
export declare function readSprintOutcomes(flowDir: string, runId: string): Promise<SprintOutcome[]>;
|