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
@@ -15,7 +15,6 @@ import { dirname, join, sep } from 'node:path';
15
15
  import { existsSync, readFileSync, realpathSync, statSync } from 'node:fs';
16
16
  import { createRequire } from 'node:module';
17
17
  import { getAugmentedPath } from './augmented-path.js';
18
- import { resolveClaudeExecutableOverride } from './native-binary-runtime.js';
19
18
 
20
19
  // Effort ladder the Claude Code CLI accepts for --effort. Models advertise their
21
20
  // own subset via supportedEffortLevels; this is the superset used as a fallback
@@ -46,6 +45,32 @@ const CACHE_TTL_MS = 10 * 60 * 1000;
46
45
  let _cache = { at: 0, key: '', models: [] };
47
46
  let _inflight = null;
48
47
 
48
+ // Who else keeps a copy of this list (the Assistant's model catalog). Told when a
49
+ // discovery returns a list that differs from the one before it, so a copy is
50
+ // dropped the moment the picker's own source changes: after a CLI update, or
51
+ // when the account's models change. The first discovery after a start counts.
52
+ const _changeListeners = new Set();
53
+
54
+ export function onClaudeModelsChanged(listener) {
55
+ if (typeof listener !== 'function') return () => {};
56
+ _changeListeners.add(listener);
57
+ return () => { _changeListeners.delete(listener); };
58
+ }
59
+
60
+ // What makes two lists the same list for a picker: ids in order, the model each
61
+ // runs as, the label, the context window and the effort levels.
62
+ export function claudeModelsSignature(models) {
63
+ return JSON.stringify((Array.isArray(models) ? models : []).map(m => [
64
+ m?.id || '', m?.resolvedModel || '', m?.label || '', m?.contextWindow || 0, (m?.effortLevels || []).join(','),
65
+ ]));
66
+ }
67
+
68
+ function notifyModelsChanged(models) {
69
+ for (const listener of [..._changeListeners]) {
70
+ try { listener(models); } catch {}
71
+ }
72
+ }
73
+
49
74
  // What a cache keyed on "the CLI" has to key on. An update never changes the
50
75
  // configured path: the native installer and Homebrew re-point a symlink at a new
51
76
  // version directory, and npm rewrites the entrypoint in place. The resolved target
@@ -155,10 +180,23 @@ export function normalizeClaudeModels(models = []) {
155
180
  return out;
156
181
  }
157
182
 
183
+ // With a shell, Node joins the command and its arguments into one line and
184
+ // quotes nothing. An installation under a folder with a space in its name
185
+ // (C:\Users\Jane Doe\AppData\Roaming\npm\claude.cmd) would be cut at the
186
+ // space, so the command is quoted here whenever a shell runs it. Where the
187
+ // value may also be a command line the user configured ("wsl codex"), pass
188
+ // `isFile`: only what is a file on disk is then treated as one word.
189
+ export function shellCommand(bin, useShell, { isFile = null } = {}) {
190
+ const value = String(bin);
191
+ if (!useShell || !/\s/.test(value) || /^".*"$/.test(value)) return value;
192
+ if (isFile && !isFile(value)) return value;
193
+ return `"${value}"`;
194
+ }
195
+
158
196
  // Ask the CLI for its model list. Resolves to [] on any failure — callers fall
159
197
  // back to CLAUDE_FALLBACK_MODELS rather than surfacing an error, because a
160
198
  // missing model list should degrade the picker, not break the panel.
161
- export function queryClaudeCliModels(claudeBin, { cwd, timeoutMs = DISCOVERY_TIMEOUT_MS } = {}) {
199
+ export function queryClaudeCliModels(claudeBin, { cwd, timeoutMs = DISCOVERY_TIMEOUT_MS, spawnImpl = spawn } = {}) {
162
200
  return new Promise((resolveResult) => {
163
201
  let bin = claudeBin;
164
202
  const args = [
@@ -200,7 +238,7 @@ export function queryClaudeCliModels(claudeBin, { cwd, timeoutMs = DISCOVERY_TIM
200
238
  timer.unref?.();
201
239
 
202
240
  try {
203
- child = spawn(bin, args, {
241
+ child = spawnImpl(shellCommand(bin, useShell), args, {
204
242
  cwd: cwd || process.cwd(),
205
243
  env: { ...process.env, PATH: getAugmentedPath(), CLAUDE_CODE_ENTRYPOINT: 'sdk-cli' },
206
244
  stdio: ['pipe', 'pipe', 'ignore'],
@@ -212,6 +250,11 @@ export function queryClaudeCliModels(claudeBin, { cwd, timeoutMs = DISCOVERY_TIM
212
250
 
213
251
  child.on('error', () => finish([]));
214
252
  child.on('exit', () => finish([]));
253
+ // A CLI that is not installed is a shell that exits at once, sometimes
254
+ // before the request below is written. The write then fails on the stream
255
+ // (EPIPE), not in the try around it, and an unhandled stream error ends the
256
+ // whole server. Seen on Linux, where `sh` is fast.
257
+ child.stdin.on('error', () => finish([]));
215
258
 
216
259
  let buf = '';
217
260
  child.stdout.setEncoding('utf-8');
@@ -245,7 +288,7 @@ export function queryClaudeCliModels(claudeBin, { cwd, timeoutMs = DISCOVERY_TIM
245
288
  // Cached discovery. `source` lets the UI distinguish a verified list from the
246
289
  // baked-in fallback. Cache is keyed on the binary's identity, so switching the
247
290
  // configured CLI (Settings > Terminal) or updating it re-discovers.
248
- export async function discoverClaudeModels(claudeBin, { force = false, cwd } = {}) {
291
+ export async function discoverClaudeModels(claudeBin, { force = false, cwd, query = queryClaudeCliModels } = {}) {
249
292
  const bin = String(claudeBin || '');
250
293
  const key = binaryIdentity(bin);
251
294
  const fresh = _cache.models.length
@@ -256,10 +299,12 @@ export async function discoverClaudeModels(claudeBin, { force = false, cwd } = {
256
299
 
257
300
  _inflight = (async () => {
258
301
  try {
259
- const raw = await queryClaudeCliModels(bin, { cwd });
302
+ const raw = await query(bin, { cwd });
260
303
  const models = normalizeClaudeModels(raw);
261
304
  if (models.length) {
305
+ const changed = claudeModelsSignature(models) !== claudeModelsSignature(_cache.models);
262
306
  _cache = { at: Date.now(), key, models };
307
+ if (changed) notifyModelsChanged(models);
263
308
  return { source: 'cli', models };
264
309
  }
265
310
  return { source: 'fallback', models: [...CLAUDE_FALLBACK_MODELS] };
@@ -274,27 +319,26 @@ export function clearClaudeModelCache() {
274
319
  _cache = { at: 0, key: '', models: [] };
275
320
  _skewCache = { key: null, result: undefined };
276
321
  _skewInflight.clear();
277
- _alignFailures.clear();
278
322
  }
279
323
 
280
324
  // ── CLI version skew ──────────────────────────────────────────────────────────
281
- // Two different Claude Code binaries are in play: this module discovers models
282
- // from the CLI resolved for terminals/agents/loops, while sidepanel chats run on
283
- // the one the Agent SDK bundles. Both accept the same *alias* ids ("default",
284
- // "opus[1m]", "sonnet"), but each maps them with its own model table — so when
285
- // the versions drift the picker labels a model from one table and the session
286
- // silently runs whatever the other table calls "opus". That is invisible from
287
- // the outside: the only symptom is the model naming a different version of
288
- // itself. Compare the two, say so, and — when the installed CLI is the newer
289
- // one — run sessions on it (see alignedClaudeExecutable below).
325
+ // One Claude Code is in play: the user's own installation. This module asks it
326
+ // for its models, and the Agent SDK starts that same executable for sidepanel
327
+ // chats, the Assistant and native loops (lib/claude-executable.js), so an alias
328
+ // such as "opus[1m]" means in a session what it meant in the picker.
329
+ //
330
+ // What can still drift is the SDK itself: each release is built against one
331
+ // Claude Code version (its manifest names it) and may send options an older
332
+ // installation does not know. That is worth one line in the log, never a
333
+ // refusal: the installed Claude Code is the only one there is to run.
290
334
 
291
335
  const _require = createRequire(import.meta.url);
292
336
 
293
- // The Claude Code version the installed Agent SDK ships, from the SDK's own
294
- // manifest (`manifest.json` → "version": "2.1.220"). Not in the package's
295
- // exports map, so walk up from the resolved entry file. null when the SDK is
296
- // absent — the legacy engine spawns the discovered CLI and cannot skew.
297
- export function sdkBundledCliVersion() {
337
+ // The Claude Code version the installed Agent SDK was built against, from the
338
+ // SDK's own manifest (`manifest.json` → "version": "2.1.220"). Not in the
339
+ // package's exports map, so walk up from the resolved entry file. null when the
340
+ // SDK is absent.
341
+ export function sdkReferenceCliVersion() {
298
342
  try {
299
343
  let dir = dirname(_require.resolve('@anthropic-ai/claude-agent-sdk'));
300
344
  for (let i = 0; i < 5; i++) {
@@ -355,7 +399,7 @@ export function queryClaudeCliVersion(claudeBin, { timeoutMs = 10000 } = {}) {
355
399
  timer.unref?.();
356
400
 
357
401
  try {
358
- child = spawn(bin, args, {
402
+ child = spawn(shellCommand(bin, useShell), args, {
359
403
  env: { ...process.env, PATH: getAugmentedPath() },
360
404
  stdio: ['ignore', 'pipe', 'ignore'],
361
405
  shell: useShell,
@@ -371,33 +415,25 @@ export function queryClaudeCliVersion(claudeBin, { timeoutMs = 10000 } = {}) {
371
415
  }
372
416
 
373
417
  // Never blocks discovery. The result is cached per binary identity — the model
374
- // endpoints ask on every request, and it now also decides which binary SDK
375
- // sessions run — so a `claude --version` spawn happens once per installed CLI,
376
- // not once per request. A CLI update changes the identity and re-probes. `null`
377
- // (nothing to compare: no SDK, unreadable CLI) is cached too. Warns once per
378
- // distinct pair so repeated checks don't spam the log.
418
+ // endpoints ask on every request — so a `claude --version` spawn happens once
419
+ // per installed CLI, not once per request. A CLI update changes the identity and
420
+ // re-probes. `null` (nothing to compare: no SDK, no CLI, unreadable version) is
421
+ // cached too. Warns once per distinct pair so repeated checks don't spam the log.
379
422
  const _warnedSkew = new Set();
380
423
  let _skewCache = { key: null, result: undefined };
381
424
  const _skewInflight = new Map(); // binary identity → pending probe
382
425
 
383
426
  function warnSkewOnce(result, claudeBin, log) {
384
- const pair = `${result.discovered}→${result.bundled}`;
427
+ // A newer installation than the SDK was built against is the ordinary state
428
+ // between two SynaBun releases, and nothing to report.
429
+ if (!result.installedOlder) return;
430
+ const pair = `${result.discovered}→${result.reference}`;
385
431
  if (_warnedSkew.has(pair)) return;
386
432
  _warnedSkew.add(pair);
387
- if (result.installedNewer) {
388
- log(
389
- `[claude-models] CLI version skew: the installed CLI ${result.discovered} (${claudeBin}) is newer `
390
- + `than the ${result.bundled} bundled with @anthropic-ai/claude-agent-sdk. Sidepanel sessions and `
391
- + 'native loops will run the installed CLI, so a picked model launches as the version the picker '
392
- + 'names. Bump @anthropic-ai/claude-agent-sdk to the release that bundles it to re-align the runtime.',
393
- );
394
- return;
395
- }
396
433
  log(
397
- `[claude-models] CLI version skew: model picker reads ${result.discovered} (${claudeBin}) `
398
- + `but sidepanel sessions run ${result.bundled} (bundled with @anthropic-ai/claude-agent-sdk). `
399
- + 'Alias ids like "opus[1m]" resolve per-binary, so a picked model can launch as a '
400
- + `different version. Align them: update the installed Claude CLI to ${result.bundled} or newer.`,
434
+ `[claude-models] The installed Claude Code is ${result.discovered} (${claudeBin}); `
435
+ + `@anthropic-ai/claude-agent-sdk was built against ${result.reference}. Sessions run the `
436
+ + `installed one. If a session misbehaves, update Claude Code to ${result.reference} or newer.`,
401
437
  );
402
438
  }
403
439
 
@@ -405,7 +441,7 @@ export async function checkClaudeCliSkew(claudeBin, {
405
441
  log = console.warn,
406
442
  force = false,
407
443
  queryVersion = queryClaudeCliVersion,
408
- bundledVersion = sdkBundledCliVersion,
444
+ referenceVersion = sdkReferenceCliVersion,
409
445
  } = {}) {
410
446
  const key = binaryIdentity(claudeBin);
411
447
  let result;
@@ -415,14 +451,14 @@ export async function checkClaudeCliSkew(claudeBin, {
415
451
  let probe = _skewInflight.get(key);
416
452
  if (!probe) {
417
453
  probe = (async () => {
418
- const bundled = bundledVersion();
419
- const discovered = bundled ? await queryVersion(claudeBin) : null;
420
- const order = compareCliVersions(discovered, bundled);
454
+ const reference = referenceVersion();
455
+ const discovered = reference ? await queryVersion(claudeBin) : null;
456
+ const order = compareCliVersions(discovered, reference);
421
457
  const value = order === null ? null : {
422
458
  discovered,
423
- bundled,
459
+ reference,
424
460
  skewed: order !== 0,
425
- installedNewer: order > 0,
461
+ installedOlder: order < 0,
426
462
  };
427
463
  _skewCache = { key, result: value };
428
464
  return value;
@@ -434,50 +470,3 @@ export async function checkClaudeCliSkew(claudeBin, {
434
470
  if (result?.skewed) warnSkewOnce(result, claudeBin, log);
435
471
  return result;
436
472
  }
437
-
438
- // Synchronous view of the last probe for this binary: the result, null (probed,
439
- // nothing to compare), or undefined (not probed at this identity — typically
440
- // because the CLI was updated since).
441
- export function cachedClaudeCliSkew(claudeBin) {
442
- return _skewCache.key === binaryIdentity(claudeBin) ? _skewCache.result : undefined;
443
- }
444
-
445
- // ── Runtime alignment ─────────────────────────────────────────────────────────
446
- // The picker's model table comes from the installed CLI; SDK sessions (sidepanel)
447
- // and native loops default to the CLI the SDK bundles. When the installed one is
448
- // newer, the same alias resolves to a newer model there — "opus[1m]" is Opus 5.5 on
449
- // 2.1.280 but Opus 5 on 2.1.278 — so the picker would promise a model the session
450
- // cannot launch. In that case sessions run the installed CLI instead. Everywhere
451
- // else the bundled, version-matched binary stays the default: when the versions
452
- // match, when the bundled one is the newer of the two, and when no usable CLI is
453
- // installed.
454
- const _alignFailures = new Set(); // binary identities whose aligned launch failed
455
-
456
- // A launch failure of the aligned CLI sends every later session back to the bundled
457
- // runtime. Keyed by identity, so the next CLI update gets a fresh chance.
458
- export function markAlignedClaudeExecutableFailed(claudeBin) {
459
- const key = binaryIdentity(claudeBin);
460
- if (key) _alignFailures.add(key);
461
- }
462
-
463
- // The path SDK sessions should run instead of the bundled CLI, or null to keep the
464
- // bundled one. Never blocks: when this binary has not been compared yet, the check
465
- // starts in the background and this call answers null, so no session waits on a
466
- // version probe — the next one aligns.
467
- export function alignedClaudeExecutable(claudeBin, {
468
- skew = cachedClaudeCliSkew(claudeBin),
469
- refresh = true,
470
- resolveOverride = resolveClaudeExecutableOverride,
471
- } = {}) {
472
- if (!claudeBin) return null;
473
- if (skew === undefined) {
474
- if (refresh) checkClaudeCliSkew(claudeBin).catch(() => {});
475
- return null;
476
- }
477
- if (!skew?.installedNewer) return null;
478
- if (_alignFailures.has(binaryIdentity(claudeBin))) return null;
479
- // The SDK spawns this path verbatim with shell:false; the shared override
480
- // contract rejects bare command names and anything that is not executable.
481
- const candidate = resolveOverride(claudeBin);
482
- return candidate?.ok && candidate.path ? candidate.path : null;
483
- }
@@ -7,9 +7,9 @@
7
7
  // one sentence the model is told, and the plan files Claude Code writes for it
8
8
  // whatever the options say.
9
9
 
10
- import { lstatSync, readFileSync, realpathSync, statSync, unlinkSync } from 'node:fs';
10
+ import { lstatSync, readFileSync, readdirSync, realpathSync, statSync, unlinkSync } from 'node:fs';
11
11
  import { homedir } from 'node:os';
12
- import { dirname, extname, isAbsolute, join, relative, resolve } from 'node:path';
12
+ import { basename, dirname, extname, isAbsolute, join, relative, resolve } from 'node:path';
13
13
 
14
14
  // Set in the environment of a temporary session's process. SynaBun's Claude
15
15
  // Code hooks read it (hooks/claude-code/shared.mjs, isTemporaryChat) and store,
@@ -386,6 +386,41 @@ export function plansDirsOf(env, { cwd = '', settings = null } = {}) {
386
386
  const real = (p) => { try { return realpathSync(p); } catch { return resolve(p); } };
387
387
  const listOf = (dirs) => (Array.isArray(dirs) ? dirs : [dirs]).filter(Boolean);
388
388
 
389
+ // Resolve existing ancestors too, when the plans directory does not exist yet.
390
+ function realPlanFolder(dir) {
391
+ const full = resolve(dir);
392
+ try { return realpathSync(full); } catch {
393
+ const parent = dirname(full);
394
+ return parent === full ? full : join(realPlanFolder(parent), basename(full));
395
+ }
396
+ }
397
+
398
+ /**
399
+ * Files present before the session starts. Filesystem creation timestamps can
400
+ * lag Date.now(), so they cannot reliably identify a newly created plan.
401
+ * Device/inode identities also preserve existing files after edits or renames.
402
+ * Missing folders start empty; unreadable folders remain unclassified.
403
+ */
404
+ export function snapshotPlanFiles(plansDirs) {
405
+ const before = { roots: new Set(), files: new Set() };
406
+ for (const dir of listOf(plansDirs)) {
407
+ const root = realPlanFolder(dir);
408
+ try {
409
+ for (const name of readdirSync(root)) {
410
+ try { before.files.add(planFileIdentity(lstatSync(join(root, name)))); } catch (err) {
411
+ if (err?.code !== 'ENOENT' && err?.code !== 'ENOTDIR') throw err;
412
+ }
413
+ }
414
+ before.roots.add(root);
415
+ } catch (err) {
416
+ if (err?.code === 'ENOENT') before.roots.add(root);
417
+ }
418
+ }
419
+ return before;
420
+ }
421
+
422
+ const planFileIdentity = (stat) => `${stat.dev}:${stat.ino}`;
423
+
389
424
  /**
390
425
  * The plan file a tool call of the session names, when it is one: a Write or
391
426
  * Edit of a Markdown file directly in a plans folder, or the file an
@@ -407,12 +442,13 @@ export function planFileOfToolCall(block, plansDirs) {
407
442
  * a plans folder whatever the session's options say (`plansDirectory` only
408
443
  * moves it inside the project), so the bridge removes it once the session's
409
444
  * process has ended. Only a regular Markdown file that is really in one of the
410
- * plans folders and was created after the session's process started: a plan
411
- * that was there before is someone else's.
445
+ * plans folders and was absent from the pre-session snapshot: a plan that was
446
+ * there before is someone else's. Callers without a snapshot retain the
447
+ * timestamp check.
412
448
  * @returns {{ removed: string[], failed: string[] }} `failed`: still there
413
449
  * because the removal itself did not work; the caller keeps them and tries again
414
450
  */
415
- export function removeTemporaryPlanFiles(paths, { plansDirs, plansDir, since }) {
451
+ export function removeTemporaryPlanFiles(paths, { plansDirs, plansDir, since, before }) {
416
452
  const removed = [];
417
453
  const failed = [];
418
454
  const roots = new Set();
@@ -422,8 +458,11 @@ export function removeTemporaryPlanFiles(paths, { plansDirs, plansDir, since })
422
458
  if (extname(path).toLowerCase() !== '.md') continue;
423
459
  const stat = lstatSync(path);
424
460
  if (!stat.isFile()) continue; // not a link, not a folder
425
- if (!roots.has(realpathSync(dirname(path)))) continue;
426
- if (!(stat.birthtimeMs >= since)) continue;
461
+ const parent = realpathSync(dirname(path));
462
+ if (!roots.has(parent)) continue;
463
+ if (before) {
464
+ if (!before.roots.has(parent) || before.files.has(planFileIdentity(stat))) continue;
465
+ } else if (!(stat.birthtimeMs >= since)) continue;
427
466
  unlinkSync(path);
428
467
  removed.push(path);
429
468
  } catch (err) {