synabun 2.0.0-beta → 2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (374) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/NOTICE +5 -0
  3. package/README.md +1 -1
  4. package/THIRD-PARTY-LICENSES.md +51 -0
  5. package/benchmarks/fixtures/browser/README.md +1 -1
  6. package/benchmarks/fixtures/desktop/README.md +1 -1
  7. package/docs/whatsapp.md +2 -2
  8. package/hooks/claude-code/pre-compact.mjs +11 -0
  9. package/hooks/claude-code/prompt-submit.mjs +60 -184
  10. package/hooks/claude-code/session-start.mjs +73 -16
  11. package/hooks/claude-code/shared.mjs +20 -0
  12. package/hooks/claude-code/stop.mjs +5 -5
  13. package/launcher.mjs +40 -0
  14. package/lib/claude-hooks.js +61 -8
  15. package/lib/client-config-repair.js +4 -3
  16. package/lib/data-home-migration.js +4 -0
  17. package/lib/desktop-pwa.js +206 -0
  18. package/lib/external-tools.js +221 -0
  19. package/lib/first-launch-protection.js +5 -0
  20. package/lib/packaged-runtime.js +110 -0
  21. package/lib/start-launcher.js +1396 -0
  22. package/mcp-server/package-lock.json +2 -2
  23. package/mcp-server/package.json +1 -3
  24. package/neural-interface/i18n/en.json +1540 -154
  25. package/neural-interface/i18n/pt-BR.json +1538 -153
  26. package/neural-interface/lib/assistant-api.js +62 -6
  27. package/neural-interface/lib/assistant-brains/claude.js +4 -0
  28. package/neural-interface/lib/assistant-catalog.js +179 -27
  29. package/neural-interface/lib/assistant-config.js +31 -2
  30. package/neural-interface/lib/assistant-dispatch.js +62 -13
  31. package/neural-interface/lib/assistant-envelope.js +9 -6
  32. package/neural-interface/lib/assistant-hidden-models.js +393 -66
  33. package/neural-interface/lib/assistant-memory.js +24 -10
  34. package/neural-interface/lib/assistant-persona.js +6 -2
  35. package/neural-interface/lib/assistant-pricing.js +21 -6
  36. package/neural-interface/lib/assistant-runtime.js +181 -12
  37. package/neural-interface/lib/assistant-task-prompt.js +13 -3
  38. package/neural-interface/lib/assistant-test-density.js +142 -0
  39. package/neural-interface/lib/assistant-user-context-budgets.js +123 -0
  40. package/neural-interface/lib/assistant-user-context.js +908 -0
  41. package/neural-interface/lib/assistant-user-knowledge.js +328 -0
  42. package/neural-interface/lib/assistant-user-learn.js +404 -0
  43. package/neural-interface/lib/assistant-user-threads.js +226 -0
  44. package/neural-interface/lib/assistant-user-writer.js +181 -0
  45. package/neural-interface/lib/augmented-path.js +23 -3
  46. package/neural-interface/lib/browser-background-tab.js +134 -0
  47. package/neural-interface/lib/browser-language.js +83 -0
  48. package/neural-interface/lib/browser-screenshot.js +678 -61
  49. package/neural-interface/lib/claude-agent-bridge.js +87 -153
  50. package/neural-interface/lib/claude-executable.js +241 -0
  51. package/neural-interface/lib/claude-model-catalog.js +82 -93
  52. package/neural-interface/lib/claude-temporary.js +46 -7
  53. package/neural-interface/lib/cloudflared/install.js +533 -0
  54. package/neural-interface/lib/cloudflared/manager.js +545 -0
  55. package/neural-interface/lib/cloudflared/pins.js +115 -0
  56. package/neural-interface/lib/cloudflared/pins.json +63 -0
  57. package/neural-interface/lib/cloudflared/tunnel.js +265 -0
  58. package/neural-interface/lib/editor-completion-endpoint.js +264 -0
  59. package/neural-interface/lib/editor-completion-opencode.js +436 -0
  60. package/neural-interface/lib/editor-completion.js +714 -0
  61. package/neural-interface/lib/editor-config.js +149 -0
  62. package/neural-interface/lib/editor-files-api.js +268 -0
  63. package/neural-interface/lib/editor-git-api.js +134 -0
  64. package/neural-interface/lib/file-explorer-api.js +1039 -0
  65. package/neural-interface/lib/file-explorer-system.js +355 -0
  66. package/neural-interface/lib/file-explorer-trash.ps1 +85 -0
  67. package/neural-interface/lib/file-explorer-watch.js +239 -0
  68. package/neural-interface/lib/git-diff-api.js +103 -0
  69. package/neural-interface/lib/git-read.js +202 -0
  70. package/neural-interface/lib/greeting/api.js +89 -0
  71. package/neural-interface/lib/greeting/budgets.js +90 -0
  72. package/neural-interface/lib/greeting/engine.js +461 -0
  73. package/neural-interface/lib/greeting/facts.js +320 -0
  74. package/neural-interface/lib/greeting/sources.js +252 -0
  75. package/neural-interface/lib/greeting/writer.js +139 -0
  76. package/neural-interface/lib/http-guards.js +189 -13
  77. package/neural-interface/lib/machine-names.js +88 -0
  78. package/neural-interface/lib/memory-api.js +31 -7
  79. package/neural-interface/lib/native-binary-runtime.js +69 -337
  80. package/neural-interface/lib/native-loop-providers.js +40 -49
  81. package/neural-interface/lib/offline-page.js +54 -0
  82. package/neural-interface/lib/plugin-installer.js +4 -2
  83. package/neural-interface/lib/project-storage.js +5 -7
  84. package/neural-interface/lib/request-gate.js +589 -0
  85. package/neural-interface/lib/session-title-generator.js +5 -0
  86. package/neural-interface/lib/synabun-update-plan.js +19 -0
  87. package/neural-interface/lib/ui-blob-api.js +108 -0
  88. package/neural-interface/lib/ui-blob-store.js +68 -0
  89. package/neural-interface/package-lock.json +701 -253
  90. package/neural-interface/package.json +13 -2
  91. package/neural-interface/public/install-app.html +34 -0
  92. package/neural-interface/public/manifest.json +2 -0
  93. package/neural-interface/public/offline.html +402 -66
  94. package/neural-interface/public/onboarding.html +264 -147
  95. package/neural-interface/public/shared/agent-runtime-options.js +22 -6
  96. package/neural-interface/public/shared/assistant/asst-automation.js +286 -0
  97. package/neural-interface/public/shared/assistant/asst-brain-picker.js +312 -62
  98. package/neural-interface/public/shared/assistant/asst-composer.js +11 -1
  99. package/neural-interface/public/shared/assistant/asst-mascot.js +26 -64
  100. package/neural-interface/public/shared/assistant/asst-menu.js +12 -8
  101. package/neural-interface/public/shared/assistant/asst-panel.js +150 -28
  102. package/neural-interface/public/shared/assistant/asst-rack-styles.js +0 -3
  103. package/neural-interface/public/shared/assistant/asst-render.js +219 -67
  104. package/neural-interface/public/shared/assistant/asst-route-models.js +108 -0
  105. package/neural-interface/public/shared/assistant/asst-route.js +23 -329
  106. package/neural-interface/public/shared/assistant/asst-routes-editor.js +495 -0
  107. package/neural-interface/public/shared/assistant/asst-sanitize.js +8 -1
  108. package/neural-interface/public/shared/assistant/asst-sidepanel.js +31 -9
  109. package/neural-interface/public/shared/assistant/asst-state.js +185 -1
  110. package/neural-interface/public/shared/assistant/asst-styles.js +162 -6
  111. package/neural-interface/public/shared/blob-store.js +111 -22
  112. package/neural-interface/public/shared/cdx/cdx-panel.js +32 -11
  113. package/neural-interface/public/shared/cdx/cdx-render.js +25 -89
  114. package/neural-interface/public/shared/cdx/cdx-styles.js +36 -0
  115. package/neural-interface/public/shared/cdx/cdx-tabs.js +87 -4
  116. package/neural-interface/public/shared/command-runner-model.js +30 -0
  117. package/neural-interface/public/shared/constants.js +6 -1
  118. package/neural-interface/public/shared/cp/cp-rehydrate.js +2 -1
  119. package/neural-interface/public/shared/cp/cp-styles.js +15 -0
  120. package/neural-interface/public/shared/editor/editor-ai-logic.js +409 -0
  121. package/neural-interface/public/shared/editor/editor-ai.js +619 -0
  122. package/neural-interface/public/shared/editor/editor-commands.js +212 -0
  123. package/neural-interface/public/shared/editor/editor-compare.js +103 -0
  124. package/neural-interface/public/shared/editor/editor-completion-list.js +172 -0
  125. package/neural-interface/public/shared/editor/editor-doc.js +257 -0
  126. package/neural-interface/public/shared/editor/editor-git-logic.js +131 -0
  127. package/neural-interface/public/shared/editor/editor-git.js +95 -0
  128. package/neural-interface/public/shared/editor/editor-languages.js +156 -0
  129. package/neural-interface/public/shared/editor/editor-lint.js +229 -0
  130. package/neural-interface/public/shared/editor/editor-loader.js +51 -0
  131. package/neural-interface/public/shared/editor/editor-markdown.js +90 -0
  132. package/neural-interface/public/shared/editor/editor-menu.js +233 -0
  133. package/neural-interface/public/shared/editor/editor-minimap.js +371 -0
  134. package/neural-interface/public/shared/editor/editor-palette-logic.js +192 -0
  135. package/neural-interface/public/shared/editor/editor-palette.js +125 -0
  136. package/neural-interface/public/shared/editor/editor-panel-logic.js +288 -0
  137. package/neural-interface/public/shared/editor/editor-panel.js +2099 -0
  138. package/neural-interface/public/shared/editor/editor-prefs.js +224 -0
  139. package/neural-interface/public/shared/editor/editor-safety.js +500 -0
  140. package/neural-interface/public/shared/editor/editor-search.js +352 -0
  141. package/neural-interface/public/shared/editor/editor-statusbar.js +144 -0
  142. package/neural-interface/public/shared/editor/editor-tabs-logic.js +331 -0
  143. package/neural-interface/public/shared/editor/editor-tabs.js +233 -0
  144. package/neural-interface/public/shared/editor/editor-theme.js +244 -0
  145. package/neural-interface/public/shared/editor/editor-view.js +332 -0
  146. package/neural-interface/public/shared/explorer/fx-api.js +216 -0
  147. package/neural-interface/public/shared/explorer/fx-links.js +204 -0
  148. package/neural-interface/public/shared/explorer/fx-logic.js +537 -0
  149. package/neural-interface/public/shared/explorer/fx-main.js +865 -0
  150. package/neural-interface/public/shared/explorer/fx-names.js +87 -0
  151. package/neural-interface/public/shared/explorer/fx-ops.js +370 -0
  152. package/neural-interface/public/shared/explorer/fx-popups.js +490 -0
  153. package/neural-interface/public/shared/explorer/fx-tree.js +790 -0
  154. package/neural-interface/public/shared/file-links.js +339 -0
  155. package/neural-interface/public/shared/greeting/greeting-card.js +178 -0
  156. package/neural-interface/public/shared/greeting/greeting-view.js +148 -0
  157. package/neural-interface/public/shared/html-shell.js +169 -170
  158. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +4 -0
  159. package/neural-interface/public/shared/ocp-v2/ocp-v2-greeting.js +47 -0
  160. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +99 -17
  161. package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +7 -1
  162. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +5 -0
  163. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +40 -0
  164. package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +3 -2
  165. package/neural-interface/public/shared/pwa-install-page.js +62 -0
  166. package/neural-interface/public/shared/pwa-install.css +12 -0
  167. package/neural-interface/public/shared/pwa-install.js +127 -0
  168. package/neural-interface/public/shared/settings/settings-code-editor-pane.js +412 -0
  169. package/neural-interface/public/shared/settings/settings-code-editor.js +328 -0
  170. package/neural-interface/public/shared/settings/settings-greeting.js +133 -0
  171. package/neural-interface/public/shared/settings/settings-ia.js +18 -4
  172. package/neural-interface/public/shared/settings/settings-rules.js +160 -0
  173. package/neural-interface/public/shared/settings/settings-user-context.js +154 -0
  174. package/neural-interface/public/shared/start-bridge.js +802 -0
  175. package/neural-interface/public/shared/styleguide/sg-colors.js +5 -2
  176. package/neural-interface/public/shared/styleguide/sg-import-export.js +4 -3
  177. package/neural-interface/public/shared/styleguide/sg-kit.js +4 -1
  178. package/neural-interface/public/shared/styleguide/sg-panel.js +9 -1
  179. package/neural-interface/public/shared/styleguide/sg-typography.js +1 -0
  180. package/neural-interface/public/shared/styles.css +2219 -1117
  181. package/neural-interface/public/shared/synabun-mascot.js +20 -56
  182. package/neural-interface/public/shared/term-ready.js +307 -0
  183. package/neural-interface/public/shared/tunnel-view.js +167 -0
  184. package/neural-interface/public/shared/ui-claude-panel.js +160 -19
  185. package/neural-interface/public/shared/ui-command-runner.js +251 -468
  186. package/neural-interface/public/shared/ui-detail.js +15 -0
  187. package/neural-interface/public/shared/ui-explorer.js +22 -0
  188. package/neural-interface/public/shared/ui-file-explorer.js +481 -2496
  189. package/neural-interface/public/shared/ui-file-links.js +103 -0
  190. package/neural-interface/public/shared/ui-help.js +26 -0
  191. package/neural-interface/public/shared/ui-invite.js +126 -116
  192. package/neural-interface/public/shared/ui-judgments.js +1 -1
  193. package/neural-interface/public/shared/ui-keybinds.js +4 -0
  194. package/neural-interface/public/shared/ui-loading.js +367 -12
  195. package/neural-interface/public/shared/ui-menubar.js +21 -55
  196. package/neural-interface/public/shared/ui-native-loop-router-state.js +11 -0
  197. package/neural-interface/public/shared/ui-native-loop-router.js +15 -2
  198. package/neural-interface/public/shared/ui-navbar.js +45 -21
  199. package/neural-interface/public/shared/ui-settings.js +491 -547
  200. package/neural-interface/public/shared/ui-sidepanel-runtime.js +2 -1
  201. package/neural-interface/public/shared/ui-sync.js +16 -0
  202. package/neural-interface/public/shared/ui-terminal.js +153 -149
  203. package/neural-interface/public/shared/ui-tunnel.js +130 -0
  204. package/neural-interface/public/shared/ui-tutorial-steps.js +6 -2
  205. package/neural-interface/public/shared/ui-whiteboard.js +12 -0
  206. package/neural-interface/public/shared/ui-worker-end.js +245 -0
  207. package/neural-interface/public/shared/ui-workspaces.js +41 -27
  208. package/neural-interface/public/shared/worker-end.js +251 -0
  209. package/neural-interface/public/sw.js +3 -1
  210. package/neural-interface/public/variant/2d/main.js +2 -1
  211. package/neural-interface/public/variant/3d/main.js +2 -1
  212. package/neural-interface/public/vendor/codemirror/chunks/apl-CSDKT72Z.js +1 -0
  213. package/neural-interface/public/vendor/codemirror/chunks/asciiarmor-JYYPU5BM.js +1 -0
  214. package/neural-interface/public/vendor/codemirror/chunks/asn1-NRWCZDA6.js +1 -0
  215. package/neural-interface/public/vendor/codemirror/chunks/asterisk-5OU6D4ZQ.js +1 -0
  216. package/neural-interface/public/vendor/codemirror/chunks/brainfuck-ID4N4SYC.js +1 -0
  217. package/neural-interface/public/vendor/codemirror/chunks/chunk-4RZWGCS2.js +1 -0
  218. package/neural-interface/public/vendor/codemirror/chunks/chunk-ACTJM3JR.js +11 -0
  219. package/neural-interface/public/vendor/codemirror/chunks/chunk-S6BMAXLK.js +1 -0
  220. package/neural-interface/public/vendor/codemirror/chunks/chunk-TO2RDOHQ.js +3 -0
  221. package/neural-interface/public/vendor/codemirror/chunks/chunk-US2GMZZQ.js +13 -0
  222. package/neural-interface/public/vendor/codemirror/chunks/chunk-WYYO5ZAJ.js +1 -0
  223. package/neural-interface/public/vendor/codemirror/chunks/chunk-XALZTDJC.js +1 -0
  224. package/neural-interface/public/vendor/codemirror/chunks/chunk-YRNUTRDV.js +1 -0
  225. package/neural-interface/public/vendor/codemirror/chunks/chunk-Z3QOKH62.js +1 -0
  226. package/neural-interface/public/vendor/codemirror/chunks/clike-OWQBSOGL.js +1 -0
  227. package/neural-interface/public/vendor/codemirror/chunks/clojure-KV75UQWC.js +1 -0
  228. package/neural-interface/public/vendor/codemirror/chunks/cmake-GTEP5Y3C.js +1 -0
  229. package/neural-interface/public/vendor/codemirror/chunks/cobol-WCZ7QEGJ.js +1 -0
  230. package/neural-interface/public/vendor/codemirror/chunks/coffeescript-TGLBOT6B.js +1 -0
  231. package/neural-interface/public/vendor/codemirror/chunks/commonlisp-WVVI432V.js +1 -0
  232. package/neural-interface/public/vendor/codemirror/chunks/crystal-S6R6HLKQ.js +1 -0
  233. package/neural-interface/public/vendor/codemirror/chunks/css-PDA2RINP.js +1 -0
  234. package/neural-interface/public/vendor/codemirror/chunks/cypher-HL5QPL4C.js +1 -0
  235. package/neural-interface/public/vendor/codemirror/chunks/d-HHJH2HAJ.js +1 -0
  236. package/neural-interface/public/vendor/codemirror/chunks/diff-MN3A35BY.js +1 -0
  237. package/neural-interface/public/vendor/codemirror/chunks/dist-25SQLBVS.js +3 -0
  238. package/neural-interface/public/vendor/codemirror/chunks/dist-27ZGGJJS.js +1 -0
  239. package/neural-interface/public/vendor/codemirror/chunks/dist-4E52OJIF.js +1 -0
  240. package/neural-interface/public/vendor/codemirror/chunks/dist-6FT73XDC.js +2 -0
  241. package/neural-interface/public/vendor/codemirror/chunks/dist-BE6YGRMW.js +1 -0
  242. package/neural-interface/public/vendor/codemirror/chunks/dist-CJSGKW2O.js +1 -0
  243. package/neural-interface/public/vendor/codemirror/chunks/dist-CRPH2WLI.js +1 -0
  244. package/neural-interface/public/vendor/codemirror/chunks/dist-CTG7JEQN.js +1 -0
  245. package/neural-interface/public/vendor/codemirror/chunks/dist-I3FEVELX.js +1 -0
  246. package/neural-interface/public/vendor/codemirror/chunks/dist-IM5BBSWZ.js +1 -0
  247. package/neural-interface/public/vendor/codemirror/chunks/dist-KERUKTIF.js +1 -0
  248. package/neural-interface/public/vendor/codemirror/chunks/dist-LXTMWZAM.js +1 -0
  249. package/neural-interface/public/vendor/codemirror/chunks/dist-MABASSET.js +1 -0
  250. package/neural-interface/public/vendor/codemirror/chunks/dist-MJVBUZLL.js +3 -0
  251. package/neural-interface/public/vendor/codemirror/chunks/dist-MNB3WZVU.js +1 -0
  252. package/neural-interface/public/vendor/codemirror/chunks/dist-QYWXOE3U.js +7 -0
  253. package/neural-interface/public/vendor/codemirror/chunks/dist-TEBOFWLZ.js +1 -0
  254. package/neural-interface/public/vendor/codemirror/chunks/dist-UNXFROM3.js +1 -0
  255. package/neural-interface/public/vendor/codemirror/chunks/dist-XL2SLQO6.js +1 -0
  256. package/neural-interface/public/vendor/codemirror/chunks/dist-XO42Y3AP.js +6 -0
  257. package/neural-interface/public/vendor/codemirror/chunks/dist-Y2WWDWJK.js +1 -0
  258. package/neural-interface/public/vendor/codemirror/chunks/dist-YFEZKWMU.js +1 -0
  259. package/neural-interface/public/vendor/codemirror/chunks/dist-ZY7SWQO6.js +1 -0
  260. package/neural-interface/public/vendor/codemirror/chunks/dockerfile-3Y4R4NCH.js +1 -0
  261. package/neural-interface/public/vendor/codemirror/chunks/dtd-5343GJ4P.js +1 -0
  262. package/neural-interface/public/vendor/codemirror/chunks/dylan-FI2CXSW2.js +1 -0
  263. package/neural-interface/public/vendor/codemirror/chunks/ebnf-GNQ77YWA.js +1 -0
  264. package/neural-interface/public/vendor/codemirror/chunks/ecl-MRPUAE2L.js +1 -0
  265. package/neural-interface/public/vendor/codemirror/chunks/eiffel-DZROES27.js +1 -0
  266. package/neural-interface/public/vendor/codemirror/chunks/elm-4KICRFKQ.js +1 -0
  267. package/neural-interface/public/vendor/codemirror/chunks/erlang-3IHYC263.js +1 -0
  268. package/neural-interface/public/vendor/codemirror/chunks/factor-C6D3E5UK.js +1 -0
  269. package/neural-interface/public/vendor/codemirror/chunks/fcl-VYTWUJMI.js +1 -0
  270. package/neural-interface/public/vendor/codemirror/chunks/forth-ZBO2EH5M.js +1 -0
  271. package/neural-interface/public/vendor/codemirror/chunks/fortran-5NDCRWIK.js +1 -0
  272. package/neural-interface/public/vendor/codemirror/chunks/gas-SKRMOXFP.js +1 -0
  273. package/neural-interface/public/vendor/codemirror/chunks/gherkin-L45YXZLW.js +1 -0
  274. package/neural-interface/public/vendor/codemirror/chunks/groovy-GLPTLN44.js +1 -0
  275. package/neural-interface/public/vendor/codemirror/chunks/haskell-E7NF7P4Y.js +1 -0
  276. package/neural-interface/public/vendor/codemirror/chunks/haxe-K2NVDOB6.js +1 -0
  277. package/neural-interface/public/vendor/codemirror/chunks/http-Q6DRQIJB.js +1 -0
  278. package/neural-interface/public/vendor/codemirror/chunks/idl-MZYNJVLN.js +1 -0
  279. package/neural-interface/public/vendor/codemirror/chunks/javascript-6YRYK2HR.js +1 -0
  280. package/neural-interface/public/vendor/codemirror/chunks/julia-HXEL2T5G.js +1 -0
  281. package/neural-interface/public/vendor/codemirror/chunks/livescript-MV7CI2JZ.js +1 -0
  282. package/neural-interface/public/vendor/codemirror/chunks/lua-E36NHOOD.js +1 -0
  283. package/neural-interface/public/vendor/codemirror/chunks/mathematica-3XOZZCMC.js +1 -0
  284. package/neural-interface/public/vendor/codemirror/chunks/mbox-ODYGFKS7.js +1 -0
  285. package/neural-interface/public/vendor/codemirror/chunks/mirc-WB43AWF5.js +1 -0
  286. package/neural-interface/public/vendor/codemirror/chunks/mllike-ZT6ET7ZH.js +1 -0
  287. package/neural-interface/public/vendor/codemirror/chunks/modelica-LLMZPFGA.js +1 -0
  288. package/neural-interface/public/vendor/codemirror/chunks/mscgen-2OPNNYFH.js +1 -0
  289. package/neural-interface/public/vendor/codemirror/chunks/mumps-6P3HWJH6.js +1 -0
  290. package/neural-interface/public/vendor/codemirror/chunks/nginx-TCGKQTRW.js +1 -0
  291. package/neural-interface/public/vendor/codemirror/chunks/nsis-ATIGIXTJ.js +1 -0
  292. package/neural-interface/public/vendor/codemirror/chunks/ntriples-5PLBI5OV.js +1 -0
  293. package/neural-interface/public/vendor/codemirror/chunks/octave-QF2S3NL6.js +1 -0
  294. package/neural-interface/public/vendor/codemirror/chunks/oz-JFIVFFH2.js +1 -0
  295. package/neural-interface/public/vendor/codemirror/chunks/pascal-JG6SW76V.js +1 -0
  296. package/neural-interface/public/vendor/codemirror/chunks/perl-4B3IWVVO.js +1 -0
  297. package/neural-interface/public/vendor/codemirror/chunks/pig-ABEBH4MI.js +1 -0
  298. package/neural-interface/public/vendor/codemirror/chunks/powershell-H32XE7TL.js +1 -0
  299. package/neural-interface/public/vendor/codemirror/chunks/properties-NN644MMA.js +1 -0
  300. package/neural-interface/public/vendor/codemirror/chunks/protobuf-YKWQK2J3.js +1 -0
  301. package/neural-interface/public/vendor/codemirror/chunks/pug-RIYXEKFW.js +1 -0
  302. package/neural-interface/public/vendor/codemirror/chunks/puppet-JZQ5WPEV.js +1 -0
  303. package/neural-interface/public/vendor/codemirror/chunks/python-EBCGGHAC.js +1 -0
  304. package/neural-interface/public/vendor/codemirror/chunks/q-5UMH2YQY.js +1 -0
  305. package/neural-interface/public/vendor/codemirror/chunks/r-7XMGG453.js +1 -0
  306. package/neural-interface/public/vendor/codemirror/chunks/rpm-IEV7TSLR.js +1 -0
  307. package/neural-interface/public/vendor/codemirror/chunks/ruby-T4SPFPNM.js +1 -0
  308. package/neural-interface/public/vendor/codemirror/chunks/sas-GEDX67ET.js +1 -0
  309. package/neural-interface/public/vendor/codemirror/chunks/scheme-FTLOWKPC.js +1 -0
  310. package/neural-interface/public/vendor/codemirror/chunks/shell-HUFRKFSJ.js +1 -0
  311. package/neural-interface/public/vendor/codemirror/chunks/sieve-P5QUDVYO.js +1 -0
  312. package/neural-interface/public/vendor/codemirror/chunks/smalltalk-2SORJNQI.js +1 -0
  313. package/neural-interface/public/vendor/codemirror/chunks/solr-M22TGAR5.js +1 -0
  314. package/neural-interface/public/vendor/codemirror/chunks/sparql-4M3KL752.js +1 -0
  315. package/neural-interface/public/vendor/codemirror/chunks/spreadsheet-3K23LA4N.js +1 -0
  316. package/neural-interface/public/vendor/codemirror/chunks/sql-VHRFMUBI.js +1 -0
  317. package/neural-interface/public/vendor/codemirror/chunks/stex-QZDAQUY2.js +1 -0
  318. package/neural-interface/public/vendor/codemirror/chunks/stylus-7ZDKAKBD.js +1 -0
  319. package/neural-interface/public/vendor/codemirror/chunks/swift-WCLCLGMR.js +1 -0
  320. package/neural-interface/public/vendor/codemirror/chunks/tcl-JLMU6WOK.js +1 -0
  321. package/neural-interface/public/vendor/codemirror/chunks/textile-4CHDKZ4T.js +1 -0
  322. package/neural-interface/public/vendor/codemirror/chunks/tiddlywiki-DKMCZZQ4.js +1 -0
  323. package/neural-interface/public/vendor/codemirror/chunks/tiki-F4JIG36Q.js +1 -0
  324. package/neural-interface/public/vendor/codemirror/chunks/toml-BHMHTIM2.js +1 -0
  325. package/neural-interface/public/vendor/codemirror/chunks/troff-YQ2KV5NT.js +1 -0
  326. package/neural-interface/public/vendor/codemirror/chunks/ttcn-ZHRCVFJY.js +1 -0
  327. package/neural-interface/public/vendor/codemirror/chunks/ttcn-cfg-KJOVTY4X.js +1 -0
  328. package/neural-interface/public/vendor/codemirror/chunks/turtle-535P5N6I.js +1 -0
  329. package/neural-interface/public/vendor/codemirror/chunks/vb-76UMQHOT.js +1 -0
  330. package/neural-interface/public/vendor/codemirror/chunks/vbscript-CGNDTK6Z.js +1 -0
  331. package/neural-interface/public/vendor/codemirror/chunks/velocity-VSJDO5T5.js +1 -0
  332. package/neural-interface/public/vendor/codemirror/chunks/verilog-4T6ETXIP.js +1 -0
  333. package/neural-interface/public/vendor/codemirror/chunks/vhdl-T7FNAXUN.js +1 -0
  334. package/neural-interface/public/vendor/codemirror/chunks/webidl-P6MJSJ6J.js +1 -0
  335. package/neural-interface/public/vendor/codemirror/chunks/xquery-UOVILRGN.js +1 -0
  336. package/neural-interface/public/vendor/codemirror/chunks/yacas-CV2APROL.js +1 -0
  337. package/neural-interface/public/vendor/codemirror/chunks/z80-3KFNVM4M.js +1 -0
  338. package/neural-interface/public/vendor/codemirror/codemirror-6.43.14-75f05e67.min.js +2 -0
  339. package/neural-interface/public/vendor/codemirror/manifest.json +60 -0
  340. package/neural-interface/scripts/build-vendor.mjs +78 -2
  341. package/neural-interface/scripts/rebuild-pty.js +15 -12
  342. package/neural-interface/scripts/vendor-codemirror-entry.js +121 -0
  343. package/neural-interface/server.js +1092 -1212
  344. package/neural-interface/templates/rulesets/README.md +1 -1
  345. package/package.json +13 -7
  346. package/postinstall.js +11 -81
  347. package/setup.js +111 -6
  348. package/benchmarks/browser-live-results.json +0 -79
  349. package/benchmarks/browser-v2-results.json +0 -258
  350. package/docs/browser-v2.md +0 -109
  351. package/docs/hook-integrity.md +0 -89
  352. package/docs/judgments.md +0 -182
  353. package/docs/style-guide.md +0 -246
  354. package/neural-interface/lib/codex-capabilities.d.ts +0 -41
  355. package/neural-interface/public/category-logos/claude.svg +0 -1
  356. package/neural-interface/public/category-logos/gemini-color.svg +0 -1
  357. package/neural-interface/public/category-logos/openai.svg +0 -1
  358. package/neural-interface/public/category-logos/synabun.png +0 -0
  359. package/neural-interface/public/claude.svg +0 -1
  360. package/neural-interface/public/gallery.svg +0 -6
  361. package/neural-interface/public/leonardoai.svg +0 -1
  362. package/neural-interface/public/mcp.svg +0 -4
  363. package/neural-interface/public/opencode-logo-dark-square.svg +0 -1
  364. package/neural-interface/public/pin-svgrepo-com.svg +0 -25
  365. package/neural-interface/public/sessionicon.svg +0 -8
  366. package/neural-interface/public/toolbar-album.svg +0 -8
  367. package/neural-interface/public/toolbar-question.svg +0 -6
  368. package/neural-interface/public/toolbar-sessions.svg +0 -6
  369. package/neural-interface/scripts/codex-protocol-fixture.mjs +0 -83
  370. package/scripts/audit-claude-hook-usage.mjs +0 -12
  371. package/scripts/audit-memory-duplicates.mjs +0 -44
  372. package/scripts/measure-claude-hook-overhead.mjs +0 -77
  373. package/scripts/recover-user-config.mjs +0 -254
  374. package/skills/synabun/synabunicon.png +0 -0
@@ -130,6 +130,14 @@ export function clampEffortId(effort, ids) {
130
130
 
131
131
  export const CODEX_EFFORT_VALUE_IDS = EFFORT_LEVELS_BY_PROFILE.codex.map(e => e.id);
132
132
 
133
+ // The Claude and Codex lists are asked again once a copy is this old (the server
134
+ // answers from its own discovery cache, so it is a local round trip): a page that
135
+ // stays open for days must not keep the list it loaded with. OpenCode's copy is
136
+ // dropped by its change events instead (`ocp-providers-changed`): its list is large.
137
+ const MODEL_LIST_MAX_AGE_MS = 60_000;
138
+ const _modelListAt = new Map();
139
+ function modelListIsFresh(key) { return Date.now() - (_modelListAt.get(key) || 0) < MODEL_LIST_MAX_AGE_MS; }
140
+
133
141
  const _codexModelsCache = new Map();
134
142
  const _codexModelsLoading = new Map();
135
143
  let _opencodeModelsCache = null;
@@ -268,7 +276,7 @@ export function mergeCodexModelIds(models = []) {
268
276
 
269
277
  export async function fetchCodexModels(force = false, accountId = 'default') {
270
278
  const account = String(accountId || 'default');
271
- if (!force && _codexModelsCache.has(account)) return _codexModelsCache.get(account);
279
+ if (!force && _codexModelsCache.has(account) && modelListIsFresh(`codex:${account}`)) return _codexModelsCache.get(account);
272
280
  if (_codexModelsLoading.has(account)) return _codexModelsLoading.get(account);
273
281
  const loading = (async () => {
274
282
  try {
@@ -278,6 +286,7 @@ export async function fetchCodexModels(force = false, accountId = 'default') {
278
286
  const models = Array.isArray(data?.models) ? data.models : [];
279
287
  const normalized = mergeCodexModelOptions(models, { fallback: false });
280
288
  _codexModelsCache.set(account, normalized);
289
+ _modelListAt.set(`codex:${account}`, Date.now());
281
290
  return normalized;
282
291
  } catch {
283
292
  const previous = _codexModelsCache.get(account) || [];
@@ -455,19 +464,25 @@ export async function fetchOpencodeModels(force = false) {
455
464
  // Live model list from the installed Claude Code CLI. Falls back to the static
456
465
  // list so the picker still renders when the CLI is missing or discovery fails.
457
466
  export async function fetchClaudeModels(force = false) {
458
- if (!force && _claudeModelsCache && _claudeModelsCache.length) return _claudeModelsCache;
467
+ if (!force && _claudeModelsCache && _claudeModelsCache.length && modelListIsFresh('claude-code')) return _claudeModelsCache;
459
468
  if (_claudeModelsLoading) return _claudeModelsLoading;
469
+ // A list the CLI verified is never traded for the unverified stand-in: a discovery
470
+ // that fails once (mid-update, mid-restart) must not strip a working picker.
471
+ const verified = () => (_claudeModelsCache?.length && _claudeModelsCache.some(m => m.catalogSource !== 'fallback') ? _claudeModelsCache : null);
460
472
  _claudeModelsLoading = (async () => {
461
473
  try {
462
474
  const resp = await fetch(`/api/claude/models${force ? '?refresh=1' : ''}`);
463
475
  const data = await resp.json().catch(() => ({}));
464
476
  const models = Array.isArray(data?.models) ? data.models : [];
465
- _claudeModelsCache = models.length
466
- ? models.map(model => ({ ...model, catalogSource: data?.source || 'cli' }))
467
- : [...CLAUDE_FALLBACK_MODELS];
477
+ if (models.length && data?.source !== 'fallback') {
478
+ _claudeModelsCache = models.map(model => ({ ...model, catalogSource: data?.source || 'cli' }));
479
+ _modelListAt.set('claude-code', Date.now());
480
+ } else {
481
+ _claudeModelsCache = verified() || (models.length ? models.map(model => ({ ...model, catalogSource: 'fallback' })) : [...CLAUDE_FALLBACK_MODELS]);
482
+ }
468
483
  return _claudeModelsCache;
469
484
  } catch {
470
- _claudeModelsCache = [...CLAUDE_FALLBACK_MODELS];
485
+ _claudeModelsCache = verified() || [...CLAUDE_FALLBACK_MODELS];
471
486
  return _claudeModelsCache;
472
487
  } finally {
473
488
  _claudeModelsLoading = null;
@@ -585,6 +600,7 @@ export function clearRuntimeOptionCaches() {
585
600
  _codexModelsLoading.clear();
586
601
  _opencodeModelsCache = null;
587
602
  _claudeModelsCache = null;
603
+ _modelListAt.clear();
588
604
  _mcpProfilePresets = null;
589
605
  _claudeAccountsCache = null;
590
606
  _opencodeAgentsCache = null;
@@ -0,0 +1,286 @@
1
+ // ═══════════════════════════════════════════
2
+ // SynaBun — Assistant: the automation trace, as words (DOM-free)
3
+ // ═══════════════════════════════════════════
4
+ //
5
+ // One `synabun.automation` event per turn phase (lib/assistant-user-context.js)
6
+ // says what the harness did for the turn: what it put into the brain's context
7
+ // (the standing digest, the per-turn notes, the related memories), what it held
8
+ // back and why, and what it learned from the user's own words afterwards.
9
+ // This module turns one snapshot into the lines asst-render.js draws: nothing
10
+ // here touches the DOM, so it is unit-tested in Node.
11
+ //
12
+ // AUTOMATION_COPY is the English; `assistant.automation.*` in i18n/*.json must
13
+ // equal it (tests/assistant-automation-view.test.mjs).
14
+
15
+ export const AUTOMATION_EVENT = 'synabun.automation';
16
+
17
+ export const AUTOMATION_COPY = Object.freeze({
18
+ title: 'Automation',
19
+ 'sum.turn': '{n} tok this turn',
20
+ 'sum.standing': '{n} standing',
21
+ 'sum.none': 'nothing injected',
22
+ 'state.waiting': 'learning after the reply',
23
+ 'state.running': 'learning…',
24
+ 'state.learned': 'learned 1 thing',
25
+ 'state.confirmed': 'confirmed 1 thing',
26
+ 'state.replaced': 'replaced 1 thing',
27
+ 'group.injected': 'Injected',
28
+ 'group.withheld': 'Withheld',
29
+ 'group.learning': 'Learning',
30
+ 'group.session': 'This conversation',
31
+ 'tier.greeting': 'Greeting',
32
+ 'tier.digest': 'Knowledge digest',
33
+ 'tier.last-thread': 'Last conversation',
34
+ 'tier.environment': 'Environment',
35
+ 'tier.open-item': 'Open item',
36
+ 'tier.cue': 'Knowledge cue',
37
+ 'tier.delta': 'New knowledge',
38
+ 'tier.recall': 'Related memories',
39
+ 'tier.knowledge': 'Knowledge of you',
40
+ 'tier.nudges': 'Recent-interaction nudges',
41
+ 'tier.turn': 'Per-turn notes',
42
+ tok: '{n} tok',
43
+ 'meta.standing': 'system slot · frozen {time}',
44
+ 'meta.standingRef': 'already in the system slot, not resent',
45
+ 'meta.memories': '{n} memories',
46
+ 'meta.memory': '1 memory',
47
+ 'meta.alreadyPresent': 'already supplied earlier',
48
+ 'meta.budget': 'budget {used}/{max} tok',
49
+ 'meta.greetingWriter': 'said at session open · written ahead by {model}',
50
+ 'meta.greetingFallback': 'said at session open · from the records, no model',
51
+ 'reason.layer-off': 'switched off in Settings',
52
+ 'reason.nothing-known': 'nothing learned yet',
53
+ 'reason.no-recent-thread': 'no recent conversation to mention',
54
+ 'reason.in-greeting': 'already said in the greeting',
55
+ 'reason.budget': 'over the turn budget, kept for a later turn',
56
+ 'reason.not-ranked': 'not ranked relevant by Jev',
57
+ 'reason.in-digest': 'already in the digest',
58
+ 'reason.already-told': 'already told in this conversation',
59
+ 'reason.replaced': 'replaced by a newer statement',
60
+ 'reason.one-per-turn': 'one cue per turn',
61
+ 'reason.unusable': 'no usable statement',
62
+ 'reason.not-delivered': 'the turn ended before the notes could be delivered',
63
+ 'reason.trivial': 'trivial prompt',
64
+ 'reason.pattern': 'a command or an acknowledgement',
65
+ 'reason.judged': 'Jev: memory would not change the reply',
66
+ 'reason.nothing-retrieved': 'nothing relevant found',
67
+ 'reason.disabled': 'automatic recall is off',
68
+ 'reason.error': 'the search failed',
69
+ 'reason.system': 'not a prompt of yours',
70
+ 'learn.waiting': 'Your words are judged once the reply is done.',
71
+ 'learn.running': 'Jev is reading what you typed…',
72
+ 'learn.skipped': 'Not judged: {reason}.',
73
+ 'learn.cues': 'Cue words: {cues}',
74
+ 'learn.judged': 'Jev: lasting signal {p} · {facet} · {scope}',
75
+ 'learn.matched': 'Matches: {statement}',
76
+ 'learn.contradicts': 'Contradicts: {statement}',
77
+ 'learn.created': 'Learned: {statement}',
78
+ 'learn.updated': 'Confirmed (seen {n}×): {statement}',
79
+ 'learn.superseded': 'Replaced “{old}” with: {statement}',
80
+ 'learn.none': 'Nothing stored: {reason}.',
81
+ 'learn.evidence': 'Evidence: “{quote}”',
82
+ 'learn.writer': 'Written by {engine}',
83
+ 'learn.writerOwn': 'Kept as your own sentence ({reason})',
84
+ 'learn.writerKept': 'Statement kept as recorded',
85
+ 'learn.cost': '{requests} Jev requests · {tokens} tok · {cost}',
86
+ 'learn.scope.global': 'all projects',
87
+ 'skip.no-cue': 'no always / never / from-now-on wording',
88
+ 'skip.trivial': 'trivial prompt',
89
+ 'skip.short': 'too short',
90
+ 'skip.origin': 'not typed by you',
91
+ 'skip.untrusted': 'forwarded content',
92
+ 'skip.no-typed-text': 'only attachments or pasted text',
93
+ 'skip.seen': 'the same words were already judged',
94
+ 'skip.gate-cap': 'this conversation reached its limit of judgments',
95
+ 'skip.write-cap': 'this conversation reached its limit of learned facts',
96
+ 'skip.layer-off': 'Knowledge of you is off',
97
+ 'skip.system': 'not a prompt of yours',
98
+ 'none.not-durable': 'not a lasting preference',
99
+ 'none.no-answer': 'Jev did not answer',
100
+ 'none.jev-unavailable': 'Jev is off or has no key',
101
+ 'none.duplicate': 'memory already states this',
102
+ 'none.write-cap': 'this conversation reached its limit of learned facts',
103
+ 'none.no-evidence': 'no sentence carried it',
104
+ 'none.no-statement': 'no usable statement',
105
+ 'none.write-error': 'the memory write failed',
106
+ 'none.no-store': 'memory is not available',
107
+ 'none.error': 'the learning step failed',
108
+ 'writer.unverified': 'the rewrite could not be checked',
109
+ 'writer.not-faithful': 'the rewrite added something',
110
+ 'writer.no-writer': 'no writer model',
111
+ 'writer.writer-cap': 'writer limit reached',
112
+ 'writer.other': 'the writer failed',
113
+ totals: 'Judged {gate}/{gateCap} · writer {writer}/{writerCap} · learned {writes}/{writeCap} · {tokens} tok injected over {turns} turns · {cost}',
114
+ open: 'Open memory',
115
+ });
116
+
117
+ const fill = (text, params) => (params ? String(text).replace(/\{(\w+)\}/g, (_, key) => (params[key] != null ? params[key] : `{${key}}`)) : String(text));
118
+
119
+ /** The translator: `t(key, params)` when it knows the key, else the English above. */
120
+ export function automationText(t, key, params) {
121
+ const full = `assistant.automation.${key}`;
122
+ let value;
123
+ try { value = typeof t === 'function' ? t(full, params) : undefined; } catch { value = undefined; }
124
+ if (typeof value === 'string' && value && value !== full) return value;
125
+ const fallback = AUTOMATION_COPY[key];
126
+ return fallback == null ? key : fill(fallback, params);
127
+ }
128
+
129
+ const num = (value) => (Number.isFinite(Number(value)) ? Number(value) : 0);
130
+
131
+ /** A dollar amount small enough to matter: 5 decimals under a cent, 2 above. */
132
+ export function formatUsd(value) {
133
+ const n = num(value);
134
+ if (n <= 0) return '$0';
135
+ return n < 0.01 ? `$${n.toFixed(5).replace(/0+$/, '').replace(/\.$/, '')}` : `$${n.toFixed(2)}`;
136
+ }
137
+ const pct = (value) => `${Math.round(num(value) * 100)}%`;
138
+ const defaultTime = (iso) => {
139
+ const ms = Date.parse(iso ?? '');
140
+ if (!Number.isFinite(ms)) return '';
141
+ try { return new Date(ms).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); } catch { return ''; }
142
+ };
143
+
144
+ function writerLine(tx, learning) {
145
+ const action = learning.action || {};
146
+ const writer = learning.writer || {};
147
+ if (!action.engine) return null;
148
+ if (action.engine === 'kept') return tx('learn.writerKept');
149
+ if (action.engine === 'user-sentence') {
150
+ const code = writer.reason && AUTOMATION_COPY[`writer.${writer.reason}`] ? writer.reason : 'other';
151
+ return tx('learn.writerOwn', { reason: tx(`writer.${code}`) });
152
+ }
153
+ return tx('learn.writer', { engine: writer.verified != null ? `${action.engine} · ${pct(writer.verified)}` : action.engine });
154
+ }
155
+
156
+ /**
157
+ * One snapshot → what the trace row shows.
158
+ * → { traceId, phase, summary, state, tone, groups:[{ key, title, rows:[{ label, meta, text, pre, ids, tone }] }] }
159
+ * tone: '' | 'busy' | 'learned'. `pre`: `text` is exact injected text (keep its line breaks).
160
+ */
161
+ export function automationView(ev = {}, { t = null, formatTime = defaultTime } = {}) {
162
+ const tx = (key, params) => automationText(t, key, params);
163
+ const tokens = ev.tokens || {};
164
+ const injected = Array.isArray(ev.injected) ? ev.injected : [];
165
+ const withheld = Array.isArray(ev.withheld) ? ev.withheld : [];
166
+ const learning = ev.learning || {};
167
+ const totals = ev.totals || {};
168
+ const tok = (n) => tx('tok', { n: num(n) });
169
+ const tier = (code) => tx(`tier.${AUTOMATION_COPY[`tier.${code}`] ? code : 'turn'}`);
170
+
171
+ // ── the one-line summary ──
172
+ const turnTokens = num(tokens.turn) + num(tokens.recall);
173
+ const parts = [];
174
+ if (turnTokens > 0) parts.push(tx('sum.turn', { n: turnTokens }));
175
+ if (num(tokens.digest) > 0) parts.push(tx('sum.standing', { n: num(tokens.digest) }));
176
+ const summary = parts.length ? parts.join(' · ') : tx('sum.none');
177
+ let state = '';
178
+ let tone = '';
179
+ const action = learning.action || null;
180
+ if (learning.state === 'waiting') { state = tx('state.waiting'); tone = 'busy'; }
181
+ else if (learning.state === 'running') { state = tx('state.running'); tone = 'busy'; }
182
+ else if (learning.state === 'done' && action && action.type && action.type !== 'none') {
183
+ state = tx(action.type === 'update' ? 'state.confirmed' : action.type === 'supersede' ? 'state.replaced' : 'state.learned');
184
+ tone = 'learned';
185
+ }
186
+
187
+ const groups = [];
188
+ // ── injected ──
189
+ const injectedRows = injected.map((item) => {
190
+ const meta = [tok(item.tokens)];
191
+ if (item.tier === 'digest') meta.push(item.text ? tx('meta.standing', { time: formatTime(item.frozenAt) }) : tx('meta.standingRef'));
192
+ // The greeting: who wrote it and what that cost (the records it was built from are the links below it).
193
+ if (item.tier === 'greeting') {
194
+ meta.push(item.source === 'writer' ? tx('meta.greetingWriter', { model: item.model || 'Claude' }) : tx('meta.greetingFallback'));
195
+ if (item.source === 'writer' && Number(item.costUsd) > 0) meta.push(formatUsd(item.costUsd));
196
+ }
197
+ if (item.tier === 'recall') {
198
+ const n = Array.isArray(item.ids) ? item.ids.length : 0;
199
+ meta.push(n === 1 ? tx('meta.memory') : tx('meta.memories', { n }));
200
+ if (item.alreadyPresent) meta.push(tx('meta.alreadyPresent'));
201
+ }
202
+ return { label: tier(item.tier), meta: meta.filter(Boolean).join(' · '), text: item.text || '', pre: item.tier === 'digest' && !!item.text, ids: item.tier === 'recall' ? [] : (Array.isArray(item.ids) ? item.ids : []), tone: '' };
203
+ });
204
+ if (injectedRows.length) {
205
+ if (num(tokens.budget) > 0) injectedRows.push({ label: tier('turn'), meta: tx('meta.budget', { used: num(tokens.turn), max: num(tokens.budget) }), text: '', pre: false, ids: [], tone: 'muted' });
206
+ groups.push({ key: 'injected', title: tx('group.injected'), rows: injectedRows });
207
+ }
208
+ // ── withheld ──
209
+ if (withheld.length) {
210
+ groups.push({
211
+ key: 'withheld', title: tx('group.withheld'),
212
+ rows: withheld.map((item) => ({
213
+ label: tier(item.tier), meta: tx(`reason.${AUTOMATION_COPY[`reason.${item.reason}`] ? item.reason : 'unusable'}`),
214
+ text: item.text || '', pre: false, ids: Array.isArray(item.ids) ? item.ids : [], tone: 'muted',
215
+ })),
216
+ });
217
+ }
218
+ // ── learning ──
219
+ const learnRows = [];
220
+ const pre = learning.prefilter || {};
221
+ if (learning.state === 'skipped') {
222
+ learnRows.push({ label: '', meta: '', text: tx('learn.skipped', { reason: tx(`skip.${AUTOMATION_COPY[`skip.${pre.reason}`] ? pre.reason : 'no-cue'}`) }), pre: false, ids: [], tone: 'muted' });
223
+ } else if (learning.state === 'waiting' || learning.state === 'running') {
224
+ if (Array.isArray(pre.cues) && pre.cues.length) learnRows.push({ label: '', meta: '', text: tx('learn.cues', { cues: pre.cues.join(', ') }), pre: false, ids: [], tone: '' });
225
+ learnRows.push({ label: '', meta: '', text: tx(learning.state === 'waiting' ? 'learn.waiting' : 'learn.running'), pre: false, ids: [], tone: 'muted' });
226
+ } else if (learning.state === 'done') {
227
+ const gate = learning.gate || null;
228
+ if (Array.isArray(pre.cues) && pre.cues.length) learnRows.push({ label: '', meta: '', text: tx('learn.cues', { cues: pre.cues.join(', ') }), pre: false, ids: [], tone: '' });
229
+ if (gate?.answered) {
230
+ learnRows.push({ label: '', meta: '', text: tx('learn.judged', { p: pct(gate.durable), facet: gate.facet || '', scope: !gate.scope || gate.scope === 'global' ? tx('learn.scope.global') : gate.scope }), pre: false, ids: [], tone: '' });
231
+ if (gate.contradicts) learnRows.push({ label: '', meta: pct(gate.contradicts.probability), text: tx('learn.contradicts', { statement: gate.contradicts.statement }), pre: false, ids: [gate.contradicts.id].filter(Boolean), tone: '' });
232
+ else if (gate.match) learnRows.push({ label: '', meta: pct(gate.match.confidence), text: tx('learn.matched', { statement: gate.match.statement }), pre: false, ids: [gate.match.id].filter(Boolean), tone: '' });
233
+ }
234
+ const act = action || { type: 'none', reason: 'error' };
235
+ if (act.type === 'none') {
236
+ const code = AUTOMATION_COPY[`none.${act.reason}`] ? act.reason : 'error';
237
+ const extra = act.reason === 'not-durable' && gate?.durable != null ? ` (${pct(gate.durable)})` : '';
238
+ learnRows.push({ label: '', meta: '', text: tx('learn.none', { reason: `${tx(`none.${code}`)}${extra}` }), pre: false, ids: [act.duplicateOf].filter(Boolean), tone: 'muted' });
239
+ } else {
240
+ const text = act.type === 'update' ? tx('learn.updated', { n: num(act.seen) || 2, statement: act.statement })
241
+ : act.type === 'supersede' ? tx('learn.superseded', { old: act.replaced || '', statement: act.statement })
242
+ : tx('learn.created', { statement: act.statement });
243
+ learnRows.push({ label: '', meta: [act.facet, !act.scope || act.scope === 'global' ? tx('learn.scope.global') : act.scope].filter(Boolean).join(' · '), text, pre: false, ids: [act.memoryId, act.supersedes].filter(Boolean), tone: 'learned' });
244
+ if (act.evidence) learnRows.push({ label: '', meta: '', text: tx('learn.evidence', { quote: act.evidence }), pre: false, ids: [], tone: '' });
245
+ const written = writerLine(tx, learning);
246
+ if (written) learnRows.push({ label: '', meta: '', text: written, pre: false, ids: [], tone: 'muted' });
247
+ }
248
+ const cost = learning.cost || {};
249
+ if (num(cost.jevRequests) > 0 || num(cost.writerUsd) > 0) {
250
+ const writerTokens = cost.writerTokens ? num(cost.writerTokens.input) + num(cost.writerTokens.output) + num(cost.writerTokens.cacheRead) + num(cost.writerTokens.cacheWrite) : 0;
251
+ learnRows.push({ label: '', meta: '', text: tx('learn.cost', { requests: num(cost.jevRequests), tokens: num(cost.jevInputTokens) + num(cost.jevOutputTokens) + writerTokens, cost: formatUsd(cost.totalUsd) }), pre: false, ids: [], tone: 'muted' });
252
+ }
253
+ }
254
+ if (learnRows.length) groups.push({ key: 'learning', title: tx('group.learning'), rows: learnRows });
255
+ // ── session totals ──
256
+ if (num(totals.turns) > 0) {
257
+ groups.push({
258
+ key: 'session', title: tx('group.session'),
259
+ rows: [{ label: '', meta: '', text: tx('totals', { gate: num(totals.gate), gateCap: num(totals.gateCap), writer: num(totals.writer), writerCap: num(totals.writerCap), writes: num(totals.writes), writeCap: num(totals.writeCap), tokens: num(totals.injectedTokens), turns: num(totals.turns), cost: formatUsd(totals.costUsd) }), pre: false, ids: [], tone: 'muted' }],
260
+ });
261
+ }
262
+ return { traceId: String(ev.traceId || ''), phase: String(ev.phase || 'sent'), title: tx('title'), summary, state, tone, groups };
263
+ }
264
+
265
+ // ── typed words (the composer) ──────────────────────────────────────────────
266
+ // A paste this long, or this many lines, is text the user did not type
267
+ // (lib/assistant-user-context-budgets.js LEARN.pasteChars / pasteLines): the
268
+ // prompt still carries it, the `typed` text the server may learn from does not.
269
+ export const PASTE_MIN_CHARS = 200;
270
+ export const PASTE_MIN_LINES = 4;
271
+
272
+ export function isLongPaste(text) {
273
+ const value = String(text ?? '');
274
+ if (!value.trim()) return false;
275
+ return value.length >= PASTE_MIN_CHARS || value.split(/\r\n|\r|\n/).filter((line) => line.trim()).length >= PASTE_MIN_LINES;
276
+ }
277
+
278
+ /** The composer's text without the long pastes still in it (those edited since count as typed). */
279
+ export function typedText(text, pastes = []) {
280
+ let out = String(text ?? '').replace(/\r\n?/g, '\n');
281
+ for (const paste of Array.isArray(pastes) ? pastes : []) {
282
+ const block = String(paste ?? '').replace(/\r\n?/g, '\n').trim();
283
+ if (block && out.includes(block)) out = out.split(block).join('\n');
284
+ }
285
+ return out.replace(/[ \t]+\n/g, '\n').replace(/\n{3,}/g, '\n\n').trim();
286
+ }