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
@@ -0,0 +1,160 @@
1
+ // ═══════════════════════════════════════════
2
+ // SETTINGS — SynaBun rules, in words
3
+ // ═══════════════════════════════════════════
4
+ //
5
+ // What the rules status (GET /api/setup/rules, lib/rulesets/installer.js) says about a tool: the name of its
6
+ // state, the action that state calls for, the sentence next to it, and what an install answered. Pure: no DOM
7
+ // and no import, so node runs it (tests/rulesets-rules-view.test.mjs).
8
+ //
9
+ // Two surfaces render the status, Settings → AI connections (ui-settings.js) and the onboarding wizard
10
+ // (onboarding.html). Both ask this module, so a state reads the same and offers the same action in both.
11
+ //
12
+ // describeRulesHost(info, { label, version, tx }) one tool: badge, path, action, note
13
+ // describeRulesInstall(result, state, { label, tx }) what Install / Update / Replace answered
14
+ // describeRulesInstallAll(result, { tx, labels }) what "install for all" answered, and where the rules live
15
+ // rulesInstallPlan(status) what "install for all" would find to do
16
+ // describeRulesInPlace(status, { tx, labels }) the same report for rules that are already there
17
+ // catalogueTranslator(messages) `tx` for a page that does not run the app's i18n
18
+ //
19
+ // `tx(key, params)` is the caller's translate function over the settings.redesign.setup.* strings (the kit's
20
+ // `tx` in Settings; the wizard reads the same catalogue, i18n/en.json).
21
+
22
+ /** The tools SynaBun installs rules for, in the order both surfaces list them. Cursor is copy-only. */
23
+ export const RULES_INSTALL_HOSTS = Object.freeze(['claude', 'gemini', 'codex', 'opencode']);
24
+
25
+ export const RULES_HOST_LABELS = Object.freeze({ claude: 'Claude Code', codex: 'Codex', opencode: 'OpenCode', gemini: 'Gemini', cursor: 'Cursor', coexistence: 'coexistence' });
26
+
27
+ /** The states that count as "the rules are in place". `shadowed` is installed too, only not loaded (Codex's override file). */
28
+ export const RULES_IN_PLACE = Object.freeze(['installed', 'newer', 'shadowed']);
29
+
30
+ /**
31
+ * One tool's rules as both surfaces show them.
32
+ *
33
+ * `info` is `status.hosts[host]`, or nothing when the status could not be read (a server that was not restarted
34
+ * after the update answers 404): then the badge says "Unavailable", the path line says what to do and no action
35
+ * is offered, because none could work.
36
+ *
37
+ * @returns {{ known: boolean, state: string, badge: string, good: boolean, path: string, pathText: string,
38
+ * action: ''|'install'|'update'|'replace', actionLabel: string, force: boolean, removable: boolean, note: string }}
39
+ */
40
+ export function describeRulesHost(info, { label, version = null, tx }) {
41
+ if (!info) {
42
+ return {
43
+ known: false, state: '', badge: tx('settings.redesign.setup.unavailable'), good: false, path: '',
44
+ pathText: tx('settings.redesign.setup.restartSynabunToFinishThisUpdate'), action: '', actionLabel: '', force: false, removable: false, note: '',
45
+ };
46
+ }
47
+ const badges = {
48
+ installed: [tx('settings.redesign.setup.installed'), true], newer: [tx('settings.redesign.setup.newer'), true], outdated: [tx('settings.redesign.setup.updateAvailable'), false], modified: [tx('settings.redesign.setup.edited2'), false],
49
+ conflict: [tx('settings.redesign.setup.conflict'), false], error: [tx('settings.redesign.setup.error'), false], shadowed: [tx('settings.redesign.setup.shadowed'), false],
50
+ 'not-installed': [tx('settings.redesign.setup.notInstalled'), false], manual: [tx('settings.redesign.setup.copyOnly'), false],
51
+ };
52
+ const [badge, good] = badges[info.state] || [info.state || tx('settings.redesign.setup.unknown'), false];
53
+ // The action the state calls for; conflict, error and shadowed only explain themselves.
54
+ const actions = { 'not-installed': ['install', tx('settings.redesign.setup.install')], outdated: ['update', tx('settings.redesign.setup.update')], modified: ['replace', tx('settings.redesign.setup.replace')] };
55
+ const [action, actionLabel] = info.detected === false ? ['', ''] : (actions[info.state] || ['', '']);
56
+ // A file without SynaBun's markers is the user's own: the server refuses to replace it, so no button.
57
+ const canAct = !!action && info.replaceable !== false;
58
+ // An edited copy is the user's: nothing replaces or removes it without the confirm behind each button.
59
+ const editedNote = tx('settings.redesign.setup.thisCopyWasEditedSoSynabun');
60
+ const stateNote = info.detected === false ? tx('settings.redesign.setup.wasNotFoundOnThisMachine', { label })
61
+ : info.state === 'modified' ? (info.replaceable === false ? (info.detail || '') : editedNote)
62
+ : info.state === 'outdated' ? (version ? tx('settings.redesign.setup.versionOfTheRulesIsAvailable', { version }) : tx('settings.redesign.setup.aNewerVersionOfTheRules'))
63
+ : ['conflict', 'error', 'shadowed', 'newer'].includes(info.state) ? (info.error || info.detail || '')
64
+ : '';
65
+ // A removal that could not finish left rules behind: say which, until a remove or an install completes.
66
+ const partial = info.partialRemoval?.error ? tx('settings.redesign.setup.theLastRemovalDidNotFinish', { error: info.partialRemoval.error }) : '';
67
+ const note = partial && stateNote && !partial.includes(stateNote) ? `${partial} ${stateNote}` : (partial || stateNote);
68
+ return {
69
+ known: true,
70
+ state: info.state || '',
71
+ badge,
72
+ good,
73
+ path: info.path || '',
74
+ pathText: info.installedVersion ? `${info.path} (v${info.installedVersion})` : (info.path || ''),
75
+ action: canAct ? action : '',
76
+ actionLabel: canAct ? actionLabel : '',
77
+ // Replace sends force, and only after the confirm that says the edited copy is backed up first.
78
+ force: canAct && action === 'replace',
79
+ removable: ['installed', 'newer', 'outdated', 'modified', 'shadowed'].includes(info.state),
80
+ note,
81
+ };
82
+ }
83
+
84
+ /** The sentence for what one tool's Install, Update or Replace answered. `state` is what the tool was in before. */
85
+ export function describeRulesInstall(result, state, { label, tx }) {
86
+ if (!result?.changed) return tx('settings.redesign.setup.rulesAreAlreadyCurrent', { label });
87
+ return tx(state === 'not-installed' ? 'settings.redesign.setup.rulesInstalled2' : 'settings.redesign.setup.rulesUpdated2', { label });
88
+ }
89
+
90
+ /**
91
+ * What "install for all" answered: `message` is the result in one sentence, `note` says which file each tool
92
+ * reads ('' when nothing was written or found), `failed` lists the tools that were refused.
93
+ * The rules are global, so a project's own CLAUDE.md and AGENTS.md stay as they are; the note says so.
94
+ */
95
+ export function describeRulesInstallAll(result, { tx, labels = RULES_HOST_LABELS }) {
96
+ const name = (host) => labels[host] || RULES_HOST_LABELS[host] || host;
97
+ const rows = Object.entries(result?.results || {});
98
+ if (!rows.length) return { message: tx('settings.redesign.setup.noConnectedToolNeedsRules'), note: '', failed: [] };
99
+ const where = rows.filter(([, row]) => row.ok !== false && row.path).map(([host, row]) => `${name(host)}: ${row.path}`).join(' · ');
100
+ const note = where ? tx('settings.redesign.setup.rulesInstalledAt', { where }) : '';
101
+ const failed = rows.filter(([, row]) => row.ok === false);
102
+ if (failed.length) {
103
+ return {
104
+ message: tx('settings.redesign.setup.installedWithFailure', { count: rows.length - failed.length, host: name(failed[0][0]), error: failed[0][1].error || failed[0][1].state }),
105
+ note,
106
+ failed: failed.map(([host]) => host),
107
+ };
108
+ }
109
+ const map = rows.map(([host]) => name(host)).join(', ');
110
+ return { message: tx(rows.some(([, row]) => row.changed) ? 'settings.redesign.setup.rulesInstalledFor' : 'settings.redesign.setup.rulesAlreadyCurrentFor', { map }), note, failed: [] };
111
+ }
112
+
113
+ /**
114
+ * What "install for all" would find to do, by the installer's own rule (installAll in lib/rulesets/installer.js):
115
+ * it takes a tool that is on this machine, connected to SynaBun (or already managed), not opted out and not in
116
+ * the middle of a removal.
117
+ *
118
+ * pending tools it would install or update
119
+ * inPlace tools whose rules are there already
120
+ * attention tools it would be refused for (an edited copy, damaged markers, an error): each needs its own answer
121
+ * skipped connected tools it leaves alone because the user took their rules out
122
+ * connected every tool above
123
+ */
124
+ export function rulesInstallPlan(status) {
125
+ const plan = { pending: [], inPlace: [], attention: [], skipped: [], connected: [] };
126
+ for (const host of RULES_INSTALL_HOSTS) {
127
+ const info = status?.hosts?.[host];
128
+ if (!info || info.detected === false) continue;
129
+ if (info.managed !== true && info.mcp !== true) continue;
130
+ plan.connected.push(host);
131
+ if (RULES_IN_PLACE.includes(info.state)) plan.inPlace.push(host);
132
+ else if (info.managed === false || info.partialRemoval) plan.skipped.push(host);
133
+ else if (info.state === 'not-installed' || info.state === 'outdated') plan.pending.push(host);
134
+ else plan.attention.push(host);
135
+ }
136
+ return plan;
137
+ }
138
+
139
+ /**
140
+ * The same report for rules that are in place already: the wizard reaches its rules step after its own toggles
141
+ * installed them, and says what Settings says after "install for all". Null when no connected tool has rules.
142
+ */
143
+ export function describeRulesInPlace(status, { tx, labels = RULES_HOST_LABELS }) {
144
+ const results = {};
145
+ for (const host of rulesInstallPlan(status).inPlace) results[host] = { ok: true, changed: true, path: status.hosts[host].path };
146
+ return Object.keys(results).length ? describeRulesInstallAll({ results }, { tx, labels }) : null;
147
+ }
148
+
149
+ /**
150
+ * `tx` over a loaded catalogue (the parsed i18n/en.json), for a page that does not run the app's i18n: the
151
+ * onboarding wizard is English only and must not wait for the app's storage. Same rules as t() in i18n.js:
152
+ * a missing key comes back as the key, `{name}` is filled from `params`.
153
+ */
154
+ export function catalogueTranslator(messages) {
155
+ return (key, params) => {
156
+ const value = String(key).split('.').reduce((node, part) => node?.[part], messages);
157
+ if (typeof value !== 'string') return key;
158
+ return params ? value.replace(/\{(\w+)\}/g, (_, name) => (params[name] != null ? params[name] : `{${name}}`)) : value;
159
+ };
160
+ }
@@ -0,0 +1,154 @@
1
+ // ═══════════════════════════════════════════
2
+ // SETTINGS — the Assistant's user context, in words
3
+ // ═══════════════════════════════════════════
4
+ //
5
+ // What `GET /api/assistant/user-context` (lib/assistant-api.js, the engine in lib/assistant-user-context.js)
6
+ // says about Settings → Automations → Automation behavior: whether the three switches can be used at all,
7
+ // what each one is set to, what stands in the way of a layer, and whether the digest is in use. Pure: no DOM
8
+ // and no import, so node runs it (tests/settings-user-context-view.test.mjs).
9
+ //
10
+ // readUserContextResponse({ status, body, error }) what the server answered → a reading
11
+ // describeUserContext(reading, { tx }) the section as ui-settings.js draws it
12
+ // describeUserContextSaveFailure(input, { tx }) the sentence for a switch that could not be saved
13
+ //
14
+ // `tx(key, params)` is the caller's translate function over the settings.redesign.* strings (the kit's `tx`).
15
+ //
16
+ // The section never shows a healthy-looking control for something that is not happening: a server without
17
+ // the engine gets disabled rows and says why, a switched-off layer says what stops, and the digest is shown
18
+ // as told to a new conversation only while "Knowledge of you" is on (the engine's preview is built either way).
19
+
20
+ const K = 'settings.redesign.hooks.uc';
21
+
22
+ /** The three layers, in the order the section lists them. */
23
+ export const USER_CONTEXT_LAYERS = Object.freeze(['knowledge', 'nudges', 'trace']);
24
+
25
+ const clean = (value, max = 200) => {
26
+ const text = String(value ?? '').replace(/\s+/g, ' ').trim();
27
+ return text.length > max ? `${text.slice(0, max - 1)}…` : text;
28
+ };
29
+
30
+ /**
31
+ * What the server answered.
32
+ *
33
+ * ready the engine is there: `payload` is { settings, capabilities, preview }
34
+ * old-server 404: the running server was started before the engine existed (public/ reloads at any
35
+ * time, lib/ only on a restart)
36
+ * failed 503 USER_CONTEXT_UNAVAILABLE: the engine did not start at boot; `reason` is the error
37
+ * unreadable anything else (no answer, a refusal, a body that is not the payload); `reason` says what
38
+ *
39
+ * @param {{ status?: number, body?: object|null, error?: string|null }} response
40
+ * @returns {{ state: 'ready'|'old-server'|'failed'|'unreadable', payload: object|null, reason: string|null }}
41
+ */
42
+ export function readUserContextResponse({ status = 0, body = null, error = null } = {}) {
43
+ if (status === 200 && body?.ok === true && body.settings && typeof body.settings === 'object') return { state: 'ready', payload: body, reason: null };
44
+ if (status === 404) return { state: 'old-server', payload: null, reason: null };
45
+ if (status === 503 && body?.code === 'USER_CONTEXT_UNAVAILABLE') return { state: 'failed', payload: null, reason: clean(body.reason) || null };
46
+ return { state: 'unreadable', payload: null, reason: clean(body?.error || error) || (status ? `HTTP ${status}` : null) };
47
+ }
48
+
49
+ /** The settings as booleans, the way the engine reads them: anything that is not exactly `false` is on. */
50
+ const layersOf = (settings) => Object.fromEntries(USER_CONTEXT_LAYERS.map((key) => [key, settings?.[key] !== false]));
51
+
52
+ // Why learning cannot run → the sentence, and whether Settings → AI decisions is where to fix it.
53
+ const LEARNING_REASONS = {
54
+ 'kill-switch': { key: 'learn.killSwitch', link: false },
55
+ 'master-off': { key: 'learn.masterOff', link: 'jv-sec-master' },
56
+ 'no-key': { key: 'learn.noKey', link: 'jv-sec-connection' },
57
+ 'surface-off': { key: 'learn.surfaceOff', link: 'jv-sec-surfaces' },
58
+ waiting: { key: 'learn.waiting', link: false },
59
+ };
60
+
61
+ /**
62
+ * The section as it is drawn.
63
+ *
64
+ * `note`: one line above the switches when they cannot be used (and why), else null.
65
+ * `layers[key]`: `on` (the stored value; false while it cannot be read), `disabled`, and `notes`: what stands
66
+ * in the way of that layer right now, each `{ text, tone: 'warn'|'info', link }` where `link` is
67
+ * `{ label, target }` (a Settings deep link) or null.
68
+ * `applies`: the line that says when a change takes effect, or ''.
69
+ * `digest`: `shown` (false without the engine), `state` 'in-use' | 'empty' | 'off', the `count` text, the `rows`
70
+ * to list (none while off), the `message` shown in place of rows (or ''), and the `omitted` line (or '').
71
+ *
72
+ * @param {{ state: string, payload: object|null, reason: string|null }} reading
73
+ * @param {{ tx: (key: string, params?: object) => string }} deps
74
+ */
75
+ export function describeUserContext(reading, { tx }) {
76
+ const state = reading?.state || 'unreadable';
77
+ const ready = state === 'ready';
78
+ const page = tx('settings.redesign.page.ai_decisions.title');
79
+ const view = {
80
+ state, ready, note: null, applies: ready ? tx(`${K}.applies`) : '',
81
+ layers: Object.fromEntries(USER_CONTEXT_LAYERS.map((key) => [key, { on: false, disabled: !ready, notes: [] }])),
82
+ digest: { shown: false, state: 'off', count: '', rows: [], message: '', omitted: '' },
83
+ };
84
+
85
+ if (!ready) {
86
+ const reason = clean(reading?.reason);
87
+ if (state === 'old-server') view.note = { text: tx(`${K}.restart`), tone: 'warn' };
88
+ else if (state === 'failed') view.note = { text: reason ? tx(`${K}.failed`, { reason }) : tx(`${K}.failedNoReason`), tone: 'warn' };
89
+ else view.note = { text: reason ? tx(`${K}.unreadable`, { reason }) : tx(`${K}.unreadableNoReason`), tone: 'warn' };
90
+ return view;
91
+ }
92
+
93
+ const { settings, capabilities, preview } = reading.payload;
94
+ const on = layersOf(settings);
95
+ const caps = capabilities && typeof capabilities === 'object' ? capabilities : {};
96
+ for (const key of USER_CONTEXT_LAYERS) view.layers[key].on = on[key];
97
+
98
+ // Without the memory store nothing is read, learned or recorded: both layers that live in it say so.
99
+ const noStore = caps.store === false;
100
+ if (noStore) {
101
+ if (on.knowledge) view.layers.knowledge.notes.push({ text: tx(`${K}.noStore`), tone: 'warn', link: null });
102
+ if (on.nudges) view.layers.nudges.notes.push({ text: tx(`${K}.noStore`), tone: 'warn', link: null });
103
+ }
104
+ // Learning needs Jev on the `user-learning` surface; the digest does not.
105
+ if (on.knowledge && !noStore && caps.jev === false) {
106
+ const known = LEARNING_REASONS[caps.jevReason] || { key: 'learn.unavailable', link: false };
107
+ view.layers.knowledge.notes.push({
108
+ text: tx(`${K}.${known.key}`, { page }), tone: 'warn',
109
+ link: known.link ? { label: tx(`${K}.openPage`, { page }), target: { tab: 'ai-decisions', scrollTo: known.link } } : null,
110
+ });
111
+ }
112
+ // The statement writer: without it (or when its last one-shot failed) a statement stays in the user's own words.
113
+ if (on.knowledge && !noStore && caps.jev !== false) {
114
+ if (caps.writer === false) view.layers.knowledge.notes.push({ text: tx(`${K}.writer.missing`), tone: 'info', link: null });
115
+ else if (caps.writerLast && caps.writerLast.ok === false) {
116
+ const reason = clean(caps.writerLast.reason, 120);
117
+ view.layers.knowledge.notes.push({ text: reason ? tx(`${K}.writer.failed`, { reason }) : tx(`${K}.writer.failedNoReason`), tone: 'info', link: null });
118
+ }
119
+ }
120
+ // The trace is a line about the two layers: with both off the engine emits nothing.
121
+ if (on.trace && !on.knowledge && !on.nudges) view.layers.trace.notes.push({ text: tx(`${K}.trace.nothing`), tone: 'info', link: null });
122
+
123
+ // The digest: what a new conversation is told, which is nothing while the layer is off.
124
+ const rows = Array.isArray(preview?.rows) ? preview.rows.filter((row) => row && row.id && row.statement) : [];
125
+ const omitted = Number(preview?.omitted) > 0 ? Math.round(Number(preview.omitted)) : 0;
126
+ view.digest.shown = true;
127
+ if (!on.knowledge) {
128
+ view.digest.state = 'off';
129
+ view.digest.count = tx('settings.redesign.common.off');
130
+ view.digest.message = tx(`${K}.off.note`);
131
+ } else {
132
+ view.digest.state = rows.length ? 'in-use' : 'empty';
133
+ view.digest.count = tx(`${K}.tokens`, { tokens: Math.max(0, Math.round(Number(preview?.tokens) || 0)), max: Math.round(Number(preview?.maxTokens) || 300) });
134
+ view.digest.rows = rows.map((row) => ({ id: String(row.id), statement: String(row.statement), facet: String(row.facet || ''), seed: row.seed === true }));
135
+ view.digest.message = rows.length ? '' : tx(`${K}.empty`);
136
+ view.digest.omitted = omitted > 0 ? tx(`${K}.omitted`, { n: omitted }) : '';
137
+ }
138
+ return view;
139
+ }
140
+
141
+ /**
142
+ * A switch that could not be saved: it goes back to where it was, and this is the sentence that says so.
143
+ *
144
+ * @param {{ name: string, wanted: boolean, status?: number, body?: object|null, error?: string|null }} input
145
+ * `name` is the switch's label, `wanted` what the click asked for
146
+ * @returns {string}
147
+ */
148
+ export function describeUserContextSaveFailure({ name, wanted, status = 0, body = null, error = null } = {}, { tx }) {
149
+ let reason = clean(body?.error || body?.message, 160);
150
+ if (!reason && status === 404) reason = tx(`${K}.save.oldServer`);
151
+ if (!reason && status) reason = `HTTP ${status}`;
152
+ if (!reason) reason = clean(error, 160) || tx(`${K}.save.noAnswer`);
153
+ return tx(`${K}.save.${wanted ? 'on' : 'off'}`, { name, reason });
154
+ }