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,321 @@
|
|
|
1
|
+
import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { slugify } from "../utils/slugify.js";
|
|
4
|
+
import { logGsdNativeEvent } from "./ee-closure.js";
|
|
5
|
+
import { isGsdNativeEnabled } from "./flags.js";
|
|
6
|
+
import { dispatchPhaseAdd, dispatchPhaseComplete, dispatchRoadmapAnalyze, dispatchRoadmapPlanProgress, } from "./gsd-dispatch.js";
|
|
7
|
+
import { phaseDirPath, planningArtifact, planningPhasesRoot, planningRoot } from "./paths.js";
|
|
8
|
+
import { readState, readWorkflowKind, setStateField } from "./workflow-engine.js";
|
|
9
|
+
const MILESTONE_PHASE_DIR_FIELD = "Milestone Phase Dir";
|
|
10
|
+
export function extractPlanTitle(planBody) {
|
|
11
|
+
const h1 = planBody.match(/^#\s+(.+)$/m);
|
|
12
|
+
if (h1?.[1]?.trim())
|
|
13
|
+
return h1[1].trim().slice(0, 120);
|
|
14
|
+
const first = planBody.split("\n").find((l) => l.trim().length > 0);
|
|
15
|
+
return (first?.trim() ?? "Task").slice(0, 120);
|
|
16
|
+
}
|
|
17
|
+
export function derivePhaseSlug(title) {
|
|
18
|
+
return slugify(title).slice(0, 60) || "task";
|
|
19
|
+
}
|
|
20
|
+
export function findPhaseDirBySlug(cwd, slug) {
|
|
21
|
+
if (!existsSync(planningPhasesRoot(cwd)))
|
|
22
|
+
return null;
|
|
23
|
+
const needle = slug.toLowerCase();
|
|
24
|
+
for (const dir of readdirSync(planningPhasesRoot(cwd))) {
|
|
25
|
+
if (dir.toLowerCase().includes(needle))
|
|
26
|
+
return dir;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
export function readMilestonePhaseDir(cwd) {
|
|
31
|
+
const statePath = planningArtifact(cwd, "STATE.md");
|
|
32
|
+
if (!existsSync(statePath))
|
|
33
|
+
return null;
|
|
34
|
+
try {
|
|
35
|
+
const raw = readFileSync(statePath, "utf8");
|
|
36
|
+
const row = raw.match(/^\|\s*Milestone Phase Dir\s*\|\s*([^|\n]+?)\s*\|/im);
|
|
37
|
+
const val = row?.[1]?.trim();
|
|
38
|
+
return val && val !== "—" && val.length > 0 ? val : null;
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
console.error(`[gsd-phase-sync] readMilestonePhaseDir failed: ${err.message}`);
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function storeMilestonePhaseDir(cwd, dirName) {
|
|
46
|
+
setStateField(cwd, MILESTONE_PHASE_DIR_FIELD, dirName);
|
|
47
|
+
}
|
|
48
|
+
/** Minimal gsd-compatible ROADMAP required before `phase add`. */
|
|
49
|
+
export function ensureTaskRoadmap(cwd, milestoneTitle) {
|
|
50
|
+
const roadmapPath = planningArtifact(cwd, "ROADMAP.md");
|
|
51
|
+
if (existsSync(roadmapPath))
|
|
52
|
+
return;
|
|
53
|
+
const title = milestoneTitle.slice(0, 80) || "Task";
|
|
54
|
+
const stub = [
|
|
55
|
+
`# Roadmap: ${title}`,
|
|
56
|
+
"",
|
|
57
|
+
"## Overview",
|
|
58
|
+
"",
|
|
59
|
+
"Task-level GSD milestone — phases sync from native gsd_* workflow.",
|
|
60
|
+
"",
|
|
61
|
+
"## Phases",
|
|
62
|
+
"",
|
|
63
|
+
`- [ ] **Phase 1: ${title}** - In progress`,
|
|
64
|
+
"",
|
|
65
|
+
"## Phase Details",
|
|
66
|
+
"",
|
|
67
|
+
`### Phase 1: ${title}`,
|
|
68
|
+
"**Goal:** Ship scoped task via gsd-native workflow",
|
|
69
|
+
"**Depends on:** Nothing (first phase)",
|
|
70
|
+
"**Plans**: TBD",
|
|
71
|
+
"",
|
|
72
|
+
"Plans:",
|
|
73
|
+
"- [ ] 01-01: Task plan",
|
|
74
|
+
"",
|
|
75
|
+
].join("\n");
|
|
76
|
+
writeFileSync(roadmapPath, `${stub}\n`, "utf8");
|
|
77
|
+
}
|
|
78
|
+
function resolvePhaseDirName(cwd, addResult) {
|
|
79
|
+
const padded = addResult.phaseNumber.padStart(2, "0");
|
|
80
|
+
const dirs = readdirSync(planningPhasesRoot(cwd));
|
|
81
|
+
const match = dirs.find((d) => d.startsWith(`${padded}-`) || d.startsWith(`${addResult.phaseNumber}-`));
|
|
82
|
+
return match ?? null;
|
|
83
|
+
}
|
|
84
|
+
export function copyPlanToPhaseDir(cwd, phaseDirName, planBody) {
|
|
85
|
+
const dest = phaseDirPath(cwd, phaseDirName, "PLAN.md");
|
|
86
|
+
mkdirSync(join(planningPhasesRoot(cwd), phaseDirName), { recursive: true });
|
|
87
|
+
writeFileSync(dest, planBody.trim(), "utf8");
|
|
88
|
+
}
|
|
89
|
+
export function writePhaseVerificationPassed(cwd, phaseDirName, phaseNumber, evidence) {
|
|
90
|
+
const padded = phaseNumber.padStart(2, "0");
|
|
91
|
+
const fileName = `${padded}-VERIFICATION.md`;
|
|
92
|
+
const path = phaseDirPath(cwd, phaseDirName, fileName);
|
|
93
|
+
const body = [
|
|
94
|
+
"---",
|
|
95
|
+
"status: passed",
|
|
96
|
+
"---",
|
|
97
|
+
"",
|
|
98
|
+
"# Verification",
|
|
99
|
+
"",
|
|
100
|
+
evidence?.trim() || "Verified via gsd_verify (muonroi-cli native host).",
|
|
101
|
+
"",
|
|
102
|
+
].join("\n");
|
|
103
|
+
writeFileSync(path, body, "utf8");
|
|
104
|
+
return path;
|
|
105
|
+
}
|
|
106
|
+
export function writePhaseSummaryStub(cwd, phaseDirName, evidence) {
|
|
107
|
+
const path = phaseDirPath(cwd, phaseDirName, "SUMMARY.md");
|
|
108
|
+
const body = ["# Summary", "", evidence?.trim() || "Task verify passed — see VERIFY.md in .planning/.", ""].join("\n");
|
|
109
|
+
writeFileSync(path, body, "utf8");
|
|
110
|
+
return path;
|
|
111
|
+
}
|
|
112
|
+
function resolvePhaseNumberForComplete(cwd, phaseDirName) {
|
|
113
|
+
const analyze = dispatchRoadmapAnalyze(cwd);
|
|
114
|
+
if (analyze.ok && analyze.data?.current_phase) {
|
|
115
|
+
return String(analyze.data.current_phase).replace(/^0+/, "") || analyze.data.current_phase;
|
|
116
|
+
}
|
|
117
|
+
const token = phaseDirName.match(/^(\d+)/);
|
|
118
|
+
return token ? token[1].replace(/^0+/, "") || token[1] : "1";
|
|
119
|
+
}
|
|
120
|
+
/** After gsd_plan writes PLAN.md — task workflow only. */
|
|
121
|
+
export function syncTaskPhaseOnPlan(cwd, opts) {
|
|
122
|
+
const steps = [];
|
|
123
|
+
if (readWorkflowKind(cwd) === "product") {
|
|
124
|
+
return { ok: true, skipped: true, skipReason: "product", steps };
|
|
125
|
+
}
|
|
126
|
+
const slug = derivePhaseSlug(opts.planTitle);
|
|
127
|
+
let phaseDirName = readMilestonePhaseDir(cwd) ?? findPhaseDirBySlug(cwd, slug);
|
|
128
|
+
if (!phaseDirName) {
|
|
129
|
+
ensureTaskRoadmap(cwd, opts.planTitle);
|
|
130
|
+
const add = dispatchPhaseAdd(cwd, opts.planTitle);
|
|
131
|
+
steps.push({
|
|
132
|
+
op: "phase-add",
|
|
133
|
+
ok: add.ok,
|
|
134
|
+
detail: add.data?.phaseNumber,
|
|
135
|
+
error: add.error,
|
|
136
|
+
});
|
|
137
|
+
if (!add.ok || !add.data) {
|
|
138
|
+
return { ok: false, skipped: false, steps, error: add.error };
|
|
139
|
+
}
|
|
140
|
+
phaseDirName = resolvePhaseDirName(cwd, add.data);
|
|
141
|
+
if (!phaseDirName) {
|
|
142
|
+
return { ok: false, skipped: false, steps, error: "phase add succeeded but phase dir not found" };
|
|
143
|
+
}
|
|
144
|
+
storeMilestonePhaseDir(cwd, phaseDirName);
|
|
145
|
+
logGsdNativeEvent(opts.sessionId ?? "gsd-native", {
|
|
146
|
+
phase: "plan",
|
|
147
|
+
depth: null,
|
|
148
|
+
loopPoint: "phase-sync:plan",
|
|
149
|
+
phaseNumber: add.data.phaseNumber,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
steps.push({ op: "phase-add", ok: true, detail: "skipped-existing-dir" });
|
|
154
|
+
}
|
|
155
|
+
try {
|
|
156
|
+
copyPlanToPhaseDir(cwd, phaseDirName, opts.planBody);
|
|
157
|
+
steps.push({ op: "copy-plan", ok: true, detail: phaseDirName });
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
steps.push({ op: "copy-plan", ok: false, error: err.message });
|
|
161
|
+
return { ok: false, skipped: false, phaseDirName, steps };
|
|
162
|
+
}
|
|
163
|
+
return { ok: true, skipped: false, phaseDirName, steps };
|
|
164
|
+
}
|
|
165
|
+
/** After gsd_verify pass — task workflow only. */
|
|
166
|
+
export function syncTaskPhaseOnVerifyPass(cwd, opts) {
|
|
167
|
+
const steps = [];
|
|
168
|
+
if (readWorkflowKind(cwd) === "product") {
|
|
169
|
+
return { ok: true, skipped: true, skipReason: "product", steps };
|
|
170
|
+
}
|
|
171
|
+
const phaseDirName = readMilestonePhaseDir(cwd) ?? latestPhaseDirName(cwd);
|
|
172
|
+
if (!phaseDirName) {
|
|
173
|
+
steps.push({ op: "phase-complete", ok: false, error: "no milestone phase dir" });
|
|
174
|
+
return { ok: false, skipped: false, steps };
|
|
175
|
+
}
|
|
176
|
+
const phaseNum = resolvePhaseNumberForComplete(cwd, phaseDirName);
|
|
177
|
+
try {
|
|
178
|
+
writePhaseSummaryStub(cwd, phaseDirName, opts?.evidence);
|
|
179
|
+
writePhaseVerificationPassed(cwd, phaseDirName, phaseNum, opts?.evidence);
|
|
180
|
+
steps.push({ op: "write-verification", ok: true });
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
steps.push({ op: "write-verification", ok: false, error: err.message });
|
|
184
|
+
return { ok: false, skipped: false, phaseDirName, steps };
|
|
185
|
+
}
|
|
186
|
+
const complete = dispatchPhaseComplete(cwd, phaseNum);
|
|
187
|
+
steps.push({ op: "phase-complete", ok: complete.ok, error: complete.error });
|
|
188
|
+
if (!complete.ok) {
|
|
189
|
+
return { ok: false, skipped: false, phaseNumber: phaseNum, phaseDirName, steps };
|
|
190
|
+
}
|
|
191
|
+
const progress = dispatchRoadmapPlanProgress(cwd, phaseNum);
|
|
192
|
+
steps.push({ op: "roadmap-progress", ok: progress.ok, detail: progress.raw?.trim(), error: progress.error });
|
|
193
|
+
logGsdNativeEvent(opts?.sessionId ?? "gsd-native", {
|
|
194
|
+
phase: "verify",
|
|
195
|
+
depth: null,
|
|
196
|
+
loopPoint: "phase-sync:verify",
|
|
197
|
+
phaseNumber: phaseNum,
|
|
198
|
+
});
|
|
199
|
+
return {
|
|
200
|
+
ok: progress.ok,
|
|
201
|
+
skipped: false,
|
|
202
|
+
phaseNumber: phaseNum,
|
|
203
|
+
phaseDirName,
|
|
204
|
+
steps,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function latestPhaseDirName(cwd) {
|
|
208
|
+
if (!existsSync(planningPhasesRoot(cwd)))
|
|
209
|
+
return null;
|
|
210
|
+
const dirs = readdirSync(planningPhasesRoot(cwd)).sort();
|
|
211
|
+
return dirs.length ? dirs[dirs.length - 1] : null;
|
|
212
|
+
}
|
|
213
|
+
/** Copy root VERIFY.md into phase dir when present (best-effort). */
|
|
214
|
+
export function mirrorVerifyMdToPhaseDir(cwd, phaseDirName) {
|
|
215
|
+
const src = planningArtifact(cwd, "VERIFY.md");
|
|
216
|
+
if (!existsSync(src))
|
|
217
|
+
return;
|
|
218
|
+
const dest = phaseDirPath(cwd, phaseDirName, "VERIFY.md");
|
|
219
|
+
try {
|
|
220
|
+
copyFileSync(src, dest);
|
|
221
|
+
}
|
|
222
|
+
catch (err) {
|
|
223
|
+
console.error(`[gsd-phase-sync] mirror VERIFY.md failed: ${err.message}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/** Automatically append user AskCard answers as clarifications to CONTEXT.md under GSD. */
|
|
227
|
+
export function appendClarificationToContext(cwd, question, answer) {
|
|
228
|
+
const planningDir = planningRoot(cwd);
|
|
229
|
+
if (!existsSync(planningDir))
|
|
230
|
+
return;
|
|
231
|
+
const contextPath = join(planningDir, "CONTEXT.md");
|
|
232
|
+
let prior = "";
|
|
233
|
+
if (existsSync(contextPath)) {
|
|
234
|
+
prior = readFileSync(contextPath, "utf8");
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
prior = "# CONTEXT\n\n## Clarifications\n\n";
|
|
238
|
+
}
|
|
239
|
+
const cleanQuestion = question.replace(/^Question:\s*/i, "").trim();
|
|
240
|
+
const entry = `### Clarification\n**Q**: ${cleanQuestion}\n**A**: ${answer.trim()}\n\n`;
|
|
241
|
+
writeFileSync(contextPath, prior + entry, "utf8");
|
|
242
|
+
}
|
|
243
|
+
/** Build TaskListSnapshot directly from GSD PLAN.md and STATE.md for automatic TUI checklist synchronization. */
|
|
244
|
+
export function getTaskListSnapshotFromGsd(cwd) {
|
|
245
|
+
if (!isGsdNativeEnabled())
|
|
246
|
+
return null;
|
|
247
|
+
const planPath = join(planningRoot(cwd), "PLAN.md");
|
|
248
|
+
if (!existsSync(planPath))
|
|
249
|
+
return null;
|
|
250
|
+
try {
|
|
251
|
+
const content = readFileSync(planPath, "utf8");
|
|
252
|
+
const state = readState(cwd);
|
|
253
|
+
const lines = content.split(/\r?\n/);
|
|
254
|
+
const items = [];
|
|
255
|
+
// Regex to match markdown checklist items or numbered list items
|
|
256
|
+
const checkboxRegex = /^\s*[-*+]\s*\[([ xX/])\]\s*(.+)$/;
|
|
257
|
+
const numberedRegex = /^\s*(\d+)\.\s*(.+)$/;
|
|
258
|
+
let itemIndex = 0;
|
|
259
|
+
for (const line of lines) {
|
|
260
|
+
const checkboxMatch = line.match(checkboxRegex);
|
|
261
|
+
if (checkboxMatch) {
|
|
262
|
+
const marker = checkboxMatch[1];
|
|
263
|
+
const subject = checkboxMatch[2].trim();
|
|
264
|
+
let status = "pending";
|
|
265
|
+
if (marker === "x" || marker === "X") {
|
|
266
|
+
status = "completed";
|
|
267
|
+
}
|
|
268
|
+
else if (marker === "/") {
|
|
269
|
+
status = "in_progress";
|
|
270
|
+
}
|
|
271
|
+
items.push({
|
|
272
|
+
id: `gsd_${itemIndex++}`,
|
|
273
|
+
subject,
|
|
274
|
+
status,
|
|
275
|
+
});
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
const numberedMatch = line.match(numberedRegex);
|
|
279
|
+
if (numberedMatch) {
|
|
280
|
+
const subject = numberedMatch[2].trim();
|
|
281
|
+
items.push({
|
|
282
|
+
id: `gsd_${itemIndex++}`,
|
|
283
|
+
subject,
|
|
284
|
+
status: "pending",
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (items.length === 0)
|
|
289
|
+
return null;
|
|
290
|
+
// Adjust statuses based on active phase
|
|
291
|
+
if (state.phase === "execute" && !items.some((it) => it.status === "in_progress")) {
|
|
292
|
+
const firstPending = items.find((it) => it.status === "pending");
|
|
293
|
+
if (firstPending) {
|
|
294
|
+
firstPending.status = "in_progress";
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
else if (state.phase === "verify" || state.phase === "review") {
|
|
298
|
+
for (const item of items) {
|
|
299
|
+
if (item.status === "in_progress" || item.status === "pending") {
|
|
300
|
+
item.status = "completed";
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const counts = {
|
|
305
|
+
completed: items.filter((it) => it.status === "completed").length,
|
|
306
|
+
inProgress: items.filter((it) => it.status === "in_progress").length,
|
|
307
|
+
pending: items.filter((it) => it.status === "pending").length,
|
|
308
|
+
total: items.length,
|
|
309
|
+
};
|
|
310
|
+
return {
|
|
311
|
+
items,
|
|
312
|
+
counts,
|
|
313
|
+
ts: Date.now(),
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
catch (err) {
|
|
317
|
+
console.error(`[gsd-plan-parser] failed to parse PLAN.md: ${err.message}`);
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
//# sourceMappingURL=phase-sync.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface GateContextInput {
|
|
2
|
+
cwd: string;
|
|
3
|
+
conversationDigest?: string | null;
|
|
4
|
+
brainData?: unknown;
|
|
5
|
+
}
|
|
6
|
+
export interface GateContextBundle {
|
|
7
|
+
conversationDigest: string;
|
|
8
|
+
eeContext: string;
|
|
9
|
+
priorPlan: string;
|
|
10
|
+
projectHints: string;
|
|
11
|
+
totalChars: number;
|
|
12
|
+
}
|
|
13
|
+
export declare function buildGateContextBundle(input: GateContextInput): GateContextBundle;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { planningArtifact } from "./paths.js";
|
|
3
|
+
import { readState } from "./workflow-engine.js";
|
|
4
|
+
function cap(text, max) {
|
|
5
|
+
const t = (text ?? "").trim();
|
|
6
|
+
if (t.length <= max)
|
|
7
|
+
return t;
|
|
8
|
+
const suffix = "…[truncated]";
|
|
9
|
+
const keep = Math.max(0, max - suffix.length);
|
|
10
|
+
return `${t.slice(0, keep)}${suffix}`;
|
|
11
|
+
}
|
|
12
|
+
/** Render EE recall (BrainData shape from layer1's pilContext fetch) into a compact block. */
|
|
13
|
+
function formatEeContext(brainData) {
|
|
14
|
+
if (!brainData || typeof brainData !== "object")
|
|
15
|
+
return "";
|
|
16
|
+
const b = brainData;
|
|
17
|
+
const principles = Array.isArray(b.t0_principles) ? b.t0_principles.map(String) : [];
|
|
18
|
+
const patterns = Array.isArray(b.t2_patterns) ? b.t2_patterns.map(String) : [];
|
|
19
|
+
const rules = Array.isArray(b.t1_rules) ? b.t1_rules.map(String) : [];
|
|
20
|
+
const lines = [
|
|
21
|
+
...principles.slice(0, 3).map((p) => `- principle: ${p}`),
|
|
22
|
+
...rules.slice(0, 3).map((r) => `- rule: ${r}`),
|
|
23
|
+
...patterns.slice(0, 3).map((p) => `- pattern: ${p}`),
|
|
24
|
+
];
|
|
25
|
+
return cap(lines.join("\n"), 600);
|
|
26
|
+
}
|
|
27
|
+
function readPriorPlan(cwd) {
|
|
28
|
+
const p = planningArtifact(cwd, "PLAN.md");
|
|
29
|
+
if (!existsSync(p))
|
|
30
|
+
return "";
|
|
31
|
+
let phase = "";
|
|
32
|
+
try {
|
|
33
|
+
phase = readState(cwd).phase ?? "";
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
console.error(`[pil-gate] readState for prior-plan phase failed: ${err.message}`);
|
|
37
|
+
}
|
|
38
|
+
const body = cap(readFileSync(p, "utf8"), 800);
|
|
39
|
+
return phase ? `phase: ${phase}\n${body}` : body;
|
|
40
|
+
}
|
|
41
|
+
export function buildGateContextBundle(input) {
|
|
42
|
+
const conversationDigest = cap(input.conversationDigest ?? "", 1200);
|
|
43
|
+
let eeContext = "";
|
|
44
|
+
try {
|
|
45
|
+
eeContext = formatEeContext(input.brainData);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
console.error(`[pil-gate] formatEeContext failed: ${err.message}`);
|
|
49
|
+
}
|
|
50
|
+
let priorPlan = "";
|
|
51
|
+
try {
|
|
52
|
+
priorPlan = readPriorPlan(input.cwd);
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
console.error(`[pil-gate] readPriorPlan failed: ${err.message}`);
|
|
56
|
+
}
|
|
57
|
+
// projectHints intentionally left "" in v1: the discovery ProjectContext scan is
|
|
58
|
+
// directory-level only (REPO_DEEP_MAP §src/pil) and produces mislead-prone
|
|
59
|
+
// substring matches. Hedged hints are the producer's job, not asserted here.
|
|
60
|
+
const projectHints = "";
|
|
61
|
+
const totalChars = conversationDigest.length + eeContext.length + priorPlan.length + projectHints.length;
|
|
62
|
+
return { conversationDigest, eeContext, priorPlan, projectHints, totalChars };
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=pil-gate-context.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { GateContextBundle } from "./pil-gate-context.js";
|
|
2
|
+
export type GateVerdict = "adequate" | "enriched" | "needs-user";
|
|
3
|
+
export interface CriticResult {
|
|
4
|
+
verdict: GateVerdict;
|
|
5
|
+
brief: string;
|
|
6
|
+
}
|
|
7
|
+
export type RunCriticFn = (prompt: string) => Promise<string>;
|
|
8
|
+
declare const CRITIC_ROLES: readonly ["grounding", "noise", "sufficiency"];
|
|
9
|
+
type CriticRole = (typeof CRITIC_ROLES)[number];
|
|
10
|
+
export declare function buildCriticPrompt(role: CriticRole, draftBrief: string, draftVerdict: GateVerdict, bundle: GateContextBundle): string;
|
|
11
|
+
/** Worst-wins AND downgrade-only: the result is never less severe than the producer verdict. */
|
|
12
|
+
export declare function mergeCriticVerdicts(producer: GateVerdict, criticVerdicts: GateVerdict[]): GateVerdict;
|
|
13
|
+
export declare function runGateCritics(args: {
|
|
14
|
+
draftBrief: string;
|
|
15
|
+
draftVerdict: GateVerdict;
|
|
16
|
+
bundle: GateContextBundle;
|
|
17
|
+
runCritic: RunCriticFn;
|
|
18
|
+
}): Promise<CriticResult>;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const RANK = { adequate: 0, enriched: 1, "needs-user": 2 };
|
|
2
|
+
const CRITIC_ROLES = ["grounding", "noise", "sufficiency"];
|
|
3
|
+
const ROLE_MANDATE = {
|
|
4
|
+
grounding: "Strip any claim not traceable to the provided context. Flag ANY area/file reference not explicitly hedged as 'confirm via grep before anchoring' — an asserted file path is a defect.",
|
|
5
|
+
noise: "Strip any line that does not change what the coding agent does. If most of the brief is noise, downgrade the verdict.",
|
|
6
|
+
sufficiency: "Decide whether 'adequate' is honest or a blocker (intent/target/scope/acceptance) is being papered over. You may flip to needs-user; you may NOT upgrade toward adequate.",
|
|
7
|
+
};
|
|
8
|
+
export function buildCriticPrompt(role, draftBrief, draftVerdict, bundle) {
|
|
9
|
+
return [
|
|
10
|
+
`You are the ${role} critic for a prompt-enrichment gate. You may only TIGHTEN — downgrade the verdict and strip lines, never upgrade or add.`,
|
|
11
|
+
ROLE_MANDATE[role],
|
|
12
|
+
"",
|
|
13
|
+
"Provided context (the ONLY sources the brief may draw on):",
|
|
14
|
+
bundle.conversationDigest ? `Recent conversation:\n${bundle.conversationDigest}` : "(no recent conversation)",
|
|
15
|
+
bundle.eeContext ? `EE recall:\n${bundle.eeContext}` : "(no EE recall)",
|
|
16
|
+
bundle.priorPlan ? `Prior plan:\n${bundle.priorPlan}` : "(no prior plan)",
|
|
17
|
+
bundle.projectHints ? `Project hints:\n${bundle.projectHints}` : "(no project hints)",
|
|
18
|
+
"",
|
|
19
|
+
`Producer verdict: ${draftVerdict}`,
|
|
20
|
+
"Producer brief:",
|
|
21
|
+
draftBrief || "(empty)",
|
|
22
|
+
"",
|
|
23
|
+
"Respond with ONLY a fenced block:",
|
|
24
|
+
"```gate-critic",
|
|
25
|
+
'{ "verdict": "adequate|enriched|needs-user", "strippedBrief": "the brief with noise/ungrounded/unhedged lines removed" }',
|
|
26
|
+
"```",
|
|
27
|
+
].join("\n");
|
|
28
|
+
}
|
|
29
|
+
function parseCritic(raw) {
|
|
30
|
+
const m = raw.match(/```gate-critic\s*([\s\S]*?)```/);
|
|
31
|
+
const body = m?.[1] ?? raw;
|
|
32
|
+
const brace = body.match(/\{[\s\S]*\}/);
|
|
33
|
+
if (!brace)
|
|
34
|
+
return null;
|
|
35
|
+
try {
|
|
36
|
+
const parsed = JSON.parse(brace[0]);
|
|
37
|
+
if (parsed.verdict !== "adequate" && parsed.verdict !== "enriched" && parsed.verdict !== "needs-user")
|
|
38
|
+
return null;
|
|
39
|
+
return { verdict: parsed.verdict, strippedBrief: String(parsed.strippedBrief ?? "") };
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
console.error(`[pil-gate] critic parse failed: ${err.message}`);
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** Worst-wins AND downgrade-only: the result is never less severe than the producer verdict. */
|
|
47
|
+
export function mergeCriticVerdicts(producer, criticVerdicts) {
|
|
48
|
+
let worst = producer;
|
|
49
|
+
for (const v of criticVerdicts) {
|
|
50
|
+
if (RANK[v] > RANK[worst])
|
|
51
|
+
worst = v;
|
|
52
|
+
}
|
|
53
|
+
return worst;
|
|
54
|
+
}
|
|
55
|
+
export async function runGateCritics(args) {
|
|
56
|
+
const settled = await Promise.all(CRITIC_ROLES.map((role) => args
|
|
57
|
+
.runCritic(buildCriticPrompt(role, args.draftBrief, args.draftVerdict, args.bundle))
|
|
58
|
+
.then((raw) => parseCritic(raw))
|
|
59
|
+
.catch((err) => {
|
|
60
|
+
console.error(`[pil-gate] critic ${role} threw: ${err.message}`);
|
|
61
|
+
return null;
|
|
62
|
+
})));
|
|
63
|
+
// Parse/throw failure is conservative: a null critic votes needs-user and keeps the producer brief.
|
|
64
|
+
const verdicts = settled.map((r) => r?.verdict ?? "needs-user");
|
|
65
|
+
const verdict = mergeCriticVerdicts(args.draftVerdict, verdicts);
|
|
66
|
+
// Prefer the shortest surviving stripped brief (most noise removed) among successful critics;
|
|
67
|
+
// fall back to the producer brief when none parsed.
|
|
68
|
+
const stripped = settled
|
|
69
|
+
.filter((r) => r !== null && r.strippedBrief.trim().length > 0)
|
|
70
|
+
.map((r) => r.strippedBrief)
|
|
71
|
+
.sort((a, b) => a.length - b.length)[0];
|
|
72
|
+
return { verdict, brief: (stripped ?? args.draftBrief).slice(0, 1500) };
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=pil-gate-critic.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { CouncilContextBundle } from "./council-context.js";
|
|
2
|
+
import { type PlanGateDimensionId } from "./plan-gate-vocabulary.js";
|
|
3
|
+
export type PlanPerspectiveId = "architect" | "skeptic" | "research" | "security" | "implementer";
|
|
4
|
+
export interface PlanPerspective {
|
|
5
|
+
id: PlanPerspectiveId;
|
|
6
|
+
role: string;
|
|
7
|
+
mandate: string;
|
|
8
|
+
/**
|
|
9
|
+
* The shared gate axis this perspective primarily owns. Ties the headless
|
|
10
|
+
* perspective set to the same criteria the interactive debate uses; the full
|
|
11
|
+
* perspective set must cover every PLAN_GATE_DIMENSION (parity-tested).
|
|
12
|
+
*/
|
|
13
|
+
dimension: PlanGateDimensionId;
|
|
14
|
+
}
|
|
15
|
+
export declare const PLAN_PERSPECTIVES: PlanPerspective[];
|
|
16
|
+
export declare function perspectivesForDepth(depth: string): PlanPerspective[];
|
|
17
|
+
export declare function buildPerspectivePrompt(perspective: PlanPerspective, planBody: string, bundle?: CouncilContextBundle): string;
|
|
18
|
+
/**
|
|
19
|
+
* Build the debate topic fed to the council leader. Bundles prior GSD context
|
|
20
|
+
* (discuss notes, research, acceptance criteria, prior concerns) with the
|
|
21
|
+
* draft plan and the model-first output contract — the leader MUST end its
|
|
22
|
+
* synthesis with a ```council-verdict fenced block; extraction falls back
|
|
23
|
+
* conservatively when it doesn't.
|
|
24
|
+
*/
|
|
25
|
+
export declare function buildDebateTopic(planBody: string, bundle: CouncilContextBundle): string;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { renderCouncilContextBlock } from "./council-context.js";
|
|
2
|
+
import { renderGateAxes } from "./plan-gate-vocabulary.js";
|
|
3
|
+
import { VERDICT_OUTPUT_CONTRACT } from "./verdict-schema.js";
|
|
4
|
+
export const PLAN_PERSPECTIVES = [
|
|
5
|
+
{
|
|
6
|
+
id: "architect",
|
|
7
|
+
role: "architect",
|
|
8
|
+
mandate: "Structural fit, file map correctness, dependency order, module boundaries.",
|
|
9
|
+
dimension: "structure",
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
id: "skeptic",
|
|
13
|
+
role: "devil's advocate",
|
|
14
|
+
mandate: "Challenge assumptions, missing edge cases, YAGNI violations, scope creep.",
|
|
15
|
+
dimension: "feasibility",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: "research",
|
|
19
|
+
role: "researcher",
|
|
20
|
+
mandate: "Ground plan claims against codebase evidence (file:line citations required).",
|
|
21
|
+
dimension: "grounding",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: "security",
|
|
25
|
+
role: "security reviewer",
|
|
26
|
+
mandate: "Permission model, path traversal, secret handling, dangerous bash patterns in planned edits.",
|
|
27
|
+
dimension: "safety",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: "implementer",
|
|
31
|
+
role: "implementer",
|
|
32
|
+
mandate: "Feasibility, estimate realism, testability of acceptance criteria.",
|
|
33
|
+
dimension: "correctness",
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
export function perspectivesForDepth(depth) {
|
|
37
|
+
if (depth === "quick")
|
|
38
|
+
return [];
|
|
39
|
+
if (depth === "standard") {
|
|
40
|
+
return PLAN_PERSPECTIVES.filter((p) => p.id === "research" || p.id === "skeptic");
|
|
41
|
+
}
|
|
42
|
+
return PLAN_PERSPECTIVES;
|
|
43
|
+
}
|
|
44
|
+
export function buildPerspectivePrompt(perspective, planBody, bundle) {
|
|
45
|
+
const lines = [`You are the ${perspective.role} on a plan review council.`, `Mandate: ${perspective.mandate}`];
|
|
46
|
+
if (bundle) {
|
|
47
|
+
lines.push("", renderCouncilContextBlock(bundle, { forPerspective: perspective.id }));
|
|
48
|
+
}
|
|
49
|
+
lines.push("",
|
|
50
|
+
// Shared gate axes (single source with the interactive debate) so headless
|
|
51
|
+
// and interactive reviews judge the plan against identical criteria.
|
|
52
|
+
renderGateAxes(), "", "Review the draft PLAN.md below, then emit your structured verdict.", VERDICT_OUTPUT_CONTRACT, "", "--- PLAN.md ---", planBody, "--- END PLAN ---");
|
|
53
|
+
return lines.join("\n");
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Build the debate topic fed to the council leader. Bundles prior GSD context
|
|
57
|
+
* (discuss notes, research, acceptance criteria, prior concerns) with the
|
|
58
|
+
* draft plan and the model-first output contract — the leader MUST end its
|
|
59
|
+
* synthesis with a ```council-verdict fenced block; extraction falls back
|
|
60
|
+
* conservatively when it doesn't.
|
|
61
|
+
*/
|
|
62
|
+
export function buildDebateTopic(planBody, bundle) {
|
|
63
|
+
return [
|
|
64
|
+
"Review and debate the proposed plan to determine if it is complete, correct, safe, and optimal for the task.",
|
|
65
|
+
"Debate the trade-offs, then converge on a single merged verdict.",
|
|
66
|
+
"",
|
|
67
|
+
// Shared gate axes (single source with the headless perspective review) so
|
|
68
|
+
// both gate paths judge the plan against identical criteria — no drift.
|
|
69
|
+
renderGateAxes(),
|
|
70
|
+
"",
|
|
71
|
+
renderCouncilContextBlock(bundle),
|
|
72
|
+
"",
|
|
73
|
+
"### Proposed PLAN.md:",
|
|
74
|
+
planBody.trim(),
|
|
75
|
+
"",
|
|
76
|
+
VERDICT_OUTPUT_CONTRACT,
|
|
77
|
+
].join("\n");
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=plan-council-prompts.js.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ToolResult } from "../types/index.js";
|
|
2
|
+
import { type PlanPerspective, type PlanPerspectiveId } from "./plan-council-prompts.js";
|
|
3
|
+
export type PerspectiveVerdict = "approve" | "revise" | "block";
|
|
4
|
+
export type VerdictSource = "structured" | "heuristic-fallback" | "parse-failed";
|
|
5
|
+
export interface PerspectiveResult {
|
|
6
|
+
id: PlanPerspectiveId;
|
|
7
|
+
role: string;
|
|
8
|
+
verdict: PerspectiveVerdict;
|
|
9
|
+
concerns: string[];
|
|
10
|
+
evidence: string[];
|
|
11
|
+
/** Where the verdict came from — model-emitted JSON or heuristic fallback. */
|
|
12
|
+
source: VerdictSource;
|
|
13
|
+
raw?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface PlanCouncilResult {
|
|
16
|
+
skipped: boolean;
|
|
17
|
+
perspectives: PerspectiveResult[];
|
|
18
|
+
planReviewPath?: string;
|
|
19
|
+
planVerifyPath?: string;
|
|
20
|
+
verdict: PerspectiveVerdict | "pass";
|
|
21
|
+
leaderModelId?: string;
|
|
22
|
+
revisionRequired: boolean;
|
|
23
|
+
/** Chars of GSD context fed to council (telemetry — surfaces grounding quality). */
|
|
24
|
+
contextBundleChars?: number;
|
|
25
|
+
/** True when prior PLAN-REVIEW concerns were surfaced to council. */
|
|
26
|
+
hadPriorConcerns?: boolean;
|
|
27
|
+
/** Where the merged verdict came from. */
|
|
28
|
+
verdictSource?: VerdictSource;
|
|
29
|
+
/** True when no structured verdict could be extracted (debate path). */
|
|
30
|
+
verdictParseFailed?: boolean;
|
|
31
|
+
}
|
|
32
|
+
export type RunPerspectiveFn = (prompt: string, perspective: PlanPerspective) => Promise<string>;
|
|
33
|
+
export interface PlanCouncilOpts {
|
|
34
|
+
cwd: string;
|
|
35
|
+
sessionModelId: string;
|
|
36
|
+
depth: string;
|
|
37
|
+
/** Optional LLM runner for perspective sub-agents (tests use heuristic when omitted). */
|
|
38
|
+
runPerspectiveFn?: RunPerspectiveFn;
|
|
39
|
+
revisionCycle?: number;
|
|
40
|
+
runDebate?: (topic: string) => Promise<string>;
|
|
41
|
+
}
|
|
42
|
+
export declare function runPlanCouncil(opts: PlanCouncilOpts): Promise<PlanCouncilResult>;
|
|
43
|
+
/** Adapter: wrap orchestrator runTask as perspective runner. */
|
|
44
|
+
export declare function taskToPerspectiveRunner(runTask: (request: import("../types/index.js").TaskRequest) => Promise<ToolResult>, sessionModelId: string): RunPerspectiveFn;
|