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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neural-memory-interface",
3
- "version": "2.0.0",
3
+ "version": "2.0.5",
4
4
  "private": true,
5
5
  "description": "Private local SynaBun interface for memory visualization and multi-agent workflows",
6
6
  "license": "Apache-2.0",
@@ -17,7 +17,6 @@
17
17
  "scripts": {
18
18
  "start": "node server.js",
19
19
  "dev": "node --watch server.js",
20
- "test": "node --test tests/*.test.mjs",
21
20
  "build:vendor": "node scripts/build-vendor.mjs",
22
21
  "postinstall": "node scripts/rebuild-pty.js && node scripts/build-vendor.mjs"
23
22
  },
@@ -52,6 +51,18 @@
52
51
  "tar": "^7.5.19"
53
52
  },
54
53
  "devDependencies": {
54
+ "@codemirror/autocomplete": "6.20.3",
55
+ "@codemirror/commands": "6.11.1",
56
+ "@codemirror/language": "6.13.1",
57
+ "@codemirror/language-data": "6.5.2",
58
+ "@codemirror/legacy-modes": "6.5.5",
59
+ "@codemirror/lint": "6.9.7",
60
+ "@codemirror/merge": "6.12.2",
61
+ "@codemirror/search": "6.7.2",
62
+ "@codemirror/state": "6.7.6",
63
+ "@codemirror/view": "6.43.14",
64
+ "@lezer/highlight": "1.2.5",
65
+ "@replit/codemirror-indentation-markers": "6.5.3",
55
66
  "esbuild": "^0.28.1",
56
67
  "three": "0.169.0"
57
68
  }
@@ -0,0 +1,34 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Install as App — SynaBun</title>
7
+ <link rel="icon" href="/favicon-32x32.png">
8
+ <link rel="apple-touch-icon" href="/apple-touch-icon.png">
9
+ <link rel="manifest" href="/manifest.json">
10
+ <link rel="stylesheet" href="/shared/styles.css">
11
+ <link rel="stylesheet" href="/shared/pwa-install.css">
12
+ </head>
13
+ <body id="pwa-install">
14
+ <!-- Hidden until pwa-install-page.js knows what this browser gets: the wizard or the main UI (Chrome or Edge
15
+ sent here by the launcher), one button (asked for from the Apps menu), or one plain instruction. -->
16
+ <main aria-labelledby="install-title" hidden>
17
+ <img src="/icon-192.png" width="48" height="48" alt="SynaBun">
18
+ <h1 id="install-title">Install SynaBun as an app</h1>
19
+ <p id="install-intro">The server is running in the background. Confirm installation once in your browser to give SynaBun its own app window.</p>
20
+ <p id="install-chromium" hidden>Chrome or Edge: choose Install as App below, or the browser's Install app menu.</p>
21
+ <p id="install-safari" hidden>Safari on macOS: choose File → Add to Dock. Keep the name SynaBun.</p>
22
+ <p id="install-other" hidden>SynaBun installs as an app from Chrome, Edge, or Safari on macOS. Open it in one of them to install.</p>
23
+ <p id="install-later">After installation, reopen the native SynaBun launcher. It starts or reuses the server and opens your installed PWA. Closing the app window leaves the server running. Use Apps → Stop Server to stop it.</p>
24
+ <div class="actions">
25
+ <button id="install-button" type="button" hidden>Install as App</button>
26
+ <a id="install-continue" href="/">Continue to SynaBun</a>
27
+ </div>
28
+ <p id="install-status" role="status" aria-live="polite"></p>
29
+ </main>
30
+ <!-- Should the script never answer, the page and its way on still show. -->
31
+ <script>setTimeout(() => { document.querySelector('main').hidden = false; }, 4000);</script>
32
+ <script type="module" src="/shared/pwa-install-page.js"></script>
33
+ </body>
34
+ </html>
@@ -1,6 +1,8 @@
1
1
  {
2
2
  "name": "SynaBun",
3
3
  "short_name": "SynaBun",
4
+ "id": "/",
5
+ "scope": "/",
4
6
  "start_url": "/",
5
7
  "display": "standalone",
6
8
  "display_override": ["window-controls-overlay", "standalone"],
@@ -28,7 +28,14 @@
28
28
  position: relative;
29
29
  }
30
30
 
31
- /* --- Mascot --- */
31
+ /* --- Mascot ---
32
+ One character, six states (data-state on .mascot-wrap), each tied to what
33
+ the page knows: asleep (nothing asked), waking (asked, nothing confirmed),
34
+ working (the launcher reports a start), ready (the server answers),
35
+ failed (the launcher reports why), stalled (nobody answered). The pill
36
+ eyes and the mouth are the app's mascot (shared/synabun-mascot.js): same
37
+ 280x140 geometry, same poses, drawn here in CSS because this page can
38
+ load nothing. */
32
39
  .mascot-wrap {
33
40
  display: inline-block;
34
41
  position: relative;
@@ -41,7 +48,87 @@
41
48
  50% { transform: translateY(-5px); }
42
49
  }
43
50
 
44
- /* --- Floating Z's --- */
51
+ .mascot-wrap .eye {
52
+ fill: rgba(255,255,255,0.45);
53
+ transform-box: fill-box;
54
+ transform-origin: center;
55
+ transform: translateY(9px) scaleY(0.1);
56
+ transition: transform 0.25s cubic-bezier(0.2, 0, 0, 1), fill 0.25s;
57
+ }
58
+
59
+ .mascot-wrap .mouth {
60
+ fill: none;
61
+ stroke: rgba(255,255,255,0.15);
62
+ stroke-width: 2.5;
63
+ stroke-linecap: round;
64
+ opacity: 0;
65
+ transition: opacity 0.25s;
66
+ }
67
+
68
+ .mascot-wrap .mouth-calm { opacity: 1; }
69
+
70
+ /* waking: half-open eyes that look from side to side, waiting on someone else */
71
+ .mascot-wrap[data-state="waking"] { animation: none; }
72
+ .mascot-wrap[data-state="waking"] .eye {
73
+ fill: rgba(255,255,255,0.7);
74
+ transform: scaleY(0.46);
75
+ animation: glance 2.6s ease-in-out infinite;
76
+ }
77
+
78
+ @keyframes glance {
79
+ 0%, 12% { transform: translateX(0) scaleY(0.46); }
80
+ 28%, 44% { transform: translateX(-9px) scaleY(0.46); }
81
+ 60%, 76% { transform: translateX(9px) scaleY(0.46); }
82
+ 90%, 100% { transform: translateX(0) scaleY(0.46); }
83
+ }
84
+
85
+ /* working: eyes wide open, taking turns: something is really running */
86
+ .mascot-wrap[data-state="working"] { animation: none; }
87
+ .mascot-wrap[data-state="working"] .eye {
88
+ fill: rgba(255,255,255,0.85);
89
+ transform: scaleY(1);
90
+ animation: work 1.1s ease-in-out infinite;
91
+ }
92
+ .mascot-wrap[data-state="working"] .eye-r { animation-delay: 0.18s; }
93
+
94
+ @keyframes work {
95
+ 0%, 100% { transform: translateY(0) scaleY(1); }
96
+ 35% { transform: translateY(-7px) scaleY(1.04); }
97
+ 60% { transform: translateY(2px) scaleY(0.92); }
98
+ }
99
+
100
+ /* ready: happy eyes, a wider smile, one hop */
101
+ .mascot-wrap[data-state="ready"] { animation: hop 0.5s cubic-bezier(0.2, 0, 0, 1) 1; }
102
+ .mascot-wrap[data-state="ready"] .eye { fill: rgba(80,220,120,0.8); transform: translateY(-4px) scaleY(0.3); }
103
+ .mascot-wrap[data-state="ready"] .eye-l { transform: translateY(-4px) rotate(-8deg) scaleY(0.3); }
104
+ .mascot-wrap[data-state="ready"] .eye-r { transform: translateY(-4px) rotate(8deg) scaleY(0.3); }
105
+ .mascot-wrap[data-state="ready"] .mouth-calm { opacity: 0; }
106
+ .mascot-wrap[data-state="ready"] .mouth-happy { opacity: 1; stroke: rgba(80,220,120,0.5); }
107
+
108
+ @keyframes hop {
109
+ 0%, 100% { transform: translateY(0); }
110
+ 45% { transform: translateY(-10px); }
111
+ }
112
+
113
+ /* failed: a wince and a short shake, then still */
114
+ .mascot-wrap[data-state="failed"] { animation: shake 0.4s ease-in-out 1; }
115
+ .mascot-wrap[data-state="failed"] .eye { fill: rgba(255,255,255,0.6); }
116
+ .mascot-wrap[data-state="failed"] .eye-l { transform: translateY(2px) rotate(12deg) scaleY(0.78); }
117
+ .mascot-wrap[data-state="failed"] .eye-r { transform: translateY(2px) rotate(-12deg) scaleY(0.74); }
118
+ .mascot-wrap[data-state="failed"] .mouth-calm { opacity: 0; }
119
+ .mascot-wrap[data-state="failed"] .mouth-sad { opacity: 1; stroke: rgba(255,255,255,0.3); }
120
+
121
+ @keyframes shake {
122
+ 0%, 100% { transform: translateX(0); }
123
+ 25% { transform: translateX(-5px); }
124
+ 75% { transform: translateX(5px); }
125
+ }
126
+
127
+ /* stalled: awake but dimmed, waiting for the person */
128
+ .mascot-wrap[data-state="stalled"] { animation: none; }
129
+ .mascot-wrap[data-state="stalled"] .eye { fill: rgba(255,255,255,0.35); transform: translateY(5px) scaleY(0.44); }
130
+
131
+ /* --- Floating Z's (asleep only) --- */
45
132
  .zzz {
46
133
  position: absolute;
47
134
  top: -4px;
@@ -50,8 +137,11 @@
50
137
  font-weight: 700;
51
138
  color: rgba(110,200,255,0.45);
52
139
  pointer-events: none;
140
+ transition: opacity 0.25s;
53
141
  }
54
142
 
143
+ .mascot-wrap:not([data-state="asleep"]) .zzz { opacity: 0; }
144
+
55
145
  .zzz span {
56
146
  position: absolute;
57
147
  bottom: 0;
@@ -85,6 +175,129 @@
85
175
  margin-bottom: 28px;
86
176
  }
87
177
 
178
+ /* --- Start Server --- */
179
+ .start {
180
+ margin-bottom: 28px;
181
+ }
182
+
183
+ .start[hidden] { display: none; }
184
+
185
+ .start-btn {
186
+ display: inline-flex;
187
+ align-items: center;
188
+ gap: 8px;
189
+ padding: 10px 24px;
190
+ background: rgba(255,255,255,0.08);
191
+ border: 1px solid rgba(255,255,255,0.15);
192
+ border-radius: 8px;
193
+ color: rgba(255,255,255,0.7);
194
+ font-family: inherit;
195
+ font-size: 13px;
196
+ font-weight: 500;
197
+ letter-spacing: 0.05em;
198
+ cursor: pointer;
199
+ transition: background 0.15s, color 0.15s, border-color 0.15s;
200
+ }
201
+
202
+ .start-btn:hover {
203
+ background: rgba(255,255,255,0.12);
204
+ border-color: rgba(255,255,255,0.25);
205
+ color: rgba(255,255,255,0.9);
206
+ }
207
+
208
+ .start-btn:focus-visible {
209
+ outline: 2px solid rgba(110,200,255,0.6);
210
+ outline-offset: 2px;
211
+ }
212
+
213
+ .start-btn:disabled {
214
+ opacity: 0.4;
215
+ cursor: wait;
216
+ }
217
+
218
+ .start-btn svg {
219
+ width: 14px;
220
+ height: 14px;
221
+ fill: none;
222
+ stroke: currentColor;
223
+ stroke-width: 2;
224
+ stroke-linecap: round;
225
+ stroke-linejoin: round;
226
+ }
227
+
228
+ /* What is happening, in order of how sure the page is: the sentence (the
229
+ live region), the page's own clock, a quieter second sentence, then the
230
+ steps the launcher reported with the time each one happened. */
231
+ .start-status {
232
+ min-height: 18px;
233
+ margin-top: 14px;
234
+ font-size: 13px;
235
+ line-height: 1.45;
236
+ color: rgba(255,255,255,0.7);
237
+ }
238
+
239
+ .start-elapsed {
240
+ min-height: 16px;
241
+ margin-top: 4px;
242
+ font-family: 'JetBrains Mono', 'SF Mono', 'Fira Code', monospace;
243
+ font-size: 11.5px;
244
+ font-variant-numeric: tabular-nums;
245
+ color: rgba(110,200,255,0.6);
246
+ }
247
+
248
+ .start-hint {
249
+ margin-top: 4px;
250
+ font-size: 11px;
251
+ line-height: 1.45;
252
+ color: rgba(255,255,255,0.35);
253
+ }
254
+
255
+ .start-hint:empty, .start-elapsed:empty { display: none; }
256
+
257
+ .start-trail {
258
+ list-style: none;
259
+ margin: 12px auto 0;
260
+ max-width: 260px;
261
+ font-size: 11px;
262
+ line-height: 1.7;
263
+ color: rgba(255,255,255,0.35);
264
+ }
265
+
266
+ .start-trail:empty { display: none; }
267
+
268
+ .start-trail li {
269
+ display: flex;
270
+ justify-content: space-between;
271
+ gap: 12px;
272
+ }
273
+
274
+ .start-trail .at {
275
+ font-family: 'JetBrains Mono', 'SF Mono', 'Fira Code', monospace;
276
+ font-variant-numeric: tabular-nums;
277
+ color: rgba(255,255,255,0.55);
278
+ }
279
+
280
+ .start-log {
281
+ margin-top: 10px;
282
+ font-family: 'JetBrains Mono', 'SF Mono', 'Fira Code', monospace;
283
+ font-size: 10.5px;
284
+ line-height: 1.5;
285
+ color: rgba(255,255,255,0.35);
286
+ overflow-wrap: anywhere;
287
+ user-select: all;
288
+ }
289
+
290
+ .start-log[hidden] { display: none; }
291
+
292
+ .manual-note {
293
+ margin: 2px 0 14px;
294
+ font-size: 11px;
295
+ line-height: 1.45;
296
+ color: rgba(255,255,255,0.35);
297
+ }
298
+
299
+ .manual-note[hidden] { display: none; }
300
+
88
301
  /* --- Command labels --- */
89
302
  .cmd-label {
90
303
  font-size: 10px;
@@ -115,7 +328,10 @@
115
328
  font-size: 11.5px;
116
329
  color: rgba(255,255,255,0.55);
117
330
  line-height: 1.5;
118
- word-break: break-all;
331
+ /* Break between words first, inside a long path only when it has to;
332
+ and no ligatures: "--prefix" must read as two hyphens. */
333
+ overflow-wrap: anywhere;
334
+ font-variant-ligatures: none;
119
335
  user-select: all;
120
336
  }
121
337
 
@@ -213,6 +429,19 @@
213
429
  90% { opacity: 1; }
214
430
  100% { transform: translateY(-10vh) translateX(30px); opacity: 0; }
215
431
  }
432
+
433
+ /* Reduced motion: every state keeps its own still face (the eyes and mouth
434
+ above), the words and the clock; nothing moves. */
435
+ @media (prefers-reduced-motion: reduce) {
436
+ .mascot-wrap, .mascot-wrap .eye, .zzz span, .retry-dot, .particles span {
437
+ animation: none !important;
438
+ }
439
+ .mascot-wrap .eye, .mascot-wrap .mouth, .zzz, .start-btn, .copy-btn {
440
+ transition: none !important;
441
+ }
442
+ .zzz span:nth-child(2) { opacity: 0.5; }
443
+ .particles { display: none; }
444
+ }
216
445
  </style>
217
446
  </head>
218
447
  <body>
@@ -221,38 +450,42 @@
221
450
  <div class="particles" id="particles"></div>
222
451
 
223
452
  <div class="card">
224
- <!-- Sleeping mascot -->
225
- <div class="mascot-wrap">
226
- <svg viewBox="0 0 280 140" width="180" height="90" style="overflow:visible">
227
- <!-- Left eye — closed -->
228
- <rect x="80" y="57" width="38" height="6" rx="3" fill="rgba(255,255,255,0.45)"/>
229
- <!-- Right eye — closed -->
230
- <rect x="162" y="57" width="38" height="6" rx="3" fill="rgba(255,255,255,0.45)"/>
231
- <!-- Peaceful smile -->
232
- <path d="M118,90 Q140,100 162,90" fill="none" stroke="rgba(255,255,255,0.15)" stroke-width="2.5" stroke-linecap="round"/>
453
+ <!-- The mascot: asleep until a start is asked for (data-state follows the bridge) -->
454
+ <div class="mascot-wrap" id="mascot" data-state="asleep">
455
+ <svg viewBox="0 0 280 140" width="180" height="90" style="overflow:visible" aria-hidden="true" focusable="false">
456
+ <rect class="eye eye-l" x="80" y="24" width="38" height="72" rx="19"/>
457
+ <rect class="eye eye-r" x="162" y="24" width="38" height="72" rx="19"/>
458
+ <path class="mouth mouth-calm" d="M118,116 Q140,128 162,116"/>
459
+ <path class="mouth mouth-happy" d="M111,112 Q140,138 169,112"/>
460
+ <path class="mouth mouth-sad" d="M123,124 Q140,114 157,124"/>
233
461
  </svg>
234
- <div class="zzz">
462
+ <div class="zzz" aria-hidden="true">
235
463
  <span>z</span>
236
464
  <span>z</span>
237
465
  <span>z</span>
238
466
  </div>
239
467
  </div>
240
468
 
241
- <div class="heading">Server is sleeping</div>
242
- <div class="subtext">The Neural Interface server isn't running.</div>
469
+ <div class="heading" id="heading">Server is sleeping</div>
470
+ <div class="subtext" id="subtext">The Neural Interface server isn't running.</div>
471
+
472
+ <div class="start" id="start" hidden>
473
+ <button class="start-btn" id="startBtn" type="button">
474
+ <svg viewBox="0 0 24 24" aria-hidden="true"><polygon points="5 3 19 12 5 21 5 3"/></svg>
475
+ <span id="startLabel">Start Server</span>
476
+ </button>
477
+ <!-- Announced when the sentence changes; the ticking clock below is not part of it. -->
478
+ <div class="start-status" id="startStatus" role="status" aria-live="polite" aria-atomic="true"></div>
479
+ <div class="start-elapsed" id="startElapsed" role="timer" aria-live="off"></div>
480
+ <div class="start-hint" id="startHint"></div>
481
+ <ul class="start-trail" id="startTrail" aria-label="What the launcher reported"></ul>
482
+ <div class="start-log" id="startLog" hidden></div>
483
+ </div>
243
484
 
244
- <div>
245
- <div class="cmd-label">npm install</div>
246
- <div class="cmd-block">
247
- <div class="cmd-text" id="cmdText"><span>synabun</span></div>
248
- <button class="copy-btn" id="copyBtn">Copy</button>
249
- </div>
250
- <div class="cmd-or" id="cmdOr" style="display:none">or</div>
251
- <div class="cmd-label" id="cmdFallbackLabel" style="display:none">git / local install</div>
252
- <div class="cmd-block" id="cmdFallback" style="display:none">
253
- <div class="cmd-text" id="cmdFallbackText"></div>
254
- <button class="copy-btn" id="copyFallbackBtn">Copy</button>
255
- </div>
485
+ <div id="manual">
486
+ <div class="cmd-label" id="manualLabel">Start it from a terminal</div>
487
+ <div id="manualList"></div>
488
+ <div class="manual-note" id="manualNote" hidden>Starting it this way once also sets up the Start button.</div>
256
489
  </div>
257
490
 
258
491
  <div class="retry" id="retry">
@@ -261,31 +494,29 @@
261
494
  </div>
262
495
  </div>
263
496
 
497
+ <!-- Filled in by the server when it serves this page (lib/offline-page.js):
498
+ where SynaBun is installed, and the Start Server bridge shared with the app. -->
499
+ <script>/*__SYNABUN_OFFLINE_FACTS__*/</script>
500
+ <script>/*__SYNABUN_START_BRIDGE__*/</script>
264
501
  <script>
265
- // --- Platform detection ---
266
- const ua = navigator.userAgent;
267
- const isWin = /Win/.test(navigator.platform) || /Windows/.test(ua);
268
- const isMac = /Mac/.test(navigator.platform);
269
- // Linux = everything else
270
-
271
- const projectDir = localStorage.getItem('synabun-project-dir');
272
-
273
- // --- Manual command fallback ---
274
- if (projectDir) {
275
- const sep = isWin ? ' & ' : ' ; ';
276
- const fallbackCmd = `cd "${projectDir}"${sep}npm start`;
277
- const cmdOr = document.getElementById('cmdOr');
278
- const cmdFallback = document.getElementById('cmdFallback');
279
- const cmdFallbackText = document.getElementById('cmdFallbackText');
280
- cmdOr.style.display = '';
281
- cmdFallback.style.display = '';
282
- const cmdFallbackLabel = document.getElementById('cmdFallbackLabel');
283
- if (cmdFallbackLabel) cmdFallbackLabel.style.display = '';
284
- cmdFallbackText.innerHTML = `<span>cd</span> "${projectDir}"${sep}<span>npm</span> start`;
285
- document.getElementById('copyFallbackBtn').addEventListener('click', function() { copyToClipboard(fallbackCmd, this); });
286
- }
287
-
288
- // --- Copy helper ---
502
+ const $ = (id) => document.getElementById(id);
503
+ const stored = (key) => { try { return localStorage.getItem(key); } catch { return null; } };
504
+
505
+ // What the server said about this install the last time it answered.
506
+ const facts = window.__SYNABUN_OFFLINE__ || {};
507
+ const projectDir = stored('synabun-project-dir') || facts.projectDir || '';
508
+ const install = stored('synabun-install-kind') || facts.install || '';
509
+ const launcher = stored('synabun-start-launcher') || facts.launcher || '';
510
+ const entry = stored('synabun-start-entry') || facts.entry || '';
511
+ const hasBridge = typeof createStartBridge === 'function';
512
+ const windows = hasBridge ? isWindowsPlatform(navigator) : /Win/.test(navigator.platform);
513
+ const mac = hasBridge ? isMacPlatform(navigator) : /Mac/.test(navigator.platform);
514
+
515
+ // --- Commands to type instead ---
516
+ const commands = hasBridge
517
+ ? manualStartCommands({ projectDir, install, windows, entry })
518
+ : [{ id: 'npm', command: 'synabun' }].concat(projectDir ? [{ id: 'git', command: 'npm --prefix "' + projectDir + '" start' }] : []);
519
+
289
520
  function copyToClipboard(text, btn) {
290
521
  navigator.clipboard.writeText(text).catch(() => {
291
522
  const ta = document.createElement('textarea');
@@ -302,23 +533,128 @@
302
533
  setTimeout(() => { btn.textContent = 'Copy'; btn.classList.remove('copied'); }, 1500);
303
534
  }
304
535
 
305
- document.getElementById('copyBtn').addEventListener('click', function() { copyToClipboard('synabun', this); });
306
-
307
- // --- Auto-retry ---
308
- const retry = document.getElementById('retry');
309
- const retryText = document.getElementById('retryText');
310
-
311
- const interval = setInterval(async () => {
536
+ const list = $('manualList');
537
+ commands.forEach((entry, i) => {
538
+ if (i > 0) {
539
+ const or = document.createElement('div');
540
+ or.className = 'cmd-or';
541
+ or.textContent = 'or';
542
+ list.appendChild(or);
543
+ }
544
+ const block = document.createElement('div');
545
+ block.className = 'cmd-block';
546
+ const text = document.createElement('div');
547
+ text.className = 'cmd-text';
548
+ const space = entry.command.indexOf(' ');
549
+ const word = document.createElement('span');
550
+ word.textContent = space < 0 ? entry.command : entry.command.slice(0, space);
551
+ text.appendChild(word);
552
+ if (space >= 0) text.appendChild(document.createTextNode(entry.command.slice(space)));
553
+ const copy = document.createElement('button');
554
+ copy.className = 'copy-btn';
555
+ copy.type = 'button';
556
+ copy.textContent = 'Copy';
557
+ copy.addEventListener('click', () => copyToClipboard(entry.command, copy));
558
+ block.append(text, copy);
559
+ list.appendChild(block);
560
+ });
561
+
562
+ // --- Start Server + reconnect ---
563
+ const retry = $('retry');
564
+ const retryText = $('retryText');
565
+
566
+ async function serverAnswers() {
312
567
  try {
313
568
  const res = await fetch('/', { method: 'HEAD', cache: 'no-store' });
314
- if (res.ok) {
315
- clearInterval(interval);
316
- retry.classList.add('connected');
317
- retryText.textContent = 'Server is back! Reconnecting...';
318
- setTimeout(() => location.reload(), 600);
319
- }
320
- } catch {}
321
- }, 3000);
569
+ return res.ok;
570
+ } catch {
571
+ return false;
572
+ }
573
+ }
574
+
575
+ function reconnect(delay) {
576
+ retry.classList.add('connected');
577
+ retryText.textContent = 'Server is back! Reconnecting...';
578
+ setTimeout(() => location.reload(), delay);
579
+ }
580
+
581
+ if (!hasBridge) {
582
+ // An older server served this page without the bridge: commands and reconnect only.
583
+ const interval = setInterval(async () => {
584
+ if (!(await serverAnswers())) return;
585
+ clearInterval(interval);
586
+ reconnect(150);
587
+ }, 3000);
588
+ } else {
589
+ const start = $('start');
590
+ const startBtn = $('startBtn');
591
+ const startLabel = $('startLabel');
592
+ const startStatus = $('startStatus');
593
+ const usable = startButtonUsable(launcher);
594
+ // Known not to be registered: no dead button, the command and why it matters.
595
+ start.hidden = !usable;
596
+ $('manualNote').hidden = usable;
597
+ if (usable) $('manualLabel').textContent = 'Or start it from a terminal';
598
+
599
+ const platform = windows ? 'windows' : mac ? 'mac' : 'linux';
600
+ const say = (line) => (line ? formatStartText(START_COPY[line.key], line.params) : '');
601
+ const headings = {
602
+ asleep: ['Server is sleeping', "The Neural Interface server isn't running."],
603
+ waking: [START_COPY.headingStarting, "The Neural Interface server isn't running yet."],
604
+ working: [START_COPY.headingStarting, "The Neural Interface server isn't running yet."],
605
+ ready: [START_COPY.headingReady, 'Loading SynaBun.'],
606
+ failed: [START_COPY.headingFailed, "The Neural Interface server isn't running."],
607
+ stalled: ['Server is sleeping', "The Neural Interface server isn't running."],
608
+ };
609
+ const labels = { start: 'Start Server', starting: 'Starting...', retry: 'Try again' };
610
+
611
+ // The launcher's own report, when this page can reach it (see start-bridge.js).
612
+ const beaconAt = startBeaconTarget(window.location);
613
+
614
+ function render(snap) {
615
+ const view = startStatusView(snap, { platform });
616
+ $('mascot').setAttribute('data-state', view.mascot);
617
+ // A restart read from the supervisor's report names itself (view.heading).
618
+ $('heading').textContent = view.heading ? START_COPY[view.heading] : headings[view.mascot][0];
619
+ $('subtext').textContent = headings[view.mascot][1];
620
+ startBtn.disabled = view.busy || view.state === 'online';
621
+ startLabel.textContent = labels[view.button];
622
+ // The live region is written only when its sentence changes.
623
+ const line = say(view.headline);
624
+ if (startStatus.textContent !== line) startStatus.textContent = line;
625
+ $('startElapsed').textContent = view.elapsed;
626
+ $('startElapsed').setAttribute('aria-label', view.elapsed ? START_COPY[view.elapsedLabel] + ': ' + view.elapsed : '');
627
+ $('startHint').textContent = say(view.hint);
628
+ $('startTrail').replaceChildren(...view.trail.map((row) => {
629
+ const item = document.createElement('li');
630
+ const what = document.createElement('span');
631
+ what.textContent = START_COPY[row.key];
632
+ const when = document.createElement('span');
633
+ when.className = 'at';
634
+ when.textContent = row.time;
635
+ item.append(what, when);
636
+ return item;
637
+ }));
638
+ const log = view.error && view.error.log ? formatStartText(START_COPY.failedLog, { path: view.error.log }) : '';
639
+ $('startLog').textContent = log;
640
+ $('startLog').hidden = !log;
641
+ retryText.textContent = view.state === 'online' ? retryText.textContent
642
+ : view.busy ? 'Waiting for the server...' : 'Checking for server...';
643
+ }
644
+
645
+ const bridge = createStartBridge({
646
+ probe: serverAnswers,
647
+ launch: () => openStartLink({ document, location: window.location, userAgent: navigator.userAgent }),
648
+ beacon: beaconAt ? () => fetchStartBeacon(beaconAt) : null,
649
+ port: beaconAt ? beaconAt.port : 0,
650
+ onUpdate: render,
651
+ onState(state) {
652
+ if (state === 'online') reconnect(START_LIMITS.reloadDelayMs);
653
+ },
654
+ });
655
+ startBtn.addEventListener('click', () => bridge.start());
656
+ bridge.watch();
657
+ }
322
658
 
323
659
  // --- Ambient particles ---
324
660
  const container = document.getElementById('particles');