muonroi-cli 1.7.1 → 1.8.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 (328) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +122 -122
  3. package/dist/packages/agent-harness-core/src/event-filter.js +1 -0
  4. package/dist/packages/agent-harness-core/src/event-redact.js +8 -0
  5. package/dist/packages/agent-harness-core/src/mcp-server.d.ts +16 -0
  6. package/dist/packages/agent-harness-core/src/mcp-server.js +88 -10
  7. package/dist/packages/agent-harness-core/src/protocol.d.ts +15 -0
  8. package/dist/packages/agent-harness-core/src/selector.js +2 -2
  9. package/dist/packages/agent-harness-core/src/transports/sidechannel.js +1 -1
  10. package/dist/packages/agent-harness-opentui/src/agent-mode.js +1 -1
  11. package/dist/packages/agent-harness-opentui/src/install.js +1 -1
  12. package/dist/src/__test-stubs__/vitest-setup.js +4 -0
  13. package/dist/src/agent-harness/__tests__/mock-model.spec.js +54 -0
  14. package/dist/src/agent-harness/mock-model.d.ts +1 -1
  15. package/dist/src/agent-harness/mock-model.js +32 -3
  16. package/dist/src/agent-harness/test-spawn.js +3 -1
  17. package/dist/src/chat/chat-keychain.js +9 -1
  18. package/dist/src/cli/cost-forensics.js +12 -12
  19. package/dist/src/cli/keys.d.ts +2 -2
  20. package/dist/src/cli/keys.js +107 -28
  21. package/dist/src/cli/usage-report.js +2 -2
  22. package/dist/src/council/__tests__/abort-threading.test.d.ts +1 -0
  23. package/dist/src/council/__tests__/abort-threading.test.js +193 -0
  24. package/dist/src/council/__tests__/clarification-prompt.test.js +21 -1
  25. package/dist/src/council/__tests__/council-turn-length-emit.test.d.ts +1 -0
  26. package/dist/src/council/__tests__/council-turn-length-emit.test.js +130 -0
  27. package/dist/src/council/__tests__/debate-round-budget.test.d.ts +1 -0
  28. package/dist/src/council/__tests__/debate-round-budget.test.js +45 -0
  29. package/dist/src/council/__tests__/evaluator-metrics.test.js +3 -0
  30. package/dist/src/council/__tests__/post-debate-recommendation.test.d.ts +1 -0
  31. package/dist/src/council/__tests__/post-debate-recommendation.test.js +58 -0
  32. package/dist/src/council/__tests__/research-tools.test.js +4 -0
  33. package/dist/src/council/__tests__/round-tools.test.js +6 -0
  34. package/dist/src/council/clarifier-question-cap.test.d.ts +12 -0
  35. package/dist/src/council/clarifier-question-cap.test.js +73 -0
  36. package/dist/src/council/clarifier.d.ts +29 -1
  37. package/dist/src/council/clarifier.js +64 -1
  38. package/dist/src/council/debate-planner.d.ts +2 -1
  39. package/dist/src/council/debate-planner.js +5 -3
  40. package/dist/src/council/debate.d.ts +9 -0
  41. package/dist/src/council/debate.js +88 -8
  42. package/dist/src/council/index.d.ts +46 -1
  43. package/dist/src/council/index.js +125 -19
  44. package/dist/src/council/llm.js +41 -13
  45. package/dist/src/council/prompts.js +56 -21
  46. package/dist/src/council/types.d.ts +14 -1
  47. package/dist/src/ee/__tests__/export-transcripts.test.js +1 -1
  48. package/dist/src/ee/bridge.d.ts +3 -1
  49. package/dist/src/ee/bridge.js +9 -3
  50. package/dist/src/ee/bridge.test.js +1 -2
  51. package/dist/src/ee/client.js +15 -2
  52. package/dist/src/ee/recall-ledger.d.ts +20 -0
  53. package/dist/src/ee/recall-ledger.js +40 -1
  54. package/dist/src/ee/search.d.ts +25 -0
  55. package/dist/src/ee/search.js +73 -0
  56. package/dist/src/ee/types.d.ts +15 -1
  57. package/dist/src/ee/who-am-i.d.ts +41 -0
  58. package/dist/src/ee/who-am-i.js +143 -0
  59. package/dist/src/ee/who-am-i.test.d.ts +1 -0
  60. package/dist/src/ee/who-am-i.test.js +101 -0
  61. package/dist/src/generated/version.d.ts +1 -1
  62. package/dist/src/generated/version.js +1 -1
  63. package/dist/src/headless/council-answers.js +1 -0
  64. package/dist/src/headless/output.d.ts +30 -1
  65. package/dist/src/headless/output.js +180 -0
  66. package/dist/src/headless/output.test.js +61 -1
  67. package/dist/src/hooks/index.js +48 -2
  68. package/dist/src/index.d.ts +2 -0
  69. package/dist/src/index.js +143 -104
  70. package/dist/src/lsp/client-normalize.test.d.ts +12 -0
  71. package/dist/src/lsp/client-normalize.test.js +34 -0
  72. package/dist/src/lsp/client.d.ts +1 -0
  73. package/dist/src/lsp/client.js +10 -2
  74. package/dist/src/lsp/manager.d.ts +1 -1
  75. package/dist/src/lsp/manager.js +2 -2
  76. package/dist/src/lsp/manager.test.js +2 -2
  77. package/dist/src/lsp/runtime.d.ts +1 -1
  78. package/dist/src/lsp/runtime.js +2 -2
  79. package/dist/src/maintain/__tests__/gh-create-pr.test.js +7 -3
  80. package/dist/src/maintain/__tests__/pr-builder.test.js +7 -3
  81. package/dist/src/mcp/__tests__/client-pool.spec.js +3 -3
  82. package/dist/src/mcp/__tests__/ee-tools.test.js +42 -14
  83. package/dist/src/mcp/__tests__/forensics-tools.test.js +3 -3
  84. package/dist/src/mcp/__tests__/lsp-tools.test.js +4 -4
  85. package/dist/src/mcp/client-pool.d.ts +1 -1
  86. package/dist/src/mcp/client-pool.js +25 -9
  87. package/dist/src/mcp/ee-tools.d.ts +10 -0
  88. package/dist/src/mcp/ee-tools.js +34 -0
  89. package/dist/src/mcp/oauth-callback.js +2 -2
  90. package/dist/src/mcp/parse-headers.test.js +14 -14
  91. package/dist/src/mcp/self-verify-jobs.js +1 -3
  92. package/dist/src/mcp/setup-guide-text.js +74 -74
  93. package/dist/src/mcp/smoke.test.js +43 -43
  94. package/dist/src/models/catalog-gemini.test.js +12 -10
  95. package/dist/src/models/catalog.json +106 -38
  96. package/dist/src/ops/doctor.js +7 -7
  97. package/dist/src/orchestrator/__tests__/auto-commit.test.d.ts +1 -0
  98. package/dist/src/orchestrator/__tests__/auto-commit.test.js +142 -0
  99. package/dist/src/orchestrator/__tests__/batch-turn-runner.test.js +2 -0
  100. package/dist/src/orchestrator/__tests__/delegations.test.d.ts +1 -0
  101. package/dist/src/orchestrator/__tests__/delegations.test.js +96 -0
  102. package/dist/src/orchestrator/__tests__/message-processor.test.js +1 -0
  103. package/dist/src/orchestrator/__tests__/stream-runner.test.js +29 -0
  104. package/dist/src/orchestrator/agent.test.js +5 -2
  105. package/dist/src/orchestrator/auto-commit.d.ts +110 -0
  106. package/dist/src/orchestrator/auto-commit.js +364 -0
  107. package/dist/src/orchestrator/batch-turn-runner.d.ts +3 -2
  108. package/dist/src/orchestrator/batch-turn-runner.js +2 -1
  109. package/dist/src/orchestrator/compaction-proposer-prompt.d.ts +8 -0
  110. package/dist/src/orchestrator/compaction-proposer-prompt.js +43 -0
  111. package/dist/src/orchestrator/compaction.d.ts +22 -0
  112. package/dist/src/orchestrator/compaction.js +42 -0
  113. package/dist/src/orchestrator/delegations.d.ts +1 -0
  114. package/dist/src/orchestrator/delegations.js +41 -0
  115. package/dist/src/orchestrator/error-utils.js +27 -2
  116. package/dist/src/orchestrator/message-processor.d.ts +21 -5
  117. package/dist/src/orchestrator/message-processor.js +219 -2573
  118. package/dist/src/orchestrator/orchestrator.d.ts +8 -2
  119. package/dist/src/orchestrator/orchestrator.js +187 -34
  120. package/dist/src/orchestrator/preprocessor.d.ts +13 -0
  121. package/dist/src/orchestrator/preprocessor.js +145 -0
  122. package/dist/src/orchestrator/prompts.d.ts +8 -0
  123. package/dist/src/orchestrator/prompts.js +76 -60
  124. package/dist/src/orchestrator/safety-askcard.d.ts +66 -0
  125. package/dist/src/orchestrator/safety-askcard.js +74 -0
  126. package/dist/src/orchestrator/sandbox.test.js +8 -5
  127. package/dist/src/orchestrator/scope-ceiling.js +1 -1
  128. package/dist/src/orchestrator/stall-watchdog.d.ts +47 -0
  129. package/dist/src/orchestrator/stall-watchdog.js +23 -0
  130. package/dist/src/orchestrator/stall-watchdog.test.js +36 -1
  131. package/dist/src/orchestrator/stream-runner.js +52 -30
  132. package/dist/src/orchestrator/sub-agent-model-tier.js +1 -1
  133. package/dist/src/orchestrator/subagent-compactor.d.ts +14 -0
  134. package/dist/src/orchestrator/subagent-compactor.js +83 -10
  135. package/dist/src/orchestrator/subagent-compactor.spec.js +132 -0
  136. package/dist/src/orchestrator/text-tool-call-detector.d.ts +9 -5
  137. package/dist/src/orchestrator/text-tool-call-detector.js +16 -12
  138. package/dist/src/orchestrator/text-tool-call-detector.test.js +66 -8
  139. package/dist/src/orchestrator/tool-args-repair.js +1 -1
  140. package/dist/src/orchestrator/tool-engine.d.ts +151 -0
  141. package/dist/src/orchestrator/tool-engine.js +3079 -0
  142. package/dist/src/orchestrator/turn-runner-deps.d.ts +1 -0
  143. package/dist/src/pil/__tests__/discovery-types.test.js +15 -4
  144. package/dist/src/pil/__tests__/discovery.test.js +89 -145
  145. package/dist/src/pil/__tests__/dual-run.test.js +2 -0
  146. package/dist/src/pil/__tests__/layer1-intent-trace.test.js +3 -0
  147. package/dist/src/pil/__tests__/layer1-intent.test.js +3 -0
  148. package/dist/src/pil/__tests__/layer16-clarity.test.js +35 -32
  149. package/dist/src/pil/__tests__/layer18-acceptance.test.js +1 -78
  150. package/dist/src/pil/__tests__/layer2_5-ponytail.test.d.ts +1 -0
  151. package/dist/src/pil/__tests__/layer2_5-ponytail.test.js +53 -0
  152. package/dist/src/pil/__tests__/layer3-ee-injection.test.js +67 -4
  153. package/dist/src/pil/__tests__/layer3-injected-chunk.test.js +14 -2
  154. package/dist/src/pil/__tests__/layer4-gsd.test.js +30 -0
  155. package/dist/src/pil/__tests__/layer5-context.test.js +39 -1
  156. package/dist/src/pil/__tests__/layer6-output.test.js +30 -2
  157. package/dist/src/pil/__tests__/orchestrator-integration.test.js +3 -1
  158. package/dist/src/pil/__tests__/pipeline.test.js +11 -8
  159. package/dist/src/pil/__tests__/response-tools.test.js +52 -0
  160. package/dist/src/pil/agent-operating-contract.d.ts +1 -1
  161. package/dist/src/pil/agent-operating-contract.js +5 -3
  162. package/dist/src/pil/agent-operating-contract.test.js +2 -2
  163. package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
  164. package/dist/src/pil/cheap-model-playbook.js +1 -1
  165. package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
  166. package/dist/src/pil/cheap-model-workbooks.js +1 -1
  167. package/dist/src/pil/config.d.ts +20 -0
  168. package/dist/src/pil/config.js +35 -0
  169. package/dist/src/pil/discovery-types.d.ts +32 -9
  170. package/dist/src/pil/discovery.d.ts +3 -3
  171. package/dist/src/pil/discovery.js +138 -244
  172. package/dist/src/pil/index.d.ts +1 -1
  173. package/dist/src/pil/index.js +1 -1
  174. package/dist/src/pil/layer1-intent.d.ts +9 -1
  175. package/dist/src/pil/layer1-intent.js +99 -44
  176. package/dist/src/pil/layer1-intent.test.js +112 -2
  177. package/dist/src/pil/layer15-context-scan.js +1 -1
  178. package/dist/src/pil/layer16-clarity.d.ts +21 -25
  179. package/dist/src/pil/layer16-clarity.js +52 -88
  180. package/dist/src/pil/layer18-acceptance.d.ts +13 -3
  181. package/dist/src/pil/layer18-acceptance.js +1 -75
  182. package/dist/src/pil/layer2-personality.js +7 -8
  183. package/dist/src/pil/layer2_5-ponytail.d.ts +2 -0
  184. package/dist/src/pil/layer2_5-ponytail.js +41 -0
  185. package/dist/src/pil/layer3-ee-injection.js +180 -14
  186. package/dist/src/pil/layer4-gsd.js +22 -8
  187. package/dist/src/pil/layer5-context.d.ts +1 -0
  188. package/dist/src/pil/layer5-context.js +26 -11
  189. package/dist/src/pil/layer6-output.js +23 -5
  190. package/dist/src/pil/llm-classify.js +3 -3
  191. package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
  192. package/dist/src/pil/native-capabilities-workbook.js +4 -3
  193. package/dist/src/pil/pipeline.js +15 -1
  194. package/dist/src/pil/response-tools.d.ts +16 -0
  195. package/dist/src/pil/response-tools.js +41 -0
  196. package/dist/src/pil/schema.d.ts +8 -0
  197. package/dist/src/pil/schema.js +24 -3
  198. package/dist/src/pil/task-tier-map.js +7 -7
  199. package/dist/src/pil/types.d.ts +9 -3
  200. package/dist/src/product-loop/__tests__/discovery-interview.test.js +103 -1
  201. package/dist/src/product-loop/__tests__/gather-selectable-alts.test.js +34 -0
  202. package/dist/src/product-loop/__tests__/sprint-self-verify.test.js +12 -12
  203. package/dist/src/product-loop/discovery-interview.d.ts +20 -0
  204. package/dist/src/product-loop/discovery-interview.js +121 -7
  205. package/dist/src/product-loop/done-gate.js +3 -3
  206. package/dist/src/product-loop/gather.js +19 -5
  207. package/dist/src/product-loop/loop-driver.js +20 -20
  208. package/dist/src/product-loop/progress-snapshot.js +4 -4
  209. package/dist/src/product-loop/sprint-self-verify.js +2 -2
  210. package/dist/src/providers/__tests__/reasoning-roundtrip.test.js +12 -0
  211. package/dist/src/providers/auth/__tests__/gemini-oauth.test.d.ts +1 -5
  212. package/dist/src/providers/auth/__tests__/gemini-oauth.test.js +1 -5
  213. package/dist/src/providers/auth/gcloud.d.ts +28 -0
  214. package/dist/src/providers/auth/gcloud.js +102 -0
  215. package/dist/src/providers/auth/gemini-oauth.d.ts +46 -19
  216. package/dist/src/providers/auth/gemini-oauth.js +292 -105
  217. package/dist/src/providers/auth/grok-oauth.d.ts +1 -1
  218. package/dist/src/providers/auth/grok-oauth.js +1 -1
  219. package/dist/src/providers/auth/registry.js +28 -6
  220. package/dist/src/providers/gemini.d.ts +1 -1
  221. package/dist/src/providers/gemini.js +10 -3
  222. package/dist/src/providers/keychain.d.ts +2 -2
  223. package/dist/src/providers/keychain.js +20 -2
  224. package/dist/src/providers/mcp-vision-bridge.js +48 -48
  225. package/dist/src/providers/openai.js +5 -1
  226. package/dist/src/providers/runtime.d.ts +1 -1
  227. package/dist/src/providers/runtime.js +11 -2
  228. package/dist/src/providers/siliconflow-sse-repair.js +1 -1
  229. package/dist/src/providers/strategies/google.strategy.d.ts +9 -2
  230. package/dist/src/providers/strategies/google.strategy.js +159 -9
  231. package/dist/src/providers/strategies/thinking-mode.js +19 -6
  232. package/dist/src/providers/types.d.ts +1 -1
  233. package/dist/src/reporter/index.js +1 -1
  234. package/dist/src/router/decide.test.js +40 -8
  235. package/dist/src/router/step-router.d.ts +20 -0
  236. package/dist/src/router/step-router.js +73 -0
  237. package/dist/src/scaffold/bb-ecosystem-apply.js +47 -47
  238. package/dist/src/scaffold/bb-quality-gate.js +5 -5
  239. package/dist/src/scaffold/continuation-prompt.js +60 -60
  240. package/dist/src/scaffold/init-new.js +453 -453
  241. package/dist/src/self-qa/__tests__/scenario-planner.test.js +3 -3
  242. package/dist/src/self-qa/agentic-loop.js +19 -19
  243. package/dist/src/self-qa/orchestrator.js +5 -5
  244. package/dist/src/self-qa/scenario-planner.js +1 -1
  245. package/dist/src/self-qa/spec-emitter.js +4 -4
  246. package/dist/src/storage/__tests__/migrations.test.js +2 -2
  247. package/dist/src/storage/index.d.ts +1 -1
  248. package/dist/src/storage/index.js +1 -1
  249. package/dist/src/storage/interaction-log.js +5 -5
  250. package/dist/src/storage/migrations.js +122 -122
  251. package/dist/src/storage/session-experience-store.js +4 -4
  252. package/dist/src/storage/sessions.d.ts +6 -0
  253. package/dist/src/storage/sessions.js +49 -42
  254. package/dist/src/storage/transcript-view.js +7 -1
  255. package/dist/src/storage/transcript.d.ts +1 -0
  256. package/dist/src/storage/transcript.js +55 -0
  257. package/dist/src/storage/ui-interaction-log.d.ts +17 -0
  258. package/dist/src/storage/usage.js +14 -14
  259. package/dist/src/storage/workspaces.js +12 -12
  260. package/dist/src/tools/__tests__/native-tools.test.js +6 -0
  261. package/dist/src/tools/bash.d.ts +36 -23
  262. package/dist/src/tools/bash.js +59 -301
  263. package/dist/src/tools/bash.test.js +2 -257
  264. package/dist/src/tools/file-tracker.d.ts +5 -0
  265. package/dist/src/tools/file-tracker.js +14 -0
  266. package/dist/src/tools/file.js +2 -0
  267. package/dist/src/tools/git-safety.d.ts +38 -1
  268. package/dist/src/tools/git-safety.js +94 -4
  269. package/dist/src/tools/git-safety.test.js +45 -1
  270. package/dist/src/tools/native-tools.d.ts +1 -1
  271. package/dist/src/tools/native-tools.js +56 -0
  272. package/dist/src/tools/registry-bash-empty-command.test.js +4 -3
  273. package/dist/src/tools/registry-git-safety.test.js +17 -6
  274. package/dist/src/tools/registry.d.ts +5 -0
  275. package/dist/src/tools/registry.js +185 -11
  276. package/dist/src/types/index.d.ts +7 -1
  277. package/dist/src/ui/app.d.ts +2 -1
  278. package/dist/src/ui/app.js +0 -0
  279. package/dist/src/ui/components/council-question-card.js +1 -0
  280. package/dist/src/ui/components/message-view.js +37 -3
  281. package/dist/src/ui/components/structured-response-view.js +7 -0
  282. package/dist/src/ui/components/task-list-panel.js +3 -12
  283. package/dist/src/ui/containers/chat-feed.d.ts +40 -0
  284. package/dist/src/ui/containers/chat-feed.js +66 -0
  285. package/dist/src/ui/containers/modals-layer.d.ts +87 -0
  286. package/dist/src/ui/containers/modals-layer.js +18 -0
  287. package/dist/src/ui/modals/session-picker-modal.js +14 -9
  288. package/dist/src/ui/modals/update-modal.js +2 -1
  289. package/dist/src/ui/slash/__tests__/menu-parity.test.d.ts +1 -0
  290. package/dist/src/ui/slash/__tests__/menu-parity.test.js +1 -0
  291. package/dist/src/ui/slash/__tests__/ponytail.test.d.ts +1 -0
  292. package/dist/src/ui/slash/__tests__/ponytail.test.js +37 -0
  293. package/dist/src/ui/slash/council-inspect.js +4 -4
  294. package/dist/src/ui/slash/export.js +16 -1
  295. package/dist/src/ui/slash/menu-items.js +1 -0
  296. package/dist/src/ui/slash/ponytail.d.ts +2 -0
  297. package/dist/src/ui/slash/ponytail.js +19 -0
  298. package/dist/src/ui/status-bar/store.js +0 -1
  299. package/dist/src/ui/status-bar/store.test.js +2 -2
  300. package/dist/src/ui/types.d.ts +7 -0
  301. package/dist/src/ui/use-app-logic.d.ts +26 -0
  302. package/dist/src/ui/use-app-logic.js +0 -0
  303. package/dist/src/ui/utils/relaunch.d.ts +17 -0
  304. package/dist/src/ui/utils/relaunch.js +28 -4
  305. package/dist/src/ui/utils/relaunch.test.js +50 -0
  306. package/dist/src/ui/utils/text.d.ts +11 -0
  307. package/dist/src/ui/utils/text.js +21 -1
  308. package/dist/src/ui/utils/text.test.js +25 -1
  309. package/dist/src/ui/utils/tools.js +3 -1
  310. package/dist/src/usage/cost-log.js +2 -2
  311. package/dist/src/usage/estimator.d.ts +14 -0
  312. package/dist/src/usage/estimator.js +22 -0
  313. package/dist/src/utils/__tests__/compaction-caps.test.d.ts +21 -0
  314. package/dist/src/utils/__tests__/compaction-caps.test.js +187 -0
  315. package/dist/src/utils/__tests__/llm-deadline-abort.test.d.ts +1 -0
  316. package/dist/src/utils/__tests__/llm-deadline-abort.test.js +33 -0
  317. package/dist/src/utils/clipboard-image.js +23 -23
  318. package/dist/src/utils/llm-deadline.d.ts +9 -1
  319. package/dist/src/utils/llm-deadline.js +31 -2
  320. package/dist/src/utils/permission-mode.d.ts +33 -0
  321. package/dist/src/utils/permission-mode.js +164 -3
  322. package/dist/src/utils/permission-mode.test.js +92 -1
  323. package/dist/src/utils/settings.d.ts +27 -31
  324. package/dist/src/utils/settings.js +100 -109
  325. package/dist/src/utils/side-question.js +2 -2
  326. package/dist/src/utils/skills.js +3 -3
  327. package/dist/src/verify/__tests__/coverage-parsers.test.js +30 -30
  328. package/package.json +1 -1
@@ -29,9 +29,9 @@ describe("scenario-planner", () => {
29
29
  expect(hits[0]?.line).toBe(3);
30
30
  });
31
31
  it("handles multiple hits in one file", () => {
32
- const src = `
33
- <Semantic id="one" role="textbox">
34
- <Semantic id="two" role="button">
32
+ const src = `
33
+ <Semantic id="one" role="textbox">
34
+ <Semantic id="two" role="button">
35
35
  `;
36
36
  const hits = extractSemanticHits(src, "f.tsx");
37
37
  expect(hits.map((h) => h.id)).toEqual(["one", "two"]);
@@ -128,8 +128,8 @@ export async function createLLMBrain(opts) {
128
128
  // flows without reasoning prose leaking through.
129
129
  // biome-ignore lint/suspicious/noExplicitAny: global flag is AI SDK's docs convention
130
130
  globalThis.AI_SDK_LOG_WARNINGS = false;
131
- if (process.env["MUONROI_DEEPSEEK_DISABLE_THINKING"] === undefined) {
132
- process.env["MUONROI_DEEPSEEK_DISABLE_THINKING"] = "1";
131
+ if (process.env.MUONROI_DEEPSEEK_DISABLE_THINKING === undefined) {
132
+ process.env.MUONROI_DEEPSEEK_DISABLE_THINKING = "1";
133
133
  }
134
134
  // Resolve the catalog before any model lookup — resolveModelRuntime needs it
135
135
  // loaded or it throws "not found in catalog". self-verify --agentic is a
@@ -281,35 +281,35 @@ function extractJsonCandidates(text) {
281
281
  function tryParseDecisionSlice(slice) {
282
282
  try {
283
283
  const obj = JSON.parse(slice);
284
- if (typeof obj["action"] !== "string")
284
+ if (typeof obj.action !== "string")
285
285
  return null;
286
- const action = obj["action"];
287
- const reason = typeof obj["reason"] === "string" ? obj["reason"] : "";
286
+ const action = obj.action;
287
+ const reason = typeof obj.reason === "string" ? obj.reason : "";
288
288
  switch (action) {
289
289
  case "type":
290
- if (typeof obj["text"] === "string")
291
- return { action, text: obj["text"], reason };
290
+ if (typeof obj.text === "string")
291
+ return { action, text: obj.text, reason };
292
292
  return null;
293
293
  case "press":
294
- if (typeof obj["key"] === "string")
295
- return { action, key: obj["key"], reason };
294
+ if (typeof obj.key === "string")
295
+ return { action, key: obj.key, reason };
296
296
  return null;
297
297
  case "wait_for": {
298
298
  const w = {
299
299
  action,
300
300
  reason,
301
- timeoutMs: typeof obj["timeoutMs"] === "number" ? obj["timeoutMs"] : 5_000,
301
+ timeoutMs: typeof obj.timeoutMs === "number" ? obj.timeoutMs : 5_000,
302
302
  };
303
- if (obj["idle"] === true)
303
+ if (obj.idle === true)
304
304
  w.idle = true;
305
- if (typeof obj["selector"] === "string")
306
- w.selector = obj["selector"];
307
- if (typeof obj["event"] === "string")
308
- w.event = obj["event"];
305
+ if (typeof obj.selector === "string")
306
+ w.selector = obj.selector;
307
+ if (typeof obj.event === "string")
308
+ w.event = obj.event;
309
309
  return w;
310
310
  }
311
311
  case "done": {
312
- const v = obj["verdict"];
312
+ const v = obj.verdict;
313
313
  if (v === "pass" || v === "fail" || v === "inconclusive") {
314
314
  return { action, verdict: v, reason };
315
315
  }
@@ -501,11 +501,11 @@ function wireDriver(inWrite, outRead) {
501
501
  const splitter = createLineSplitter((line) => {
502
502
  try {
503
503
  const msg = JSON.parse(line);
504
- if (msg["mode"] === "live")
504
+ if (msg.mode === "live")
505
505
  driver._ingest({ kind: "frame", frame: msg });
506
- else if (msg["t"] === "idle")
506
+ else if (msg.t === "idle")
507
507
  driver._ingest({ kind: "idle" });
508
- else if (msg["t"] === "event")
508
+ else if (msg.t === "event")
509
509
  driver._ingest({ kind: "event", event: msg });
510
510
  }
511
511
  catch { }
@@ -119,19 +119,19 @@ export async function runScenarios(scenarios, opts = {}) {
119
119
  }
120
120
  function wireDriver(inWrite, outRead) {
121
121
  const driver = createDriver({
122
- sendKey: (k) => inWrite.write(JSON.stringify({ op: "press", key: k }) + "\n"),
123
- sendType: (t) => inWrite.write(JSON.stringify({ op: "type", text: t }) + "\n"),
122
+ sendKey: (k) => inWrite.write(`${JSON.stringify({ op: "press", key: k })}\n`),
123
+ sendType: (t) => inWrite.write(`${JSON.stringify({ op: "type", text: t })}\n`),
124
124
  });
125
125
  const splitter = createLineSplitter((line) => {
126
126
  try {
127
127
  const msg = JSON.parse(line);
128
- if (msg["mode"] === "live") {
128
+ if (msg.mode === "live") {
129
129
  driver._ingest({ kind: "frame", frame: msg });
130
130
  }
131
- else if (msg["t"] === "idle") {
131
+ else if (msg.t === "idle") {
132
132
  driver._ingest({ kind: "idle" });
133
133
  }
134
- else if (msg["t"] === "event") {
134
+ else if (msg.t === "event") {
135
135
  driver._ingest({ kind: "event", event: msg });
136
136
  }
137
137
  }
@@ -99,7 +99,7 @@ function parseAttrs(chunk) {
99
99
  }
100
100
  // `isModal` may appear without `={true}` in JSX (boolean shorthand). Detect.
101
101
  if (/\bisModal\b(?!\s*=)/.test(chunk))
102
- out["isModal"] = true;
102
+ out.isModal = true;
103
103
  return out;
104
104
  }
105
105
  function buildScenariosFromHits(hits, allFiles, maxScenarios) {
@@ -95,12 +95,12 @@ function stepToCode(step) {
95
95
  case "wait_for": {
96
96
  const obj = {};
97
97
  if (step.idle)
98
- obj["idle"] = true;
98
+ obj.idle = true;
99
99
  if (step.selector)
100
- obj["selector"] = step.selector;
100
+ obj.selector = step.selector;
101
101
  if (step.event)
102
- obj["event"] = step.event;
103
- obj["timeoutMs"] = step.timeoutMs ?? 5_000;
102
+ obj.event = step.event;
103
+ obj.timeoutMs = step.timeoutMs ?? 5_000;
104
104
  return `await driver.wait_for(${JSON.stringify(obj)});`;
105
105
  }
106
106
  }
@@ -313,7 +313,7 @@ describe("DB migrations", () => {
313
313
  ]);
314
314
  raw.rows.set("usage_events", []);
315
315
  // Insert without pil_active/enrichment_delta — should default to 0
316
- db.prepare(`INSERT INTO usage_events (session_id, message_seq, source, model, input_tokens, output_tokens, total_tokens, cost_micros, created_at)
316
+ db.prepare(`INSERT INTO usage_events (session_id, message_seq, source, model, input_tokens, output_tokens, total_tokens, cost_micros, created_at)
317
317
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run("sess1", null, "orchestrator", "claude", 100, 50, 150, 0, new Date().toISOString());
318
318
  const usageRows = raw.rows.get("usage_events");
319
319
  expect(usageRows).toHaveLength(1);
@@ -346,7 +346,7 @@ describe("DB migrations", () => {
346
346
  },
347
347
  ]);
348
348
  raw.rows.set("usage_events", []);
349
- db.prepare(`INSERT INTO usage_events (session_id, message_seq, source, model, input_tokens, output_tokens, total_tokens, cost_micros, created_at, pil_active, enrichment_delta)
349
+ db.prepare(`INSERT INTO usage_events (session_id, message_seq, source, model, input_tokens, output_tokens, total_tokens, cost_micros, created_at, pil_active, enrichment_delta)
350
350
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run("sess2", null, "orchestrator", "claude", 100, 50, 150, 0, new Date().toISOString(), 1, -120);
351
351
  const usageRows = raw.rows.get("usage_events");
352
352
  expect(usageRows).toHaveLength(1);
@@ -3,7 +3,7 @@ export { loadConfig, type MuonroiConfig } from "./config.js";
3
3
  export { getDatabasePath } from "./db.js";
4
4
  export { type InteractionEventType, logInteraction } from "./interaction-log.js";
5
5
  export { SessionStore } from "./sessions.js";
6
- export { appendCompaction, appendMessages, appendSystemMessage, buildChatEntries, getNextMessageSequence, loadLatestCompaction, loadRawTranscript, loadTranscript, loadTranscriptState, markMessageCompleted, markMessageErrored, markToolCallErrored, persistMessageWriteAhead, persistToolCallWriteAhead, } from "./transcript.js";
6
+ export { appendCompaction, appendMessages, appendSystemMessage, buildChatEntries, getLastTodoWriteArgs, getNextMessageSequence, loadLatestCompaction, loadRawTranscript, loadTranscript, loadTranscriptState, markMessageCompleted, markMessageErrored, markToolCallErrored, persistMessageWriteAhead, persistToolCallWriteAhead, } from "./transcript.js";
7
7
  export { buildEffectiveTranscript, type LoadedTranscriptState, type PersistedCompaction } from "./transcript-view.js";
8
8
  export { logUIInteraction, type UIInteractionSubtype } from "./ui-interaction-log.js";
9
9
  export { getSessionTotalTokens, listSessionUsage, recordUsageEvent, type TokenUsageLike } from "./usage.js";
@@ -4,7 +4,7 @@ export { loadConfig } from "./config.js";
4
4
  export { getDatabasePath } from "./db.js";
5
5
  export { logInteraction } from "./interaction-log.js";
6
6
  export { SessionStore } from "./sessions.js";
7
- export { appendCompaction, appendMessages, appendSystemMessage, buildChatEntries, getNextMessageSequence, loadLatestCompaction, loadRawTranscript, loadTranscript, loadTranscriptState, markMessageCompleted, markMessageErrored, markToolCallErrored, persistMessageWriteAhead, persistToolCallWriteAhead, } from "./transcript.js";
7
+ export { appendCompaction, appendMessages, appendSystemMessage, buildChatEntries, getLastTodoWriteArgs, getNextMessageSequence, loadLatestCompaction, loadRawTranscript, loadTranscript, loadTranscriptState, markMessageCompleted, markMessageErrored, markToolCallErrored, persistMessageWriteAhead, persistToolCallWriteAhead, } from "./transcript.js";
8
8
  export { buildEffectiveTranscript } from "./transcript-view.js";
9
9
  export { logUIInteraction } from "./ui-interaction-log.js";
10
10
  export { getSessionTotalTokens, listSessionUsage, recordUsageEvent } from "./usage.js";
@@ -55,10 +55,10 @@ export function selectEEInjectionsForRun(runId, limit = 20) {
55
55
  try {
56
56
  const db = getDatabase();
57
57
  return db
58
- .prepare(`SELECT session_id, event_subtype, duration_ms, metadata_json, created_at
59
- FROM interaction_logs
60
- WHERE session_id = ? AND event_type = 'ee_injection'
61
- ORDER BY created_at DESC
58
+ .prepare(`SELECT session_id, event_subtype, duration_ms, metadata_json, created_at
59
+ FROM interaction_logs
60
+ WHERE session_id = ? AND event_type = 'ee_injection'
61
+ ORDER BY created_at DESC
62
62
  LIMIT ?`)
63
63
  .all(runId, limit);
64
64
  }
@@ -74,7 +74,7 @@ export function logInteraction(sessionId, eventType, metadata) {
74
74
  try {
75
75
  const db = getDatabase();
76
76
  const metadataJson = metadata?.data ? JSON.stringify(metadata.data) : null;
77
- db.prepare(`INSERT INTO interaction_logs (session_id, event_type, event_subtype, model, duration_ms, input_tokens, output_tokens, metadata_json, created_at)
77
+ db.prepare(`INSERT INTO interaction_logs (session_id, event_type, event_subtype, model, duration_ms, input_tokens, output_tokens, metadata_json, created_at)
78
78
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(sessionId, eventType, metadata?.eventSubtype ?? null, metadata?.model ?? null, metadata?.durationMs ?? null, metadata?.inputTokens ?? null, metadata?.outputTokens ?? null, metadataJson, new Date().toISOString());
79
79
  maybePruneOld();
80
80
  }
@@ -13,9 +13,9 @@ export function applyMigrations(db) {
13
13
  db.pragma("user_version = 2");
14
14
  }
15
15
  if (version < 3) {
16
- db.exec(`
17
- ALTER TABLE usage_events ADD COLUMN pil_active INTEGER NOT NULL DEFAULT 0;
18
- ALTER TABLE usage_events ADD COLUMN enrichment_delta INTEGER NOT NULL DEFAULT 0;
16
+ db.exec(`
17
+ ALTER TABLE usage_events ADD COLUMN pil_active INTEGER NOT NULL DEFAULT 0;
18
+ ALTER TABLE usage_events ADD COLUMN enrichment_delta INTEGER NOT NULL DEFAULT 0;
19
19
  `);
20
20
  db.pragma("user_version = 3");
21
21
  }
@@ -34,24 +34,24 @@ export function applyMigrations(db) {
34
34
  db.pragma("user_version = 4");
35
35
  }
36
36
  if (version < 5) {
37
- db.exec(`
38
- CREATE TABLE IF NOT EXISTS interaction_logs (
39
- id INTEGER PRIMARY KEY AUTOINCREMENT,
40
- session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
41
- event_type TEXT NOT NULL,
42
- event_subtype TEXT,
43
- model TEXT,
44
- duration_ms INTEGER,
45
- input_tokens INTEGER,
46
- output_tokens INTEGER,
47
- metadata_json TEXT,
48
- created_at TEXT NOT NULL
49
- ) STRICT;
50
-
51
- CREATE INDEX IF NOT EXISTS idx_interaction_logs_session
52
- ON interaction_logs(session_id, created_at DESC);
53
- CREATE INDEX IF NOT EXISTS idx_interaction_logs_event_type
54
- ON interaction_logs(event_type, created_at DESC);
37
+ db.exec(`
38
+ CREATE TABLE IF NOT EXISTS interaction_logs (
39
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
40
+ session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
41
+ event_type TEXT NOT NULL,
42
+ event_subtype TEXT,
43
+ model TEXT,
44
+ duration_ms INTEGER,
45
+ input_tokens INTEGER,
46
+ output_tokens INTEGER,
47
+ metadata_json TEXT,
48
+ created_at TEXT NOT NULL
49
+ ) STRICT;
50
+
51
+ CREATE INDEX IF NOT EXISTS idx_interaction_logs_session
52
+ ON interaction_logs(session_id, created_at DESC);
53
+ CREATE INDEX IF NOT EXISTS idx_interaction_logs_event_type
54
+ ON interaction_logs(event_type, created_at DESC);
55
55
  `);
56
56
  db.pragma("user_version = 5");
57
57
  }
@@ -91,110 +91,110 @@ export function applyMigrations(db) {
91
91
  migrate();
92
92
  }
93
93
  function createInitialSchema(db) {
94
- db.exec(`
95
- CREATE TABLE IF NOT EXISTS workspaces (
96
- id TEXT PRIMARY KEY,
97
- scope_key TEXT NOT NULL UNIQUE,
98
- canonical_path TEXT NOT NULL,
99
- git_root TEXT,
100
- display_name TEXT NOT NULL,
101
- last_seen_at TEXT NOT NULL
102
- ) STRICT;
103
-
104
- CREATE TABLE IF NOT EXISTS sessions (
105
- id TEXT PRIMARY KEY,
106
- workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
107
- title TEXT,
108
- model TEXT NOT NULL,
109
- mode TEXT NOT NULL,
110
- cwd_at_start TEXT NOT NULL,
111
- cwd_last TEXT NOT NULL,
112
- status TEXT NOT NULL,
113
- created_at TEXT NOT NULL,
114
- updated_at TEXT NOT NULL
115
- ) STRICT;
116
-
117
- CREATE TABLE IF NOT EXISTS messages (
118
- session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
119
- seq INTEGER NOT NULL,
120
- role TEXT NOT NULL,
121
- message_json TEXT NOT NULL,
122
- created_at TEXT NOT NULL,
123
- status TEXT,
124
- PRIMARY KEY (session_id, seq)
125
- ) STRICT;
126
-
127
- CREATE TABLE IF NOT EXISTS tool_calls (
128
- id INTEGER PRIMARY KEY AUTOINCREMENT,
129
- session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
130
- message_seq INTEGER NOT NULL,
131
- tool_call_id TEXT NOT NULL,
132
- tool_name TEXT NOT NULL,
133
- args_json TEXT NOT NULL,
134
- status TEXT NOT NULL,
135
- started_at TEXT NOT NULL,
136
- completed_at TEXT,
137
- UNIQUE(session_id, tool_call_id)
138
- ) STRICT;
139
-
140
- CREATE TABLE IF NOT EXISTS tool_results (
141
- id INTEGER PRIMARY KEY AUTOINCREMENT,
142
- tool_call_row_id INTEGER NOT NULL REFERENCES tool_calls(id) ON DELETE CASCADE,
143
- output_kind TEXT NOT NULL,
144
- output_json TEXT NOT NULL,
145
- success INTEGER NOT NULL,
146
- created_at TEXT NOT NULL
147
- ) STRICT;
148
-
149
- CREATE TABLE IF NOT EXISTS usage_events (
150
- id INTEGER PRIMARY KEY AUTOINCREMENT,
151
- session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
152
- message_seq INTEGER,
153
- source TEXT NOT NULL,
154
- model TEXT NOT NULL,
155
- input_tokens INTEGER NOT NULL DEFAULT 0,
156
- output_tokens INTEGER NOT NULL DEFAULT 0,
157
- total_tokens INTEGER NOT NULL DEFAULT 0,
158
- cost_micros INTEGER NOT NULL DEFAULT 0,
159
- created_at TEXT NOT NULL,
160
- cache_read_tokens INTEGER NOT NULL DEFAULT 0,
161
- cache_creation_tokens INTEGER NOT NULL DEFAULT 0
162
- ) STRICT;
163
-
164
- CREATE TABLE IF NOT EXISTS compactions (
165
- id INTEGER PRIMARY KEY AUTOINCREMENT,
166
- session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
167
- first_kept_seq INTEGER NOT NULL,
168
- summary TEXT NOT NULL,
169
- tokens_before INTEGER NOT NULL DEFAULT 0,
170
- created_at TEXT NOT NULL
171
- ) STRICT;
172
-
173
- CREATE INDEX IF NOT EXISTS idx_sessions_workspace_updated
174
- ON sessions(workspace_id, updated_at DESC);
175
- CREATE INDEX IF NOT EXISTS idx_messages_session_seq
176
- ON messages(session_id, seq);
177
- CREATE INDEX IF NOT EXISTS idx_tool_calls_session_seq
178
- ON tool_calls(session_id, message_seq);
179
- CREATE INDEX IF NOT EXISTS idx_usage_events_session_created
180
- ON usage_events(session_id, created_at DESC);
181
- CREATE INDEX IF NOT EXISTS idx_compactions_session_created
182
- ON compactions(session_id, created_at DESC);
94
+ db.exec(`
95
+ CREATE TABLE IF NOT EXISTS workspaces (
96
+ id TEXT PRIMARY KEY,
97
+ scope_key TEXT NOT NULL UNIQUE,
98
+ canonical_path TEXT NOT NULL,
99
+ git_root TEXT,
100
+ display_name TEXT NOT NULL,
101
+ last_seen_at TEXT NOT NULL
102
+ ) STRICT;
103
+
104
+ CREATE TABLE IF NOT EXISTS sessions (
105
+ id TEXT PRIMARY KEY,
106
+ workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
107
+ title TEXT,
108
+ model TEXT NOT NULL,
109
+ mode TEXT NOT NULL,
110
+ cwd_at_start TEXT NOT NULL,
111
+ cwd_last TEXT NOT NULL,
112
+ status TEXT NOT NULL,
113
+ created_at TEXT NOT NULL,
114
+ updated_at TEXT NOT NULL
115
+ ) STRICT;
116
+
117
+ CREATE TABLE IF NOT EXISTS messages (
118
+ session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
119
+ seq INTEGER NOT NULL,
120
+ role TEXT NOT NULL,
121
+ message_json TEXT NOT NULL,
122
+ created_at TEXT NOT NULL,
123
+ status TEXT,
124
+ PRIMARY KEY (session_id, seq)
125
+ ) STRICT;
126
+
127
+ CREATE TABLE IF NOT EXISTS tool_calls (
128
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
129
+ session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
130
+ message_seq INTEGER NOT NULL,
131
+ tool_call_id TEXT NOT NULL,
132
+ tool_name TEXT NOT NULL,
133
+ args_json TEXT NOT NULL,
134
+ status TEXT NOT NULL,
135
+ started_at TEXT NOT NULL,
136
+ completed_at TEXT,
137
+ UNIQUE(session_id, tool_call_id)
138
+ ) STRICT;
139
+
140
+ CREATE TABLE IF NOT EXISTS tool_results (
141
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
142
+ tool_call_row_id INTEGER NOT NULL REFERENCES tool_calls(id) ON DELETE CASCADE,
143
+ output_kind TEXT NOT NULL,
144
+ output_json TEXT NOT NULL,
145
+ success INTEGER NOT NULL,
146
+ created_at TEXT NOT NULL
147
+ ) STRICT;
148
+
149
+ CREATE TABLE IF NOT EXISTS usage_events (
150
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
151
+ session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
152
+ message_seq INTEGER,
153
+ source TEXT NOT NULL,
154
+ model TEXT NOT NULL,
155
+ input_tokens INTEGER NOT NULL DEFAULT 0,
156
+ output_tokens INTEGER NOT NULL DEFAULT 0,
157
+ total_tokens INTEGER NOT NULL DEFAULT 0,
158
+ cost_micros INTEGER NOT NULL DEFAULT 0,
159
+ created_at TEXT NOT NULL,
160
+ cache_read_tokens INTEGER NOT NULL DEFAULT 0,
161
+ cache_creation_tokens INTEGER NOT NULL DEFAULT 0
162
+ ) STRICT;
163
+
164
+ CREATE TABLE IF NOT EXISTS compactions (
165
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
166
+ session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
167
+ first_kept_seq INTEGER NOT NULL,
168
+ summary TEXT NOT NULL,
169
+ tokens_before INTEGER NOT NULL DEFAULT 0,
170
+ created_at TEXT NOT NULL
171
+ ) STRICT;
172
+
173
+ CREATE INDEX IF NOT EXISTS idx_sessions_workspace_updated
174
+ ON sessions(workspace_id, updated_at DESC);
175
+ CREATE INDEX IF NOT EXISTS idx_messages_session_seq
176
+ ON messages(session_id, seq);
177
+ CREATE INDEX IF NOT EXISTS idx_tool_calls_session_seq
178
+ ON tool_calls(session_id, message_seq);
179
+ CREATE INDEX IF NOT EXISTS idx_usage_events_session_created
180
+ ON usage_events(session_id, created_at DESC);
181
+ CREATE INDEX IF NOT EXISTS idx_compactions_session_created
182
+ ON compactions(session_id, created_at DESC);
183
183
  `);
184
184
  }
185
185
  function createCompactionSchema(db) {
186
- db.exec(`
187
- CREATE TABLE IF NOT EXISTS compactions (
188
- id INTEGER PRIMARY KEY AUTOINCREMENT,
189
- session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
190
- first_kept_seq INTEGER NOT NULL,
191
- summary TEXT NOT NULL,
192
- tokens_before INTEGER NOT NULL DEFAULT 0,
193
- created_at TEXT NOT NULL
194
- ) STRICT;
195
-
196
- CREATE INDEX IF NOT EXISTS idx_compactions_session_created
197
- ON compactions(session_id, created_at DESC);
186
+ db.exec(`
187
+ CREATE TABLE IF NOT EXISTS compactions (
188
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
189
+ session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
190
+ first_kept_seq INTEGER NOT NULL,
191
+ summary TEXT NOT NULL,
192
+ tokens_before INTEGER NOT NULL DEFAULT 0,
193
+ created_at TEXT NOT NULL
194
+ ) STRICT;
195
+
196
+ CREATE INDEX IF NOT EXISTS idx_compactions_session_created
197
+ ON compactions(session_id, created_at DESC);
198
198
  `);
199
199
  }
200
200
  //# sourceMappingURL=migrations.js.map
@@ -70,8 +70,8 @@ function parseCounts(json) {
70
70
  export function selectSessionExperience(sessionId) {
71
71
  try {
72
72
  const row = getDatabase()
73
- .prepare(`SELECT metadata_json FROM interaction_logs
74
- WHERE session_id = ? AND event_type = ?
73
+ .prepare(`SELECT metadata_json FROM interaction_logs
74
+ WHERE session_id = ? AND event_type = ?
75
75
  ORDER BY created_at DESC, id DESC LIMIT 1`)
76
76
  .get(sessionId, EVENT_TYPE);
77
77
  return parseCounts(row?.metadata_json ?? null);
@@ -150,8 +150,8 @@ export function computeExperienceAggregate(rows, limit = 100) {
150
150
  export function aggregateSessionExperience(limit = 100) {
151
151
  try {
152
152
  const rows = getDatabase()
153
- .prepare(`SELECT session_id, metadata_json, created_at FROM interaction_logs
154
- WHERE event_type = ?
153
+ .prepare(`SELECT session_id, metadata_json, created_at FROM interaction_logs
154
+ WHERE event_type = ?
155
155
  ORDER BY created_at DESC, id DESC`)
156
156
  .all(EVENT_TYPE);
157
157
  return computeExperienceAggregate(rows, limit);
@@ -8,6 +8,12 @@ export declare class SessionStore {
8
8
  /**
9
9
  * List recent sessions in this workspace (most recently updated first).
10
10
  * Used by the `/sessions` slash command for resume picking.
11
+ *
12
+ * Only sessions that actually have a persisted message are returned. Every
13
+ * CLI launch WITHOUT `--session` opens a fresh empty session, and test /
14
+ * harness runs leave behind title-only stubs — without this filter the picker
15
+ * fills with empty rows that resume to a blank screen, so a user picking one
16
+ * thinks resume is broken.
11
17
  */
12
18
  listRecentSessions(limit?: number): SessionInfo[];
13
19
  getLatestSession(): SessionInfo | null;