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.
Files changed (477) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +133 -122
  3. package/dist/packages/agent-harness-core/src/driver.d.ts +27 -1
  4. package/dist/packages/agent-harness-core/src/driver.js +46 -0
  5. package/dist/packages/agent-harness-core/src/event-tee.d.ts +48 -0
  6. package/dist/packages/agent-harness-core/src/event-tee.js +77 -0
  7. package/dist/packages/agent-harness-core/src/mcp-server.d.ts +11 -0
  8. package/dist/packages/agent-harness-core/src/mcp-server.js +87 -15
  9. package/dist/packages/agent-harness-core/src/protocol.d.ts +66 -2
  10. package/dist/packages/agent-harness-core/src/protocol.js +15 -0
  11. package/dist/packages/agent-harness-core/src/visual-quality.d.ts +58 -0
  12. package/dist/packages/agent-harness-core/src/visual-quality.js +141 -0
  13. package/dist/packages/agent-harness-opentui/src/agent-mode.d.ts +6 -0
  14. package/dist/packages/agent-harness-opentui/src/agent-mode.js +14 -1
  15. package/dist/packages/agent-harness-opentui/src/input-bridge.d.ts +2 -10
  16. package/dist/packages/agent-harness-opentui/src/input-bridge.js +103 -16
  17. package/dist/packages/agent-harness-opentui/src/install.d.ts +8 -0
  18. package/dist/packages/agent-harness-opentui/src/install.js +10 -0
  19. package/dist/packages/agent-harness-opentui/src/semantic.js +12 -10
  20. package/dist/packages/agent-harness-opentui/src/visual-capture.d.ts +56 -0
  21. package/dist/packages/agent-harness-opentui/src/visual-capture.js +103 -0
  22. package/dist/src/agent-harness/mock-model.d.ts +28 -0
  23. package/dist/src/agent-harness/mock-model.js +63 -1
  24. package/dist/src/agent-harness/test-spawn.js +31 -0
  25. package/dist/src/cli/config/screen-providers.js +1 -1
  26. package/dist/src/cli/cost-forensics.d.ts +10 -0
  27. package/dist/src/cli/cost-forensics.js +30 -15
  28. package/dist/src/cli/keys-bundle.d.ts +1 -1
  29. package/dist/src/cli/keys-bundle.js +1 -1
  30. package/dist/src/cli/keys.d.ts +2 -2
  31. package/dist/src/cli/keys.js +19 -81
  32. package/dist/src/council/clarifier.d.ts +28 -2
  33. package/dist/src/council/clarifier.js +81 -15
  34. package/dist/src/council/context.js +49 -15
  35. package/dist/src/council/debate-checkpoint.d.ts +129 -0
  36. package/dist/src/council/debate-checkpoint.js +176 -0
  37. package/dist/src/council/debate-planner.js +51 -3
  38. package/dist/src/council/debate-summary.d.ts +25 -0
  39. package/dist/src/council/debate-summary.js +85 -0
  40. package/dist/src/council/debate.d.ts +169 -2
  41. package/dist/src/council/debate.js +1210 -134
  42. package/dist/src/council/index.d.ts +85 -1
  43. package/dist/src/council/index.js +634 -196
  44. package/dist/src/council/leader.d.ts +26 -0
  45. package/dist/src/council/leader.js +150 -9
  46. package/dist/src/council/llm.d.ts +32 -0
  47. package/dist/src/council/llm.js +231 -38
  48. package/dist/src/council/panel-select.d.ts +30 -0
  49. package/dist/src/council/panel-select.js +72 -0
  50. package/dist/src/council/planner.js +23 -0
  51. package/dist/src/council/preflight.d.ts +7 -0
  52. package/dist/src/council/preflight.js +14 -2
  53. package/dist/src/council/prompts.d.ts +30 -3
  54. package/dist/src/council/prompts.js +254 -84
  55. package/dist/src/council/stance-recall.d.ts +42 -0
  56. package/dist/src/council/stance-recall.js +57 -0
  57. package/dist/src/council/strip-think.d.ts +17 -0
  58. package/dist/src/council/strip-think.js +33 -0
  59. package/dist/src/council/types.d.ts +128 -0
  60. package/dist/src/ee/artifact-cache.d.ts +16 -0
  61. package/dist/src/ee/artifact-cache.js +32 -0
  62. package/dist/src/ee/auth.d.ts +1 -0
  63. package/dist/src/ee/auth.js +15 -2
  64. package/dist/src/ee/bridge.d.ts +10 -0
  65. package/dist/src/ee/bridge.js +58 -0
  66. package/dist/src/ee/client.js +81 -18
  67. package/dist/src/ee/export-transcripts.d.ts +1 -0
  68. package/dist/src/ee/export-transcripts.js +8 -10
  69. package/dist/src/ee/extract-session.js +29 -0
  70. package/dist/src/ee/extract-style.d.ts +58 -0
  71. package/dist/src/ee/extract-style.js +270 -0
  72. package/dist/src/ee/recall-ledger.d.ts +9 -0
  73. package/dist/src/ee/recall-ledger.js +3 -0
  74. package/dist/src/ee/scope.d.ts +1 -0
  75. package/dist/src/ee/scope.js +26 -1
  76. package/dist/src/ee/search.d.ts +7 -0
  77. package/dist/src/ee/search.js +24 -0
  78. package/dist/src/ee/transcript-emit.js +2 -0
  79. package/dist/src/ee/types.d.ts +22 -0
  80. package/dist/src/ee/who-am-i-brain.d.ts +35 -0
  81. package/dist/src/ee/who-am-i-brain.js +220 -0
  82. package/dist/src/ee/who-am-i.d.ts +10 -3
  83. package/dist/src/ee/who-am-i.js +12 -0
  84. package/dist/src/ee/workflow-event.d.ts +48 -0
  85. package/dist/src/ee/workflow-event.js +81 -0
  86. package/dist/src/flow/compaction/compress.d.ts +3 -3
  87. package/dist/src/flow/compaction/compress.js +45 -8
  88. package/dist/src/flow/compaction/extract.d.ts +4 -7
  89. package/dist/src/flow/compaction/extract.js +50 -10
  90. package/dist/src/flow/compaction/index.d.ts +13 -1
  91. package/dist/src/flow/compaction/index.js +70 -3
  92. package/dist/src/flow/compaction/input-guard.d.ts +24 -0
  93. package/dist/src/flow/compaction/input-guard.js +43 -0
  94. package/dist/src/flow/fold-planning.d.ts +36 -0
  95. package/dist/src/flow/fold-planning.js +83 -0
  96. package/dist/src/flow/hierarchy.d.ts +146 -0
  97. package/dist/src/flow/hierarchy.js +427 -0
  98. package/dist/src/flow/index.d.ts +1 -0
  99. package/dist/src/flow/index.js +2 -0
  100. package/dist/src/flow/run-artifacts.d.ts +102 -0
  101. package/dist/src/flow/run-artifacts.js +208 -0
  102. package/dist/src/generated/version.d.ts +1 -1
  103. package/dist/src/generated/version.js +1 -1
  104. package/dist/src/gsd/assessment-schema.d.ts +44 -0
  105. package/dist/src/gsd/assessment-schema.js +134 -0
  106. package/dist/src/gsd/capability-registry.d.ts +45 -0
  107. package/dist/src/gsd/capability-registry.js +337 -0
  108. package/dist/src/gsd/complexity-assessor.d.ts +39 -0
  109. package/dist/src/gsd/complexity-assessor.js +152 -0
  110. package/dist/src/gsd/config-bridge.d.ts +7 -0
  111. package/dist/src/gsd/config-bridge.js +114 -0
  112. package/dist/src/gsd/config-loader.d.ts +27 -0
  113. package/dist/src/gsd/config-loader.js +50 -0
  114. package/dist/src/gsd/council-context.d.ts +44 -0
  115. package/dist/src/gsd/council-context.js +114 -0
  116. package/dist/src/gsd/ee-closure.d.ts +28 -0
  117. package/dist/src/gsd/ee-closure.js +49 -0
  118. package/dist/src/gsd/flags.d.ts +55 -0
  119. package/dist/src/gsd/flags.js +83 -0
  120. package/dist/src/gsd/gsd-dispatch.d.ts +58 -0
  121. package/dist/src/gsd/gsd-dispatch.js +131 -0
  122. package/dist/src/gsd/gsd-runtime.d.ts +22 -0
  123. package/dist/src/gsd/gsd-runtime.js +37 -0
  124. package/dist/src/gsd/host-adapter.d.ts +11 -0
  125. package/dist/src/gsd/host-adapter.js +29 -0
  126. package/dist/src/gsd/index.d.ts +24 -1
  127. package/dist/src/gsd/index.js +27 -0
  128. package/dist/src/gsd/loop-host-contract.d.ts +21 -0
  129. package/dist/src/gsd/loop-host-contract.js +39 -0
  130. package/dist/src/gsd/loop-host.d.ts +69 -0
  131. package/dist/src/gsd/loop-host.js +245 -0
  132. package/dist/src/gsd/loop-resolver.d.ts +36 -0
  133. package/dist/src/gsd/loop-resolver.js +79 -0
  134. package/dist/src/gsd/model-tier.d.ts +13 -0
  135. package/dist/src/gsd/model-tier.js +45 -0
  136. package/dist/src/gsd/mutation-gate.d.ts +16 -0
  137. package/dist/src/gsd/mutation-gate.js +41 -0
  138. package/dist/src/gsd/native-roadmap.d.ts +89 -0
  139. package/dist/src/gsd/native-roadmap.js +343 -0
  140. package/dist/src/gsd/native-state.d.ts +47 -0
  141. package/dist/src/gsd/native-state.js +220 -0
  142. package/dist/src/gsd/paths.d.ts +23 -0
  143. package/dist/src/gsd/paths.js +66 -0
  144. package/dist/src/gsd/phase-dag.d.ts +12 -0
  145. package/dist/src/gsd/phase-dag.js +94 -0
  146. package/dist/src/gsd/phase-sync.d.ts +42 -0
  147. package/dist/src/gsd/phase-sync.js +321 -0
  148. package/dist/src/gsd/pil-gate-context.d.ts +13 -0
  149. package/dist/src/gsd/pil-gate-context.js +64 -0
  150. package/dist/src/gsd/pil-gate-critic.d.ts +19 -0
  151. package/dist/src/gsd/pil-gate-critic.js +74 -0
  152. package/dist/src/gsd/plan-council-prompts.d.ts +25 -0
  153. package/dist/src/gsd/plan-council-prompts.js +79 -0
  154. package/dist/src/gsd/plan-council.d.ts +44 -0
  155. package/dist/src/gsd/plan-council.js +251 -0
  156. package/dist/src/gsd/plan-gate-vocabulary.d.ts +40 -0
  157. package/dist/src/gsd/plan-gate-vocabulary.js +64 -0
  158. package/dist/src/gsd/product-workspace.d.ts +13 -0
  159. package/dist/src/gsd/product-workspace.js +124 -0
  160. package/dist/src/gsd/ship-bridge.d.ts +25 -0
  161. package/dist/src/gsd/ship-bridge.js +65 -0
  162. package/dist/src/gsd/state-document.d.ts +40 -0
  163. package/dist/src/gsd/state-document.js +163 -0
  164. package/dist/src/gsd/verdict-schema.d.ts +39 -0
  165. package/dist/src/gsd/verdict-schema.js +144 -0
  166. package/dist/src/gsd/verify-context.d.ts +22 -0
  167. package/dist/src/gsd/verify-context.js +27 -0
  168. package/dist/src/gsd/verify-council-prompts.d.ts +19 -0
  169. package/dist/src/gsd/verify-council-prompts.js +85 -0
  170. package/dist/src/gsd/verify-council.d.ts +25 -0
  171. package/dist/src/gsd/verify-council.js +119 -0
  172. package/dist/src/gsd/verify-gate-vocabulary.d.ts +25 -0
  173. package/dist/src/gsd/verify-gate-vocabulary.js +46 -0
  174. package/dist/src/gsd/workflow-engine.d.ts +60 -0
  175. package/dist/src/gsd/workflow-engine.js +207 -0
  176. package/dist/src/gsd/workflow-tools.d.ts +13 -0
  177. package/dist/src/gsd/workflow-tools.js +277 -0
  178. package/dist/src/hooks/index.js +1 -1
  179. package/dist/src/index.js +44 -11
  180. package/dist/src/maintain/pr-builder.js +23 -13
  181. package/dist/src/mcp/auto-setup.js +57 -32
  182. package/dist/src/mcp/client-pool.js +1 -1
  183. package/dist/src/mcp/ee-tools.js +1 -0
  184. package/dist/src/mcp/oauth-callback.js +2 -2
  185. package/dist/src/mcp/research-onboarding.js +8 -7
  186. package/dist/src/mcp/runtime.js +34 -2
  187. package/dist/src/mcp/setup-guide-text.d.ts +1 -1
  188. package/dist/src/mcp/setup-guide-text.js +77 -76
  189. package/dist/src/models/catalog-client.d.ts +87 -0
  190. package/dist/src/models/catalog-client.js +105 -38
  191. package/dist/src/models/catalog.json +528 -265
  192. package/dist/src/models/registry.d.ts +22 -7
  193. package/dist/src/models/registry.js +73 -10
  194. package/dist/src/ops/doctor.js +8 -8
  195. package/dist/src/orchestrator/auto-commit.js +1 -1
  196. package/dist/src/orchestrator/batch-turn-runner.js +2 -2
  197. package/dist/src/orchestrator/cache-prefix.d.ts +67 -0
  198. package/dist/src/orchestrator/cache-prefix.js +83 -0
  199. package/dist/src/orchestrator/compact-request.d.ts +32 -0
  200. package/dist/src/orchestrator/compact-request.js +41 -0
  201. package/dist/src/orchestrator/compaction.d.ts +10 -0
  202. package/dist/src/orchestrator/compaction.js +27 -7
  203. package/dist/src/orchestrator/council-manager.d.ts +12 -3
  204. package/dist/src/orchestrator/council-manager.js +65 -24
  205. package/dist/src/orchestrator/cross-turn-dedup.d.ts +6 -0
  206. package/dist/src/orchestrator/cross-turn-dedup.js +22 -1
  207. package/dist/src/orchestrator/error-utils.d.ts +29 -0
  208. package/dist/src/orchestrator/error-utils.js +132 -24
  209. package/dist/src/orchestrator/grounding-check.js +39 -1
  210. package/dist/src/orchestrator/message-processor.js +242 -33
  211. package/dist/src/orchestrator/orchestrator.d.ts +39 -3
  212. package/dist/src/orchestrator/orchestrator.js +651 -102
  213. package/dist/src/orchestrator/preprocessor.js +1 -1
  214. package/dist/src/orchestrator/proactive-compact-detector.d.ts +26 -0
  215. package/dist/src/orchestrator/proactive-compact-detector.js +36 -0
  216. package/dist/src/orchestrator/prompts.js +159 -159
  217. package/dist/src/orchestrator/reactive-delegation.d.ts +39 -0
  218. package/dist/src/orchestrator/reactive-delegation.js +59 -0
  219. package/dist/src/orchestrator/retry-classifier.d.ts +2 -1
  220. package/dist/src/orchestrator/retry-classifier.js +46 -2
  221. package/dist/src/orchestrator/safety-intercept.d.ts +45 -0
  222. package/dist/src/orchestrator/safety-intercept.js +55 -0
  223. package/dist/src/orchestrator/scope-reminder.js +1 -1
  224. package/dist/src/orchestrator/session-experience.d.ts +2 -1
  225. package/dist/src/orchestrator/session-experience.js +2 -1
  226. package/dist/src/orchestrator/should-run-gate.d.ts +5 -0
  227. package/dist/src/orchestrator/should-run-gate.js +18 -0
  228. package/dist/src/orchestrator/stall-watchdog.d.ts +24 -3
  229. package/dist/src/orchestrator/stall-watchdog.js +47 -13
  230. package/dist/src/orchestrator/stream-runner.js +62 -29
  231. package/dist/src/orchestrator/sub-agent-cap.d.ts +13 -1
  232. package/dist/src/orchestrator/sub-agent-cap.js +16 -1
  233. package/dist/src/orchestrator/sub-agent-model-tier.d.ts +13 -1
  234. package/dist/src/orchestrator/sub-agent-model-tier.js +16 -2
  235. package/dist/src/orchestrator/subagent-compactor.d.ts +53 -1
  236. package/dist/src/orchestrator/subagent-compactor.js +126 -15
  237. package/dist/src/orchestrator/tool-engine.d.ts +26 -0
  238. package/dist/src/orchestrator/tool-engine.js +669 -56
  239. package/dist/src/orchestrator/tool-limit-auto-recover.d.ts +22 -0
  240. package/dist/src/orchestrator/tool-limit-auto-recover.js +30 -0
  241. package/dist/src/orchestrator/turn-runner-deps.d.ts +19 -0
  242. package/dist/src/orchestrator/turn-watchdog.d.ts +37 -0
  243. package/dist/src/orchestrator/turn-watchdog.js +55 -0
  244. package/dist/src/pil/agent-operating-contract.d.ts +1 -1
  245. package/dist/src/pil/agent-operating-contract.js +1 -1
  246. package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
  247. package/dist/src/pil/cheap-model-playbook.js +5 -1
  248. package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
  249. package/dist/src/pil/cheap-model-workbooks.js +1 -1
  250. package/dist/src/pil/discovery-types.d.ts +1 -0
  251. package/dist/src/pil/discovery.js +16 -11
  252. package/dist/src/pil/layer1-intent.d.ts +18 -6
  253. package/dist/src/pil/layer1-intent.js +66 -757
  254. package/dist/src/pil/layer15-context-scan.js +15 -1
  255. package/dist/src/pil/layer2_5-ponytail.js +8 -8
  256. package/dist/src/pil/layer3-ee-injection.js +23 -8
  257. package/dist/src/pil/layer4-gsd.js +69 -16
  258. package/dist/src/pil/layer5-context.js +7 -3
  259. package/dist/src/pil/layer6-output.d.ts +23 -0
  260. package/dist/src/pil/layer6-output.js +5 -1
  261. package/dist/src/pil/llm-classify.d.ts +33 -2
  262. package/dist/src/pil/llm-classify.js +123 -131
  263. package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
  264. package/dist/src/pil/native-capabilities-workbook.js +1 -0
  265. package/dist/src/pil/pipeline.js +34 -2
  266. package/dist/src/pil/response-tools.js +5 -3
  267. package/dist/src/pil/schema.d.ts +1 -0
  268. package/dist/src/pil/schema.js +2 -0
  269. package/dist/src/pil/types.d.ts +18 -0
  270. package/dist/src/playbook/directives.d.ts +4 -0
  271. package/dist/src/playbook/directives.js +17 -5
  272. package/dist/src/product-loop/backlog-builder.d.ts +14 -1
  273. package/dist/src/product-loop/backlog-builder.js +30 -6
  274. package/dist/src/product-loop/discovery-context-format.js +3 -1
  275. package/dist/src/product-loop/discovery-ecosystem.js +4 -1
  276. package/dist/src/product-loop/discovery-interview.js +32 -3
  277. package/dist/src/product-loop/discovery-schema.js +5 -1
  278. package/dist/src/product-loop/done-gate.js +3 -3
  279. package/dist/src/product-loop/ideal-trace.d.ts +7 -0
  280. package/dist/src/product-loop/ideal-trace.js +64 -0
  281. package/dist/src/product-loop/index.d.ts +13 -1
  282. package/dist/src/product-loop/index.js +333 -52
  283. package/dist/src/product-loop/loop-driver.d.ts +7 -0
  284. package/dist/src/product-loop/loop-driver.js +327 -116
  285. package/dist/src/product-loop/phase-plan.d.ts +5 -0
  286. package/dist/src/product-loop/phase-plan.js +39 -2
  287. package/dist/src/product-loop/phase-runner.js +9 -1
  288. package/dist/src/product-loop/progress-snapshot.js +4 -4
  289. package/dist/src/product-loop/sprint-runner.d.ts +111 -0
  290. package/dist/src/product-loop/sprint-runner.js +559 -16
  291. package/dist/src/product-loop/types.d.ts +36 -5
  292. package/dist/src/providers/adapter.d.ts +1 -1
  293. package/dist/src/providers/adapter.js +3 -4
  294. package/dist/src/providers/auth/browser-flow.d.ts +1 -1
  295. package/dist/src/providers/auth/browser-flow.js +1 -1
  296. package/dist/src/providers/auth/openai-oauth.js +1 -1
  297. package/dist/src/providers/auth/registry.js +0 -34
  298. package/dist/src/providers/auth/token-store.js +4 -1
  299. package/dist/src/providers/auth/types.d.ts +1 -1
  300. package/dist/src/providers/auth/types.js +1 -1
  301. package/dist/src/providers/capabilities.d.ts +24 -5
  302. package/dist/src/providers/capabilities.js +42 -24
  303. package/dist/src/providers/endpoints.d.ts +2 -2
  304. package/dist/src/providers/endpoints.js +11 -10
  305. package/dist/src/providers/keychain.d.ts +1 -1
  306. package/dist/src/providers/keychain.js +7 -9
  307. package/dist/src/providers/mcp-vision-bridge.js +82 -172
  308. package/dist/src/providers/openai-compatible.js +8 -1
  309. package/dist/src/providers/pricing.d.ts +2 -2
  310. package/dist/src/providers/pricing.js +3 -13
  311. package/dist/src/providers/runtime.d.ts +27 -2
  312. package/dist/src/providers/runtime.js +78 -15
  313. package/dist/src/providers/strategies/base.strategy.d.ts +16 -0
  314. package/dist/src/providers/strategies/base.strategy.js +24 -1
  315. package/dist/src/providers/strategies/{siliconflow.strategy.d.ts → opencode-go.strategy.d.ts} +3 -3
  316. package/dist/src/providers/strategies/opencode-go.strategy.js +83 -0
  317. package/dist/src/providers/strategies/registry.js +4 -4
  318. package/dist/src/providers/strategies/thinking-mode.d.ts +109 -0
  319. package/dist/src/providers/strategies/thinking-mode.js +280 -1
  320. package/dist/src/providers/strategies/zai.strategy.d.ts +14 -0
  321. package/dist/src/providers/strategies/zai.strategy.js +44 -0
  322. package/dist/src/providers/types.d.ts +5 -6
  323. package/dist/src/providers/types.js +2 -2
  324. package/dist/src/providers/vision-backend.d.ts +47 -0
  325. package/dist/src/providers/vision-backend.js +258 -0
  326. package/dist/src/providers/vision-proxy.d.ts +22 -9
  327. package/dist/src/providers/vision-proxy.js +63 -132
  328. package/dist/src/providers/wire-debug.js +95 -0
  329. package/dist/src/reporter/index.js +1 -1
  330. package/dist/src/router/decide.d.ts +13 -0
  331. package/dist/src/router/decide.js +138 -36
  332. package/dist/src/router/peak-hour.d.ts +38 -0
  333. package/dist/src/router/peak-hour.js +107 -0
  334. package/dist/src/router/step-router.js +3 -2
  335. package/dist/src/router/warm.js +4 -5
  336. package/dist/src/scaffold/bb-ecosystem-apply.js +47 -47
  337. package/dist/src/scaffold/bb-quality-gate.js +5 -5
  338. package/dist/src/scaffold/continuation-prompt.d.ts +11 -0
  339. package/dist/src/scaffold/continuation-prompt.js +86 -60
  340. package/dist/src/scaffold/init-new.js +453 -453
  341. package/dist/src/scaffold/point-to-existing.d.ts +21 -0
  342. package/dist/src/scaffold/point-to-existing.js +25 -0
  343. package/dist/src/self-qa/agentic-loop.js +22 -22
  344. package/dist/src/{ui/state → state}/active-run.d.ts +19 -0
  345. package/dist/src/{ui/state → state}/active-run.js +21 -0
  346. package/dist/src/{ui/status-bar/store.d.ts → state/status-bar-store.d.ts} +4 -1
  347. package/dist/src/{ui/status-bar/store.js → state/status-bar-store.js} +12 -9
  348. package/dist/src/state/turn-trace.d.ts +43 -0
  349. package/dist/src/state/turn-trace.js +32 -0
  350. package/dist/src/storage/db.js +2 -1
  351. package/dist/src/storage/index.d.ts +1 -1
  352. package/dist/src/storage/index.js +1 -1
  353. package/dist/src/storage/interaction-log.d.ts +1 -1
  354. package/dist/src/storage/interaction-log.js +5 -5
  355. package/dist/src/storage/migrations.js +196 -126
  356. package/dist/src/storage/session-experience-store.js +4 -4
  357. package/dist/src/storage/sessions.d.ts +28 -10
  358. package/dist/src/storage/sessions.js +112 -55
  359. package/dist/src/storage/transcript-view.js +1 -1
  360. package/dist/src/storage/transcript.d.ts +51 -0
  361. package/dist/src/storage/transcript.js +383 -112
  362. package/dist/src/storage/usage.js +14 -14
  363. package/dist/src/storage/workspaces.js +12 -12
  364. package/dist/src/tools/file.d.ts +15 -0
  365. package/dist/src/tools/file.js +32 -0
  366. package/dist/src/tools/native-tools.js +5 -0
  367. package/dist/src/tools/registry.d.ts +3 -0
  368. package/dist/src/tools/registry.js +460 -22
  369. package/dist/src/tools/research.d.ts +29 -0
  370. package/dist/src/tools/research.js +233 -0
  371. package/dist/src/types/index.d.ts +118 -3
  372. package/dist/src/ui/app.js +0 -0
  373. package/dist/src/ui/cards/product-status-card.js +1 -1
  374. package/dist/src/ui/components/bubble-body-guard.d.ts +27 -0
  375. package/dist/src/ui/components/bubble-body-guard.js +50 -0
  376. package/dist/src/ui/components/context-rail.d.ts +26 -0
  377. package/dist/src/ui/components/context-rail.js +33 -0
  378. package/dist/src/ui/components/council-conclusion-card.d.ts +73 -0
  379. package/dist/src/ui/components/council-conclusion-card.js +420 -0
  380. package/dist/src/ui/components/council-debate-pill.d.ts +36 -0
  381. package/dist/src/ui/components/council-debate-pill.js +34 -0
  382. package/dist/src/ui/components/council-info-card.js +2 -2
  383. package/dist/src/ui/components/council-leader-bubble.d.ts +10 -3
  384. package/dist/src/ui/components/council-leader-bubble.js +21 -11
  385. package/dist/src/ui/components/council-message-bubble.d.ts +15 -2
  386. package/dist/src/ui/components/council-message-bubble.js +16 -15
  387. package/dist/src/ui/components/council-phase-timeline.d.ts +9 -1
  388. package/dist/src/ui/components/council-phase-timeline.js +49 -15
  389. package/dist/src/ui/components/council-placeholder-bubble.d.ts +16 -9
  390. package/dist/src/ui/components/council-placeholder-bubble.js +32 -29
  391. package/dist/src/ui/components/council-question-card.js +12 -12
  392. package/dist/src/ui/components/council-rail-rounds.d.ts +26 -0
  393. package/dist/src/ui/components/council-rail-rounds.js +57 -0
  394. package/dist/src/ui/components/council-round-group.d.ts +38 -0
  395. package/dist/src/ui/components/council-round-group.js +88 -0
  396. package/dist/src/ui/components/council-status-list.d.ts +3 -1
  397. package/dist/src/ui/components/council-status-list.js +36 -24
  398. package/dist/src/ui/components/council-synthesis-banner.d.ts +7 -2
  399. package/dist/src/ui/components/council-synthesis-banner.js +20 -5
  400. package/dist/src/ui/components/halt-recovery-card.js +9 -5
  401. package/dist/src/ui/components/jump-to-latest-pill.d.ts +11 -0
  402. package/dist/src/ui/components/jump-to-latest-pill.js +14 -0
  403. package/dist/src/ui/components/prompt-box.js +18 -16
  404. package/dist/src/ui/components/session-tree-card.d.ts +14 -0
  405. package/dist/src/ui/components/session-tree-card.js +46 -0
  406. package/dist/src/ui/components/slash-inline-menu.d.ts +12 -0
  407. package/dist/src/ui/components/slash-inline-menu.js +26 -5
  408. package/dist/src/ui/components/task-list-panel.d.ts +14 -1
  409. package/dist/src/ui/components/task-list-panel.js +22 -2
  410. package/dist/src/ui/containers/modals-layer.d.ts +2 -1
  411. package/dist/src/ui/hooks/use-session-picker.d.ts +3 -3
  412. package/dist/src/ui/mcp-modal.js +2 -4
  413. package/dist/src/ui/modals/api-key-modal.js +1 -1
  414. package/dist/src/ui/modals/connect-modal.js +4 -3
  415. package/dist/src/ui/modals/session-picker-modal.d.ts +2 -2
  416. package/dist/src/ui/modals/session-picker-modal.js +3 -5
  417. package/dist/src/ui/picker-providers.d.ts +1 -1
  418. package/dist/src/ui/picker-providers.js +1 -1
  419. package/dist/src/ui/primitives/index.d.ts +1 -0
  420. package/dist/src/ui/primitives/index.js +2 -0
  421. package/dist/src/ui/primitives/semantic-primitives.d.ts +76 -0
  422. package/dist/src/ui/primitives/semantic-primitives.js +81 -0
  423. package/dist/src/ui/slash/compact.js +5 -7
  424. package/dist/src/ui/slash/cost.js +1 -1
  425. package/dist/src/ui/slash/council-inspect.js +4 -4
  426. package/dist/src/ui/slash/council.js +19 -1
  427. package/dist/src/ui/slash/debug.d.ts +3 -31
  428. package/dist/src/ui/slash/debug.js +9 -20
  429. package/dist/src/ui/slash/ideal.d.ts +6 -2
  430. package/dist/src/ui/slash/ideal.js +97 -7
  431. package/dist/src/ui/slash/menu-items.d.ts +7 -0
  432. package/dist/src/ui/slash/menu-items.js +12 -18
  433. package/dist/src/ui/slash/registry.d.ts +2 -0
  434. package/dist/src/ui/slash/registry.js +4 -0
  435. package/dist/src/ui/status-bar/cache-hit.d.ts +6 -0
  436. package/dist/src/ui/status-bar/cache-hit.js +9 -0
  437. package/dist/src/ui/status-bar/index.d.ts +1 -1
  438. package/dist/src/ui/status-bar/index.js +7 -3
  439. package/dist/src/ui/status-bar/usd-meter.d.ts +5 -4
  440. package/dist/src/ui/status-bar/usd-meter.js +6 -4
  441. package/dist/src/ui/theme.d.ts +1 -0
  442. package/dist/src/ui/theme.js +2 -0
  443. package/dist/src/ui/types.d.ts +7 -0
  444. package/dist/src/ui/use-app-logic.js +0 -0
  445. package/dist/src/ui/utils/format.d.ts +14 -0
  446. package/dist/src/ui/utils/format.js +23 -3
  447. package/dist/src/usage/downgrade.js +2 -2
  448. package/dist/src/usage/product-ledger.js +2 -2
  449. package/dist/src/utils/clipboard-image.js +23 -23
  450. package/dist/src/utils/install-manager.js +14 -11
  451. package/dist/src/utils/logger.js +2 -2
  452. package/dist/src/utils/permission-mode.js +5 -3
  453. package/dist/src/utils/redactor.js +1 -1
  454. package/dist/src/utils/settings.d.ts +153 -5
  455. package/dist/src/utils/settings.js +233 -29
  456. package/dist/src/utils/side-question.js +2 -2
  457. package/dist/src/utils/skills.js +3 -3
  458. package/dist/src/utils/visible-retry.d.ts +11 -0
  459. package/dist/src/utils/visible-retry.js +10 -1
  460. package/dist/src/verify/entrypoint.d.ts +1 -1
  461. package/dist/src/verify/entrypoint.js +1 -1
  462. package/dist/src/verify/recipes.d.ts +13 -0
  463. package/dist/src/verify/recipes.js +15 -0
  464. package/package.json +135 -132
  465. package/dist/src/providers/auth/gcloud.d.ts +0 -28
  466. package/dist/src/providers/auth/gcloud.js +0 -102
  467. package/dist/src/providers/auth/gemini-oauth.d.ts +0 -82
  468. package/dist/src/providers/auth/gemini-oauth.js +0 -472
  469. package/dist/src/providers/gemini.d.ts +0 -11
  470. package/dist/src/providers/gemini.js +0 -45
  471. package/dist/src/providers/siliconflow-sse-repair.d.ts +0 -58
  472. package/dist/src/providers/siliconflow-sse-repair.js +0 -177
  473. package/dist/src/providers/strategies/google.strategy.d.ts +0 -22
  474. package/dist/src/providers/strategies/google.strategy.js +0 -174
  475. package/dist/src/providers/strategies/siliconflow.strategy.js +0 -29
  476. package/dist/src/ui/containers/chat-feed.d.ts +0 -40
  477. package/dist/src/ui/containers/chat-feed.js +0 -66
@@ -0,0 +1,129 @@
1
+ /**
2
+ * src/council/debate-checkpoint.ts
3
+ *
4
+ * C (mid-debate checkpoint) — persist the CB-1 council debate's per-round state
5
+ * so a break mid-debate (provider 5xx on round 5, host crash, cap breach) can
6
+ * resume from the last completed round instead of re-running the whole debate.
7
+ *
8
+ * The debate accumulates all state in RAM (`exchangeLogs`, `active`,
9
+ * `runningSummary`, `archive`, convergence trackers). Without a checkpoint a
10
+ * break loses every round — a 5-round multi-provider debate must restart from
11
+ * round 1. This module owns the on-disk snapshot: `runDebate` writes it after
12
+ * each completed round and deletes it on normal completion; the resume path
13
+ * reads it and seeds `runDebate` so it skips research + openings + completed
14
+ * rounds.
15
+ *
16
+ * File: `<checkpointDir>/debate-checkpoint.json` (checkpointDir = the run dir,
17
+ * `.muonroi-flow/runs/<runId>`). Written atomically (tmp + rename) so a crash
18
+ * mid-write can never leave a half-JSON file.
19
+ */
20
+ import type { ClarifiedSpec, CouncilParticipant, DebateArchiveEntry } from "./types.js";
21
+ /** Bump when the checkpoint shape changes incompatibly so stale files are ignored. */
22
+ export declare const DEBATE_CHECKPOINT_VERSION: 1;
23
+ export declare const DEBATE_CHECKPOINT_FILE = "debate-checkpoint.json";
24
+ /**
25
+ * Serializable snapshot of an in-flight debate, written after each completed
26
+ * discussion round. `exchangeLogs` (a `Map`) is stored as entry tuples since
27
+ * JSON has no Map; everything else in the payload is already JSON-native.
28
+ */
29
+ export interface DebateCheckpoint {
30
+ version: typeof DEBATE_CHECKPOINT_VERSION;
31
+ /**
32
+ * Identity guard — the checkpoint is only restored when it matches the debate
33
+ * about to run. `problemStatement` pins the spec; `participantModels` pins the
34
+ * panel. A mismatch (spec changed, panel re-resolved differently) => ignore
35
+ * the stale checkpoint and run the debate fresh rather than splice wrong state.
36
+ */
37
+ problemStatement: string;
38
+ participantModels: string[];
39
+ /** Rounds fully completed (transcript + summary persisted). Resume starts at roundCount+1. */
40
+ roundCount: number;
41
+ /** Current round budget after any leader/user extensions. */
42
+ maxRounds: number;
43
+ /** Accumulated per-pair transcript (Map<pairKey, turns[]> serialized as entries). */
44
+ exchangeLogs: Array<[string, string[]]>;
45
+ /** Latest inter-round summary. */
46
+ runningSummary: string;
47
+ /** Research findings (so the research phase is not re-run on resume). */
48
+ researchFindings?: string;
49
+ /** Surviving participants with their latest position + stance (so openings are not re-run). */
50
+ active: CouncilParticipant[];
51
+ /** Citation archive accumulated so far. */
52
+ archive: DebateArchiveEntry[];
53
+ /** Convergence continuity: last round's per-criterion met flags. */
54
+ lastCriteriaMet: boolean[];
55
+ /** B4 auto-remedy high-water mark of pinned criteria met. */
56
+ bestCriteriaMetCount: number;
57
+ /** B4 consecutive evaluated rounds with no new met criterion. */
58
+ roundsSinceProgress: number;
59
+ /** Topic carried into the next round from the prior leader nextRoundFocus. */
60
+ nextTopic?: string;
61
+ /** Wall-clock the checkpoint was written (ISO). Diagnostics only. */
62
+ savedAt: string;
63
+ }
64
+ /** Input to {@link buildDebateCheckpoint} — the live round-loop locals. */
65
+ export interface DebateCheckpointInput {
66
+ problemStatement: string;
67
+ roundCount: number;
68
+ maxRounds: number;
69
+ exchangeLogs: Map<string, string[]>;
70
+ runningSummary: string;
71
+ researchFindings?: string;
72
+ active: CouncilParticipant[];
73
+ archive: DebateArchiveEntry[];
74
+ lastCriteriaMet: boolean[];
75
+ bestCriteriaMetCount: number;
76
+ roundsSinceProgress: number;
77
+ nextTopic?: string;
78
+ /** ISO timestamp; the caller supplies it (Date.now is unavailable in some sandboxes). */
79
+ savedAt: string;
80
+ }
81
+ /** Build the serializable checkpoint payload from live debate state. */
82
+ export declare function buildDebateCheckpoint(input: DebateCheckpointInput): DebateCheckpoint;
83
+ /** Rehydrate `exchangeLogs` from the serialized entry tuples. */
84
+ export declare function restoreExchangeLogs(cp: DebateCheckpoint): Map<string, string[]>;
85
+ /**
86
+ * Whether `cp` describes the debate that is about to run. Guards against
87
+ * splicing a stale checkpoint (different question, re-resolved panel) into a
88
+ * fresh debate. Participant order is not significant; the model SET must match.
89
+ */
90
+ export declare function checkpointMatches(cp: DebateCheckpoint, problemStatement: string, participantModels: string[]): boolean;
91
+ /**
92
+ * Atomically write the checkpoint to `<dir>/debate-checkpoint.json`.
93
+ * Non-fatal: a checkpoint write failure must never break the live debate — it
94
+ * only forfeits resumability for that round. Logs with context (No-Silent-Catch).
95
+ */
96
+ export declare function writeDebateCheckpoint(dir: string, cp: DebateCheckpoint): Promise<void>;
97
+ /**
98
+ * Read + parse the checkpoint. Returns null when absent or unparseable (a
99
+ * corrupt checkpoint must not crash resume — the debate just runs fresh).
100
+ */
101
+ export declare function readDebateCheckpoint(dir: string): Promise<DebateCheckpoint | null>;
102
+ /**
103
+ * Delete the checkpoint (debate completed normally, or the run was aborted).
104
+ * Non-fatal — a leftover checkpoint is only re-validated (and discarded on
105
+ * mismatch) on the next resume, never silently mis-applied.
106
+ */
107
+ export declare function deleteDebateCheckpoint(dir: string): Promise<void>;
108
+ export declare const DEBATE_INPUTS_FILE = "debate-inputs.json";
109
+ /**
110
+ * C-v2 — the minimal gather-stage outputs needed to re-enter the council debate
111
+ * on a fresh session (cross-process resume) WITHOUT re-running the interactive
112
+ * discovery + interview. Persisted once at debate start; the loop-driver resume
113
+ * entry restores `clarifiedSpec` + `conversationContext` and jumps straight to
114
+ * the research/debate stage (participants + leader are re-resolved from the
115
+ * session model deterministically, then matched against the checkpoint panel).
116
+ */
117
+ export interface DebateInputs {
118
+ version: typeof DEBATE_CHECKPOINT_VERSION;
119
+ problemStatement: string;
120
+ clarifiedSpec: ClarifiedSpec;
121
+ conversationContext: string;
122
+ savedAt: string;
123
+ }
124
+ /** Atomically persist the debate inputs. Non-fatal on failure (forfeits cross-session resume only). */
125
+ export declare function writeDebateInputs(dir: string, inputs: DebateInputs): Promise<void>;
126
+ /** Read the debate inputs. Returns null when absent/unparseable/version-mismatched. */
127
+ export declare function readDebateInputs(dir: string): Promise<DebateInputs | null>;
128
+ /** Delete the debate inputs (debate + scoping finished, or run aborted). Non-fatal. */
129
+ export declare function deleteDebateInputs(dir: string): Promise<void>;
@@ -0,0 +1,176 @@
1
+ /**
2
+ * src/council/debate-checkpoint.ts
3
+ *
4
+ * C (mid-debate checkpoint) — persist the CB-1 council debate's per-round state
5
+ * so a break mid-debate (provider 5xx on round 5, host crash, cap breach) can
6
+ * resume from the last completed round instead of re-running the whole debate.
7
+ *
8
+ * The debate accumulates all state in RAM (`exchangeLogs`, `active`,
9
+ * `runningSummary`, `archive`, convergence trackers). Without a checkpoint a
10
+ * break loses every round — a 5-round multi-provider debate must restart from
11
+ * round 1. This module owns the on-disk snapshot: `runDebate` writes it after
12
+ * each completed round and deletes it on normal completion; the resume path
13
+ * reads it and seeds `runDebate` so it skips research + openings + completed
14
+ * rounds.
15
+ *
16
+ * File: `<checkpointDir>/debate-checkpoint.json` (checkpointDir = the run dir,
17
+ * `.muonroi-flow/runs/<runId>`). Written atomically (tmp + rename) so a crash
18
+ * mid-write can never leave a half-JSON file.
19
+ */
20
+ import { promises as fs } from "node:fs";
21
+ import * as path from "node:path";
22
+ /** Bump when the checkpoint shape changes incompatibly so stale files are ignored. */
23
+ export const DEBATE_CHECKPOINT_VERSION = 1;
24
+ export const DEBATE_CHECKPOINT_FILE = "debate-checkpoint.json";
25
+ /** Build the serializable checkpoint payload from live debate state. */
26
+ export function buildDebateCheckpoint(input) {
27
+ return {
28
+ version: DEBATE_CHECKPOINT_VERSION,
29
+ problemStatement: input.problemStatement,
30
+ participantModels: input.active.map((p) => p.model),
31
+ roundCount: input.roundCount,
32
+ maxRounds: input.maxRounds,
33
+ exchangeLogs: [...input.exchangeLogs.entries()].map(([k, v]) => [k, [...v]]),
34
+ runningSummary: input.runningSummary,
35
+ researchFindings: input.researchFindings,
36
+ active: input.active,
37
+ archive: input.archive,
38
+ lastCriteriaMet: [...input.lastCriteriaMet],
39
+ bestCriteriaMetCount: input.bestCriteriaMetCount,
40
+ roundsSinceProgress: input.roundsSinceProgress,
41
+ nextTopic: input.nextTopic,
42
+ savedAt: input.savedAt,
43
+ };
44
+ }
45
+ /** Rehydrate `exchangeLogs` from the serialized entry tuples. */
46
+ export function restoreExchangeLogs(cp) {
47
+ return new Map(cp.exchangeLogs.map(([k, v]) => [k, [...v]]));
48
+ }
49
+ /**
50
+ * Whether `cp` describes the debate that is about to run. Guards against
51
+ * splicing a stale checkpoint (different question, re-resolved panel) into a
52
+ * fresh debate. Participant order is not significant; the model SET must match.
53
+ */
54
+ export function checkpointMatches(cp, problemStatement, participantModels) {
55
+ if (cp.version !== DEBATE_CHECKPOINT_VERSION)
56
+ return false;
57
+ if (cp.roundCount < 1)
58
+ return false; // nothing useful to resume from
59
+ if (cp.problemStatement !== problemStatement)
60
+ return false;
61
+ const a = [...cp.participantModels].sort();
62
+ const b = [...participantModels].sort();
63
+ if (a.length !== b.length)
64
+ return false;
65
+ return a.every((m, i) => m === b[i]);
66
+ }
67
+ /**
68
+ * Atomically write the checkpoint to `<dir>/debate-checkpoint.json`.
69
+ * Non-fatal: a checkpoint write failure must never break the live debate — it
70
+ * only forfeits resumability for that round. Logs with context (No-Silent-Catch).
71
+ */
72
+ export async function writeDebateCheckpoint(dir, cp) {
73
+ const finalPath = path.join(dir, DEBATE_CHECKPOINT_FILE);
74
+ const tmpPath = `${finalPath}.${process.pid}.tmp`;
75
+ try {
76
+ await fs.mkdir(dir, { recursive: true });
77
+ await fs.writeFile(tmpPath, JSON.stringify(cp), "utf8");
78
+ await fs.rename(tmpPath, finalPath);
79
+ }
80
+ catch (err) {
81
+ console.error(`[debate-checkpoint] write failed (dir=${dir}, round=${cp.roundCount}): ${err?.message}`);
82
+ // Best-effort cleanup of the temp file; ignore if it never got created.
83
+ await fs.rm(tmpPath, { force: true }).catch(() => { });
84
+ }
85
+ }
86
+ /**
87
+ * Read + parse the checkpoint. Returns null when absent or unparseable (a
88
+ * corrupt checkpoint must not crash resume — the debate just runs fresh).
89
+ */
90
+ export async function readDebateCheckpoint(dir) {
91
+ const finalPath = path.join(dir, DEBATE_CHECKPOINT_FILE);
92
+ let raw;
93
+ try {
94
+ raw = await fs.readFile(finalPath, "utf8");
95
+ }
96
+ catch (err) {
97
+ if (err?.code !== "ENOENT") {
98
+ console.error(`[debate-checkpoint] read failed (dir=${dir}): ${err?.message}`);
99
+ }
100
+ return null;
101
+ }
102
+ try {
103
+ const parsed = JSON.parse(raw);
104
+ if (parsed?.version !== DEBATE_CHECKPOINT_VERSION)
105
+ return null;
106
+ return parsed;
107
+ }
108
+ catch (err) {
109
+ console.error(`[debate-checkpoint] parse failed (dir=${dir}): ${err?.message}`);
110
+ return null;
111
+ }
112
+ }
113
+ /**
114
+ * Delete the checkpoint (debate completed normally, or the run was aborted).
115
+ * Non-fatal — a leftover checkpoint is only re-validated (and discarded on
116
+ * mismatch) on the next resume, never silently mis-applied.
117
+ */
118
+ export async function deleteDebateCheckpoint(dir) {
119
+ const finalPath = path.join(dir, DEBATE_CHECKPOINT_FILE);
120
+ try {
121
+ await fs.rm(finalPath, { force: true });
122
+ }
123
+ catch (err) {
124
+ console.error(`[debate-checkpoint] delete failed (dir=${dir}): ${err?.message}`);
125
+ }
126
+ }
127
+ // ── Debate inputs (C-v2 cross-session resume) ────────────────────────────────
128
+ export const DEBATE_INPUTS_FILE = "debate-inputs.json";
129
+ /** Atomically persist the debate inputs. Non-fatal on failure (forfeits cross-session resume only). */
130
+ export async function writeDebateInputs(dir, inputs) {
131
+ const finalPath = path.join(dir, DEBATE_INPUTS_FILE);
132
+ const tmpPath = `${finalPath}.${process.pid}.tmp`;
133
+ try {
134
+ await fs.mkdir(dir, { recursive: true });
135
+ await fs.writeFile(tmpPath, JSON.stringify(inputs), "utf8");
136
+ await fs.rename(tmpPath, finalPath);
137
+ }
138
+ catch (err) {
139
+ console.error(`[debate-checkpoint] inputs write failed (dir=${dir}): ${err?.message}`);
140
+ await fs.rm(tmpPath, { force: true }).catch(() => { });
141
+ }
142
+ }
143
+ /** Read the debate inputs. Returns null when absent/unparseable/version-mismatched. */
144
+ export async function readDebateInputs(dir) {
145
+ const finalPath = path.join(dir, DEBATE_INPUTS_FILE);
146
+ let raw;
147
+ try {
148
+ raw = await fs.readFile(finalPath, "utf8");
149
+ }
150
+ catch (err) {
151
+ if (err?.code !== "ENOENT") {
152
+ console.error(`[debate-checkpoint] inputs read failed (dir=${dir}): ${err?.message}`);
153
+ }
154
+ return null;
155
+ }
156
+ try {
157
+ const parsed = JSON.parse(raw);
158
+ if (parsed?.version !== DEBATE_CHECKPOINT_VERSION)
159
+ return null;
160
+ return parsed;
161
+ }
162
+ catch (err) {
163
+ console.error(`[debate-checkpoint] inputs parse failed (dir=${dir}): ${err?.message}`);
164
+ return null;
165
+ }
166
+ }
167
+ /** Delete the debate inputs (debate + scoping finished, or run aborted). Non-fatal. */
168
+ export async function deleteDebateInputs(dir) {
169
+ try {
170
+ await fs.rm(path.join(dir, DEBATE_INPUTS_FILE), { force: true });
171
+ }
172
+ catch (err) {
173
+ console.error(`[debate-checkpoint] inputs delete failed (dir=${dir}): ${err?.message}`);
174
+ }
175
+ }
176
+ //# sourceMappingURL=debate-checkpoint.js.map
@@ -3,6 +3,7 @@ import { z } from "zod";
3
3
  import { loadKeyForProvider } from "../providers/keychain.js";
4
4
  import { createProviderFactory, detectProviderForModel, resolveModelRuntime } from "../providers/runtime.js";
5
5
  import { withDeadlineRace, withTimeoutSignal } from "../utils/llm-deadline.js";
6
+ import { logger } from "../utils/logger.js";
6
7
  import { getProviderStallTimeoutMs } from "../utils/settings.js";
7
8
  import { tracedGenerate } from "./llm.js";
8
9
  import { buildDebatePlanPrompt } from "./prompts.js";
@@ -94,6 +95,37 @@ function injectAuditorStance(plan, eeWarnings, experienceMode) {
94
95
  }
95
96
  return { ...plan, stances };
96
97
  }
98
+ /**
99
+ * PIL task types whose deliverable is understanding/evaluation of something that
100
+ * already exists — never a build. The user asked to assess, not to implement.
101
+ */
102
+ const ANALYSIS_TASK_TYPES = new Set(["analyze"]);
103
+ function isAnalysisTaskType(taskType) {
104
+ return !!taskType && ANALYSIS_TASK_TYPES.has(taskType);
105
+ }
106
+ /**
107
+ * Deterministic backstop for post-debate drift (session c4f78752a316).
108
+ *
109
+ * PIL is the authoritative intent classifier. When it says the request is
110
+ * analysis/evaluation, the leader LLM must not be allowed to silently reshape the
111
+ * debate into an `implementation_plan` — that shape makes the post-debate AskCard
112
+ * default to "generate_plan" (build a plan) via pickPostDebateRecommendation,
113
+ * which is the wrong next step for a request that only wanted an assessment.
114
+ *
115
+ * The prompt already asks the leader to honor the intent (soft), but LLMs drift;
116
+ * this coerces a drifted shape back to "evaluation" so the synthesis stays the
117
+ * deliverable and the default action becomes save_exit. Non-implementation shapes
118
+ * are left untouched.
119
+ */
120
+ function enforceAnalysisIntentShape(plan, taskType) {
121
+ if (!isAnalysisTaskType(taskType))
122
+ return plan;
123
+ if (plan.outputShape.kind !== "implementation_plan")
124
+ return plan;
125
+ logger.info("orchestrator", `[debate-planner] PIL taskType=${taskType} (analysis) but leader chose implementation_plan; ` +
126
+ "coercing outputShape.kind→evaluation to honor analysis intent");
127
+ return { ...plan, outputShape: { ...plan.outputShape, kind: "evaluation" } };
128
+ }
97
129
  export async function* planDebate(spec, leaderModelId, llm, eeWarnings, // CQ-13: experience snippets to seed prompt
98
130
  experienceMode, // CQ-14: controls Experience Auditor injection
99
131
  taskType, // CQ-11: task type from PIL (e.g. "architecture", "bugfix")
@@ -101,6 +133,10 @@ complexityTier, // CQ-11: complexity tier from PIL (e.g. "heavy", "medium", "lig
101
133
  signal) {
102
134
  const eeSnippets = eeWarnings?.map((w) => w.text).filter(Boolean) ?? [];
103
135
  const { system: baseSystem, prompt } = buildDebatePlanPrompt(spec);
136
+ // Every return path funnels through here: auditor + product-stance injection,
137
+ // plus the deterministic analysis-intent backstop (applied first so a coerced
138
+ // shape doesn't get a spurious product stance injected for it).
139
+ const finalizePlan = (plan) => ensureProductStance(injectAuditorStance(enforceAnalysisIntentShape(plan, taskType), eeWarnings, experienceMode));
104
140
  // Build calibration context from PIL metadata
105
141
  const pilCalibration = [];
106
142
  if (taskType)
@@ -111,6 +147,18 @@ signal) {
111
147
  if (pilCalibration.length > 0) {
112
148
  system += `\n\n## Task Context (from PIL)\n${pilCalibration.join("\n")}`;
113
149
  }
150
+ // Hard intent lock (steers stances AND shape). PIL already classified this as
151
+ // analysis; the deterministic backstop in finalizePlan enforces it regardless,
152
+ // but steering the leader here keeps the whole roster/synthesis on-intent.
153
+ if (isAnalysisTaskType(taskType)) {
154
+ system +=
155
+ `\n\n## INTENT LOCK (authoritative)\n` +
156
+ `PIL classified this request as ANALYSIS/EVALUATION (taskType=${taskType}). The user wants to ` +
157
+ `understand and assess what ALREADY exists — not to build anything. ` +
158
+ `outputShape.kind MUST be "evaluation" or "investigation" — NEVER "implementation_plan". ` +
159
+ `Do NOT propose building, implementing, scaffolding, or "I'll spec that in vN". ` +
160
+ `Stances must be analyst/critic/investigator voices, not implementers.`;
161
+ }
114
162
  if (eeSnippets.length > 0) {
115
163
  system += `\n\n## Experience Warnings (from brain)\nNote these past mistakes when designing debate stances:\n${eeSnippets.map((s) => `- ${s}`).join("\n")}`;
116
164
  }
@@ -158,7 +206,7 @@ signal) {
158
206
  outputShape,
159
207
  plannedRounds,
160
208
  };
161
- return ensureProductStance(injectAuditorStance(plan, eeWarnings, experienceMode));
209
+ return finalizePlan(plan);
162
210
  }
163
211
  // Invalid even with schema — fall through to retry with a sanitize-failure message
164
212
  throw new Error("Sanitize check failed: stances.length < 2 or outputShape is null");
@@ -180,7 +228,7 @@ signal) {
180
228
  });
181
229
  const retryParsed = parsePlan(retryRaw);
182
230
  if (retryParsed)
183
- return ensureProductStance(injectAuditorStance(retryParsed, eeWarnings, experienceMode));
231
+ return finalizePlan(retryParsed);
184
232
  }
185
233
  catch (retryErr) {
186
234
  yield {
@@ -190,7 +238,7 @@ signal) {
190
238
  }
191
239
  }
192
240
  // All attempts exhausted — return fallback
193
- return ensureProductStance(injectAuditorStance(FALLBACK_PLAN, eeWarnings, experienceMode));
241
+ return finalizePlan(FALLBACK_PLAN);
194
242
  }
195
243
  function parsePlan(raw) {
196
244
  try {
@@ -0,0 +1,25 @@
1
+ /**
2
+ * src/council/debate-summary.ts
3
+ *
4
+ * Fallback debate-summary synthesis.
5
+ *
6
+ * The /ideal research phase persists the debate into `research.md` +
7
+ * `delegations.md` from `DebateState.runningSummary`. But a debate that returns
8
+ * after opening statements (e.g. the leader routes straight to the preflight
9
+ * gate without evaluation rounds) leaves `runningSummary` empty — and the whole
10
+ * debate (opening positions, design/impl reasoning) was silently dropped from
11
+ * the canonical artifacts, surviving only in TUI scrollback.
12
+ *
13
+ * This builds a faithful fallback from the participants' latest positions
14
+ * (`active[]`), falling back to per-round archive excerpts, so the research
15
+ * artifact ALWAYS captures the debate. Pure + synchronous → unit-testable.
16
+ */
17
+ import type { DebateState } from "./types.js";
18
+ /**
19
+ * Return a markdown summary of the debate suitable for `research.md` /
20
+ * `delegations.md`. Prefers `state.runningSummary` when present; otherwise
21
+ * synthesizes one from `active[]` positions, then `archive[]` excerpts. Returns
22
+ * "" only when there is genuinely nothing to show (no summary, no positions, no
23
+ * archive) — callers keep their existing "(no summary produced)" placeholder.
24
+ */
25
+ export declare function resolveDebateSummary(state: Pick<DebateState, "runningSummary" | "active" | "archive">): string;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * src/council/debate-summary.ts
3
+ *
4
+ * Fallback debate-summary synthesis.
5
+ *
6
+ * The /ideal research phase persists the debate into `research.md` +
7
+ * `delegations.md` from `DebateState.runningSummary`. But a debate that returns
8
+ * after opening statements (e.g. the leader routes straight to the preflight
9
+ * gate without evaluation rounds) leaves `runningSummary` empty — and the whole
10
+ * debate (opening positions, design/impl reasoning) was silently dropped from
11
+ * the canonical artifacts, surviving only in TUI scrollback.
12
+ *
13
+ * This builds a faithful fallback from the participants' latest positions
14
+ * (`active[]`), falling back to per-round archive excerpts, so the research
15
+ * artifact ALWAYS captures the debate. Pure + synchronous → unit-testable.
16
+ */
17
+ /** Cap so the fallback can't balloon the artifact; per-position + overall. */
18
+ const PER_POSITION_CHARS = 4000;
19
+ const TOTAL_CHARS = 16000;
20
+ /**
21
+ * Return a markdown summary of the debate suitable for `research.md` /
22
+ * `delegations.md`. Prefers `state.runningSummary` when present; otherwise
23
+ * synthesizes one from `active[]` positions, then `archive[]` excerpts. Returns
24
+ * "" only when there is genuinely nothing to show (no summary, no positions, no
25
+ * archive) — callers keep their existing "(no summary produced)" placeholder.
26
+ */
27
+ export function resolveDebateSummary(state) {
28
+ const running = state.runningSummary?.trim();
29
+ if (running)
30
+ return running;
31
+ const fromPositions = summarizeFromActive(state.active);
32
+ if (fromPositions)
33
+ return fromPositions;
34
+ return summarizeFromArchive(state.archive);
35
+ }
36
+ function speakerLabel(role, stanceName) {
37
+ return stanceName?.trim() ? `${stanceName} (${role})` : role;
38
+ }
39
+ function summarizeFromActive(active) {
40
+ if (!Array.isArray(active) || active.length === 0)
41
+ return "";
42
+ const parts = [
43
+ "_(Synthesized from participants' final positions — the debate produced no running summary.)_",
44
+ "",
45
+ ];
46
+ let total = 0;
47
+ for (const p of active) {
48
+ const position = (p.position ?? "").trim();
49
+ if (!position)
50
+ continue;
51
+ const clipped = position.length > PER_POSITION_CHARS ? `${position.slice(0, PER_POSITION_CHARS)}…` : position;
52
+ const block = `### ${speakerLabel(p.role, p.stance?.name)}\n\n${clipped}`;
53
+ if (total + block.length > TOTAL_CHARS) {
54
+ parts.push("_(remaining positions truncated)_");
55
+ break;
56
+ }
57
+ parts.push(block, "");
58
+ total += block.length;
59
+ }
60
+ // Only the header + no real positions → nothing worth persisting.
61
+ return parts.length > 2 ? parts.join("\n").trimEnd() : "";
62
+ }
63
+ function summarizeFromArchive(archive) {
64
+ if (!Array.isArray(archive) || archive.length === 0)
65
+ return "";
66
+ const parts = [
67
+ "_(Synthesized from per-round debate excerpts — the debate produced no running summary.)_",
68
+ "",
69
+ ];
70
+ let total = 0;
71
+ for (const e of archive) {
72
+ const excerpt = (e.excerpt ?? "").trim();
73
+ if (!excerpt)
74
+ continue;
75
+ const block = `### Round ${e.round} — ${speakerLabel(e.role, e.stanceName)}\n\n${excerpt}`;
76
+ if (total + block.length > TOTAL_CHARS) {
77
+ parts.push("_(remaining excerpts truncated)_");
78
+ break;
79
+ }
80
+ parts.push(block, "");
81
+ total += block.length;
82
+ }
83
+ return parts.length > 2 ? parts.join("\n").trimEnd() : "";
84
+ }
85
+ //# sourceMappingURL=debate-summary.js.map