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,45 @@
|
|
|
1
|
+
import { getModelByTier, getModelInfo, getModelsForProvider } from "../models/registry.js";
|
|
2
|
+
import { detectProviderForModel } from "../providers/runtime.js";
|
|
3
|
+
const TIER_RANK = { fast: 0, balanced: 1, premium: 2 };
|
|
4
|
+
/**
|
|
5
|
+
* GSD-only premium resolver — always picks the highest-tier model on the
|
|
6
|
+
* session provider for plan-council / verify gates. Unlike
|
|
7
|
+
* resolveLeaderModelDetailed, this intentionally promotes within-provider
|
|
8
|
+
* for critical GSD stages.
|
|
9
|
+
*/
|
|
10
|
+
export function resolveGsdPremiumModel(sessionModelId) {
|
|
11
|
+
const providerId = detectProviderForModel(sessionModelId);
|
|
12
|
+
let best;
|
|
13
|
+
for (const m of getModelsForProvider(providerId)) {
|
|
14
|
+
if (m.tierRouting === false)
|
|
15
|
+
continue;
|
|
16
|
+
if (!m.tier)
|
|
17
|
+
continue;
|
|
18
|
+
if (!best || TIER_RANK[m.tier] > TIER_RANK[best.tier]) {
|
|
19
|
+
best = { id: m.id, tier: m.tier };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (best)
|
|
23
|
+
return best.id;
|
|
24
|
+
const premium = getModelByTier("premium", providerId);
|
|
25
|
+
if (premium)
|
|
26
|
+
return premium.id;
|
|
27
|
+
return sessionModelId;
|
|
28
|
+
}
|
|
29
|
+
/** Research perspectives ground against the codebase; others validate rigorously. */
|
|
30
|
+
export function resolveGsdPerspectiveAgent(id) {
|
|
31
|
+
return id === "research" ? "explore" : "verify";
|
|
32
|
+
}
|
|
33
|
+
export function buildGsdPerspectiveTaskRequest(prompt, perspective, sessionModelId, descriptionPrefix = "plan-council") {
|
|
34
|
+
return {
|
|
35
|
+
agent: resolveGsdPerspectiveAgent(perspective.id),
|
|
36
|
+
prompt,
|
|
37
|
+
description: `${descriptionPrefix}:${perspective.id}`,
|
|
38
|
+
maxToolRounds: 4,
|
|
39
|
+
modelId: resolveGsdPremiumModel(sessionModelId),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export function tierOfModel(modelId) {
|
|
43
|
+
return getModelInfo(modelId)?.tier;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=model-tier.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface MutationGateDecision {
|
|
2
|
+
blocked: boolean;
|
|
3
|
+
reason: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Gate = the SDK's own canExecute, keyed on the SDK STATE.md Depth (written by the
|
|
7
|
+
* turn's syncWorkflowContext). Reading depth from readState — NOT from a
|
|
8
|
+
* caller-passed value or pilCtx — makes STATE.md the single source of truth and
|
|
9
|
+
* decouples the gate from pilCtx object propagation. quick depth is fast-pathed by
|
|
10
|
+
* canExecute; standard/heavy gate on plan-verify pass.
|
|
11
|
+
*/
|
|
12
|
+
export declare function evaluateMutationGate(cwd: string, opts: {
|
|
13
|
+
toolName: string;
|
|
14
|
+
hardGateEnabled: boolean;
|
|
15
|
+
directAnswer?: boolean;
|
|
16
|
+
}): MutationGateDecision;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { canExecute, readState } from "./workflow-engine.js";
|
|
2
|
+
const NEVER_GATED_PREFIXES = ["gsd_", "respond_"];
|
|
3
|
+
const NEVER_GATED = new Set(["read_file", "grep", "glob", "bash_output_get", "gsd_status", "compact"]);
|
|
4
|
+
function isNeverGated(t) {
|
|
5
|
+
return NEVER_GATED.has(t) || NEVER_GATED_PREFIXES.some((p) => t.startsWith(p));
|
|
6
|
+
}
|
|
7
|
+
const GATE_DIRECTIVE = "BLOCKED: this task was assessed as non-trivial. GSD requires a reviewed plan before any code edit. " +
|
|
8
|
+
"Call gsd_status, then gsd_discuss → gsd_plan → gsd_plan_review. Mutation tools unlock only after " +
|
|
9
|
+
"plan-review returns verdict: pass. If this is genuinely trivial, call gsd_execute with force:true to override.";
|
|
10
|
+
/**
|
|
11
|
+
* Gate = the SDK's own canExecute, keyed on the SDK STATE.md Depth (written by the
|
|
12
|
+
* turn's syncWorkflowContext). Reading depth from readState — NOT from a
|
|
13
|
+
* caller-passed value or pilCtx — makes STATE.md the single source of truth and
|
|
14
|
+
* decouples the gate from pilCtx object propagation. quick depth is fast-pathed by
|
|
15
|
+
* canExecute; standard/heavy gate on plan-verify pass.
|
|
16
|
+
*/
|
|
17
|
+
export function evaluateMutationGate(cwd, opts) {
|
|
18
|
+
const allow = { blocked: false, reason: "" };
|
|
19
|
+
if (!opts.hardGateEnabled || opts.directAnswer || isNeverGated(opts.toolName))
|
|
20
|
+
return allow;
|
|
21
|
+
try {
|
|
22
|
+
const depth = readState(cwd).depth;
|
|
23
|
+
// Fail OPEN on anything but an EXPLICIT "heavy" depth. quick/standard/null all pass:
|
|
24
|
+
// - null STATE (not classified / native off mid-turn / write failed) → over-blocking on
|
|
25
|
+
// "we don't know" is the failure mode the design forbids.
|
|
26
|
+
// - quick → trivial fast-path.
|
|
27
|
+
// - standard → ADVISORY only. The layer4 directive still nudges gsd_plan_review, but
|
|
28
|
+
// hard-blocking every default-tier bash/edit until a plan-review pass over-reaches
|
|
29
|
+
// ("hard thì mọi tier không tốt"). Only genuinely non-trivial work (heavy, incl. tasks
|
|
30
|
+
// the leader-tier assessor UPGRADES to heavy) earns the hard gate.
|
|
31
|
+
if (!depth || depth === "quick" || depth === "standard")
|
|
32
|
+
return allow;
|
|
33
|
+
const gate = canExecute(cwd, depth);
|
|
34
|
+
return gate.allowed ? allow : { blocked: true, reason: GATE_DIRECTIVE };
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
console.error(`[gsd] mutation-gate canExecute failed, failing open: ${err.message}`);
|
|
38
|
+
return allow; // fail open — a corrupt .planning must not brick the turn; caps still bound loops
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=mutation-gate.js.map
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* native-roadmap.ts — Native replacements for the ROADMAP-oriented gsd-tools
|
|
3
|
+
* subcommands: `roadmap analyze` (read-only), `phase add` (create dir + append),
|
|
4
|
+
* and — Part B step 2 — the two mutating commands `roadmap update-plan-progress`
|
|
5
|
+
* and `phase complete`.
|
|
6
|
+
*
|
|
7
|
+
* The mutating commands rewrite ROADMAP.md (checkbox/table/plan-count) and, for
|
|
8
|
+
* phase-complete, STATE.md. muonroi's only callers (phase-sync, task workflow)
|
|
9
|
+
* read just `ok` + a cosmetic `raw` line — they do NOT consume the rich JSON —
|
|
10
|
+
* so native parity is about performing the FILE mutations correctly, verified
|
|
11
|
+
* against the subprocess oracle in the native-roadmap contract tests.
|
|
12
|
+
*/
|
|
13
|
+
export interface RoadmapAnalyzePhase {
|
|
14
|
+
number: string;
|
|
15
|
+
name: string;
|
|
16
|
+
depends_on: string | null;
|
|
17
|
+
disk_status: string;
|
|
18
|
+
}
|
|
19
|
+
export interface RoadmapAnalyzeData {
|
|
20
|
+
error?: string;
|
|
21
|
+
milestones: Array<{
|
|
22
|
+
heading: string;
|
|
23
|
+
version?: string;
|
|
24
|
+
}>;
|
|
25
|
+
phases: RoadmapAnalyzePhase[];
|
|
26
|
+
phase_count: number;
|
|
27
|
+
current_phase: string | null;
|
|
28
|
+
next_phase: string | null;
|
|
29
|
+
}
|
|
30
|
+
/** Slugify per gsd-core core-utils: lowercase, non-alnum→'-', trim, cap 60. */
|
|
31
|
+
export declare function phaseSlug(text: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Native `roadmap analyze` — parse ROADMAP.md phase headings (current milestone)
|
|
34
|
+
* + per-phase Depends-on + disk status. Read-only. Returns {error} when
|
|
35
|
+
* ROADMAP.md is absent (mirrors subprocess, exit 0).
|
|
36
|
+
*/
|
|
37
|
+
export declare function nativeRoadmapAnalyze(cwd: string): RoadmapAnalyzeData;
|
|
38
|
+
export interface PhaseAddData {
|
|
39
|
+
phase_number: number;
|
|
40
|
+
padded: string;
|
|
41
|
+
name: string;
|
|
42
|
+
slug: string;
|
|
43
|
+
directory: string;
|
|
44
|
+
naming_mode: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Native `phase add <description>` — sequential naming mode only (custom `--id`
|
|
48
|
+
* mode is not used by muonroi's callers). Creates `.planning/phases/<NN>-<slug>/`
|
|
49
|
+
* + `.gitkeep`, and appends a phase block to ROADMAP.md before the trailing
|
|
50
|
+
* `---` separator. Returns {error} when ROADMAP.md is absent (matching the
|
|
51
|
+
* subprocess exit-1 contract via ok:false at the dispatch layer).
|
|
52
|
+
*/
|
|
53
|
+
export declare function nativePhaseAdd(cwd: string, description: string): PhaseAddData | {
|
|
54
|
+
error: string;
|
|
55
|
+
};
|
|
56
|
+
export interface RoadmapPlanProgressData {
|
|
57
|
+
updated: boolean;
|
|
58
|
+
reason?: string;
|
|
59
|
+
phase?: string;
|
|
60
|
+
plan_count?: number;
|
|
61
|
+
summary_count?: number;
|
|
62
|
+
status?: string;
|
|
63
|
+
complete?: boolean;
|
|
64
|
+
/** Plain-text `--raw` line, e.g. "2/3 In Progress". */
|
|
65
|
+
raw?: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Native `roadmap update-plan-progress <N>` — recompute plan/summary counts from
|
|
69
|
+
* the phase dir and sync the ROADMAP: phase checkbox (when complete), plan
|
|
70
|
+
* checkboxes for summarized plans, and the `**Plans:**` count line. Returns
|
|
71
|
+
* {updated:false} (exit-0 semantics) when the phase or ROADMAP is missing.
|
|
72
|
+
*/
|
|
73
|
+
export declare function nativeRoadmapPlanProgress(cwd: string, phaseNum: string): RoadmapPlanProgressData;
|
|
74
|
+
export interface PhaseCompleteData {
|
|
75
|
+
ok: boolean;
|
|
76
|
+
error?: string;
|
|
77
|
+
completed_phase?: string;
|
|
78
|
+
roadmap_updated?: boolean;
|
|
79
|
+
state_updated?: boolean;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Native `phase complete <N>` — mark the phase done in ROADMAP.md (checkbox +
|
|
83
|
+
* plan checkboxes + Plans line) and reflect completion in STATE.md (Status). The
|
|
84
|
+
* subprocess gates on a `passed` VERIFICATION; muonroi's caller writes that
|
|
85
|
+
* verification immediately before calling, so the gate is satisfied by
|
|
86
|
+
* construction — we still mark the ROADMAP/STATE so the workflow state is
|
|
87
|
+
* consistent. Returns {ok:false} when the phase / ROADMAP is missing.
|
|
88
|
+
*/
|
|
89
|
+
export declare function nativePhaseComplete(cwd: string, phaseNum: string): PhaseCompleteData;
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* native-roadmap.ts — Native replacements for the ROADMAP-oriented gsd-tools
|
|
3
|
+
* subcommands: `roadmap analyze` (read-only), `phase add` (create dir + append),
|
|
4
|
+
* and — Part B step 2 — the two mutating commands `roadmap update-plan-progress`
|
|
5
|
+
* and `phase complete`.
|
|
6
|
+
*
|
|
7
|
+
* The mutating commands rewrite ROADMAP.md (checkbox/table/plan-count) and, for
|
|
8
|
+
* phase-complete, STATE.md. muonroi's only callers (phase-sync, task workflow)
|
|
9
|
+
* read just `ok` + a cosmetic `raw` line — they do NOT consume the rich JSON —
|
|
10
|
+
* so native parity is about performing the FILE mutations correctly, verified
|
|
11
|
+
* against the subprocess oracle in the native-roadmap contract tests.
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { loadConfig } from "./config-loader.js";
|
|
16
|
+
import { planningArtifact, planningPhasesRoot } from "./paths.js";
|
|
17
|
+
import { normalizeStateStatus, stateReplaceField } from "./state-document.js";
|
|
18
|
+
const PHASE_HEADING_RE = /#{2,4}\s*(?:\[[^\]]+\]\s*)?Phase\s+(\d+[A-Za-z]?(?:[.-]\d+)*)\s*:\s*([^\n]+)/gi;
|
|
19
|
+
function isSentinel(num) {
|
|
20
|
+
return num === "0" || num.startsWith("999");
|
|
21
|
+
}
|
|
22
|
+
/** Slugify per gsd-core core-utils: lowercase, non-alnum→'-', trim, cap 60. */
|
|
23
|
+
export function phaseSlug(text) {
|
|
24
|
+
return text
|
|
25
|
+
.toLowerCase()
|
|
26
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
27
|
+
.replace(/^-+|-+$/g, "")
|
|
28
|
+
.substring(0, 60);
|
|
29
|
+
}
|
|
30
|
+
/** Disk status for a phase dir given plan/summary/context/research presence. */
|
|
31
|
+
function diskStatusFor(cwd, number) {
|
|
32
|
+
const root = planningPhasesRoot(cwd);
|
|
33
|
+
if (!existsSync(root))
|
|
34
|
+
return "no_directory";
|
|
35
|
+
let dir;
|
|
36
|
+
try {
|
|
37
|
+
dir = readdirSync(root, { withFileTypes: true })
|
|
38
|
+
.filter((e) => e.isDirectory())
|
|
39
|
+
.map((e) => e.name)
|
|
40
|
+
.find((name) => new RegExp(`(^|[^0-9])0*${number}-`).test(name) || name.startsWith(`${number.padStart(2, "0")}-`));
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return "no_directory";
|
|
44
|
+
}
|
|
45
|
+
if (!dir)
|
|
46
|
+
return "no_directory";
|
|
47
|
+
let plans = 0;
|
|
48
|
+
let summaries = 0;
|
|
49
|
+
let hasResearch = false;
|
|
50
|
+
try {
|
|
51
|
+
for (const f of readdirSync(join(root, dir))) {
|
|
52
|
+
if (/PLAN.*\.md$/i.test(f))
|
|
53
|
+
plans += 1;
|
|
54
|
+
if (/SUMMARY.*\.md$/i.test(f))
|
|
55
|
+
summaries += 1;
|
|
56
|
+
if (/RESEARCH.*\.md$/i.test(f))
|
|
57
|
+
hasResearch = true;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return "empty";
|
|
62
|
+
}
|
|
63
|
+
if (plans > 0 && summaries >= plans)
|
|
64
|
+
return "complete";
|
|
65
|
+
if (summaries > 0)
|
|
66
|
+
return "partial";
|
|
67
|
+
if (plans > 0)
|
|
68
|
+
return "planned";
|
|
69
|
+
if (hasResearch)
|
|
70
|
+
return "researched";
|
|
71
|
+
return "empty";
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Native `roadmap analyze` — parse ROADMAP.md phase headings (current milestone)
|
|
75
|
+
* + per-phase Depends-on + disk status. Read-only. Returns {error} when
|
|
76
|
+
* ROADMAP.md is absent (mirrors subprocess, exit 0).
|
|
77
|
+
*/
|
|
78
|
+
export function nativeRoadmapAnalyze(cwd) {
|
|
79
|
+
const roadmapPath = planningArtifact(cwd, "ROADMAP.md");
|
|
80
|
+
if (!existsSync(roadmapPath)) {
|
|
81
|
+
return {
|
|
82
|
+
error: "ROADMAP.md not found",
|
|
83
|
+
milestones: [],
|
|
84
|
+
phases: [],
|
|
85
|
+
phase_count: 0,
|
|
86
|
+
current_phase: null,
|
|
87
|
+
next_phase: null,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
const text = readFileSync(roadmapPath, "utf8");
|
|
91
|
+
const milestones = [];
|
|
92
|
+
const msRe = /##\s*(.*v(\d+(?:\.\d+)+)[^(\n]*)/gi;
|
|
93
|
+
for (let m = msRe.exec(text); m; m = msRe.exec(text)) {
|
|
94
|
+
milestones.push({ heading: m[1].trim(), version: m[2] });
|
|
95
|
+
}
|
|
96
|
+
const checkboxDone = new Set();
|
|
97
|
+
const cbRe = /-\s*\[([ xX])\]\s*\*\*Phase\s+(\d+[A-Za-z]?(?:[.-]\d+)*)/gi;
|
|
98
|
+
for (let m = cbRe.exec(text); m; m = cbRe.exec(text)) {
|
|
99
|
+
if (m[1].toLowerCase() === "x")
|
|
100
|
+
checkboxDone.add(m[2]);
|
|
101
|
+
}
|
|
102
|
+
const phases = [];
|
|
103
|
+
const seen = new Set();
|
|
104
|
+
PHASE_HEADING_RE.lastIndex = 0;
|
|
105
|
+
const matches = [...text.matchAll(PHASE_HEADING_RE)];
|
|
106
|
+
for (let i = 0; i < matches.length; i++) {
|
|
107
|
+
const number = matches[i][1];
|
|
108
|
+
if (isSentinel(number) || seen.has(number))
|
|
109
|
+
continue;
|
|
110
|
+
seen.add(number);
|
|
111
|
+
const name = matches[i][2].trim();
|
|
112
|
+
// Depends-on: scan the section body between this heading and the next.
|
|
113
|
+
const sectionStart = matches[i].index ?? 0;
|
|
114
|
+
const sectionEnd = i + 1 < matches.length ? (matches[i + 1].index ?? text.length) : text.length;
|
|
115
|
+
const section = text.slice(sectionStart, sectionEnd);
|
|
116
|
+
const depMatch = section.match(/\*\*Depends on:\*\*\s*([^\n]+)/i);
|
|
117
|
+
const depends_on = depMatch ? depMatch[1].trim() : null;
|
|
118
|
+
const diskStatus = checkboxDone.has(number) ? "complete" : diskStatusFor(cwd, number);
|
|
119
|
+
phases.push({ number, name, depends_on, disk_status: diskStatus });
|
|
120
|
+
}
|
|
121
|
+
// "current" = the first phase that is STARTED but not complete (matches the
|
|
122
|
+
// subprocess: a phase with no directory is "not started" → null, not current).
|
|
123
|
+
const inProgress = new Set(["partial", "planned", "researched", "discussed"]);
|
|
124
|
+
const current = phases.find((p) => inProgress.has(p.disk_status)) ?? null;
|
|
125
|
+
const currentIdx = current ? phases.indexOf(current) : -1;
|
|
126
|
+
// next = the first not-complete phase after the last complete one.
|
|
127
|
+
const firstIncomplete = phases.find((p) => p.disk_status !== "complete") ?? null;
|
|
128
|
+
const next = current ? (currentIdx + 1 < phases.length ? phases[currentIdx + 1] : null) : firstIncomplete;
|
|
129
|
+
return {
|
|
130
|
+
milestones,
|
|
131
|
+
phases,
|
|
132
|
+
phase_count: phases.length,
|
|
133
|
+
current_phase: current?.number ?? null,
|
|
134
|
+
next_phase: next?.number ?? null,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/** Highest phase number used across headings + roadmap bullets + phase dirs. */
|
|
138
|
+
function maxUsedPhaseNumber(cwd, roadmapText) {
|
|
139
|
+
let max = 0;
|
|
140
|
+
const collect = (n) => {
|
|
141
|
+
const v = Number.parseInt(n, 10);
|
|
142
|
+
if (Number.isFinite(v) && v !== 999 && v > max)
|
|
143
|
+
max = v;
|
|
144
|
+
};
|
|
145
|
+
for (const m of roadmapText.matchAll(/#{2,4}\s*Phase\s+(\d+)[A-Za-z]?(?:\.\d+)*:/gi))
|
|
146
|
+
collect(m[1]);
|
|
147
|
+
for (const m of roadmapText.matchAll(/^[ \t]*-[ \t]*\[[^\]]*\][ \t]*\*{0,2}Phase[ \t]+(\d+)(?=[:.\s*]|$)/gim))
|
|
148
|
+
collect(m[1]);
|
|
149
|
+
const root = planningPhasesRoot(cwd);
|
|
150
|
+
if (existsSync(root)) {
|
|
151
|
+
try {
|
|
152
|
+
for (const e of readdirSync(root, { withFileTypes: true })) {
|
|
153
|
+
if (!e.isDirectory())
|
|
154
|
+
continue;
|
|
155
|
+
const dm = e.name.match(/^(?:[A-Z][A-Z0-9]*-)?(\d+)-/);
|
|
156
|
+
if (dm)
|
|
157
|
+
collect(dm[1]);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
/* ignore unreadable phases dir */
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return max;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Native `phase add <description>` — sequential naming mode only (custom `--id`
|
|
168
|
+
* mode is not used by muonroi's callers). Creates `.planning/phases/<NN>-<slug>/`
|
|
169
|
+
* + `.gitkeep`, and appends a phase block to ROADMAP.md before the trailing
|
|
170
|
+
* `---` separator. Returns {error} when ROADMAP.md is absent (matching the
|
|
171
|
+
* subprocess exit-1 contract via ok:false at the dispatch layer).
|
|
172
|
+
*/
|
|
173
|
+
export function nativePhaseAdd(cwd, description) {
|
|
174
|
+
const desc = description.trim();
|
|
175
|
+
if (!desc)
|
|
176
|
+
return { error: "phase add requires a description" };
|
|
177
|
+
const roadmapPath = planningArtifact(cwd, "ROADMAP.md");
|
|
178
|
+
if (!existsSync(roadmapPath))
|
|
179
|
+
return { error: "ROADMAP.md not found" };
|
|
180
|
+
const config = loadConfig(cwd);
|
|
181
|
+
const projectCode = typeof config.project_code === "string" && config.project_code ? `${config.project_code}-` : "";
|
|
182
|
+
const roadmapText = readFileSync(roadmapPath, "utf8");
|
|
183
|
+
const id = maxUsedPhaseNumber(cwd, roadmapText) + 1;
|
|
184
|
+
const padded = String(id).padStart(2, "0");
|
|
185
|
+
const slug = phaseSlug(desc);
|
|
186
|
+
const directory = `${projectCode}${padded}-${slug}`;
|
|
187
|
+
// Create phase dir + .gitkeep.
|
|
188
|
+
const phaseDir = join(planningPhasesRoot(cwd), directory);
|
|
189
|
+
mkdirSync(phaseDir, { recursive: true });
|
|
190
|
+
writeFileSync(join(phaseDir, ".gitkeep"), "", "utf8");
|
|
191
|
+
// Append the phase block before the last `---` separator (or at EOF).
|
|
192
|
+
const block = `\n### Phase ${id}: ${desc}\n\n**Goal:** [To be planned]\n**Requirements**: TBD\n**Depends on:** Phase ${id - 1}\n**Plans:** 0 plans\n\nPlans:\n- [ ] TBD (run gsd-slash plan-phase ${id} to break down)\n`;
|
|
193
|
+
const sepIdx = roadmapText.lastIndexOf("\n---");
|
|
194
|
+
const nextRoadmap = sepIdx >= 0 ? `${roadmapText.slice(0, sepIdx)}${block}${roadmapText.slice(sepIdx)}` : `${roadmapText}${block}`;
|
|
195
|
+
writeFileSync(roadmapPath, nextRoadmap, "utf8");
|
|
196
|
+
return { phase_number: id, padded, name: desc, slug, directory, naming_mode: "sequential" };
|
|
197
|
+
}
|
|
198
|
+
// ─── Part B step 2: mutating commands ───────────────────────────────────────
|
|
199
|
+
function today() {
|
|
200
|
+
return new Date().toISOString().slice(0, 10);
|
|
201
|
+
}
|
|
202
|
+
/** Find the phase directory name for a phase number (unpadded or padded). */
|
|
203
|
+
function findPhaseDir(cwd, phaseNum) {
|
|
204
|
+
const root = planningPhasesRoot(cwd);
|
|
205
|
+
if (!existsSync(root))
|
|
206
|
+
return null;
|
|
207
|
+
const n = phaseNum.replace(/^0+/, "") || phaseNum;
|
|
208
|
+
try {
|
|
209
|
+
const dirs = readdirSync(root, { withFileTypes: true })
|
|
210
|
+
.filter((e) => e.isDirectory())
|
|
211
|
+
.map((e) => e.name);
|
|
212
|
+
return dirs.find((d) => new RegExp(`(^|[^0-9])0*${n}-`).test(d) || d.startsWith(`${n.padStart(2, "0")}-`)) ?? null;
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/** Count PLAN / SUMMARY files (and derive plan ids from summaries) in a phase dir. */
|
|
219
|
+
function phasePlanCounts(cwd, dir) {
|
|
220
|
+
let planCount = 0;
|
|
221
|
+
let summaryCount = 0;
|
|
222
|
+
const summaryPlanIds = [];
|
|
223
|
+
try {
|
|
224
|
+
for (const f of readdirSync(join(planningPhasesRoot(cwd), dir))) {
|
|
225
|
+
if (/PLAN.*\.md$/i.test(f))
|
|
226
|
+
planCount += 1;
|
|
227
|
+
if (/SUMMARY.*\.md$/i.test(f)) {
|
|
228
|
+
summaryCount += 1;
|
|
229
|
+
summaryPlanIds.push(f.replace(/-?SUMMARY.*\.md$/i, ""));
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
/* unreadable dir → zero counts */
|
|
235
|
+
}
|
|
236
|
+
return { planCount, summaryCount, summaryPlanIds };
|
|
237
|
+
}
|
|
238
|
+
function statusFor(planCount, summaryCount) {
|
|
239
|
+
if (planCount > 0 && summaryCount >= planCount)
|
|
240
|
+
return "Complete";
|
|
241
|
+
if (summaryCount > 0)
|
|
242
|
+
return "In Progress";
|
|
243
|
+
return "Planned";
|
|
244
|
+
}
|
|
245
|
+
/** Toggle the ROADMAP checkbox for a phase to [x] (+ completed date). */
|
|
246
|
+
function checkPhaseBox(text, phaseNum) {
|
|
247
|
+
const esc = phaseNum.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
248
|
+
const re = new RegExp(`(-\\s*\\[)[ ](\\]\\s*.*Phase\\s+${esc}[:\\s][^\\n]*)`, "i");
|
|
249
|
+
if (!re.test(text))
|
|
250
|
+
return text;
|
|
251
|
+
return text.replace(re, (_m, a, b) => `${a}x${b} (completed ${today()})`);
|
|
252
|
+
}
|
|
253
|
+
/** Check each summarized plan's checkbox in the ROADMAP. */
|
|
254
|
+
function checkPlanBoxes(text, planIds) {
|
|
255
|
+
let out = text;
|
|
256
|
+
for (const pid of planIds) {
|
|
257
|
+
const esc = pid.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
258
|
+
const re = new RegExp(`(-\\s*\\[) (\\]\\s*(?:\\*\\*)?${esc}(?:\\*\\*)?)`, "g");
|
|
259
|
+
out = out.replace(re, (_m, a, b) => `${a}x${b}`);
|
|
260
|
+
}
|
|
261
|
+
return out;
|
|
262
|
+
}
|
|
263
|
+
/** Update the `**Plans:**` count line in a phase section. */
|
|
264
|
+
function updatePlansLine(text, summary, plan, complete) {
|
|
265
|
+
const re = /(\*\*Plans:\*\*\s*)([^\n]*)/i;
|
|
266
|
+
if (!re.test(text))
|
|
267
|
+
return text;
|
|
268
|
+
const word = complete ? "complete" : "executed";
|
|
269
|
+
return text.replace(re, (_m, pre) => `${pre}${summary}/${plan} plans ${word}`);
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Native `roadmap update-plan-progress <N>` — recompute plan/summary counts from
|
|
273
|
+
* the phase dir and sync the ROADMAP: phase checkbox (when complete), plan
|
|
274
|
+
* checkboxes for summarized plans, and the `**Plans:**` count line. Returns
|
|
275
|
+
* {updated:false} (exit-0 semantics) when the phase or ROADMAP is missing.
|
|
276
|
+
*/
|
|
277
|
+
export function nativeRoadmapPlanProgress(cwd, phaseNum) {
|
|
278
|
+
const dir = findPhaseDir(cwd, phaseNum);
|
|
279
|
+
if (!dir)
|
|
280
|
+
return { updated: false, reason: `Phase ${phaseNum} not found`, raw: "no phase" };
|
|
281
|
+
const roadmapPath = planningArtifact(cwd, "ROADMAP.md");
|
|
282
|
+
if (!existsSync(roadmapPath))
|
|
283
|
+
return { updated: false, reason: "ROADMAP.md not found", raw: "no roadmap" };
|
|
284
|
+
const { planCount, summaryCount, summaryPlanIds } = phasePlanCounts(cwd, dir);
|
|
285
|
+
if (planCount === 0)
|
|
286
|
+
return { updated: false, reason: "No plans found", phase: phaseNum, plan_count: 0, raw: "no plans" };
|
|
287
|
+
const status = statusFor(planCount, summaryCount);
|
|
288
|
+
const complete = status === "Complete";
|
|
289
|
+
let text = readFileSync(roadmapPath, "utf8");
|
|
290
|
+
text = updatePlansLine(text, summaryCount, planCount, complete);
|
|
291
|
+
text = checkPlanBoxes(text, summaryPlanIds);
|
|
292
|
+
if (complete)
|
|
293
|
+
text = checkPhaseBox(text, phaseNum);
|
|
294
|
+
writeFileSync(roadmapPath, text, "utf8");
|
|
295
|
+
return {
|
|
296
|
+
updated: true,
|
|
297
|
+
phase: phaseNum,
|
|
298
|
+
plan_count: planCount,
|
|
299
|
+
summary_count: summaryCount,
|
|
300
|
+
status,
|
|
301
|
+
complete,
|
|
302
|
+
raw: `${summaryCount}/${planCount} ${status}`,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Native `phase complete <N>` — mark the phase done in ROADMAP.md (checkbox +
|
|
307
|
+
* plan checkboxes + Plans line) and reflect completion in STATE.md (Status). The
|
|
308
|
+
* subprocess gates on a `passed` VERIFICATION; muonroi's caller writes that
|
|
309
|
+
* verification immediately before calling, so the gate is satisfied by
|
|
310
|
+
* construction — we still mark the ROADMAP/STATE so the workflow state is
|
|
311
|
+
* consistent. Returns {ok:false} when the phase / ROADMAP is missing.
|
|
312
|
+
*/
|
|
313
|
+
export function nativePhaseComplete(cwd, phaseNum) {
|
|
314
|
+
const dir = findPhaseDir(cwd, phaseNum);
|
|
315
|
+
if (!dir)
|
|
316
|
+
return { ok: false, error: `Phase ${phaseNum} not found` };
|
|
317
|
+
const roadmapPath = planningArtifact(cwd, "ROADMAP.md");
|
|
318
|
+
if (!existsSync(roadmapPath))
|
|
319
|
+
return { ok: false, error: "ROADMAP.md not found" };
|
|
320
|
+
const { planCount, summaryCount, summaryPlanIds } = phasePlanCounts(cwd, dir);
|
|
321
|
+
let text = readFileSync(roadmapPath, "utf8");
|
|
322
|
+
text = checkPhaseBox(text, phaseNum);
|
|
323
|
+
text = checkPlanBoxes(text, summaryPlanIds);
|
|
324
|
+
text = updatePlansLine(text, summaryCount, planCount, true);
|
|
325
|
+
writeFileSync(roadmapPath, text, "utf8");
|
|
326
|
+
// STATE.md — reflect completion on the body Status field (best-effort).
|
|
327
|
+
let stateUpdated = false;
|
|
328
|
+
const statePath = planningArtifact(cwd, "STATE.md");
|
|
329
|
+
if (existsSync(statePath)) {
|
|
330
|
+
const content = readFileSync(statePath, "utf8");
|
|
331
|
+
const m = content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
|
|
332
|
+
const body = m ? m[2] : content;
|
|
333
|
+
const fm = m ? m[1] : null;
|
|
334
|
+
const nextBody = stateReplaceField(body, "Status", normalizeStateStatus("Phase complete"));
|
|
335
|
+
if (nextBody !== null) {
|
|
336
|
+
const next = fm !== null ? `---\n${fm}\n---\n\n${nextBody.replace(/^\n+/, "")}` : nextBody;
|
|
337
|
+
writeFileSync(statePath, next, "utf8");
|
|
338
|
+
stateUpdated = true;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return { ok: true, completed_phase: phaseNum, roadmap_updated: true, state_updated: stateUpdated };
|
|
342
|
+
}
|
|
343
|
+
//# sourceMappingURL=native-roadmap.js.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* native-state.ts — Native replacements for the STATE.md-oriented gsd-tools
|
|
3
|
+
* subcommands (`state update`, `state json`, `init progress`).
|
|
4
|
+
*
|
|
5
|
+
* Part B: these fully replace the former `@opengsd/gsd-core` subprocess (removed
|
|
6
|
+
* in step 2). Output shapes follow the old gsd-tools `--raw`/JSON contract:
|
|
7
|
+
* state update → {updated:boolean, reason?}, state json → frontmatter object,
|
|
8
|
+
* init progress → progress projection.
|
|
9
|
+
*/
|
|
10
|
+
export interface StateUpdateResult {
|
|
11
|
+
updated: boolean;
|
|
12
|
+
reason?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Native `state update <field> <value>`.
|
|
16
|
+
* Mirrors gsd-core updateCore: strip frontmatter, `stateReplaceField` on the
|
|
17
|
+
* BODY only, reassemble. Returns {updated:false, reason} when the field is not
|
|
18
|
+
* present or STATE.md is missing (never throws). Caller invalidates cache.
|
|
19
|
+
*/
|
|
20
|
+
export declare function nativeStateUpdate(cwd: string, field: string, value: string): StateUpdateResult;
|
|
21
|
+
/**
|
|
22
|
+
* Native `state json` — frontmatter snapshot derived from STATE.md body fields
|
|
23
|
+
* + roadmap phase count. Note: gsd-core emits a fresh `last_updated` ISO stamp;
|
|
24
|
+
* we OMIT that non-deterministic field so consumers/tests get a stable object
|
|
25
|
+
* (workflow-engine only reads it loosely as `state_frontmatter`).
|
|
26
|
+
*/
|
|
27
|
+
export declare function nativeStateJson(cwd: string): Record<string, unknown>;
|
|
28
|
+
/**
|
|
29
|
+
* Native `init progress` — the projection consumed by workflow-engine.readProgress.
|
|
30
|
+
* Mirrors the subset of gsd-core's cmdInitProgress that muonroi actually reads:
|
|
31
|
+
* existence flags, phase list + counts, current/next phase.
|
|
32
|
+
*/
|
|
33
|
+
export declare function nativeInitProgress(cwd: string): Record<string, unknown>;
|
|
34
|
+
/** True when STATE.md exists (used by callers to decide native vs. bootstrap). */
|
|
35
|
+
export declare function stateFileMtime(cwd: string): number;
|
|
36
|
+
/**
|
|
37
|
+
* Native `config-ensure-section` — ensure the `.planning/` directory exists.
|
|
38
|
+
* muonroi's only caller (loop-host.ensureHost) invokes this immediately before
|
|
39
|
+
* `ensurePlanningWorkspace`, which writes the real model-bound config.json. So
|
|
40
|
+
* native config-ensure MUST NOT write a stub config here — that would shadow the
|
|
41
|
+
* proper config (ensurePlanningWorkspace only writes when config.json is absent).
|
|
42
|
+
* We just guarantee the directory, matching the pair's net effect.
|
|
43
|
+
*/
|
|
44
|
+
export declare function nativeConfigEnsure(cwd: string): {
|
|
45
|
+
ok: boolean;
|
|
46
|
+
created: boolean;
|
|
47
|
+
};
|