muonroi-cli 1.8.4 → 1.9.0

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 (562) 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-filter.js +11 -0
  5. package/dist/packages/agent-harness-core/src/event-redact.js +7 -0
  6. package/dist/packages/agent-harness-core/src/event-tee.d.ts +64 -0
  7. package/dist/packages/agent-harness-core/src/event-tee.js +104 -0
  8. package/dist/packages/agent-harness-core/src/mcp-server.d.ts +25 -0
  9. package/dist/packages/agent-harness-core/src/mcp-server.js +169 -21
  10. package/dist/packages/agent-harness-core/src/predicate.d.ts +1 -1
  11. package/dist/packages/agent-harness-core/src/protocol.d.ts +90 -4
  12. package/dist/packages/agent-harness-core/src/protocol.js +15 -0
  13. package/dist/packages/agent-harness-core/src/visual-quality.d.ts +58 -0
  14. package/dist/packages/agent-harness-core/src/visual-quality.js +141 -0
  15. package/dist/packages/agent-harness-opentui/src/agent-mode.d.ts +6 -0
  16. package/dist/packages/agent-harness-opentui/src/agent-mode.js +14 -1
  17. package/dist/packages/agent-harness-opentui/src/input-bridge.d.ts +2 -10
  18. package/dist/packages/agent-harness-opentui/src/input-bridge.js +103 -16
  19. package/dist/packages/agent-harness-opentui/src/install.d.ts +8 -0
  20. package/dist/packages/agent-harness-opentui/src/install.js +10 -0
  21. package/dist/packages/agent-harness-opentui/src/semantic.js +12 -10
  22. package/dist/packages/agent-harness-opentui/src/visual-capture.d.ts +56 -0
  23. package/dist/packages/agent-harness-opentui/src/visual-capture.js +103 -0
  24. package/dist/src/agent-harness/mock-model.d.ts +38 -0
  25. package/dist/src/agent-harness/mock-model.js +69 -3
  26. package/dist/src/agent-harness/test-spawn.js +31 -0
  27. package/dist/src/chat/chat-keychain.d.ts +7 -12
  28. package/dist/src/chat/chat-keychain.js +19 -86
  29. package/dist/src/cli/config/screen-providers.js +1 -1
  30. package/dist/src/cli/cost-forensics.d.ts +10 -0
  31. package/dist/src/cli/cost-forensics.js +18 -3
  32. package/dist/src/cli/keys-bundle.d.ts +1 -1
  33. package/dist/src/cli/keys-bundle.js +1 -1
  34. package/dist/src/cli/keys.d.ts +10 -47
  35. package/dist/src/cli/keys.js +31 -399
  36. package/dist/src/council/clarifier.d.ts +31 -3
  37. package/dist/src/council/clarifier.js +220 -32
  38. package/dist/src/council/context.js +49 -15
  39. package/dist/src/council/debate-checkpoint.d.ts +129 -0
  40. package/dist/src/council/debate-checkpoint.js +176 -0
  41. package/dist/src/council/debate-planner.js +54 -5
  42. package/dist/src/council/debate-summary.d.ts +25 -0
  43. package/dist/src/council/debate-summary.js +85 -0
  44. package/dist/src/council/debate.d.ts +169 -2
  45. package/dist/src/council/debate.js +1265 -135
  46. package/dist/src/council/index.d.ts +108 -1
  47. package/dist/src/council/index.js +670 -197
  48. package/dist/src/council/leader.d.ts +26 -0
  49. package/dist/src/council/leader.js +150 -9
  50. package/dist/src/council/llm.d.ts +94 -0
  51. package/dist/src/council/llm.js +348 -55
  52. package/dist/src/council/panel-select.d.ts +30 -0
  53. package/dist/src/council/panel-select.js +82 -0
  54. package/dist/src/council/planner.js +40 -0
  55. package/dist/src/council/preflight.d.ts +17 -0
  56. package/dist/src/council/preflight.js +50 -2
  57. package/dist/src/council/prompts.d.ts +39 -4
  58. package/dist/src/council/prompts.js +256 -69
  59. package/dist/src/council/stance-recall.d.ts +42 -0
  60. package/dist/src/council/stance-recall.js +57 -0
  61. package/dist/src/council/strip-think.d.ts +17 -0
  62. package/dist/src/council/strip-think.js +33 -0
  63. package/dist/src/council/types.d.ts +138 -0
  64. package/dist/src/ee/artifact-cache.d.ts +16 -0
  65. package/dist/src/ee/artifact-cache.js +32 -0
  66. package/dist/src/ee/auth.d.ts +20 -0
  67. package/dist/src/ee/auth.js +54 -2
  68. package/dist/src/ee/bridge.d.ts +10 -0
  69. package/dist/src/ee/bridge.js +58 -0
  70. package/dist/src/ee/client.js +109 -21
  71. package/dist/src/ee/ee-onboarding.js +6 -26
  72. package/dist/src/ee/export-transcripts.d.ts +1 -0
  73. package/dist/src/ee/export-transcripts.js +8 -10
  74. package/dist/src/ee/extract-session.js +29 -0
  75. package/dist/src/ee/extract-style.d.ts +58 -0
  76. package/dist/src/ee/extract-style.js +270 -0
  77. package/dist/src/ee/recall-ledger.d.ts +9 -0
  78. package/dist/src/ee/recall-ledger.js +3 -0
  79. package/dist/src/ee/scope.d.ts +1 -0
  80. package/dist/src/ee/scope.js +26 -1
  81. package/dist/src/ee/search.d.ts +7 -0
  82. package/dist/src/ee/search.js +24 -0
  83. package/dist/src/ee/transcript-emit.js +2 -0
  84. package/dist/src/ee/types.d.ts +22 -0
  85. package/dist/src/ee/who-am-i-brain.d.ts +35 -0
  86. package/dist/src/ee/who-am-i-brain.js +220 -0
  87. package/dist/src/ee/who-am-i.d.ts +10 -3
  88. package/dist/src/ee/who-am-i.js +12 -0
  89. package/dist/src/ee/workflow-event.d.ts +48 -0
  90. package/dist/src/ee/workflow-event.js +81 -0
  91. package/dist/src/flow/compaction/compress.d.ts +3 -3
  92. package/dist/src/flow/compaction/compress.js +58 -8
  93. package/dist/src/flow/compaction/extract.d.ts +4 -7
  94. package/dist/src/flow/compaction/extract.js +50 -10
  95. package/dist/src/flow/compaction/index.d.ts +14 -1
  96. package/dist/src/flow/compaction/index.js +96 -3
  97. package/dist/src/flow/compaction/input-guard.d.ts +24 -0
  98. package/dist/src/flow/compaction/input-guard.js +43 -0
  99. package/dist/src/flow/compaction/progress.d.ts +35 -0
  100. package/dist/src/flow/compaction/progress.js +35 -0
  101. package/dist/src/flow/fold-planning.d.ts +36 -0
  102. package/dist/src/flow/fold-planning.js +83 -0
  103. package/dist/src/flow/hierarchy.d.ts +146 -0
  104. package/dist/src/flow/hierarchy.js +427 -0
  105. package/dist/src/flow/index.d.ts +1 -0
  106. package/dist/src/flow/index.js +2 -0
  107. package/dist/src/flow/run-artifacts.d.ts +102 -0
  108. package/dist/src/flow/run-artifacts.js +208 -0
  109. package/dist/src/generated/version.d.ts +1 -1
  110. package/dist/src/generated/version.js +1 -1
  111. package/dist/src/gsd/assessment-schema.d.ts +44 -0
  112. package/dist/src/gsd/assessment-schema.js +134 -0
  113. package/dist/src/gsd/capability-registry.d.ts +45 -0
  114. package/dist/src/gsd/capability-registry.js +337 -0
  115. package/dist/src/gsd/complexity-assessor.d.ts +39 -0
  116. package/dist/src/gsd/complexity-assessor.js +152 -0
  117. package/dist/src/gsd/config-bridge.d.ts +7 -0
  118. package/dist/src/gsd/config-bridge.js +114 -0
  119. package/dist/src/gsd/config-loader.d.ts +27 -0
  120. package/dist/src/gsd/config-loader.js +50 -0
  121. package/dist/src/gsd/council-context.d.ts +44 -0
  122. package/dist/src/gsd/council-context.js +114 -0
  123. package/dist/src/gsd/ee-closure.d.ts +28 -0
  124. package/dist/src/gsd/ee-closure.js +49 -0
  125. package/dist/src/gsd/flags.d.ts +66 -0
  126. package/dist/src/gsd/flags.js +102 -0
  127. package/dist/src/gsd/gsd-dispatch.d.ts +58 -0
  128. package/dist/src/gsd/gsd-dispatch.js +131 -0
  129. package/dist/src/gsd/gsd-runtime.d.ts +22 -0
  130. package/dist/src/gsd/gsd-runtime.js +37 -0
  131. package/dist/src/gsd/host-adapter.d.ts +11 -0
  132. package/dist/src/gsd/host-adapter.js +29 -0
  133. package/dist/src/gsd/index.d.ts +24 -1
  134. package/dist/src/gsd/index.js +27 -0
  135. package/dist/src/gsd/loop-host-contract.d.ts +21 -0
  136. package/dist/src/gsd/loop-host-contract.js +39 -0
  137. package/dist/src/gsd/loop-host.d.ts +69 -0
  138. package/dist/src/gsd/loop-host.js +245 -0
  139. package/dist/src/gsd/loop-resolver.d.ts +36 -0
  140. package/dist/src/gsd/loop-resolver.js +79 -0
  141. package/dist/src/gsd/model-tier.d.ts +13 -0
  142. package/dist/src/gsd/model-tier.js +45 -0
  143. package/dist/src/gsd/mutation-gate.d.ts +16 -0
  144. package/dist/src/gsd/mutation-gate.js +41 -0
  145. package/dist/src/gsd/native-roadmap.d.ts +89 -0
  146. package/dist/src/gsd/native-roadmap.js +343 -0
  147. package/dist/src/gsd/native-state.d.ts +47 -0
  148. package/dist/src/gsd/native-state.js +220 -0
  149. package/dist/src/gsd/paths.d.ts +23 -0
  150. package/dist/src/gsd/paths.js +66 -0
  151. package/dist/src/gsd/phase-dag.d.ts +12 -0
  152. package/dist/src/gsd/phase-dag.js +94 -0
  153. package/dist/src/gsd/phase-sync.d.ts +42 -0
  154. package/dist/src/gsd/phase-sync.js +321 -0
  155. package/dist/src/gsd/pil-gate-context.d.ts +13 -0
  156. package/dist/src/gsd/pil-gate-context.js +64 -0
  157. package/dist/src/gsd/pil-gate-critic.d.ts +19 -0
  158. package/dist/src/gsd/pil-gate-critic.js +74 -0
  159. package/dist/src/gsd/plan-council-prompts.d.ts +25 -0
  160. package/dist/src/gsd/plan-council-prompts.js +79 -0
  161. package/dist/src/gsd/plan-council.d.ts +44 -0
  162. package/dist/src/gsd/plan-council.js +283 -0
  163. package/dist/src/gsd/plan-gate-vocabulary.d.ts +40 -0
  164. package/dist/src/gsd/plan-gate-vocabulary.js +64 -0
  165. package/dist/src/gsd/product-workspace.d.ts +13 -0
  166. package/dist/src/gsd/product-workspace.js +124 -0
  167. package/dist/src/gsd/ship-bridge.d.ts +25 -0
  168. package/dist/src/gsd/ship-bridge.js +65 -0
  169. package/dist/src/gsd/state-document.d.ts +40 -0
  170. package/dist/src/gsd/state-document.js +163 -0
  171. package/dist/src/gsd/verdict-schema.d.ts +39 -0
  172. package/dist/src/gsd/verdict-schema.js +144 -0
  173. package/dist/src/gsd/verify-context.d.ts +22 -0
  174. package/dist/src/gsd/verify-context.js +27 -0
  175. package/dist/src/gsd/verify-council-prompts.d.ts +19 -0
  176. package/dist/src/gsd/verify-council-prompts.js +85 -0
  177. package/dist/src/gsd/verify-council.d.ts +25 -0
  178. package/dist/src/gsd/verify-council.js +119 -0
  179. package/dist/src/gsd/verify-gate-vocabulary.d.ts +25 -0
  180. package/dist/src/gsd/verify-gate-vocabulary.js +46 -0
  181. package/dist/src/gsd/workflow-engine.d.ts +60 -0
  182. package/dist/src/gsd/workflow-engine.js +207 -0
  183. package/dist/src/gsd/workflow-tools.d.ts +13 -0
  184. package/dist/src/gsd/workflow-tools.js +277 -0
  185. package/dist/src/headless/council-answers.js +4 -0
  186. package/dist/src/hooks/index.js +1 -1
  187. package/dist/src/index.js +172 -270
  188. package/dist/src/lsp/builtins.js +3 -1
  189. package/dist/src/lsp/manager.d.ts +5 -1
  190. package/dist/src/lsp/manager.js +249 -3
  191. package/dist/src/lsp/npm-cache.d.ts +11 -1
  192. package/dist/src/lsp/npm-cache.js +17 -1
  193. package/dist/src/lsp/runtime.d.ts +6 -1
  194. package/dist/src/lsp/runtime.js +17 -1
  195. package/dist/src/lsp/types.d.ts +83 -1
  196. package/dist/src/lsp/types.js +10 -0
  197. package/dist/src/maintain/pr-builder.js +23 -13
  198. package/dist/src/mcp/auto-setup.js +57 -32
  199. package/dist/src/mcp/client-pool.js +44 -16
  200. package/dist/src/mcp/lsp-tools.d.ts +5 -1
  201. package/dist/src/mcp/lsp-tools.js +93 -2
  202. package/dist/src/mcp/mcp-keychain.d.ts +3 -5
  203. package/dist/src/mcp/mcp-keychain.js +9 -49
  204. package/dist/src/mcp/research-onboarding.js +8 -7
  205. package/dist/src/mcp/runtime.js +34 -2
  206. package/dist/src/mcp/setup-guide-text.d.ts +1 -1
  207. package/dist/src/mcp/setup-guide-text.js +22 -2
  208. package/dist/src/mcp/tools-server.d.ts +10 -0
  209. package/dist/src/mcp/tools-server.js +10 -2
  210. package/dist/src/models/catalog-client.d.ts +87 -0
  211. package/dist/src/models/catalog-client.js +105 -38
  212. package/dist/src/models/catalog.json +528 -265
  213. package/dist/src/models/registry.d.ts +22 -7
  214. package/dist/src/models/registry.js +73 -10
  215. package/dist/src/ops/doctor.js +1 -1
  216. package/dist/src/orchestrator/ask-user.d.ts +61 -0
  217. package/dist/src/orchestrator/ask-user.js +65 -0
  218. package/dist/src/orchestrator/auto-commit.js +1 -1
  219. package/dist/src/orchestrator/batch-turn-runner.js +2 -2
  220. package/dist/src/orchestrator/cache-prefix.d.ts +67 -0
  221. package/dist/src/orchestrator/cache-prefix.js +83 -0
  222. package/dist/src/orchestrator/compact-request.d.ts +32 -0
  223. package/dist/src/orchestrator/compact-request.js +41 -0
  224. package/dist/src/orchestrator/compaction.d.ts +12 -3
  225. package/dist/src/orchestrator/compaction.js +35 -15
  226. package/dist/src/orchestrator/council-manager.d.ts +12 -3
  227. package/dist/src/orchestrator/council-manager.js +74 -32
  228. package/dist/src/orchestrator/council-request.d.ts +49 -0
  229. package/dist/src/orchestrator/council-request.js +62 -0
  230. package/dist/src/orchestrator/cross-turn-dedup.d.ts +6 -0
  231. package/dist/src/orchestrator/cross-turn-dedup.js +22 -1
  232. package/dist/src/orchestrator/error-utils.d.ts +29 -0
  233. package/dist/src/orchestrator/error-utils.js +132 -24
  234. package/dist/src/orchestrator/grounding-check.js +39 -1
  235. package/dist/src/orchestrator/interactive-pause.d.ts +26 -0
  236. package/dist/src/orchestrator/interactive-pause.js +36 -0
  237. package/dist/src/orchestrator/message-processor.d.ts +4 -0
  238. package/dist/src/orchestrator/message-processor.js +268 -41
  239. package/dist/src/orchestrator/orchestrator.d.ts +64 -3
  240. package/dist/src/orchestrator/orchestrator.js +823 -120
  241. package/dist/src/orchestrator/preprocessor.js +3 -3
  242. package/dist/src/orchestrator/proactive-compact-detector.d.ts +26 -0
  243. package/dist/src/orchestrator/proactive-compact-detector.js +36 -0
  244. package/dist/src/orchestrator/prompts.js +17 -17
  245. package/dist/src/orchestrator/reactive-delegation.d.ts +39 -0
  246. package/dist/src/orchestrator/reactive-delegation.js +59 -0
  247. package/dist/src/orchestrator/retry-classifier.d.ts +2 -1
  248. package/dist/src/orchestrator/retry-classifier.js +46 -2
  249. package/dist/src/orchestrator/safety-askcard.d.ts +1 -1
  250. package/dist/src/orchestrator/safety-askcard.js +5 -2
  251. package/dist/src/orchestrator/safety-intercept.d.ts +50 -0
  252. package/dist/src/orchestrator/safety-intercept.js +62 -0
  253. package/dist/src/orchestrator/scope-reminder.js +1 -1
  254. package/dist/src/orchestrator/session-experience.d.ts +2 -1
  255. package/dist/src/orchestrator/session-experience.js +2 -1
  256. package/dist/src/orchestrator/should-run-gate.d.ts +5 -0
  257. package/dist/src/orchestrator/should-run-gate.js +18 -0
  258. package/dist/src/orchestrator/stall-watchdog.d.ts +31 -3
  259. package/dist/src/orchestrator/stall-watchdog.js +65 -10
  260. package/dist/src/orchestrator/stream-runner.d.ts +13 -3
  261. package/dist/src/orchestrator/stream-runner.js +115 -49
  262. package/dist/src/orchestrator/sub-agent-cap.d.ts +13 -1
  263. package/dist/src/orchestrator/sub-agent-cap.js +16 -1
  264. package/dist/src/orchestrator/sub-agent-model-tier.d.ts +13 -1
  265. package/dist/src/orchestrator/sub-agent-model-tier.js +16 -2
  266. package/dist/src/orchestrator/subagent-compactor.d.ts +53 -1
  267. package/dist/src/orchestrator/subagent-compactor.js +126 -15
  268. package/dist/src/orchestrator/tool-engine.d.ts +41 -0
  269. package/dist/src/orchestrator/tool-engine.js +846 -66
  270. package/dist/src/orchestrator/tool-limit-auto-recover.d.ts +22 -0
  271. package/dist/src/orchestrator/tool-limit-auto-recover.js +30 -0
  272. package/dist/src/orchestrator/turn-runner-deps.d.ts +19 -0
  273. package/dist/src/orchestrator/turn-watchdog.d.ts +44 -0
  274. package/dist/src/orchestrator/turn-watchdog.js +84 -0
  275. package/dist/src/pil/agent-operating-contract.d.ts +1 -1
  276. package/dist/src/pil/agent-operating-contract.js +6 -4
  277. package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
  278. package/dist/src/pil/cheap-model-playbook.js +5 -1
  279. package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
  280. package/dist/src/pil/cheap-model-workbooks.js +1 -1
  281. package/dist/src/pil/discovery-types.d.ts +1 -0
  282. package/dist/src/pil/discovery.d.ts +1 -1
  283. package/dist/src/pil/discovery.js +18 -13
  284. package/dist/src/pil/layer1-intent.d.ts +18 -6
  285. package/dist/src/pil/layer1-intent.js +66 -757
  286. package/dist/src/pil/layer15-context-scan.js +15 -1
  287. package/dist/src/pil/layer1_5-complexity-size.d.ts +7 -0
  288. package/dist/src/pil/layer1_5-complexity-size.js +31 -5
  289. package/dist/src/pil/layer3-ee-injection.js +23 -8
  290. package/dist/src/pil/layer4-gsd.js +69 -16
  291. package/dist/src/pil/layer5-context.js +7 -3
  292. package/dist/src/pil/layer6-output.d.ts +23 -0
  293. package/dist/src/pil/layer6-output.js +5 -1
  294. package/dist/src/pil/llm-classify.d.ts +111 -5
  295. package/dist/src/pil/llm-classify.js +421 -189
  296. package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
  297. package/dist/src/pil/native-capabilities-workbook.js +8 -0
  298. package/dist/src/pil/pipeline.js +36 -2
  299. package/dist/src/pil/repo-grounding-probe.d.ts +15 -0
  300. package/dist/src/pil/repo-grounding-probe.js +136 -0
  301. package/dist/src/pil/repo-structure-hints.d.ts +7 -0
  302. package/dist/src/pil/repo-structure-hints.js +45 -0
  303. package/dist/src/pil/response-tools.js +5 -3
  304. package/dist/src/pil/schema.d.ts +1 -0
  305. package/dist/src/pil/schema.js +2 -0
  306. package/dist/src/pil/types.d.ts +18 -0
  307. package/dist/src/playbook/directives.d.ts +4 -0
  308. package/dist/src/playbook/directives.js +17 -5
  309. package/dist/src/product-loop/artifact-io.js +4 -0
  310. package/dist/src/product-loop/backlog-builder.d.ts +14 -1
  311. package/dist/src/product-loop/backlog-builder.js +30 -6
  312. package/dist/src/product-loop/criteria-seed.d.ts +51 -0
  313. package/dist/src/product-loop/criteria-seed.js +200 -0
  314. package/dist/src/product-loop/discovery-context-format.js +3 -1
  315. package/dist/src/product-loop/discovery-ecosystem.js +4 -1
  316. package/dist/src/product-loop/discovery-interview.d.ts +9 -0
  317. package/dist/src/product-loop/discovery-interview.js +60 -12
  318. package/dist/src/product-loop/discovery-recommender.js +2 -1
  319. package/dist/src/product-loop/discovery-schema.js +19 -2
  320. package/dist/src/product-loop/discovery-triage.d.ts +23 -0
  321. package/dist/src/product-loop/discovery-triage.js +109 -0
  322. package/dist/src/product-loop/gather.js +150 -2
  323. package/dist/src/product-loop/ideal-trace.d.ts +7 -0
  324. package/dist/src/product-loop/ideal-trace.js +64 -0
  325. package/dist/src/product-loop/index.d.ts +13 -1
  326. package/dist/src/product-loop/index.js +340 -52
  327. package/dist/src/product-loop/loop-driver.d.ts +7 -0
  328. package/dist/src/product-loop/loop-driver.js +330 -106
  329. package/dist/src/product-loop/phase-plan.d.ts +21 -0
  330. package/dist/src/product-loop/phase-plan.js +81 -6
  331. package/dist/src/product-loop/phase-rituals.d.ts +3 -0
  332. package/dist/src/product-loop/phase-rituals.js +8 -3
  333. package/dist/src/product-loop/phase-runner.js +39 -12
  334. package/dist/src/product-loop/plan-adherence-review.d.ts +26 -0
  335. package/dist/src/product-loop/plan-adherence-review.js +144 -0
  336. package/dist/src/product-loop/sprint-runner.d.ts +173 -0
  337. package/dist/src/product-loop/sprint-runner.js +863 -19
  338. package/dist/src/product-loop/types.d.ts +61 -5
  339. package/dist/src/providers/adapter.d.ts +1 -1
  340. package/dist/src/providers/adapter.js +3 -4
  341. package/dist/src/providers/anthropic.d.ts +9 -8
  342. package/dist/src/providers/anthropic.js +13 -47
  343. package/dist/src/providers/auth/browser-flow.d.ts +1 -1
  344. package/dist/src/providers/auth/browser-flow.js +1 -1
  345. package/dist/src/providers/auth/grok-oauth.d.ts +1 -0
  346. package/dist/src/providers/auth/grok-oauth.js +30 -5
  347. package/dist/src/providers/auth/openai-oauth.d.ts +1 -0
  348. package/dist/src/providers/auth/openai-oauth.js +15 -1
  349. package/dist/src/providers/auth/registry.js +0 -34
  350. package/dist/src/providers/auth/token-store.d.ts +9 -9
  351. package/dist/src/providers/auth/token-store.js +8 -67
  352. package/dist/src/providers/auth/types.d.ts +9 -1
  353. package/dist/src/providers/auth/types.js +1 -1
  354. package/dist/src/providers/capabilities.d.ts +24 -5
  355. package/dist/src/providers/capabilities.js +42 -24
  356. package/dist/src/providers/endpoints.d.ts +2 -2
  357. package/dist/src/providers/endpoints.js +11 -10
  358. package/dist/src/providers/env-store.d.ts +17 -0
  359. package/dist/src/providers/env-store.js +228 -0
  360. package/dist/src/providers/keychain.d.ts +22 -18
  361. package/dist/src/providers/keychain.js +127 -140
  362. package/dist/src/providers/mcp-vision-bridge.js +56 -146
  363. package/dist/src/providers/openai-compatible.js +8 -1
  364. package/dist/src/providers/pricing.d.ts +2 -2
  365. package/dist/src/providers/pricing.js +3 -13
  366. package/dist/src/providers/runtime.d.ts +43 -3
  367. package/dist/src/providers/runtime.js +88 -14
  368. package/dist/src/providers/strategies/base.strategy.d.ts +16 -0
  369. package/dist/src/providers/strategies/base.strategy.js +24 -1
  370. package/dist/src/providers/strategies/{siliconflow.strategy.d.ts → opencode-go.strategy.d.ts} +3 -3
  371. package/dist/src/providers/strategies/opencode-go.strategy.js +83 -0
  372. package/dist/src/providers/strategies/registry.js +4 -4
  373. package/dist/src/providers/strategies/thinking-mode.d.ts +109 -0
  374. package/dist/src/providers/strategies/thinking-mode.js +288 -1
  375. package/dist/src/providers/strategies/xai.strategy.js +27 -0
  376. package/dist/src/providers/strategies/zai.strategy.d.ts +14 -0
  377. package/dist/src/providers/strategies/zai.strategy.js +44 -0
  378. package/dist/src/providers/types.d.ts +5 -6
  379. package/dist/src/providers/types.js +2 -2
  380. package/dist/src/providers/vision-backend.d.ts +47 -0
  381. package/dist/src/providers/vision-backend.js +258 -0
  382. package/dist/src/providers/vision-proxy.d.ts +22 -9
  383. package/dist/src/providers/vision-proxy.js +63 -132
  384. package/dist/src/providers/warm.d.ts +65 -0
  385. package/dist/src/providers/warm.js +145 -0
  386. package/dist/src/providers/wire-debug.js +95 -0
  387. package/dist/src/router/decide.d.ts +13 -0
  388. package/dist/src/router/decide.js +138 -36
  389. package/dist/src/router/peak-hour.d.ts +38 -0
  390. package/dist/src/router/peak-hour.js +107 -0
  391. package/dist/src/router/step-router.js +3 -2
  392. package/dist/src/router/warm.js +4 -5
  393. package/dist/src/scaffold/continuation-prompt.d.ts +11 -0
  394. package/dist/src/scaffold/continuation-prompt.js +26 -0
  395. package/dist/src/scaffold/point-to-existing.d.ts +21 -0
  396. package/dist/src/scaffold/point-to-existing.js +25 -0
  397. package/dist/src/self-qa/agentic-loop.js +6 -5
  398. package/dist/src/{ui/state → state}/active-run.d.ts +19 -0
  399. package/dist/src/{ui/state → state}/active-run.js +21 -0
  400. package/dist/src/{ui/status-bar/store.d.ts → state/status-bar-store.d.ts} +4 -1
  401. package/dist/src/{ui/status-bar/store.js → state/status-bar-store.js} +12 -9
  402. package/dist/src/state/turn-trace.d.ts +43 -0
  403. package/dist/src/state/turn-trace.js +32 -0
  404. package/dist/src/storage/db.js +2 -1
  405. package/dist/src/storage/index.d.ts +1 -1
  406. package/dist/src/storage/index.js +1 -1
  407. package/dist/src/storage/interaction-log.d.ts +1 -1
  408. package/dist/src/storage/migrations.js +71 -1
  409. package/dist/src/storage/sessions.d.ts +28 -10
  410. package/dist/src/storage/sessions.js +78 -21
  411. package/dist/src/storage/transcript-view.js +1 -1
  412. package/dist/src/storage/transcript.d.ts +51 -0
  413. package/dist/src/storage/transcript.js +340 -15
  414. package/dist/src/tools/file.d.ts +15 -0
  415. package/dist/src/tools/file.js +32 -0
  416. package/dist/src/tools/git-safety.d.ts +19 -0
  417. package/dist/src/tools/git-safety.js +168 -0
  418. package/dist/src/tools/native-tools.d.ts +1 -1
  419. package/dist/src/tools/native-tools.js +81 -1
  420. package/dist/src/tools/registry.d.ts +20 -0
  421. package/dist/src/tools/registry.js +576 -23
  422. package/dist/src/tools/research.d.ts +29 -0
  423. package/dist/src/tools/research.js +233 -0
  424. package/dist/src/types/index.d.ts +147 -4
  425. package/dist/src/ui/app.js +0 -0
  426. package/dist/src/ui/cards/product-status-card.js +1 -1
  427. package/dist/src/ui/components/agent-rail-activities.d.ts +26 -0
  428. package/dist/src/ui/components/agent-rail-activities.js +47 -0
  429. package/dist/src/ui/components/bubble-body-guard.d.ts +27 -0
  430. package/dist/src/ui/components/bubble-body-guard.js +50 -0
  431. package/dist/src/ui/components/compact-progress-card.d.ts +24 -0
  432. package/dist/src/ui/components/compact-progress-card.js +42 -0
  433. package/dist/src/ui/components/context-rail.d.ts +26 -0
  434. package/dist/src/ui/components/context-rail.js +33 -0
  435. package/dist/src/ui/components/council-conclusion-card.d.ts +73 -0
  436. package/dist/src/ui/components/council-conclusion-card.js +420 -0
  437. package/dist/src/ui/components/council-debate-pill.d.ts +36 -0
  438. package/dist/src/ui/components/council-debate-pill.js +34 -0
  439. package/dist/src/ui/components/council-info-card.js +2 -2
  440. package/dist/src/ui/components/council-leader-bubble.d.ts +10 -3
  441. package/dist/src/ui/components/council-leader-bubble.js +21 -11
  442. package/dist/src/ui/components/council-message-bubble.d.ts +15 -2
  443. package/dist/src/ui/components/council-message-bubble.js +16 -15
  444. package/dist/src/ui/components/council-phase-timeline.d.ts +9 -1
  445. package/dist/src/ui/components/council-phase-timeline.js +66 -17
  446. package/dist/src/ui/components/council-placeholder-bubble.d.ts +16 -9
  447. package/dist/src/ui/components/council-placeholder-bubble.js +32 -29
  448. package/dist/src/ui/components/council-question-card.js +13 -12
  449. package/dist/src/ui/components/council-rail-rounds.d.ts +26 -0
  450. package/dist/src/ui/components/council-rail-rounds.js +57 -0
  451. package/dist/src/ui/components/council-round-group.d.ts +38 -0
  452. package/dist/src/ui/components/council-round-group.js +88 -0
  453. package/dist/src/ui/components/council-status-list.d.ts +3 -1
  454. package/dist/src/ui/components/council-status-list.js +36 -24
  455. package/dist/src/ui/components/council-synthesis-banner.d.ts +7 -2
  456. package/dist/src/ui/components/council-synthesis-banner.js +20 -5
  457. package/dist/src/ui/components/halt-recovery-card.js +9 -5
  458. package/dist/src/ui/components/jump-to-latest-pill.d.ts +11 -0
  459. package/dist/src/ui/components/jump-to-latest-pill.js +14 -0
  460. package/dist/src/ui/components/message-view.d.ts +15 -0
  461. package/dist/src/ui/components/message-view.js +50 -1
  462. package/dist/src/ui/components/prompt-box.js +18 -16
  463. package/dist/src/ui/components/session-tree-card.d.ts +14 -0
  464. package/dist/src/ui/components/session-tree-card.js +46 -0
  465. package/dist/src/ui/components/slash-inline-menu.d.ts +12 -0
  466. package/dist/src/ui/components/slash-inline-menu.js +26 -5
  467. package/dist/src/ui/components/task-list-panel.d.ts +14 -1
  468. package/dist/src/ui/components/task-list-panel.js +22 -2
  469. package/dist/src/ui/components/tool-group.d.ts +15 -3
  470. package/dist/src/ui/components/tool-group.js +69 -11
  471. package/dist/src/ui/containers/modals-layer.d.ts +4 -2
  472. package/dist/src/ui/containers/modals-layer.js +2 -2
  473. package/dist/src/ui/council-harness-event.d.ts +57 -0
  474. package/dist/src/ui/council-harness-event.js +46 -0
  475. package/dist/src/ui/heartbeat-debug.d.ts +29 -0
  476. package/dist/src/ui/heartbeat-debug.js +45 -0
  477. package/dist/src/ui/hooks/use-session-picker.d.ts +3 -3
  478. package/dist/src/ui/mcp-modal.js +2 -4
  479. package/dist/src/ui/modals/api-key-modal.js +1 -1
  480. package/dist/src/ui/modals/connect-modal.js +4 -3
  481. package/dist/src/ui/modals/model-picker-modal.d.ts +8 -18
  482. package/dist/src/ui/modals/model-picker-modal.js +8 -10
  483. package/dist/src/ui/modals/session-picker-modal.d.ts +2 -2
  484. package/dist/src/ui/modals/session-picker-modal.js +3 -5
  485. package/dist/src/ui/picker-providers.d.ts +1 -1
  486. package/dist/src/ui/picker-providers.js +1 -1
  487. package/dist/src/ui/primitives/index.d.ts +1 -0
  488. package/dist/src/ui/primitives/index.js +2 -0
  489. package/dist/src/ui/primitives/semantic-primitives.d.ts +76 -0
  490. package/dist/src/ui/primitives/semantic-primitives.js +81 -0
  491. package/dist/src/ui/slash/compact.js +5 -7
  492. package/dist/src/ui/slash/cost.js +1 -1
  493. package/dist/src/ui/slash/council.js +19 -1
  494. package/dist/src/ui/slash/debug.d.ts +3 -31
  495. package/dist/src/ui/slash/debug.js +9 -20
  496. package/dist/src/ui/slash/ee.js +81 -0
  497. package/dist/src/ui/slash/ideal.d.ts +6 -2
  498. package/dist/src/ui/slash/ideal.js +97 -7
  499. package/dist/src/ui/slash/menu-items.d.ts +7 -0
  500. package/dist/src/ui/slash/menu-items.js +23 -20
  501. package/dist/src/ui/slash/registry.d.ts +2 -0
  502. package/dist/src/ui/slash/registry.js +4 -0
  503. package/dist/src/ui/status-bar/cache-hit.d.ts +6 -0
  504. package/dist/src/ui/status-bar/cache-hit.js +9 -0
  505. package/dist/src/ui/status-bar/index.d.ts +1 -1
  506. package/dist/src/ui/status-bar/index.js +7 -3
  507. package/dist/src/ui/status-bar/usd-meter.d.ts +5 -4
  508. package/dist/src/ui/status-bar/usd-meter.js +6 -4
  509. package/dist/src/ui/theme.d.ts +1 -0
  510. package/dist/src/ui/theme.js +2 -0
  511. package/dist/src/ui/types.d.ts +7 -0
  512. package/dist/src/ui/use-app-logic.js +0 -0
  513. package/dist/src/ui/utils/agent-activities.d.ts +39 -0
  514. package/dist/src/ui/utils/agent-activities.js +96 -0
  515. package/dist/src/ui/utils/format.d.ts +14 -0
  516. package/dist/src/ui/utils/format.js +23 -3
  517. package/dist/src/ui/utils/group-tool-entries.d.ts +26 -0
  518. package/dist/src/ui/utils/group-tool-entries.js +111 -0
  519. package/dist/src/ui/utils/tool-summary.d.ts +21 -0
  520. package/dist/src/ui/utils/tool-summary.js +91 -0
  521. package/dist/src/usage/downgrade.js +2 -2
  522. package/dist/src/usage/product-ledger.js +2 -2
  523. package/dist/src/utils/event-loop-monitor.d.ts +85 -0
  524. package/dist/src/utils/event-loop-monitor.js +107 -0
  525. package/dist/src/utils/install-manager.js +2 -1
  526. package/dist/src/utils/llm-deadline.d.ts +14 -0
  527. package/dist/src/utils/llm-deadline.js +19 -0
  528. package/dist/src/utils/logger.js +2 -2
  529. package/dist/src/utils/loop-profiler.d.ts +102 -0
  530. package/dist/src/utils/loop-profiler.js +202 -0
  531. package/dist/src/utils/permission-mode.js +5 -3
  532. package/dist/src/utils/redactor.js +1 -1
  533. package/dist/src/utils/settings.d.ts +180 -5
  534. package/dist/src/utils/settings.js +271 -31
  535. package/dist/src/utils/side-question.d.ts +1 -2
  536. package/dist/src/utils/side-question.js +2 -2
  537. package/dist/src/utils/visible-retry.d.ts +11 -0
  538. package/dist/src/utils/visible-retry.js +10 -1
  539. package/dist/src/verify/entrypoint.d.ts +1 -1
  540. package/dist/src/verify/entrypoint.js +52 -17
  541. package/dist/src/verify/orchestrator.d.ts +1 -1
  542. package/dist/src/verify/orchestrator.js +20 -3
  543. package/dist/src/verify/recipes.d.ts +13 -0
  544. package/dist/src/verify/recipes.js +15 -0
  545. package/package.json +134 -132
  546. package/dist/src/cli/bw-vault.d.ts +0 -55
  547. package/dist/src/cli/bw-vault.js +0 -133
  548. package/dist/src/mcp/ee-tools.d.ts +0 -46
  549. package/dist/src/mcp/ee-tools.js +0 -193
  550. package/dist/src/providers/auth/gcloud.d.ts +0 -28
  551. package/dist/src/providers/auth/gcloud.js +0 -102
  552. package/dist/src/providers/auth/gemini-oauth.d.ts +0 -82
  553. package/dist/src/providers/auth/gemini-oauth.js +0 -472
  554. package/dist/src/providers/gemini.d.ts +0 -11
  555. package/dist/src/providers/gemini.js +0 -45
  556. package/dist/src/providers/siliconflow-sse-repair.d.ts +0 -58
  557. package/dist/src/providers/siliconflow-sse-repair.js +0 -177
  558. package/dist/src/providers/strategies/google.strategy.d.ts +0 -22
  559. package/dist/src/providers/strategies/google.strategy.js +0 -174
  560. package/dist/src/providers/strategies/siliconflow.strategy.js +0 -29
  561. package/dist/src/ui/containers/chat-feed.d.ts +0 -40
  562. package/dist/src/ui/containers/chat-feed.js +0 -66
@@ -99,6 +99,119 @@ export function loadTranscriptState(sessionId) {
99
99
  export function loadTranscript(sessionId) {
100
100
  return loadTranscriptState(sessionId).messages;
101
101
  }
102
+ /**
103
+ * Resume a session together with every session in its conversation tree.
104
+ *
105
+ * When a session has spawned child sessions (silent rotations, sub-agents,
106
+ * sub-sessions), resuming only the parent loses the work that happened in the
107
+ * children. This loader walks up to the root and then down through all
108
+ * descendants, applies each session's own compaction, merges the messages
109
+ * chronologically, and returns them as one flat transcript for the model.
110
+ *
111
+ * Sequence numbers from sessions other than the one being resumed are replaced
112
+ * with `null` so that usage attribution and compaction still belong to the
113
+ * resumed session.
114
+ */
115
+ export function loadSessionChainTranscriptState(sessionId) {
116
+ const chain = getSessionChain(sessionId);
117
+ if (chain.length <= 1) {
118
+ return loadTranscriptState(sessionId);
119
+ }
120
+ const records = [];
121
+ for (const sid of chain) {
122
+ const rows = loadMessageRows(sid);
123
+ const messages = rows.map((row) => JSON.parse(row.message_json));
124
+ const seqs = rows.map((row) => row.seq);
125
+ const timestamps = rows.map((row) => new Date(row.created_at));
126
+ const effective = buildEffectiveTranscript(messages, seqs, timestamps, loadLatestCompaction(sid));
127
+ for (let i = 0; i < effective.messages.length; i++) {
128
+ records.push({
129
+ sessionId: sid,
130
+ message: effective.messages[i],
131
+ seq: effective.seqs[i],
132
+ timestamp: effective.timestamps[i],
133
+ });
134
+ }
135
+ }
136
+ // getSessionChain already orders sessions by creation time. Preserve each
137
+ // session's internal effective-transcript order (especially compaction
138
+ // summaries, which must precede their kept tail) instead of re-sorting by
139
+ // individual message timestamps.
140
+ return {
141
+ messages: records.map((r) => r.message),
142
+ seqs: records.map((r) => (r.sessionId === sessionId ? r.seq : null)),
143
+ timestamps: records.map((r) => r.timestamp),
144
+ compaction: loadLatestCompaction(sessionId),
145
+ };
146
+ }
147
+ /**
148
+ * Enumerate the full session chain (root + all descendants) with per-session
149
+ * metadata, ordered root-first then by creation time. Read-only; safe to call
150
+ * on every render. Returns a single-node array for a session with no children.
151
+ */
152
+ export function getSessionChainInfos(sessionId) {
153
+ const chain = getSessionChain(sessionId);
154
+ if (chain.length === 0)
155
+ return [];
156
+ const db = getDatabase();
157
+ const placeholders = chain.map(() => "?").join(",");
158
+ let rows = [];
159
+ try {
160
+ rows = db
161
+ .prepare(`
162
+ SELECT s.id, s.parent_session_id, s.kind, s.model, s.status, s.created_at,
163
+ (SELECT COUNT(*) FROM messages m WHERE m.session_id = s.id) AS msgs
164
+ FROM sessions s
165
+ WHERE s.id IN (${placeholders})
166
+ `)
167
+ .all(...chain);
168
+ }
169
+ catch (err) {
170
+ logger.error("storage", "getSessionChainInfos query failed", {
171
+ sessionId,
172
+ message: err?.message,
173
+ });
174
+ return [];
175
+ }
176
+ const byId = new Map(rows.map((r) => [r.id, r]));
177
+ const depthOf = (id) => {
178
+ let depth = 0;
179
+ let cur = id;
180
+ const seen = new Set();
181
+ while (cur && !seen.has(cur)) {
182
+ seen.add(cur);
183
+ const parent = byId.get(cur)?.parent_session_id ?? null;
184
+ // Only count parents that are inside this chain (the walk-up root has none).
185
+ if (parent && byId.has(parent)) {
186
+ depth++;
187
+ cur = parent;
188
+ }
189
+ else {
190
+ break;
191
+ }
192
+ }
193
+ return depth;
194
+ };
195
+ const nodes = chain
196
+ .map((id) => byId.get(id))
197
+ .filter((r) => r !== undefined)
198
+ .map((r) => ({
199
+ id: r.id,
200
+ kind: r.kind ?? null,
201
+ model: r.model,
202
+ status: r.status,
203
+ messageCount: r.msgs,
204
+ parentId: r.parent_session_id,
205
+ depth: depthOf(r.id),
206
+ isCurrent: r.id === sessionId,
207
+ }));
208
+ // Render order: shallowest first (root → children → grandchildren) so the rail
209
+ // always shows the parent on top with descendants indented under it. Ties keep
210
+ // getSessionChain's created_at order. A stable index-carrying sort — chain
211
+ // created_at can tie at second granularity, so depth is the deterministic key.
212
+ const chainIndex = new Map(nodes.map((n, i) => [n.id, i]));
213
+ return nodes.sort((a, b) => a.depth - b.depth || chainIndex.get(a.id) - chainIndex.get(b.id));
214
+ }
102
215
  export function getNextMessageSequence(sessionId) {
103
216
  return getNextSequence(getDatabase(), sessionId);
104
217
  }
@@ -150,6 +263,7 @@ export function appendMessages(sessionId, messages) {
150
263
  const createdAt = new Date().toISOString();
151
264
  insertedSeqs.push(seq);
152
265
  insertMessage.run(sessionId, seq, message.role, JSON.stringify(message), createdAt);
266
+ indexMessageInFts(db, sessionId, seq, message.role, JSON.stringify(message));
153
267
  if (message.role === "assistant" && Array.isArray(message.content)) {
154
268
  for (const part of message.content) {
155
269
  if (part.type !== "tool-call")
@@ -212,9 +326,13 @@ export function persistToolCallWriteAhead(sessionId, messageSeq, toolCallId, too
212
326
  `)
213
327
  .run(sessionId, messageSeq, toolCallId, toolName, argsJson, now);
214
328
  }
215
- catch {
216
- // Fail-open: write-ahead is best-effort. The post-stream UPDATE path
217
- // will still finalize the row from `appendMessages(...)`.
329
+ catch (err) {
330
+ logger.error("storage", `[transcript] persistToolCallWriteAhead failed: ${err.message}`, {
331
+ sessionId,
332
+ messageSeq,
333
+ toolCallId,
334
+ toolName,
335
+ });
218
336
  }
219
337
  }
220
338
  /**
@@ -253,16 +371,20 @@ export function persistToolCallWriteAhead(sessionId, messageSeq, toolCallId, too
253
371
  export function persistMessageWriteAhead(sessionId, seq, role, messageJson) {
254
372
  const now = new Date().toISOString();
255
373
  try {
256
- getDatabase()
257
- .prepare(`
374
+ const db = getDatabase();
375
+ db.prepare(`
258
376
  INSERT OR IGNORE INTO messages (
259
377
  session_id, seq, role, message_json, created_at, status
260
378
  ) VALUES (?, ?, ?, ?, ?, 'pending')
261
- `)
262
- .run(sessionId, seq, role, messageJson, now);
379
+ `).run(sessionId, seq, role, messageJson, now);
380
+ indexMessageInFts(db, sessionId, seq, role, messageJson);
263
381
  }
264
- catch {
265
- /* fail-open */
382
+ catch (err) {
383
+ logger.error("storage", `[transcript] persistMessageWriteAhead failed: ${err.message}`, {
384
+ sessionId,
385
+ seq,
386
+ role,
387
+ });
266
388
  }
267
389
  }
268
390
  /**
@@ -282,8 +404,8 @@ export function markMessageCompleted(sessionId, seq) {
282
404
  `)
283
405
  .run(sessionId, seq);
284
406
  }
285
- catch {
286
- /* fail-open */
407
+ catch (err) {
408
+ logger.error("storage", `[transcript] markMessageCompleted failed: ${err.message}`, { sessionId, seq });
287
409
  }
288
410
  }
289
411
  /**
@@ -304,8 +426,8 @@ export function markMessageErrored(sessionId, seq) {
304
426
  `)
305
427
  .run(sessionId, seq);
306
428
  }
307
- catch {
308
- /* fail-open */
429
+ catch (err) {
430
+ logger.error("storage", `[transcript] markMessageErrored failed: ${err.message}`, { sessionId, seq });
309
431
  }
310
432
  }
311
433
  /**
@@ -482,13 +604,19 @@ export function buildChatEntries(sessionId) {
482
604
  catch (err) {
483
605
  logger.error("storage", "Failed to load session metadata for chain in buildChatEntries", { error: err });
484
606
  }
607
+ // One read per session in the chain — the prompt/answer reconciliation below
608
+ // and the render walk both need every session's records.
609
+ const recordsBySession = new Map();
610
+ for (const sid of chain) {
611
+ recordsBySession.set(sid, buildEffectiveMessageRecords(sid));
612
+ }
485
613
  // Map each child sub-session's initial user prompt to its creation timestamp
486
614
  const childPrompts = new Map();
487
615
  for (let i = 1; i < chain.length; i++) {
488
616
  const sid = chain[i];
489
617
  const meta = sessionMeta.get(sid);
490
618
  if (meta && meta.parent_session_id) {
491
- const records = buildEffectiveMessageRecords(sid);
619
+ const records = recordsBySession.get(sid) ?? [];
492
620
  const firstUser = records.find((r) => r.message.role === "user");
493
621
  if (firstUser) {
494
622
  const content = renderUserContent(firstUser.message.content);
@@ -498,14 +626,38 @@ export function buildChatEntries(sessionId) {
498
626
  }
499
627
  }
500
628
  }
629
+ // When a sub-session finishes, the orchestrator absorbs its LAST assistant
630
+ // message into the PARENT (salvageSubSessionOutput + appendCompletedTurn,
631
+ // orchestrator.ts) so the parent keeps context continuity. That content is
632
+ // therefore persisted in BOTH sessions, and the chain walk below would render
633
+ // the final answer twice. Keep the parent's copy — it sits in the timeline
634
+ // where the user actually asked — and drop the child's, mirroring how the
635
+ // child's duplicated user prompt is handled above.
636
+ const absorbedByChild = new Map();
637
+ for (let i = 1; i < chain.length; i++) {
638
+ const sid = chain[i];
639
+ const parentId = sessionMeta.get(sid)?.parent_session_id;
640
+ if (!parentId)
641
+ continue;
642
+ const parentRecords = recordsBySession.get(parentId);
643
+ if (!parentRecords)
644
+ continue;
645
+ const text = lastAssistantText(recordsBySession.get(sid) ?? []);
646
+ if (text && parentRecords.some((r) => r.message.role === "assistant" && assistantText(r.message) === text)) {
647
+ absorbedByChild.set(sid, text);
648
+ }
649
+ }
501
650
  const callMap = new Map();
502
651
  const entries = [];
503
652
  const renderedResponseCallIds = new Set();
504
653
  let lastTimestamp;
505
654
  for (let i = 0; i < chain.length; i++) {
506
655
  const sid = chain[i];
507
- const records = buildEffectiveMessageRecords(sid);
656
+ const records = recordsBySession.get(sid) ?? [];
508
657
  const isChildSession = i > 0;
658
+ // Only the single message the parent absorbed is dropped, so a child that
659
+ // legitimately repeats itself still renders its other turns.
660
+ let absorbedPending = absorbedByChild.get(sid);
509
661
  for (let j = 0; j < records.length; j++) {
510
662
  const { message, timestamp } = records[j];
511
663
  lastTimestamp = timestamp;
@@ -536,8 +688,15 @@ export function buildChatEntries(sessionId) {
536
688
  continue;
537
689
  }
538
690
  if (message.role === "assistant") {
691
+ // Call first regardless: it registers this message's tool-calls in
692
+ // callMap, which the tool-result branch below needs even when the
693
+ // message itself is skipped as an absorbed duplicate.
539
694
  const text = renderAssistantContent(message.content, callMap);
540
695
  if (text) {
696
+ if (absorbedPending !== undefined && text === absorbedPending) {
697
+ absorbedPending = undefined;
698
+ continue;
699
+ }
541
700
  entries.push({ type: "assistant", content: text, timestamp });
542
701
  }
543
702
  continue;
@@ -622,6 +781,23 @@ export function buildChatEntries(sessionId) {
622
781
  logger.debug("storage", "Built chat entries successfully", { sessionId, count: entries.length });
623
782
  return entries;
624
783
  }
784
+ /** Rendered text of an assistant message, with no callMap side effect. */
785
+ function assistantText(message) {
786
+ return renderAssistantContent(message.content, new Map());
787
+ }
788
+ /**
789
+ * Text of the session's LAST assistant message — the one the sub-session
790
+ * absorption path hands to the parent. Empty when that message carried only
791
+ * tool-calls (nothing renders, so nothing can duplicate).
792
+ */
793
+ function lastAssistantText(records) {
794
+ for (let i = records.length - 1; i >= 0; i--) {
795
+ const message = records[i].message;
796
+ if (message.role === "assistant")
797
+ return assistantText(message);
798
+ }
799
+ return "";
800
+ }
625
801
  function getNextSequence(db, sessionId) {
626
802
  const row = db
627
803
  .prepare(`
@@ -721,4 +897,153 @@ export function getLastTodoWriteArgs(sessionId) {
721
897
  }
722
898
  return null;
723
899
  }
900
+ /**
901
+ * Persist the approved plan text for a session so that "tiếp tục"/"continue"
902
+ * turns (which are classified as chitchat/general by PIL Pass 0) can re-inject
903
+ * the APPROVED PLAN section into the system prompt instead of forgetting context.
904
+ *
905
+ * Stored as a synthetic tool_call row (tool_name='__approved_plan') so we reuse
906
+ * the existing schema and getLast* query pattern without a new table/migration.
907
+ * The planText is stored verbatim in args_json.
908
+ */
909
+ export function persistApprovedPlan(sessionId, planText) {
910
+ if (!sessionId || !planText)
911
+ return;
912
+ const db = getDatabase();
913
+ const toolCallId = `approved-plan-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
914
+ const now = new Date().toISOString();
915
+ try {
916
+ db.prepare(`
917
+ INSERT OR REPLACE INTO tool_calls (session_id, message_seq, tool_call_id, tool_name, args_json, status, started_at, completed_at)
918
+ VALUES (?, 0, ?, '__approved_plan', ?, 'completed', ?, ?)
919
+ `).run(sessionId, toolCallId, planText, now, now);
920
+ }
921
+ catch {
922
+ /* best-effort persistence; never block the turn */
923
+ }
924
+ }
925
+ /** Load the most recent persisted approved plan for this session (or parent chain). */
926
+ export function getLastApprovedPlan(sessionId) {
927
+ const chain = getSessionChain(sessionId);
928
+ const db = getDatabase();
929
+ for (let i = chain.length - 1; i >= 0; i--) {
930
+ try {
931
+ // 1) Prefer our synthetic persisted row (written by setPlanContext + persistApprovedPlan).
932
+ const synthetic = db
933
+ .prepare(`
934
+ SELECT args_json
935
+ FROM tool_calls
936
+ WHERE session_id = ? AND tool_name = '__approved_plan'
937
+ ORDER BY id DESC
938
+ LIMIT 1
939
+ `)
940
+ .get(chain[i]);
941
+ if (synthetic?.args_json) {
942
+ return synthetic.args_json;
943
+ }
944
+ // 2) Fallback: scan real plan tool_calls (respond_plan / generate_plan) written by
945
+ // council, PIL response-tools, or generate_plan UI. Extract a human-readable slice.
946
+ const planRow = db
947
+ .prepare(`
948
+ SELECT args_json, tool_name
949
+ FROM tool_calls
950
+ WHERE session_id = ? AND tool_name IN ('respond_plan', 'generate_plan')
951
+ ORDER BY id DESC
952
+ LIMIT 1
953
+ `)
954
+ .get(chain[i]);
955
+ if (planRow?.args_json) {
956
+ try {
957
+ const parsed = JSON.parse(planRow.args_json);
958
+ // respond_plan shape typically has { steps, assumptions?, risks? } or { plan: {...} }
959
+ const candidate = parsed?.plan ?? parsed;
960
+ if (candidate && (Array.isArray(candidate.steps) || typeof candidate === "object")) {
961
+ return JSON.stringify(candidate, null, 2);
962
+ }
963
+ // generate_plan may carry raw text or { content, steps }
964
+ if (typeof parsed === "string")
965
+ return parsed;
966
+ if (parsed && typeof parsed === "object")
967
+ return JSON.stringify(parsed, null, 2);
968
+ }
969
+ catch {
970
+ // not JSON — return as-is (may be a raw string payload)
971
+ if (typeof planRow.args_json === "string" && planRow.args_json.trim().length > 0) {
972
+ return planRow.args_json;
973
+ }
974
+ }
975
+ }
976
+ }
977
+ catch {
978
+ // ignore and check parent
979
+ }
980
+ }
981
+ return null;
982
+ }
983
+ function indexMessageInFts(db, sessionId, seq, role, messageJsonStr) {
984
+ db.prepare(`DELETE FROM session_history_fts WHERE session_id = ? AND seq = ?`).run(sessionId, seq);
985
+ let message;
986
+ try {
987
+ message = JSON.parse(messageJsonStr);
988
+ }
989
+ catch (err) {
990
+ logger.error("storage", `[transcript] Failed to parse message JSON for FTS indexing: ${err.message}`, {
991
+ sessionId,
992
+ seq,
993
+ role,
994
+ });
995
+ return;
996
+ }
997
+ let content = "";
998
+ let toolName = "";
999
+ let toolArgs = "";
1000
+ let toolOutput = "";
1001
+ const msgContent = message.content;
1002
+ if (typeof msgContent === "string") {
1003
+ content = msgContent;
1004
+ }
1005
+ else if (Array.isArray(msgContent)) {
1006
+ const textParts = [];
1007
+ const toolNames = [];
1008
+ const argParts = [];
1009
+ const outputParts = [];
1010
+ for (const part of msgContent) {
1011
+ if (part && typeof part === "object") {
1012
+ if (part.type === "text" && typeof part.text === "string") {
1013
+ textParts.push(part.text);
1014
+ }
1015
+ else if (part.type === "tool-call" && typeof part.toolName === "string") {
1016
+ toolNames.push(part.toolName);
1017
+ if (part.input !== undefined) {
1018
+ argParts.push(typeof part.input === "string" ? part.input : JSON.stringify(part.input));
1019
+ }
1020
+ }
1021
+ else if (part.type === "tool-result" && typeof part.toolName === "string") {
1022
+ toolNames.push(part.toolName);
1023
+ if (part.output !== undefined) {
1024
+ outputParts.push(typeof part.output === "string" ? part.output : JSON.stringify(part.output));
1025
+ }
1026
+ }
1027
+ }
1028
+ }
1029
+ content = textParts.join("\n").trim();
1030
+ toolName = toolNames.join(", ").trim();
1031
+ toolArgs = argParts.join("\n").trim();
1032
+ toolOutput = outputParts.join("\n").trim();
1033
+ }
1034
+ try {
1035
+ db.prepare(`
1036
+ INSERT INTO session_history_fts (session_id, seq, role, tool_name, content, tool_args, tool_output)
1037
+ VALUES (?, ?, ?, ?, ?, ?, ?)
1038
+ `).run(sessionId, seq, role, toolName || null, content || null, toolArgs || null, toolOutput || null);
1039
+ }
1040
+ catch (err) {
1041
+ logger.error("storage", `[transcript] Failed to execute FTS indexing query: ${err.message}`, {
1042
+ sessionId,
1043
+ seq,
1044
+ role,
1045
+ });
1046
+ throw err;
1047
+ }
1048
+ }
724
1049
  //# sourceMappingURL=transcript.js.map
@@ -14,5 +14,20 @@ export interface FileResult {
14
14
  lspDiagnostics?: LspDiagnosticFile[];
15
15
  }
16
16
  export declare function readFile(filePath: string, cwd: string, startLine?: number, endLine?: number, tracker?: FileTracker): FileResult;
17
+ /**
18
+ * O1 — read MULTIPLE files in ONE tool call. This is the lossless batching
19
+ * lever: a single `read_file` carrying N paths is ONE tool_call, so it is
20
+ * NEVER split by `splitParallelToolCalls` (which only reshapes assistant turns
21
+ * with >1 tool_calls) — the ≥50% fresh-input cut holds on every provider,
22
+ * including the kimi/glm/deepseek-go sequential-split cohort.
23
+ *
24
+ * Quality gate (council regression vector "partial multi-path reads"): each
25
+ * file is capped INDEPENDENTLY at `perFileCap` with an EXPLICIT truncation
26
+ * marker, so no file is ever silently dropped by a downstream head/tail
27
+ * whole-result cap. With `perFileCap = floor(MAX_TOOL_OUTPUT_CHARS / n)` the
28
+ * concatenated total stays under the registry cap, making the outer
29
+ * `truncateOutput` a no-op — every requested file is represented.
30
+ */
31
+ export declare function readFiles(filePaths: string[], cwd: string, tracker?: FileTracker, perFileCap?: number): FileResult;
17
32
  export declare function writeFile(filePath: string, content: string, cwd: string, tracker?: FileTracker): Promise<FileResult>;
18
33
  export declare function editFile(filePath: string, oldString: string, newString: string, cwd: string, tracker?: FileTracker): Promise<FileResult>;
@@ -51,6 +51,38 @@ export function readFile(filePath, cwd, startLine, endLine, tracker) {
51
51
  return { success: false, output: `Failed to read file: ${msg}` };
52
52
  }
53
53
  }
54
+ /**
55
+ * O1 — read MULTIPLE files in ONE tool call. This is the lossless batching
56
+ * lever: a single `read_file` carrying N paths is ONE tool_call, so it is
57
+ * NEVER split by `splitParallelToolCalls` (which only reshapes assistant turns
58
+ * with >1 tool_calls) — the ≥50% fresh-input cut holds on every provider,
59
+ * including the kimi/glm/deepseek-go sequential-split cohort.
60
+ *
61
+ * Quality gate (council regression vector "partial multi-path reads"): each
62
+ * file is capped INDEPENDENTLY at `perFileCap` with an EXPLICIT truncation
63
+ * marker, so no file is ever silently dropped by a downstream head/tail
64
+ * whole-result cap. With `perFileCap = floor(MAX_TOOL_OUTPUT_CHARS / n)` the
65
+ * concatenated total stays under the registry cap, making the outer
66
+ * `truncateOutput` a no-op — every requested file is represented.
67
+ */
68
+ export function readFiles(filePaths, cwd, tracker, perFileCap) {
69
+ if (filePaths.length === 0) {
70
+ return { success: false, output: "read_file: no paths provided (file_path or file_paths required)" };
71
+ }
72
+ const parts = [];
73
+ for (const filePath of filePaths) {
74
+ const r = readFile(filePath, cwd, undefined, undefined, tracker);
75
+ let out = r.output;
76
+ if (perFileCap && perFileCap > 0 && out.length > perFileCap) {
77
+ // Head-truncate this ONE file with an explicit, self-describing marker.
78
+ // Never silently elide: the model is told this file was cut and how to
79
+ // get the rest (single read + line range).
80
+ out = `${out.slice(0, perFileCap)}\n... [${out.length - perFileCap} chars of ${filePath} truncated in this batch read — read it singly with start_line/end_line for the rest] ...`;
81
+ }
82
+ parts.push(out);
83
+ }
84
+ return { success: true, output: parts.join("\n\n") };
85
+ }
54
86
  export async function writeFile(filePath, content, cwd, tracker) {
55
87
  try {
56
88
  const full = resolvePath(filePath, cwd);
@@ -90,6 +90,25 @@ export interface StagingBlockResult {
90
90
  * 2. Setting MUONROI_ALLOW_BROAD_STAGE=1 (escape hatch, logged to decision-log).
91
91
  */
92
92
  export declare function checkSensitiveStaging(cwd: string): StagingBlockResult;
93
+ export type DestructiveKind = "checkout-discard" | "restore" | "reset-hard" | "clean" | "stash-drop" | "rm-tracked";
94
+ export interface DestructiveShape {
95
+ kind: DestructiveKind | null;
96
+ /** true when the risk is untracked files (clean) rather than tracked mods. */
97
+ untrackedRisk: boolean;
98
+ }
99
+ export declare function analyzeDestructiveGit(command: string): DestructiveShape;
100
+ export interface DestructiveBlockResult {
101
+ blocked: boolean;
102
+ kind: DestructiveKind | null;
103
+ message: string;
104
+ }
105
+ /**
106
+ * Pre-execution guard: block a working-tree-destroying command when it would
107
+ * actually discard uncommitted work. Returns blocked=false (no message) when
108
+ * the command is non-destructive, when nothing is at risk, or when the user set
109
+ * the escape hatch. Deterministic + cheap (a couple of git plumbing calls).
110
+ */
111
+ export declare function checkDestructiveOp(command: string, cwd: string): DestructiveBlockResult;
93
112
  /**
94
113
  * @deprecated Use checkSensitiveStaging() for hard-blocking.
95
114
  * Kept for call sites that emit a trailing warning (non-broad-stage contexts).