muonroi-cli 1.8.4 → 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 (458) hide show
  1. package/LICENSE +17 -5
  2. package/dist/packages/agent-harness-core/src/driver.d.ts +27 -1
  3. package/dist/packages/agent-harness-core/src/driver.js +46 -0
  4. package/dist/packages/agent-harness-core/src/event-tee.d.ts +48 -0
  5. package/dist/packages/agent-harness-core/src/event-tee.js +77 -0
  6. package/dist/packages/agent-harness-core/src/mcp-server.d.ts +11 -0
  7. package/dist/packages/agent-harness-core/src/mcp-server.js +87 -15
  8. package/dist/packages/agent-harness-core/src/protocol.d.ts +66 -2
  9. package/dist/packages/agent-harness-core/src/protocol.js +15 -0
  10. package/dist/packages/agent-harness-core/src/visual-quality.d.ts +58 -0
  11. package/dist/packages/agent-harness-core/src/visual-quality.js +141 -0
  12. package/dist/packages/agent-harness-opentui/src/agent-mode.d.ts +6 -0
  13. package/dist/packages/agent-harness-opentui/src/agent-mode.js +14 -1
  14. package/dist/packages/agent-harness-opentui/src/input-bridge.d.ts +2 -10
  15. package/dist/packages/agent-harness-opentui/src/input-bridge.js +103 -16
  16. package/dist/packages/agent-harness-opentui/src/install.d.ts +8 -0
  17. package/dist/packages/agent-harness-opentui/src/install.js +10 -0
  18. package/dist/packages/agent-harness-opentui/src/semantic.js +12 -10
  19. package/dist/packages/agent-harness-opentui/src/visual-capture.d.ts +56 -0
  20. package/dist/packages/agent-harness-opentui/src/visual-capture.js +103 -0
  21. package/dist/src/agent-harness/mock-model.d.ts +28 -0
  22. package/dist/src/agent-harness/mock-model.js +63 -1
  23. package/dist/src/agent-harness/test-spawn.js +31 -0
  24. package/dist/src/cli/config/screen-providers.js +1 -1
  25. package/dist/src/cli/cost-forensics.d.ts +10 -0
  26. package/dist/src/cli/cost-forensics.js +18 -3
  27. package/dist/src/cli/keys-bundle.d.ts +1 -1
  28. package/dist/src/cli/keys-bundle.js +1 -1
  29. package/dist/src/cli/keys.d.ts +2 -2
  30. package/dist/src/cli/keys.js +19 -81
  31. package/dist/src/council/clarifier.d.ts +28 -2
  32. package/dist/src/council/clarifier.js +81 -15
  33. package/dist/src/council/context.js +49 -15
  34. package/dist/src/council/debate-checkpoint.d.ts +129 -0
  35. package/dist/src/council/debate-checkpoint.js +176 -0
  36. package/dist/src/council/debate-planner.js +51 -3
  37. package/dist/src/council/debate-summary.d.ts +25 -0
  38. package/dist/src/council/debate-summary.js +85 -0
  39. package/dist/src/council/debate.d.ts +169 -2
  40. package/dist/src/council/debate.js +1210 -134
  41. package/dist/src/council/index.d.ts +85 -1
  42. package/dist/src/council/index.js +634 -196
  43. package/dist/src/council/leader.d.ts +26 -0
  44. package/dist/src/council/leader.js +150 -9
  45. package/dist/src/council/llm.d.ts +32 -0
  46. package/dist/src/council/llm.js +231 -38
  47. package/dist/src/council/panel-select.d.ts +30 -0
  48. package/dist/src/council/panel-select.js +72 -0
  49. package/dist/src/council/planner.js +23 -0
  50. package/dist/src/council/preflight.d.ts +7 -0
  51. package/dist/src/council/preflight.js +14 -2
  52. package/dist/src/council/prompts.d.ts +30 -3
  53. package/dist/src/council/prompts.js +234 -64
  54. package/dist/src/council/stance-recall.d.ts +42 -0
  55. package/dist/src/council/stance-recall.js +57 -0
  56. package/dist/src/council/strip-think.d.ts +17 -0
  57. package/dist/src/council/strip-think.js +33 -0
  58. package/dist/src/council/types.d.ts +128 -0
  59. package/dist/src/ee/artifact-cache.d.ts +16 -0
  60. package/dist/src/ee/artifact-cache.js +32 -0
  61. package/dist/src/ee/auth.d.ts +1 -0
  62. package/dist/src/ee/auth.js +15 -2
  63. package/dist/src/ee/bridge.d.ts +10 -0
  64. package/dist/src/ee/bridge.js +58 -0
  65. package/dist/src/ee/client.js +81 -18
  66. package/dist/src/ee/export-transcripts.d.ts +1 -0
  67. package/dist/src/ee/export-transcripts.js +8 -10
  68. package/dist/src/ee/extract-session.js +29 -0
  69. package/dist/src/ee/extract-style.d.ts +58 -0
  70. package/dist/src/ee/extract-style.js +270 -0
  71. package/dist/src/ee/recall-ledger.d.ts +9 -0
  72. package/dist/src/ee/recall-ledger.js +3 -0
  73. package/dist/src/ee/scope.d.ts +1 -0
  74. package/dist/src/ee/scope.js +26 -1
  75. package/dist/src/ee/search.d.ts +7 -0
  76. package/dist/src/ee/search.js +24 -0
  77. package/dist/src/ee/transcript-emit.js +2 -0
  78. package/dist/src/ee/types.d.ts +22 -0
  79. package/dist/src/ee/who-am-i-brain.d.ts +35 -0
  80. package/dist/src/ee/who-am-i-brain.js +220 -0
  81. package/dist/src/ee/who-am-i.d.ts +10 -3
  82. package/dist/src/ee/who-am-i.js +12 -0
  83. package/dist/src/ee/workflow-event.d.ts +48 -0
  84. package/dist/src/ee/workflow-event.js +81 -0
  85. package/dist/src/flow/compaction/compress.d.ts +3 -3
  86. package/dist/src/flow/compaction/compress.js +45 -8
  87. package/dist/src/flow/compaction/extract.d.ts +4 -7
  88. package/dist/src/flow/compaction/extract.js +50 -10
  89. package/dist/src/flow/compaction/index.d.ts +13 -1
  90. package/dist/src/flow/compaction/index.js +70 -3
  91. package/dist/src/flow/compaction/input-guard.d.ts +24 -0
  92. package/dist/src/flow/compaction/input-guard.js +43 -0
  93. package/dist/src/flow/fold-planning.d.ts +36 -0
  94. package/dist/src/flow/fold-planning.js +83 -0
  95. package/dist/src/flow/hierarchy.d.ts +146 -0
  96. package/dist/src/flow/hierarchy.js +427 -0
  97. package/dist/src/flow/index.d.ts +1 -0
  98. package/dist/src/flow/index.js +2 -0
  99. package/dist/src/flow/run-artifacts.d.ts +102 -0
  100. package/dist/src/flow/run-artifacts.js +208 -0
  101. package/dist/src/generated/version.d.ts +1 -1
  102. package/dist/src/generated/version.js +1 -1
  103. package/dist/src/gsd/assessment-schema.d.ts +44 -0
  104. package/dist/src/gsd/assessment-schema.js +134 -0
  105. package/dist/src/gsd/capability-registry.d.ts +45 -0
  106. package/dist/src/gsd/capability-registry.js +337 -0
  107. package/dist/src/gsd/complexity-assessor.d.ts +39 -0
  108. package/dist/src/gsd/complexity-assessor.js +152 -0
  109. package/dist/src/gsd/config-bridge.d.ts +7 -0
  110. package/dist/src/gsd/config-bridge.js +114 -0
  111. package/dist/src/gsd/config-loader.d.ts +27 -0
  112. package/dist/src/gsd/config-loader.js +50 -0
  113. package/dist/src/gsd/council-context.d.ts +44 -0
  114. package/dist/src/gsd/council-context.js +114 -0
  115. package/dist/src/gsd/ee-closure.d.ts +28 -0
  116. package/dist/src/gsd/ee-closure.js +49 -0
  117. package/dist/src/gsd/flags.d.ts +55 -0
  118. package/dist/src/gsd/flags.js +83 -0
  119. package/dist/src/gsd/gsd-dispatch.d.ts +58 -0
  120. package/dist/src/gsd/gsd-dispatch.js +131 -0
  121. package/dist/src/gsd/gsd-runtime.d.ts +22 -0
  122. package/dist/src/gsd/gsd-runtime.js +37 -0
  123. package/dist/src/gsd/host-adapter.d.ts +11 -0
  124. package/dist/src/gsd/host-adapter.js +29 -0
  125. package/dist/src/gsd/index.d.ts +24 -1
  126. package/dist/src/gsd/index.js +27 -0
  127. package/dist/src/gsd/loop-host-contract.d.ts +21 -0
  128. package/dist/src/gsd/loop-host-contract.js +39 -0
  129. package/dist/src/gsd/loop-host.d.ts +69 -0
  130. package/dist/src/gsd/loop-host.js +245 -0
  131. package/dist/src/gsd/loop-resolver.d.ts +36 -0
  132. package/dist/src/gsd/loop-resolver.js +79 -0
  133. package/dist/src/gsd/model-tier.d.ts +13 -0
  134. package/dist/src/gsd/model-tier.js +45 -0
  135. package/dist/src/gsd/mutation-gate.d.ts +16 -0
  136. package/dist/src/gsd/mutation-gate.js +41 -0
  137. package/dist/src/gsd/native-roadmap.d.ts +89 -0
  138. package/dist/src/gsd/native-roadmap.js +343 -0
  139. package/dist/src/gsd/native-state.d.ts +47 -0
  140. package/dist/src/gsd/native-state.js +220 -0
  141. package/dist/src/gsd/paths.d.ts +23 -0
  142. package/dist/src/gsd/paths.js +66 -0
  143. package/dist/src/gsd/phase-dag.d.ts +12 -0
  144. package/dist/src/gsd/phase-dag.js +94 -0
  145. package/dist/src/gsd/phase-sync.d.ts +42 -0
  146. package/dist/src/gsd/phase-sync.js +321 -0
  147. package/dist/src/gsd/pil-gate-context.d.ts +13 -0
  148. package/dist/src/gsd/pil-gate-context.js +64 -0
  149. package/dist/src/gsd/pil-gate-critic.d.ts +19 -0
  150. package/dist/src/gsd/pil-gate-critic.js +74 -0
  151. package/dist/src/gsd/plan-council-prompts.d.ts +25 -0
  152. package/dist/src/gsd/plan-council-prompts.js +79 -0
  153. package/dist/src/gsd/plan-council.d.ts +44 -0
  154. package/dist/src/gsd/plan-council.js +251 -0
  155. package/dist/src/gsd/plan-gate-vocabulary.d.ts +40 -0
  156. package/dist/src/gsd/plan-gate-vocabulary.js +64 -0
  157. package/dist/src/gsd/product-workspace.d.ts +13 -0
  158. package/dist/src/gsd/product-workspace.js +124 -0
  159. package/dist/src/gsd/ship-bridge.d.ts +25 -0
  160. package/dist/src/gsd/ship-bridge.js +65 -0
  161. package/dist/src/gsd/state-document.d.ts +40 -0
  162. package/dist/src/gsd/state-document.js +163 -0
  163. package/dist/src/gsd/verdict-schema.d.ts +39 -0
  164. package/dist/src/gsd/verdict-schema.js +144 -0
  165. package/dist/src/gsd/verify-context.d.ts +22 -0
  166. package/dist/src/gsd/verify-context.js +27 -0
  167. package/dist/src/gsd/verify-council-prompts.d.ts +19 -0
  168. package/dist/src/gsd/verify-council-prompts.js +85 -0
  169. package/dist/src/gsd/verify-council.d.ts +25 -0
  170. package/dist/src/gsd/verify-council.js +119 -0
  171. package/dist/src/gsd/verify-gate-vocabulary.d.ts +25 -0
  172. package/dist/src/gsd/verify-gate-vocabulary.js +46 -0
  173. package/dist/src/gsd/workflow-engine.d.ts +60 -0
  174. package/dist/src/gsd/workflow-engine.js +207 -0
  175. package/dist/src/gsd/workflow-tools.d.ts +13 -0
  176. package/dist/src/gsd/workflow-tools.js +277 -0
  177. package/dist/src/hooks/index.js +1 -1
  178. package/dist/src/index.js +44 -11
  179. package/dist/src/maintain/pr-builder.js +23 -13
  180. package/dist/src/mcp/auto-setup.js +57 -32
  181. package/dist/src/mcp/client-pool.js +1 -1
  182. package/dist/src/mcp/ee-tools.js +1 -0
  183. package/dist/src/mcp/research-onboarding.js +8 -7
  184. package/dist/src/mcp/runtime.js +34 -2
  185. package/dist/src/models/catalog-client.d.ts +87 -0
  186. package/dist/src/models/catalog-client.js +105 -38
  187. package/dist/src/models/catalog.json +528 -265
  188. package/dist/src/models/registry.d.ts +22 -7
  189. package/dist/src/models/registry.js +73 -10
  190. package/dist/src/ops/doctor.js +1 -1
  191. package/dist/src/orchestrator/auto-commit.js +1 -1
  192. package/dist/src/orchestrator/batch-turn-runner.js +2 -2
  193. package/dist/src/orchestrator/cache-prefix.d.ts +67 -0
  194. package/dist/src/orchestrator/cache-prefix.js +83 -0
  195. package/dist/src/orchestrator/compact-request.d.ts +32 -0
  196. package/dist/src/orchestrator/compact-request.js +41 -0
  197. package/dist/src/orchestrator/compaction.d.ts +10 -0
  198. package/dist/src/orchestrator/compaction.js +27 -7
  199. package/dist/src/orchestrator/council-manager.d.ts +12 -3
  200. package/dist/src/orchestrator/council-manager.js +65 -24
  201. package/dist/src/orchestrator/cross-turn-dedup.d.ts +6 -0
  202. package/dist/src/orchestrator/cross-turn-dedup.js +22 -1
  203. package/dist/src/orchestrator/error-utils.d.ts +29 -0
  204. package/dist/src/orchestrator/error-utils.js +132 -24
  205. package/dist/src/orchestrator/grounding-check.js +39 -1
  206. package/dist/src/orchestrator/message-processor.js +242 -33
  207. package/dist/src/orchestrator/orchestrator.d.ts +39 -3
  208. package/dist/src/orchestrator/orchestrator.js +651 -102
  209. package/dist/src/orchestrator/preprocessor.js +1 -1
  210. package/dist/src/orchestrator/proactive-compact-detector.d.ts +26 -0
  211. package/dist/src/orchestrator/proactive-compact-detector.js +36 -0
  212. package/dist/src/orchestrator/prompts.js +17 -17
  213. package/dist/src/orchestrator/reactive-delegation.d.ts +39 -0
  214. package/dist/src/orchestrator/reactive-delegation.js +59 -0
  215. package/dist/src/orchestrator/retry-classifier.d.ts +2 -1
  216. package/dist/src/orchestrator/retry-classifier.js +46 -2
  217. package/dist/src/orchestrator/safety-intercept.d.ts +45 -0
  218. package/dist/src/orchestrator/safety-intercept.js +55 -0
  219. package/dist/src/orchestrator/scope-reminder.js +1 -1
  220. package/dist/src/orchestrator/session-experience.d.ts +2 -1
  221. package/dist/src/orchestrator/session-experience.js +2 -1
  222. package/dist/src/orchestrator/should-run-gate.d.ts +5 -0
  223. package/dist/src/orchestrator/should-run-gate.js +18 -0
  224. package/dist/src/orchestrator/stall-watchdog.d.ts +24 -3
  225. package/dist/src/orchestrator/stall-watchdog.js +47 -13
  226. package/dist/src/orchestrator/stream-runner.js +62 -29
  227. package/dist/src/orchestrator/sub-agent-cap.d.ts +13 -1
  228. package/dist/src/orchestrator/sub-agent-cap.js +16 -1
  229. package/dist/src/orchestrator/sub-agent-model-tier.d.ts +13 -1
  230. package/dist/src/orchestrator/sub-agent-model-tier.js +16 -2
  231. package/dist/src/orchestrator/subagent-compactor.d.ts +53 -1
  232. package/dist/src/orchestrator/subagent-compactor.js +126 -15
  233. package/dist/src/orchestrator/tool-engine.d.ts +22 -0
  234. package/dist/src/orchestrator/tool-engine.js +620 -56
  235. package/dist/src/orchestrator/tool-limit-auto-recover.d.ts +22 -0
  236. package/dist/src/orchestrator/tool-limit-auto-recover.js +30 -0
  237. package/dist/src/orchestrator/turn-runner-deps.d.ts +19 -0
  238. package/dist/src/orchestrator/turn-watchdog.d.ts +37 -0
  239. package/dist/src/orchestrator/turn-watchdog.js +55 -0
  240. package/dist/src/pil/agent-operating-contract.d.ts +1 -1
  241. package/dist/src/pil/agent-operating-contract.js +1 -1
  242. package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
  243. package/dist/src/pil/cheap-model-playbook.js +5 -1
  244. package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
  245. package/dist/src/pil/cheap-model-workbooks.js +1 -1
  246. package/dist/src/pil/discovery-types.d.ts +1 -0
  247. package/dist/src/pil/discovery.js +16 -11
  248. package/dist/src/pil/layer1-intent.d.ts +18 -6
  249. package/dist/src/pil/layer1-intent.js +66 -757
  250. package/dist/src/pil/layer15-context-scan.js +15 -1
  251. package/dist/src/pil/layer3-ee-injection.js +23 -8
  252. package/dist/src/pil/layer4-gsd.js +69 -16
  253. package/dist/src/pil/layer5-context.js +7 -3
  254. package/dist/src/pil/layer6-output.d.ts +23 -0
  255. package/dist/src/pil/layer6-output.js +5 -1
  256. package/dist/src/pil/llm-classify.d.ts +33 -2
  257. package/dist/src/pil/llm-classify.js +123 -131
  258. package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
  259. package/dist/src/pil/native-capabilities-workbook.js +1 -0
  260. package/dist/src/pil/pipeline.js +34 -2
  261. package/dist/src/pil/response-tools.js +5 -3
  262. package/dist/src/pil/schema.d.ts +1 -0
  263. package/dist/src/pil/schema.js +2 -0
  264. package/dist/src/pil/types.d.ts +18 -0
  265. package/dist/src/playbook/directives.d.ts +4 -0
  266. package/dist/src/playbook/directives.js +17 -5
  267. package/dist/src/product-loop/backlog-builder.d.ts +14 -1
  268. package/dist/src/product-loop/backlog-builder.js +30 -6
  269. package/dist/src/product-loop/discovery-context-format.js +3 -1
  270. package/dist/src/product-loop/discovery-ecosystem.js +4 -1
  271. package/dist/src/product-loop/discovery-interview.js +32 -3
  272. package/dist/src/product-loop/discovery-schema.js +5 -1
  273. package/dist/src/product-loop/ideal-trace.d.ts +7 -0
  274. package/dist/src/product-loop/ideal-trace.js +64 -0
  275. package/dist/src/product-loop/index.d.ts +13 -1
  276. package/dist/src/product-loop/index.js +333 -52
  277. package/dist/src/product-loop/loop-driver.d.ts +7 -0
  278. package/dist/src/product-loop/loop-driver.js +310 -99
  279. package/dist/src/product-loop/phase-plan.d.ts +5 -0
  280. package/dist/src/product-loop/phase-plan.js +39 -2
  281. package/dist/src/product-loop/phase-runner.js +9 -1
  282. package/dist/src/product-loop/sprint-runner.d.ts +111 -0
  283. package/dist/src/product-loop/sprint-runner.js +559 -16
  284. package/dist/src/product-loop/types.d.ts +36 -5
  285. package/dist/src/providers/adapter.d.ts +1 -1
  286. package/dist/src/providers/adapter.js +3 -4
  287. package/dist/src/providers/auth/browser-flow.d.ts +1 -1
  288. package/dist/src/providers/auth/browser-flow.js +1 -1
  289. package/dist/src/providers/auth/openai-oauth.js +1 -1
  290. package/dist/src/providers/auth/registry.js +0 -34
  291. package/dist/src/providers/auth/token-store.js +4 -1
  292. package/dist/src/providers/auth/types.d.ts +1 -1
  293. package/dist/src/providers/auth/types.js +1 -1
  294. package/dist/src/providers/capabilities.d.ts +24 -5
  295. package/dist/src/providers/capabilities.js +42 -24
  296. package/dist/src/providers/endpoints.d.ts +2 -2
  297. package/dist/src/providers/endpoints.js +11 -10
  298. package/dist/src/providers/keychain.d.ts +1 -1
  299. package/dist/src/providers/keychain.js +7 -9
  300. package/dist/src/providers/mcp-vision-bridge.js +56 -146
  301. package/dist/src/providers/openai-compatible.js +8 -1
  302. package/dist/src/providers/pricing.d.ts +2 -2
  303. package/dist/src/providers/pricing.js +3 -13
  304. package/dist/src/providers/runtime.d.ts +27 -2
  305. package/dist/src/providers/runtime.js +78 -15
  306. package/dist/src/providers/strategies/base.strategy.d.ts +16 -0
  307. package/dist/src/providers/strategies/base.strategy.js +24 -1
  308. package/dist/src/providers/strategies/{siliconflow.strategy.d.ts → opencode-go.strategy.d.ts} +3 -3
  309. package/dist/src/providers/strategies/opencode-go.strategy.js +83 -0
  310. package/dist/src/providers/strategies/registry.js +4 -4
  311. package/dist/src/providers/strategies/thinking-mode.d.ts +109 -0
  312. package/dist/src/providers/strategies/thinking-mode.js +280 -1
  313. package/dist/src/providers/strategies/zai.strategy.d.ts +14 -0
  314. package/dist/src/providers/strategies/zai.strategy.js +44 -0
  315. package/dist/src/providers/types.d.ts +5 -6
  316. package/dist/src/providers/types.js +2 -2
  317. package/dist/src/providers/vision-backend.d.ts +47 -0
  318. package/dist/src/providers/vision-backend.js +258 -0
  319. package/dist/src/providers/vision-proxy.d.ts +22 -9
  320. package/dist/src/providers/vision-proxy.js +63 -132
  321. package/dist/src/providers/wire-debug.js +95 -0
  322. package/dist/src/router/decide.d.ts +13 -0
  323. package/dist/src/router/decide.js +138 -36
  324. package/dist/src/router/peak-hour.d.ts +38 -0
  325. package/dist/src/router/peak-hour.js +107 -0
  326. package/dist/src/router/step-router.js +3 -2
  327. package/dist/src/router/warm.js +4 -5
  328. package/dist/src/scaffold/continuation-prompt.d.ts +11 -0
  329. package/dist/src/scaffold/continuation-prompt.js +26 -0
  330. package/dist/src/scaffold/point-to-existing.d.ts +21 -0
  331. package/dist/src/scaffold/point-to-existing.js +25 -0
  332. package/dist/src/self-qa/agentic-loop.js +3 -3
  333. package/dist/src/{ui/state → state}/active-run.d.ts +19 -0
  334. package/dist/src/{ui/state → state}/active-run.js +21 -0
  335. package/dist/src/{ui/status-bar/store.d.ts → state/status-bar-store.d.ts} +4 -1
  336. package/dist/src/{ui/status-bar/store.js → state/status-bar-store.js} +12 -9
  337. package/dist/src/state/turn-trace.d.ts +43 -0
  338. package/dist/src/state/turn-trace.js +32 -0
  339. package/dist/src/storage/db.js +2 -1
  340. package/dist/src/storage/index.d.ts +1 -1
  341. package/dist/src/storage/index.js +1 -1
  342. package/dist/src/storage/interaction-log.d.ts +1 -1
  343. package/dist/src/storage/migrations.js +71 -1
  344. package/dist/src/storage/sessions.d.ts +28 -10
  345. package/dist/src/storage/sessions.js +78 -21
  346. package/dist/src/storage/transcript-view.js +1 -1
  347. package/dist/src/storage/transcript.d.ts +51 -0
  348. package/dist/src/storage/transcript.js +284 -13
  349. package/dist/src/tools/file.d.ts +15 -0
  350. package/dist/src/tools/file.js +32 -0
  351. package/dist/src/tools/native-tools.js +5 -0
  352. package/dist/src/tools/registry.d.ts +3 -0
  353. package/dist/src/tools/registry.js +460 -22
  354. package/dist/src/tools/research.d.ts +29 -0
  355. package/dist/src/tools/research.js +233 -0
  356. package/dist/src/types/index.d.ts +118 -3
  357. package/dist/src/ui/app.js +0 -0
  358. package/dist/src/ui/cards/product-status-card.js +1 -1
  359. package/dist/src/ui/components/bubble-body-guard.d.ts +27 -0
  360. package/dist/src/ui/components/bubble-body-guard.js +50 -0
  361. package/dist/src/ui/components/context-rail.d.ts +26 -0
  362. package/dist/src/ui/components/context-rail.js +33 -0
  363. package/dist/src/ui/components/council-conclusion-card.d.ts +73 -0
  364. package/dist/src/ui/components/council-conclusion-card.js +420 -0
  365. package/dist/src/ui/components/council-debate-pill.d.ts +36 -0
  366. package/dist/src/ui/components/council-debate-pill.js +34 -0
  367. package/dist/src/ui/components/council-info-card.js +2 -2
  368. package/dist/src/ui/components/council-leader-bubble.d.ts +10 -3
  369. package/dist/src/ui/components/council-leader-bubble.js +21 -11
  370. package/dist/src/ui/components/council-message-bubble.d.ts +15 -2
  371. package/dist/src/ui/components/council-message-bubble.js +16 -15
  372. package/dist/src/ui/components/council-phase-timeline.d.ts +9 -1
  373. package/dist/src/ui/components/council-phase-timeline.js +49 -15
  374. package/dist/src/ui/components/council-placeholder-bubble.d.ts +16 -9
  375. package/dist/src/ui/components/council-placeholder-bubble.js +32 -29
  376. package/dist/src/ui/components/council-question-card.js +12 -12
  377. package/dist/src/ui/components/council-rail-rounds.d.ts +26 -0
  378. package/dist/src/ui/components/council-rail-rounds.js +57 -0
  379. package/dist/src/ui/components/council-round-group.d.ts +38 -0
  380. package/dist/src/ui/components/council-round-group.js +88 -0
  381. package/dist/src/ui/components/council-status-list.d.ts +3 -1
  382. package/dist/src/ui/components/council-status-list.js +36 -24
  383. package/dist/src/ui/components/council-synthesis-banner.d.ts +7 -2
  384. package/dist/src/ui/components/council-synthesis-banner.js +20 -5
  385. package/dist/src/ui/components/halt-recovery-card.js +9 -5
  386. package/dist/src/ui/components/jump-to-latest-pill.d.ts +11 -0
  387. package/dist/src/ui/components/jump-to-latest-pill.js +14 -0
  388. package/dist/src/ui/components/prompt-box.js +18 -16
  389. package/dist/src/ui/components/session-tree-card.d.ts +14 -0
  390. package/dist/src/ui/components/session-tree-card.js +46 -0
  391. package/dist/src/ui/components/slash-inline-menu.d.ts +12 -0
  392. package/dist/src/ui/components/slash-inline-menu.js +26 -5
  393. package/dist/src/ui/components/task-list-panel.d.ts +14 -1
  394. package/dist/src/ui/components/task-list-panel.js +22 -2
  395. package/dist/src/ui/containers/modals-layer.d.ts +2 -1
  396. package/dist/src/ui/hooks/use-session-picker.d.ts +3 -3
  397. package/dist/src/ui/mcp-modal.js +2 -4
  398. package/dist/src/ui/modals/api-key-modal.js +1 -1
  399. package/dist/src/ui/modals/connect-modal.js +4 -3
  400. package/dist/src/ui/modals/session-picker-modal.d.ts +2 -2
  401. package/dist/src/ui/modals/session-picker-modal.js +3 -5
  402. package/dist/src/ui/picker-providers.d.ts +1 -1
  403. package/dist/src/ui/picker-providers.js +1 -1
  404. package/dist/src/ui/primitives/index.d.ts +1 -0
  405. package/dist/src/ui/primitives/index.js +2 -0
  406. package/dist/src/ui/primitives/semantic-primitives.d.ts +76 -0
  407. package/dist/src/ui/primitives/semantic-primitives.js +81 -0
  408. package/dist/src/ui/slash/compact.js +5 -7
  409. package/dist/src/ui/slash/cost.js +1 -1
  410. package/dist/src/ui/slash/council.js +19 -1
  411. package/dist/src/ui/slash/debug.d.ts +3 -31
  412. package/dist/src/ui/slash/debug.js +9 -20
  413. package/dist/src/ui/slash/ideal.d.ts +6 -2
  414. package/dist/src/ui/slash/ideal.js +97 -7
  415. package/dist/src/ui/slash/menu-items.d.ts +7 -0
  416. package/dist/src/ui/slash/menu-items.js +12 -18
  417. package/dist/src/ui/slash/registry.d.ts +2 -0
  418. package/dist/src/ui/slash/registry.js +4 -0
  419. package/dist/src/ui/status-bar/cache-hit.d.ts +6 -0
  420. package/dist/src/ui/status-bar/cache-hit.js +9 -0
  421. package/dist/src/ui/status-bar/index.d.ts +1 -1
  422. package/dist/src/ui/status-bar/index.js +7 -3
  423. package/dist/src/ui/status-bar/usd-meter.d.ts +5 -4
  424. package/dist/src/ui/status-bar/usd-meter.js +6 -4
  425. package/dist/src/ui/theme.d.ts +1 -0
  426. package/dist/src/ui/theme.js +2 -0
  427. package/dist/src/ui/types.d.ts +7 -0
  428. package/dist/src/ui/use-app-logic.js +0 -0
  429. package/dist/src/ui/utils/format.d.ts +14 -0
  430. package/dist/src/ui/utils/format.js +23 -3
  431. package/dist/src/usage/downgrade.js +2 -2
  432. package/dist/src/usage/product-ledger.js +2 -2
  433. package/dist/src/utils/install-manager.js +2 -1
  434. package/dist/src/utils/logger.js +2 -2
  435. package/dist/src/utils/permission-mode.js +5 -3
  436. package/dist/src/utils/redactor.js +1 -1
  437. package/dist/src/utils/settings.d.ts +153 -5
  438. package/dist/src/utils/settings.js +233 -29
  439. package/dist/src/utils/visible-retry.d.ts +11 -0
  440. package/dist/src/utils/visible-retry.js +10 -1
  441. package/dist/src/verify/entrypoint.d.ts +1 -1
  442. package/dist/src/verify/entrypoint.js +1 -1
  443. package/dist/src/verify/recipes.d.ts +13 -0
  444. package/dist/src/verify/recipes.js +15 -0
  445. package/package.json +135 -132
  446. package/dist/src/providers/auth/gcloud.d.ts +0 -28
  447. package/dist/src/providers/auth/gcloud.js +0 -102
  448. package/dist/src/providers/auth/gemini-oauth.d.ts +0 -82
  449. package/dist/src/providers/auth/gemini-oauth.js +0 -472
  450. package/dist/src/providers/gemini.d.ts +0 -11
  451. package/dist/src/providers/gemini.js +0 -45
  452. package/dist/src/providers/siliconflow-sse-repair.d.ts +0 -58
  453. package/dist/src/providers/siliconflow-sse-repair.js +0 -177
  454. package/dist/src/providers/strategies/google.strategy.d.ts +0 -22
  455. package/dist/src/providers/strategies/google.strategy.js +0 -174
  456. package/dist/src/providers/strategies/siliconflow.strategy.js +0 -29
  457. package/dist/src/ui/containers/chat-feed.d.ts +0 -40
  458. package/dist/src/ui/containers/chat-feed.js +0 -66
@@ -0,0 +1,73 @@
1
+ import type { Theme } from "../theme.js";
2
+ /**
3
+ * Structured post-debate conclusion, parsed from the leader synthesis JSON.
4
+ *
5
+ * When a debate's deliverable is an evaluation/decision, the synthesizer emits a
6
+ * JSON object (summary + strengths/weaknesses/recommendation/coverage_matrix …).
7
+ * Rendered verbatim (the old CouncilSynthesisBanner path) it reads as an unbroken
8
+ * wall of JSON — "freetext khó nhìn". This card lifts the known sections into a
9
+ * scannable layout. When the text is NOT parseable structured JSON (e.g. the
10
+ * synthesizer emitted a `---READABLE---` prose tail), `parseConclusion` returns
11
+ * null and the caller falls back to plain-text rendering.
12
+ */
13
+ export interface DimensionScore {
14
+ dimension: string;
15
+ score: number;
16
+ justification: string;
17
+ }
18
+ export interface OperationalRisk {
19
+ risk: string;
20
+ severity: string;
21
+ trigger: string;
22
+ }
23
+ export interface NextAction {
24
+ action: string;
25
+ label: string;
26
+ reason?: string;
27
+ }
28
+ export interface ParsedConclusion {
29
+ summary?: string;
30
+ recommendation?: string;
31
+ strengths: string[];
32
+ weaknesses: string[];
33
+ risks: string[];
34
+ tradeoffs: string[];
35
+ dimensionScores: DimensionScore[];
36
+ operationalRisks: OperationalRisk[];
37
+ priorityFixes: string[];
38
+ nextActions: NextAction[];
39
+ /** Generic rows: each row is a list of its string cell values, best-effort. */
40
+ coverage: string[][];
41
+ /** Leftover top-level keys (implementation_plan etc.) as generic titled sections. */
42
+ sections: Array<{
43
+ title: string;
44
+ items: string[];
45
+ }>;
46
+ }
47
+ /**
48
+ * Best-effort parse of possibly-truncated JSON. Providers cut synthesis output
49
+ * at maxTokens mid-array (live-verified 2026-07-06: `"nextActions":[…"action":"ask`),
50
+ * which made the whole conclusion fall back to a raw-JSON text wall.
51
+ *
52
+ * Single scan tracking string/escape state and the open-bracket stack. A "safe
53
+ * point" is the index AFTER a complete VALUE (string close, bracket close, or a
54
+ * number/true/false/null character). A closed string is only tentatively safe:
55
+ * if the next structural char is `:` it was a KEY, so we roll back to the
56
+ * previous safe point (otherwise the cut would produce a dangling `{"key"` —
57
+ * invalid JSON). The bracket stack is snapshotted at each safe point so the
58
+ * appended closers match the cut position, not the ragged end.
59
+ */
60
+ export declare function salvageJson(body: string): Record<string, unknown> | null;
61
+ /**
62
+ * Best-effort parse of a synthesis body into a structured conclusion. Returns
63
+ * null when the text is not a JSON object with at least one recognizable section
64
+ * — the caller then renders it as plain text.
65
+ */
66
+ export declare function parseConclusion(text: string): ParsedConclusion | null;
67
+ export interface CouncilConclusionCardProps {
68
+ conclusion: ParsedConclusion;
69
+ /** Round number for a per-round synthesis; undefined = final synthesis. */
70
+ round?: number;
71
+ theme: Theme;
72
+ }
73
+ export declare function CouncilConclusionCard({ conclusion, round, theme: t }: CouncilConclusionCardProps): import("react").ReactNode;
@@ -0,0 +1,420 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
2
+ function asStringArray(v) {
3
+ if (!Array.isArray(v))
4
+ return [];
5
+ return v.filter((x) => typeof x === "string" && x.trim().length > 0).map((x) => x.trim());
6
+ }
7
+ function firstString(obj, keys) {
8
+ for (const k of keys) {
9
+ const val = obj[k];
10
+ if (typeof val === "string" && val.trim().length > 0)
11
+ return val.trim();
12
+ }
13
+ return undefined;
14
+ }
15
+ function firstArray(obj, keys) {
16
+ for (const k of keys) {
17
+ const arr = asStringArray(obj[k]);
18
+ if (arr.length > 0)
19
+ return arr;
20
+ }
21
+ return [];
22
+ }
23
+ function coverageRows(obj) {
24
+ for (const k of ["coverage_matrix", "coverage", "criteria", "coverageMatrix"]) {
25
+ const raw = obj[k];
26
+ if (!Array.isArray(raw))
27
+ continue;
28
+ const rows = [];
29
+ for (const item of raw) {
30
+ if (item && typeof item === "object") {
31
+ const cells = Object.values(item)
32
+ .filter((c) => typeof c === "string" && c.trim().length > 0)
33
+ .map((c) => c.trim());
34
+ if (cells.length > 0)
35
+ rows.push(cells);
36
+ }
37
+ else if (typeof item === "string" && item.trim().length > 0) {
38
+ rows.push([item.trim()]);
39
+ }
40
+ }
41
+ if (rows.length > 0)
42
+ return rows;
43
+ }
44
+ return [];
45
+ }
46
+ function parseDimensionScores(obj) {
47
+ const raw = obj.dimension_scores ?? obj.dimensionScores ?? obj.scores;
48
+ if (!Array.isArray(raw))
49
+ return [];
50
+ const out = [];
51
+ for (const item of raw) {
52
+ if (!item || typeof item !== "object")
53
+ continue;
54
+ const row = item;
55
+ const dimension = String(row.dimension ?? row.name ?? row.criteria ?? "").trim();
56
+ const scoreRaw = row.score ?? row.rating ?? row.value;
57
+ const score = typeof scoreRaw === "number" ? scoreRaw : Number.parseInt(String(scoreRaw), 10);
58
+ const justification = String(row.justification ?? row.reason ?? row.note ?? "").trim();
59
+ if (dimension && Number.isFinite(score)) {
60
+ out.push({ dimension, score, justification: justification || "(no justification)" });
61
+ }
62
+ }
63
+ return out;
64
+ }
65
+ function parseOperationalRisks(obj) {
66
+ const raw = obj.operational_risks ?? obj.operationalRisks ?? obj.risks;
67
+ if (!Array.isArray(raw))
68
+ return [];
69
+ const out = [];
70
+ for (const item of raw) {
71
+ if (!item || typeof item !== "object")
72
+ continue;
73
+ const row = item;
74
+ const risk = String(row.risk ?? row.name ?? row.title ?? "").trim();
75
+ const severity = String(row.severity ?? row.level ?? row.impact ?? "").trim();
76
+ const trigger = String(row.trigger ?? row.when ?? row.condition ?? "").trim();
77
+ if (risk) {
78
+ out.push({ risk, severity: severity || "Unknown", trigger: trigger || "(not specified)" });
79
+ }
80
+ }
81
+ return out;
82
+ }
83
+ function parsePriorityFixes(obj) {
84
+ const raw = obj.priority_fixes ?? obj.priorityFixes ?? obj.fixes ?? obj.action_items;
85
+ if (Array.isArray(raw)) {
86
+ const strings = asStringArray(raw);
87
+ if (strings.length > 0)
88
+ return strings;
89
+ const flat = [];
90
+ for (const item of raw) {
91
+ if (item && typeof item === "object") {
92
+ const cells = Object.entries(item)
93
+ .filter(([, cv]) => cv !== null && cv !== undefined && typeof cv !== "object")
94
+ .map(([ck, cv]) => `${ck}: ${String(cv)}`);
95
+ if (cells.length > 0)
96
+ flat.push(cells.join(" · "));
97
+ }
98
+ }
99
+ if (flat.length > 0)
100
+ return flat;
101
+ }
102
+ return [];
103
+ }
104
+ function parseNextActions(obj) {
105
+ const raw = obj.nextActions ?? obj.next_actions ?? obj.actions;
106
+ if (!Array.isArray(raw))
107
+ return [];
108
+ const out = [];
109
+ for (const item of raw) {
110
+ if (!item || typeof item !== "object")
111
+ continue;
112
+ const row = item;
113
+ const action = String(row.action ?? row.id ?? row.key ?? "").trim();
114
+ const label = String(row.label ?? row.title ?? row.summary ?? action).trim();
115
+ const reason = String(row.reason ?? row.why ?? row.explanation ?? "").trim();
116
+ if (label) {
117
+ out.push({ action: action || label, label, reason: reason || undefined });
118
+ }
119
+ }
120
+ return out;
121
+ }
122
+ /**
123
+ * Best-effort parse of possibly-truncated JSON. Providers cut synthesis output
124
+ * at maxTokens mid-array (live-verified 2026-07-06: `"nextActions":[…"action":"ask`),
125
+ * which made the whole conclusion fall back to a raw-JSON text wall.
126
+ *
127
+ * Single scan tracking string/escape state and the open-bracket stack. A "safe
128
+ * point" is the index AFTER a complete VALUE (string close, bracket close, or a
129
+ * number/true/false/null character). A closed string is only tentatively safe:
130
+ * if the next structural char is `:` it was a KEY, so we roll back to the
131
+ * previous safe point (otherwise the cut would produce a dangling `{"key"` —
132
+ * invalid JSON). The bracket stack is snapshotted at each safe point so the
133
+ * appended closers match the cut position, not the ragged end.
134
+ */
135
+ export function salvageJson(body) {
136
+ try {
137
+ const direct = JSON.parse(body);
138
+ return direct && typeof direct === "object" && !Array.isArray(direct) ? direct : null;
139
+ }
140
+ catch {
141
+ // fall through to salvage — expected branch for truncated output
142
+ }
143
+ const stack = [];
144
+ let inString = false;
145
+ let escaped = false;
146
+ let lastSafe = -1;
147
+ let stackAtSafe = [];
148
+ let prevSafe = -1;
149
+ let stackAtPrevSafe = [];
150
+ let lastStringEnd = -1; // safe point created by the most recent string close
151
+ const markSafe = (endExclusive) => {
152
+ if (endExclusive === lastSafe)
153
+ return;
154
+ prevSafe = lastSafe;
155
+ stackAtPrevSafe = stackAtSafe;
156
+ lastSafe = endExclusive;
157
+ stackAtSafe = stack.slice();
158
+ };
159
+ for (let i = 0; i < body.length; i++) {
160
+ const ch = body[i];
161
+ if (inString) {
162
+ if (escaped)
163
+ escaped = false;
164
+ else if (ch === "\\")
165
+ escaped = true;
166
+ else if (ch === '"') {
167
+ inString = false;
168
+ markSafe(i + 1);
169
+ lastStringEnd = i + 1;
170
+ }
171
+ continue;
172
+ }
173
+ if (ch === '"')
174
+ inString = true;
175
+ else if (ch === "{" || ch === "[")
176
+ stack.push(ch === "{" ? "}" : "]");
177
+ else if (ch === "}" || ch === "]") {
178
+ stack.pop();
179
+ markSafe(i + 1);
180
+ }
181
+ else if (ch === ":") {
182
+ // The string that just closed was a key, not a value — retract it.
183
+ if (lastSafe === lastStringEnd && prevSafe !== -1) {
184
+ lastSafe = prevSafe;
185
+ stackAtSafe = stackAtPrevSafe;
186
+ }
187
+ }
188
+ else if (/[0-9el]/.test(ch)) {
189
+ // Number / true / false / null terminal characters (outside strings,
190
+ // JSON only allows literals here) — cheap approximation of a value end.
191
+ markSafe(i + 1);
192
+ }
193
+ }
194
+ if (lastSafe <= 0)
195
+ return null;
196
+ const prefix = body.slice(0, lastSafe).replace(/,\s*$/, "") + stackAtSafe.reverse().join("");
197
+ try {
198
+ const parsed = JSON.parse(prefix);
199
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
200
+ }
201
+ catch {
202
+ // salvage failed — caller renders plain text; expected for hopeless input
203
+ return null;
204
+ }
205
+ }
206
+ /** "agreed_architecture" → "Agreed Architecture"; "actionItems" → "Action Items". */
207
+ function titleCase(key) {
208
+ return key
209
+ .replace(/([a-z])([A-Z])/g, "$1 $2")
210
+ .replace(/[_-]+/g, " ")
211
+ .trim()
212
+ .replace(/\b\w/g, (c) => c.toUpperCase());
213
+ }
214
+ /** Keys never worth a generic section: routing/meta fields. */
215
+ const NOISE_KEYS = new Set([
216
+ "type",
217
+ "nextActions",
218
+ "next_actions",
219
+ "sections",
220
+ "kind",
221
+ "dimension_scores",
222
+ "dimensionScores",
223
+ "dimensions",
224
+ "operational_risks",
225
+ "operationalRisks",
226
+ "risk_matrix",
227
+ "priority_fixes",
228
+ "priorityFixes",
229
+ "fixes",
230
+ "action_items",
231
+ ]);
232
+ /** Color a numeric score (1-5) by quality tier. */
233
+ function scoreColor(score, theme) {
234
+ if (score <= 2)
235
+ return theme.diffRemovedFg;
236
+ if (score === 3)
237
+ return theme.mdItalic;
238
+ return theme.diffAddedFg;
239
+ }
240
+ function severityColor(severity, theme) {
241
+ const s = severity.toLowerCase();
242
+ if (s.includes("critical") || s.includes("high"))
243
+ return theme.diffRemovedFg;
244
+ if (s.includes("medium") || s.includes("moderate"))
245
+ return theme.mdItalic;
246
+ return theme.diffAddedFg;
247
+ }
248
+ /** Compact ASCII bar for a 1-5 score: e.g. "[### ]". */
249
+ function scoreBar(score) {
250
+ const clamped = Math.max(1, Math.min(5, Math.round(score)));
251
+ const filled = "#".repeat(clamped);
252
+ const empty = " ".repeat(5 - clamped);
253
+ return `[${filled}${empty}]`;
254
+ }
255
+ /** Flatten one unknown top-level value into displayable bullet items. */
256
+ function flattenValue(v) {
257
+ if (typeof v === "string")
258
+ return v.trim().length > 0 ? [v.trim()] : [];
259
+ if (Array.isArray(v)) {
260
+ const items = [];
261
+ for (const el of v) {
262
+ if (typeof el === "string" && el.trim().length > 0)
263
+ items.push(el.trim());
264
+ else if (el && typeof el === "object") {
265
+ const cells = Object.entries(el)
266
+ .filter(([, cv]) => cv !== null && cv !== undefined && typeof cv !== "object")
267
+ .map(([ck, cv]) => `${ck}: ${String(cv)}`);
268
+ if (cells.length > 0)
269
+ items.push(cells.join(" · "));
270
+ }
271
+ }
272
+ return items;
273
+ }
274
+ return [];
275
+ }
276
+ /**
277
+ * Best-effort parse of a synthesis body into a structured conclusion. Returns
278
+ * null when the text is not a JSON object with at least one recognizable section
279
+ * — the caller then renders it as plain text.
280
+ */
281
+ export function parseConclusion(text) {
282
+ const trimmed = text.trim();
283
+ // A `---READABLE---` prose tail means the synthesizer already produced human
284
+ // copy; don't try to structure it — let the plain-text path render the prose.
285
+ if (trimmed.includes("---READABLE---"))
286
+ return null;
287
+ // Strip a leading ```json … ``` fence if present, then isolate the object.
288
+ const fenced = trimmed.match(/```(?:json)?\s*([\s\S]*?)```/);
289
+ const body = (fenced ? fenced[1] : trimmed).trim();
290
+ const start = body.indexOf("{");
291
+ if (start === -1)
292
+ return null;
293
+ const end = body.lastIndexOf("}");
294
+ // Truncated output may have NO balanced end — hand the raw tail to salvage.
295
+ const candidate = end > start ? body.slice(start, end + 1) : body.slice(start);
296
+ const parsed = salvageJson(candidate) ?? (end > start ? salvageJson(body.slice(start)) : null);
297
+ if (!parsed)
298
+ return null;
299
+ const summary = firstString(parsed, ["summary", "conclusion"]);
300
+ const recommendation = firstString(parsed, ["recommendation", "decision", "verdict"]);
301
+ const strengths = firstArray(parsed, ["strengths", "pros", "agreed"]);
302
+ const weaknesses = firstArray(parsed, ["weaknesses", "cons", "gaps"]);
303
+ const risks = firstArray(parsed, ["risks", "concerns"]);
304
+ const tradeoffs = firstArray(parsed, ["tradeoffs", "trade_offs", "trade-offs"]);
305
+ const coverage = coverageRows(parsed);
306
+ const dimensionScores = parseDimensionScores(parsed);
307
+ const operationalRisks = parseOperationalRisks(parsed);
308
+ const priorityFixes = parsePriorityFixes(parsed);
309
+ const nextActions = parseNextActions(parsed);
310
+ // Track which keys the named extractions actually consumed (a key only
311
+ // counts as consumed when it produced content — object-shaped `risks`
312
+ // yield [] above and must still reach the generic pass below).
313
+ const consumed = new Set();
314
+ if (summary)
315
+ for (const k of ["summary", "conclusion"])
316
+ if (firstString(parsed, [k]))
317
+ consumed.add(k);
318
+ if (recommendation)
319
+ for (const k of ["recommendation", "decision", "verdict"])
320
+ if (firstString(parsed, [k]))
321
+ consumed.add(k);
322
+ const arrayKeyGroups = [
323
+ [["strengths", "pros", "agreed"], strengths],
324
+ [["weaknesses", "cons", "gaps"], weaknesses],
325
+ [["risks", "concerns"], risks],
326
+ [["tradeoffs", "trade_offs", "trade-offs"], tradeoffs],
327
+ ];
328
+ for (const [keys, extracted] of arrayKeyGroups) {
329
+ if (extracted.length > 0)
330
+ for (const k of keys)
331
+ if (asStringArray(parsed[k]).length > 0)
332
+ consumed.add(k);
333
+ }
334
+ if (coverage.length > 0)
335
+ for (const k of ["coverage_matrix", "coverage", "criteria", "coverageMatrix"])
336
+ if (Array.isArray(parsed[k]))
337
+ consumed.add(k);
338
+ if (dimensionScores.length > 0)
339
+ for (const k of ["dimension_scores", "dimensionScores", "dimensions", "scores"])
340
+ if (Array.isArray(parsed[k]))
341
+ consumed.add(k);
342
+ if (operationalRisks.length > 0)
343
+ for (const k of ["operational_risks", "operationalRisks", "risk_matrix"])
344
+ if (Array.isArray(parsed[k]))
345
+ consumed.add(k);
346
+ if (priorityFixes.length > 0)
347
+ for (const k of ["priority_fixes", "priorityFixes", "fixes", "action_items"])
348
+ if (Array.isArray(parsed[k]))
349
+ consumed.add(k);
350
+ if (nextActions.length > 0)
351
+ for (const k of ["nextActions", "next_actions"])
352
+ if (Array.isArray(parsed[k]))
353
+ consumed.add(k);
354
+ const sections = [];
355
+ for (const [key, value] of Object.entries(parsed)) {
356
+ if (consumed.has(key) || NOISE_KEYS.has(key))
357
+ continue;
358
+ const items = flattenValue(value);
359
+ if (items.length > 0)
360
+ sections.push({ title: titleCase(key), items });
361
+ }
362
+ const hasContent = !!summary ||
363
+ !!recommendation ||
364
+ strengths.length > 0 ||
365
+ weaknesses.length > 0 ||
366
+ risks.length > 0 ||
367
+ tradeoffs.length > 0 ||
368
+ coverage.length > 0 ||
369
+ dimensionScores.length > 0 ||
370
+ operationalRisks.length > 0 ||
371
+ priorityFixes.length > 0 ||
372
+ nextActions.length > 0 ||
373
+ sections.length > 0;
374
+ if (!hasContent)
375
+ return null;
376
+ return {
377
+ summary,
378
+ recommendation,
379
+ strengths,
380
+ weaknesses,
381
+ risks,
382
+ tradeoffs,
383
+ coverage,
384
+ dimensionScores,
385
+ operationalRisks,
386
+ priorityFixes,
387
+ nextActions,
388
+ sections,
389
+ };
390
+ }
391
+ function BulletSection({ title, items, color, theme: t, marker = "•" }) {
392
+ if (items.length === 0)
393
+ return null;
394
+ return (_jsxs("box", { flexDirection: "column", marginTop: 1, children: [_jsx("text", { fg: color, attributes: 1, children: title }), items.map((it, i) => (_jsxs("box", { flexDirection: "row", children: [_jsx("text", { fg: t.textMuted, children: ` ${marker} ` }), _jsx("text", { fg: t.text, children: it })] }, `${title}-${i}`)))] }));
395
+ }
396
+ function DimensionScoreTable({ scores, theme: t }) {
397
+ if (scores.length === 0)
398
+ return null;
399
+ return (_jsxs("box", { flexDirection: "column", marginTop: 1, children: [_jsx("text", { fg: t.accent, attributes: 1, children: "Dimension Scores" }), scores.map((s, i) => (_jsxs("box", { flexDirection: "column", marginTop: 1, children: [_jsxs("box", { flexDirection: "row", children: [_jsx("text", { fg: t.text, children: s.dimension }), _jsx("box", { flexGrow: 1 }), _jsx("text", { fg: scoreColor(s.score, t), attributes: 1, children: `${s.score}/5 ${scoreBar(s.score)}` })] }), _jsx("text", { fg: t.textMuted, children: ` ${s.justification}` })] }, `dim-${i}`)))] }));
400
+ }
401
+ function RiskTable({ risks, theme: t }) {
402
+ if (risks.length === 0)
403
+ return null;
404
+ return (_jsxs("box", { flexDirection: "column", marginTop: 1, children: [_jsx("text", { fg: t.diffRemovedFg, attributes: 1, children: "Operational Risks" }), risks.map((r, i) => (_jsxs("box", { flexDirection: "column", marginTop: 1, children: [_jsxs("box", { flexDirection: "row", children: [_jsx("text", { fg: t.text, attributes: 1, children: r.risk }), _jsx("box", { flexGrow: 1 }), _jsx("text", { fg: severityColor(r.severity, t), children: r.severity })] }), _jsx("text", { fg: t.textMuted, children: ` Trigger: ${r.trigger}` })] }, `risk-${i}`)))] }));
405
+ }
406
+ function PriorityFixList({ fixes, theme: t }) {
407
+ if (fixes.length === 0)
408
+ return null;
409
+ return (_jsxs("box", { flexDirection: "column", marginTop: 1, children: [_jsx("text", { fg: t.mdItalic, attributes: 1, children: "Priority Fixes" }), fixes.map((fix, i) => (_jsxs("box", { flexDirection: "row", children: [_jsx("text", { fg: t.textMuted, children: ` ${i + 1}. ` }), _jsx("text", { fg: t.text, children: fix })] }, `fix-${i}`)))] }));
410
+ }
411
+ function NextActionList({ actions, theme: t }) {
412
+ if (actions.length === 0)
413
+ return null;
414
+ return (_jsxs("box", { flexDirection: "column", marginTop: 1, children: [_jsx("text", { fg: t.planStepNum, attributes: 1, children: "Next Actions" }), actions.map((a, i) => (_jsxs("box", { flexDirection: "column", marginTop: 1, children: [_jsxs("box", { flexDirection: "row", children: [_jsx("text", { fg: t.textMuted, children: ` ${i + 1}. ` }), _jsx("text", { fg: t.text, attributes: 1, children: a.label })] }), a.reason && _jsx("text", { fg: t.textMuted, children: ` ${a.reason}` })] }, `act-${i}`)))] }));
415
+ }
416
+ export function CouncilConclusionCard({ conclusion, round, theme: t }) {
417
+ const title = round === undefined ? "Final Conclusion" : `Round ${round} Conclusion`;
418
+ return (_jsxs("box", { flexDirection: "column", marginBottom: 1, border: ["left"], borderColor: t.councilSynthesisBorder, paddingLeft: 2, children: [_jsx("text", { fg: t.councilSynthesisBorder, attributes: 1, children: title }), conclusion.summary && (_jsx("box", { marginTop: 1, children: _jsx("text", { fg: t.text, children: conclusion.summary }) })), conclusion.recommendation && (_jsxs("box", { flexDirection: "column", marginTop: 1, children: [_jsx("text", { fg: t.accent, attributes: 1, children: "Recommendation" }), _jsx("text", { fg: t.text, children: conclusion.recommendation })] })), _jsx(DimensionScoreTable, { scores: conclusion.dimensionScores, theme: t }), _jsx(BulletSection, { title: "Strengths", items: conclusion.strengths, color: t.diffAddedFg, theme: t }), _jsx(BulletSection, { title: "Weaknesses", items: conclusion.weaknesses, color: t.diffRemovedFg, theme: t }), _jsx(RiskTable, { risks: conclusion.operationalRisks, theme: t }), _jsx(BulletSection, { title: "Risks", items: conclusion.risks, color: t.diffRemovedFg, theme: t }), _jsx(BulletSection, { title: "Trade-offs", items: conclusion.tradeoffs, color: t.mdItalic, theme: t }), _jsx(PriorityFixList, { fixes: conclusion.priorityFixes, theme: t }), _jsx(NextActionList, { actions: conclusion.nextActions, theme: t }), conclusion.coverage.length > 0 && (_jsxs("box", { flexDirection: "column", marginTop: 1, children: [_jsx("text", { fg: t.textMuted, attributes: 1, children: "Coverage" }), conclusion.coverage.map((row, i) => (_jsxs("box", { flexDirection: "row", children: [_jsx("text", { fg: t.textMuted, children: " – " }), _jsx("text", { fg: t.text, children: row.join(" · ") })] }, `cov-${i}`)))] })), conclusion.sections.map((sec) => (_jsx(BulletSection, { title: sec.title, items: sec.items, color: t.accent, theme: t }, sec.title)))] }));
419
+ }
420
+ //# sourceMappingURL=council-conclusion-card.js.map
@@ -0,0 +1,36 @@
1
+ import type { ReactNode } from "react";
2
+ import type { Theme } from "../theme.js";
3
+ export interface CouncilDebatePillProps {
4
+ /** Number of debate turns folded into the pill (leader + debate + research). */
5
+ count: number;
6
+ /** Debate still running — show a spinner + live tail; false → done summary. */
7
+ active: boolean;
8
+ /** Expanded → render full transcript (children); collapsed → header + tail only. */
9
+ expanded: boolean;
10
+ /**
11
+ * Last few non-empty lines of the most recent debate turn, joined with " · ".
12
+ * Only shown while active + collapsed to mimic the "thinking" pill. Empty
13
+ * string = nothing to show yet.
14
+ */
15
+ tailText: string;
16
+ theme: Theme;
17
+ /** Full debate bubbles, rendered only when `expanded` is true. */
18
+ children?: ReactNode;
19
+ }
20
+ /**
21
+ * Collapsible debate transcript, styled after the reasoning ("[Thought]") pill.
22
+ *
23
+ * The council debate can emit dozens of tall bubbles. Rendering them all inline
24
+ * buries the synthesis/deliverable and floods the scrollback. This pill folds
25
+ * the back-and-forth into a single line:
26
+ * - active + collapsed → spinner + "Debating… (N turns)" + a live tail of the
27
+ * latest turn (like the reasoning pill's last-3-lines preview).
28
+ * - done + collapsed → "Debated N turns" summary; detail is hidden.
29
+ * - expanded → full transcript in a left-bordered box.
30
+ * Toggle via Ctrl+O (wired in use-app-logic handleKey). Synthesis is rendered
31
+ * OUTSIDE this pill by the caller so the deliverable is always visible.
32
+ *
33
+ * ASCII-only strings on purpose: this file's siblings mangle non-ASCII glyphs
34
+ * to mojibake under the repo's encoding, so we mirror the "[Thought]" pill idiom.
35
+ */
36
+ export declare function CouncilDebatePill({ count, active, expanded, tailText, theme: t, children }: CouncilDebatePillProps): ReactNode;
@@ -0,0 +1,34 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
4
+ function Spinner() {
5
+ const [frame, setFrame] = useState(0);
6
+ useEffect(() => {
7
+ const id = setInterval(() => setFrame((n) => (n + 1) % SPINNER_FRAMES.length), 100);
8
+ return () => clearInterval(id);
9
+ }, []);
10
+ return _jsx(_Fragment, { children: SPINNER_FRAMES[frame] });
11
+ }
12
+ /**
13
+ * Collapsible debate transcript, styled after the reasoning ("[Thought]") pill.
14
+ *
15
+ * The council debate can emit dozens of tall bubbles. Rendering them all inline
16
+ * buries the synthesis/deliverable and floods the scrollback. This pill folds
17
+ * the back-and-forth into a single line:
18
+ * - active + collapsed → spinner + "Debating… (N turns)" + a live tail of the
19
+ * latest turn (like the reasoning pill's last-3-lines preview).
20
+ * - done + collapsed → "Debated N turns" summary; detail is hidden.
21
+ * - expanded → full transcript in a left-bordered box.
22
+ * Toggle via Ctrl+O (wired in use-app-logic handleKey). Synthesis is rendered
23
+ * OUTSIDE this pill by the caller so the deliverable is always visible.
24
+ *
25
+ * ASCII-only strings on purpose: this file's siblings mangle non-ASCII glyphs
26
+ * to mojibake under the repo's encoding, so we mirror the "[Thought]" pill idiom.
27
+ */
28
+ export function CouncilDebatePill({ count, active, expanded, tailText, theme: t, children }) {
29
+ const turnLabel = count === 1 ? "turn" : "turns";
30
+ const header = active ? `[Council] Debating... (${count} ${turnLabel})` : `[Council] Debated ${count} ${turnLabel}`;
31
+ const hint = expanded ? "Ctrl+O to collapse" : "Ctrl+O to expand";
32
+ return (_jsxs("box", { paddingLeft: 3, marginTop: 1, flexShrink: 0, flexDirection: "column", children: [_jsxs("box", { children: [active ? (_jsx("text", { fg: t.accent, children: _jsx(Spinner, {}) })) : null, _jsx("text", { fg: t.textMuted, children: `${active ? " " : ""}${header} · ${hint}` })] }), expanded ? (_jsx("box", { border: ["left"], borderColor: t.textMuted, paddingLeft: 2, marginTop: 1, flexDirection: "column", children: children })) : active && tailText ? (_jsx("box", { border: ["left"], borderColor: t.textMuted, paddingLeft: 2, marginTop: 1, children: _jsx("text", { fg: t.textMuted, children: tailText }) })) : null] }));
33
+ }
34
+ //# sourceMappingURL=council-debate-pill.js.map
@@ -1,10 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
2
- import { Semantic } from "@muonroi/agent-harness-opentui";
2
+ import { ListItem } from "../primitives/index.js";
3
3
  const MAX_CARD_COLS = 100;
4
4
  const FALLBACK_THRESHOLD = 70;
5
5
  export function CouncilInfoCardView({ card, terminalCols, theme }) {
6
6
  const fallback = terminalCols < FALLBACK_THRESHOLD;
7
7
  const width = fallback ? terminalCols : Math.min(terminalCols - 2, MAX_CARD_COLS);
8
- return (_jsx(Semantic, { id: "info-card", role: "listitem", name: card.title, children: _jsx("box", { flexDirection: "column", marginBottom: 1, children: _jsxs("box", { width: width, borderStyle: "single", borderColor: theme.councilInfoCardBorder, flexDirection: "column", paddingLeft: 1, paddingRight: 1, children: [_jsx("text", { fg: theme.councilInfoCardTitle, attributes: 1, children: card.title }), card.sections.map((section, i) => (_jsxs("box", { flexDirection: "column", marginTop: 1, children: [_jsx("text", { fg: theme.councilInfoCardHeading, attributes: 1, children: section.heading }), _jsx("text", { fg: theme.text, children: section.body })] }, `${section.heading}-${i}`)))] }) }) }));
8
+ return (_jsx(ListItem, { id: "info-card", name: card.title, children: _jsx("box", { flexDirection: "column", marginBottom: 1, children: _jsxs("box", { width: width, borderStyle: "single", borderColor: theme.councilInfoCardBorder, flexDirection: "column", paddingLeft: 1, paddingRight: 1, children: [_jsx("text", { fg: theme.councilInfoCardTitle, attributes: 1, children: card.title }), card.sections.map((section, i) => (_jsxs("box", { flexDirection: "column", marginTop: 1, children: [_jsx("text", { fg: theme.councilInfoCardHeading, attributes: 1, children: section.heading }), _jsx("text", { fg: theme.text, children: section.body })] }, `${section.heading}-${i}`)))] }) }) }));
9
9
  }
10
10
  //# sourceMappingURL=council-info-card.js.map
@@ -1,10 +1,17 @@
1
1
  import type { CouncilMessage } from "../../types/index.js";
2
+ import type { Theme } from "../theme.js";
2
3
  export interface CouncilLeaderBubbleProps {
3
4
  msg: CouncilMessage;
4
5
  terminalCols: number;
6
+ theme: Theme;
5
7
  }
6
- export declare function buildLeaderHeader(round: number | undefined): string;
8
+ export declare function buildLeaderHeader(round: number | undefined, phase?: CouncilMessage["phase"]): string;
7
9
  /**
8
- * Centered, narrow (40% width), gray-bordered bubble for leader evaluations.
10
+ * Leader evaluation, rendered as a linear group-chat row (matching the debate
11
+ * speakers) instead of a centered narrow bubble — a muted gray left bar marks
12
+ * it as the moderator's turn while keeping the single downward reading flow.
13
+ *
14
+ * B5: a pre-round `directive` steers the debate and is rendered with the accent
15
+ * color so the leader visibly LEADS each round; `verdict`/`eval` stay muted.
9
16
  */
10
- export declare function CouncilLeaderBubble({ msg, terminalCols }: CouncilLeaderBubbleProps): import("react").ReactNode;
17
+ export declare function CouncilLeaderBubble({ msg, terminalCols, theme: t }: CouncilLeaderBubbleProps): import("react").ReactNode;
@@ -1,17 +1,27 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
2
- import { dark } from "../theme.js";
3
- import { computeBubbleLayout } from "./bubble-layout.js";
4
- export function buildLeaderHeader(round) {
5
- return round !== undefined ? `Leader · round ${round} eval` : "Leader";
2
+ import { capBubbleBody } from "./bubble-body-guard.js";
3
+ export function buildLeaderHeader(round, phase) {
4
+ // B5: distinguish the leader's pre-round steering from its post-round grading
5
+ // so the conductor role reads clearly in the transcript (not a faint "eval").
6
+ const suffix = phase === "directive" ? "directive" : phase === "verdict" ? "verdict" : "eval";
7
+ const label = phase === "directive" ? "▶ Leader" : "Leader";
8
+ return round !== undefined ? `${label} · round ${round} ${suffix}` : label;
6
9
  }
7
10
  /**
8
- * Centered, narrow (40% width), gray-bordered bubble for leader evaluations.
11
+ * Leader evaluation, rendered as a linear group-chat row (matching the debate
12
+ * speakers) instead of a centered narrow bubble — a muted gray left bar marks
13
+ * it as the moderator's turn while keeping the single downward reading flow.
14
+ *
15
+ * B5: a pre-round `directive` steers the debate and is rendered with the accent
16
+ * color so the leader visibly LEADS each round; `verdict`/`eval` stay muted.
9
17
  */
10
- export function CouncilLeaderBubble({ msg, terminalCols }) {
11
- const layout = computeBubbleLayout(terminalCols);
12
- const width = layout.leaderCols;
13
- const centerIndent = Math.max(0, Math.floor((terminalCols - width) / 2));
14
- const header = buildLeaderHeader(msg.round);
15
- return (_jsx("box", { flexDirection: "column", marginBottom: 1, marginLeft: centerIndent, children: _jsxs("box", { width: width, borderStyle: "single", borderColor: dark.councilLeaderBorder, flexDirection: "column", paddingLeft: 1, paddingRight: 1, children: [_jsx("text", { fg: dark.textMuted, attributes: 1, children: header }), _jsx("text", { fg: dark.textMuted, children: msg.text.trim() })] }) }));
18
+ export function CouncilLeaderBubble({ msg, terminalCols, theme: t }) {
19
+ const header = buildLeaderHeader(msg.round, msg.phase);
20
+ const isDirective = msg.phase === "directive";
21
+ const headerColor = isDirective ? t.accent : t.textMuted;
22
+ const borderColor = isDirective ? t.accent : t.councilLeaderBorder;
23
+ // Same unbounded-<text> guard as the speaker bubble (see bubble-body-guard.ts).
24
+ const bodyText = capBubbleBody(msg.text.trim(), terminalCols);
25
+ return (_jsxs("box", { flexDirection: "column", marginBottom: 1, border: ["left"], borderColor: borderColor, paddingLeft: 2, children: [_jsx("text", { fg: headerColor, attributes: 1, children: header }), _jsx("text", { fg: t.textMuted, children: bodyText })] }));
16
26
  }
17
27
  //# sourceMappingURL=council-leader-bubble.js.map