synabun 2.0.10 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (656) hide show
  1. package/CHANGELOG.md +207 -0
  2. package/README.md +25 -2
  3. package/THIRD-PARTY-LICENSES.md +22 -0
  4. package/bin/synabun.js +71 -24
  5. package/docs/whatsapp.md +13 -13
  6. package/hooks/claude-code/pre-websearch.mjs +12 -1
  7. package/hooks/claude-code/shared.mjs +5 -0
  8. package/hooks/claude-code/stop.mjs +1 -1
  9. package/lib/claude-hooks.js +172 -18
  10. package/lib/client-config-repair.js +30 -17
  11. package/lib/desktop-app.js +7 -1
  12. package/lib/external-tools.js +7 -6
  13. package/lib/first-launch-protection.js +57 -12
  14. package/lib/mcp-dist.js +176 -0
  15. package/lib/release-npm-ci.mjs +138 -0
  16. package/lib/release-publish.mjs +91 -0
  17. package/lib/release-scan.mjs +50 -0
  18. package/lib/server-crash-record.js +123 -0
  19. package/lib/server-exit.js +318 -0
  20. package/lib/server-supervisor.js +508 -0
  21. package/lib/start-launcher.js +37 -4
  22. package/lib/tools-cli.js +45 -0
  23. package/lib/update-snapshot.js +302 -0
  24. package/lib/virustotal.mjs +203 -0
  25. package/lib/windows-crash-event.js +269 -0
  26. package/mcp-server/dist/http.d.ts +20 -1
  27. package/mcp-server/dist/http.d.ts.map +1 -1
  28. package/mcp-server/dist/http.js +59 -12
  29. package/mcp-server/dist/http.js.map +1 -1
  30. package/mcp-server/dist/index.d.ts +33 -27
  31. package/mcp-server/dist/index.d.ts.map +1 -1
  32. package/mcp-server/dist/index.js +128 -143
  33. package/mcp-server/dist/index.js.map +1 -1
  34. package/mcp-server/dist/preload.js +1 -1
  35. package/mcp-server/dist/preload.js.map +1 -1
  36. package/mcp-server/dist/services/budget-judgments.d.ts +1 -1
  37. package/mcp-server/dist/services/budget-judgments.d.ts.map +1 -1
  38. package/mcp-server/dist/services/budget-judgments.js +5 -3
  39. package/mcp-server/dist/services/budget-judgments.js.map +1 -1
  40. package/mcp-server/dist/services/codex-config-heal.d.ts +6 -2
  41. package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
  42. package/mcp-server/dist/services/codex-config-heal.js +81 -28
  43. package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
  44. package/mcp-server/dist/services/identity.d.ts +2 -2
  45. package/mcp-server/dist/services/identity.js +2 -2
  46. package/mcp-server/dist/services/memory-judge-backfill.d.ts +6 -0
  47. package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -1
  48. package/mcp-server/dist/services/memory-judge-backfill.js +7 -1
  49. package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -1
  50. package/mcp-server/dist/services/memory-sessions.d.ts +1 -1
  51. package/mcp-server/dist/services/memory-sessions.d.ts.map +1 -1
  52. package/mcp-server/dist/services/memory-sessions.js +28 -2
  53. package/mcp-server/dist/services/memory-sessions.js.map +1 -1
  54. package/mcp-server/dist/services/neural-interface.d.ts +18 -11
  55. package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
  56. package/mcp-server/dist/services/neural-interface.js +67 -11
  57. package/mcp-server/dist/services/neural-interface.js.map +1 -1
  58. package/mcp-server/dist/services/server-instructions.d.ts +7 -2
  59. package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
  60. package/mcp-server/dist/services/server-instructions.js +22 -63
  61. package/mcp-server/dist/services/server-instructions.js.map +1 -1
  62. package/mcp-server/dist/services/tool-catalog.d.ts +120 -0
  63. package/mcp-server/dist/services/tool-catalog.d.ts.map +1 -0
  64. package/mcp-server/dist/services/tool-catalog.js +339 -0
  65. package/mcp-server/dist/services/tool-catalog.js.map +1 -0
  66. package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts +12 -0
  67. package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts.map +1 -0
  68. package/mcp-server/dist/services/tool-list-refresh-barrier.js +40 -0
  69. package/mcp-server/dist/services/tool-list-refresh-barrier.js.map +1 -0
  70. package/mcp-server/dist/services/tool-list.d.ts +108 -0
  71. package/mcp-server/dist/services/tool-list.d.ts.map +1 -0
  72. package/mcp-server/dist/services/tool-list.js +334 -0
  73. package/mcp-server/dist/services/tool-list.js.map +1 -0
  74. package/mcp-server/dist/services/tool-runtime.d.ts +161 -0
  75. package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -0
  76. package/mcp-server/dist/services/tool-runtime.js +400 -0
  77. package/mcp-server/dist/services/tool-runtime.js.map +1 -0
  78. package/mcp-server/dist/services/typesafe-config.js +1 -1
  79. package/mcp-server/dist/services/typesafe-config.js.map +1 -1
  80. package/mcp-server/dist/services/whiteboard-geometry.d.ts +26 -2
  81. package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -1
  82. package/mcp-server/dist/services/whiteboard-geometry.js +91 -8
  83. package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -1
  84. package/mcp-server/dist/tools/agents.d.ts +14 -14
  85. package/mcp-server/dist/tools/agents.d.ts.map +1 -1
  86. package/mcp-server/dist/tools/agents.js +29 -19
  87. package/mcp-server/dist/tools/agents.js.map +1 -1
  88. package/mcp-server/dist/tools/browser-batch.d.ts +3 -3
  89. package/mcp-server/dist/tools/choice.d.ts +6 -0
  90. package/mcp-server/dist/tools/choice.d.ts.map +1 -1
  91. package/mcp-server/dist/tools/choice.js +18 -13
  92. package/mcp-server/dist/tools/choice.js.map +1 -1
  93. package/mcp-server/dist/tools/git-tools.js +2 -2
  94. package/mcp-server/dist/tools/git-tools.js.map +1 -1
  95. package/mcp-server/dist/tools/image-tools.d.ts +1 -1
  96. package/mcp-server/dist/tools/image-tools.js +1 -1
  97. package/mcp-server/dist/tools/morelogin.d.ts.map +1 -1
  98. package/mcp-server/dist/tools/morelogin.js +9 -6
  99. package/mcp-server/dist/tools/morelogin.js.map +1 -1
  100. package/mcp-server/dist/tools/skill-tools.d.ts +505 -0
  101. package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -0
  102. package/mcp-server/dist/tools/skill-tools.js +642 -0
  103. package/mcp-server/dist/tools/skill-tools.js.map +1 -0
  104. package/mcp-server/dist/tools/skill.d.ts +7 -0
  105. package/mcp-server/dist/tools/skill.d.ts.map +1 -0
  106. package/mcp-server/dist/tools/skill.js +11 -0
  107. package/mcp-server/dist/tools/skill.js.map +1 -0
  108. package/mcp-server/dist/tools/tool-groups.d.ts +68 -0
  109. package/mcp-server/dist/tools/tool-groups.d.ts.map +1 -0
  110. package/mcp-server/dist/tools/tool-groups.js +147 -0
  111. package/mcp-server/dist/tools/tool-groups.js.map +1 -0
  112. package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -1
  113. package/mcp-server/dist/tools/whiteboard-format.js +7 -4
  114. package/mcp-server/dist/tools/whiteboard-format.js.map +1 -1
  115. package/mcp-server/dist/tools/whiteboard-tools.d.ts +64 -13
  116. package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -1
  117. package/mcp-server/dist/tools/whiteboard-tools.js +30 -5
  118. package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -1
  119. package/mcp-server/package-lock.json +2 -2
  120. package/mcp-server/package.json +1 -1
  121. package/mcp-server/src/http.ts +75 -12
  122. package/mcp-server/src/index.ts +147 -154
  123. package/mcp-server/src/preload.ts +12 -12
  124. package/mcp-server/src/services/budget-judgments.ts +5 -3
  125. package/mcp-server/src/services/codex-config-heal.ts +80 -29
  126. package/mcp-server/src/services/identity.ts +2 -2
  127. package/mcp-server/src/services/memory-judge-backfill.ts +7 -1
  128. package/mcp-server/src/services/memory-sessions.ts +24 -3
  129. package/mcp-server/src/services/neural-interface.ts +81 -21
  130. package/mcp-server/src/services/server-instructions.ts +29 -64
  131. package/mcp-server/src/services/tool-catalog.ts +403 -0
  132. package/mcp-server/src/services/tool-list-refresh-barrier.ts +33 -0
  133. package/mcp-server/src/services/tool-list.ts +410 -0
  134. package/mcp-server/src/services/tool-runtime.ts +457 -0
  135. package/mcp-server/src/services/typesafe-config.ts +1 -1
  136. package/mcp-server/src/services/whiteboard-geometry.ts +94 -9
  137. package/mcp-server/src/tools/agents.ts +29 -20
  138. package/mcp-server/src/tools/choice.ts +17 -12
  139. package/mcp-server/src/tools/git-tools.ts +2 -2
  140. package/mcp-server/src/tools/image-tools.ts +1 -1
  141. package/mcp-server/src/tools/morelogin.ts +6 -4
  142. package/mcp-server/src/tools/skill-tools.ts +592 -0
  143. package/mcp-server/src/tools/skill.ts +13 -0
  144. package/mcp-server/src/tools/tool-groups.ts +164 -0
  145. package/mcp-server/src/tools/whiteboard-format.ts +9 -3
  146. package/mcp-server/src/tools/whiteboard-tools.ts +39 -5
  147. package/neural-interface/i18n/en.json +3953 -228
  148. package/neural-interface/i18n/pt-BR.json +3901 -179
  149. package/neural-interface/lib/agent-sandbox-elevation.js +6 -0
  150. package/neural-interface/lib/antigravity/acp-client-host.js +554 -0
  151. package/neural-interface/lib/antigravity/acp-connection.js +299 -0
  152. package/neural-interface/lib/antigravity/bypass.js +100 -0
  153. package/neural-interface/lib/antigravity/catalog.js +273 -0
  154. package/neural-interface/lib/antigravity/home.js +260 -0
  155. package/neural-interface/lib/antigravity/migrate-gemini.js +139 -0
  156. package/neural-interface/lib/antigravity/panel-bridge.js +1058 -0
  157. package/neural-interface/lib/antigravity/policy-hook.mjs +78 -0
  158. package/neural-interface/lib/antigravity/policy.js +74 -0
  159. package/neural-interface/lib/antigravity/tool-call.js +178 -0
  160. package/neural-interface/lib/antigravity/transcripts.js +252 -0
  161. package/neural-interface/lib/antigravity/usage.js +43 -0
  162. package/neural-interface/lib/assistant-api.js +128 -28
  163. package/neural-interface/lib/assistant-brains/antigravity.js +423 -0
  164. package/neural-interface/lib/assistant-brains/claude.js +4 -3
  165. package/neural-interface/lib/assistant-brains/codex-browser-policy-hook.mjs +12 -2
  166. package/neural-interface/lib/assistant-brains/codex-route-gate-hook.mjs +32 -9
  167. package/neural-interface/lib/assistant-brains/codex.js +9 -5
  168. package/neural-interface/lib/assistant-brains/opencode.js +120 -54
  169. package/neural-interface/lib/assistant-brains/opencode2-browser-policy/index.js +28 -13
  170. package/neural-interface/lib/assistant-brains/opencode2-route-gate/index.js +59 -19
  171. package/neural-interface/lib/assistant-budget-planner.js +7 -3
  172. package/neural-interface/lib/assistant-budget-split.js +42 -15
  173. package/neural-interface/lib/assistant-catalog.js +81 -15
  174. package/neural-interface/lib/assistant-config.js +6 -3
  175. package/neural-interface/lib/assistant-dispatch.js +1073 -200
  176. package/neural-interface/lib/assistant-envelope.js +156 -2
  177. package/neural-interface/lib/assistant-evidence.js +80 -0
  178. package/neural-interface/lib/assistant-hidden-models.js +7 -5
  179. package/neural-interface/lib/assistant-persona.js +93 -19
  180. package/neural-interface/lib/assistant-plan-permissions.js +25 -9
  181. package/neural-interface/lib/assistant-route-gate-codex.js +3 -0
  182. package/neural-interface/lib/assistant-route-gate.js +6 -4
  183. package/neural-interface/lib/assistant-router.js +245 -38
  184. package/neural-interface/lib/assistant-runtime.js +214 -30
  185. package/neural-interface/lib/assistant-task-prompt.js +87 -21
  186. package/neural-interface/lib/assistant-tools.js +51 -0
  187. package/neural-interface/lib/assistant-usage.js +29 -0
  188. package/neural-interface/lib/backup-service.js +626 -4
  189. package/neural-interface/lib/backup-zip-reader.js +10 -5
  190. package/neural-interface/lib/backup-zip-writer.js +257 -0
  191. package/neural-interface/lib/browser-execution.js +10 -2
  192. package/neural-interface/lib/browser-guard-cdp.js +84 -0
  193. package/neural-interface/lib/browser-network-guard.js +476 -0
  194. package/neural-interface/lib/browser-policy-roots.js +64 -0
  195. package/neural-interface/lib/browser-tool-policy.js +198 -38
  196. package/neural-interface/lib/claude-agent-bridge.js +11 -2
  197. package/neural-interface/lib/claude-history-cache.js +210 -0
  198. package/neural-interface/lib/claude-hooks-status.js +103 -0
  199. package/neural-interface/lib/claude-model-catalog.js +5 -1
  200. package/neural-interface/lib/claude-temporary.js +5 -11
  201. package/neural-interface/lib/cli-install-api.js +1 -1
  202. package/neural-interface/lib/cli-install.js +163 -154
  203. package/neural-interface/lib/cli-resolver.js +13 -3
  204. package/neural-interface/lib/cli-update-planner.js +52 -41
  205. package/neural-interface/lib/cloudflared/tunnel.js +42 -2
  206. package/neural-interface/lib/codex-mcp-approvals.js +11 -0
  207. package/neural-interface/lib/codex-rollout-reader.js +52 -0
  208. package/neural-interface/lib/codex-worker-app-server.js +191 -0
  209. package/neural-interface/lib/confined-fs.js +30 -3
  210. package/neural-interface/lib/crash-notice-api.js +98 -0
  211. package/neural-interface/lib/editor-completion-opencode.js +68 -68
  212. package/neural-interface/lib/editor-git-api.js +3 -20
  213. package/neural-interface/lib/exec-loop-command.js +13 -10
  214. package/neural-interface/lib/file-explorer-api.js +74 -40
  215. package/neural-interface/lib/file-explorer-watch.js +9 -3
  216. package/neural-interface/lib/git-bash/install.js +52 -6
  217. package/neural-interface/lib/git-bash/manager.js +59 -17
  218. package/neural-interface/lib/git-bash/pins.js +12 -0
  219. package/neural-interface/lib/git-read.js +2 -2
  220. package/neural-interface/lib/git-status-runner.js +390 -0
  221. package/neural-interface/lib/git-status-watchdog.js +40 -0
  222. package/neural-interface/lib/greeting/budgets.js +1 -0
  223. package/neural-interface/lib/greeting/engine.js +2 -2
  224. package/neural-interface/lib/greeting/sources.js +10 -12
  225. package/neural-interface/lib/greeting/writer.js +1 -1
  226. package/neural-interface/lib/http-guards.js +8 -2
  227. package/neural-interface/lib/install-details.js +4 -1
  228. package/neural-interface/lib/mcp-agent-servers.js +67 -0
  229. package/neural-interface/lib/mcp-client-config.js +35 -33
  230. package/neural-interface/lib/mcp-external-servers.js +332 -0
  231. package/neural-interface/lib/mcp-installer.js +2 -1
  232. package/neural-interface/lib/{mcp-profile-refresh-coordinator.js → mcp-tools-refresh-coordinator.js} +4 -4
  233. package/neural-interface/lib/memory-session-capture.js +17 -3
  234. package/neural-interface/lib/morelogin.js +177 -25
  235. package/neural-interface/lib/native-loop-providers.js +965 -66
  236. package/neural-interface/lib/native-loop-runtime.js +290 -42
  237. package/neural-interface/lib/opencode-config.js +557 -0
  238. package/neural-interface/lib/opencode-db-schema.js +17 -34
  239. package/neural-interface/lib/opencode-history.js +48 -218
  240. package/neural-interface/lib/opencode-mcp-ready.js +108 -0
  241. package/neural-interface/lib/opencode-native-boundary.js +53 -0
  242. package/neural-interface/lib/opencode-protocol.js +249 -112
  243. package/neural-interface/lib/opencode-runtime-config.js +32 -22
  244. package/neural-interface/lib/opencode-serve-records.js +39 -21
  245. package/neural-interface/lib/opencode-v2-client.js +48 -153
  246. package/neural-interface/lib/opencode-v2-ws-requests.js +36 -210
  247. package/neural-interface/lib/opencode-worker-data.js +27 -0
  248. package/neural-interface/lib/opencode2-client.js +73 -37
  249. package/neural-interface/lib/opencode2-proxy.js +23 -63
  250. package/neural-interface/lib/opencode2-translate.js +51 -2
  251. package/neural-interface/lib/owner-authority.js +249 -0
  252. package/neural-interface/lib/page-session.js +275 -0
  253. package/neural-interface/lib/path-confine.js +12 -9
  254. package/neural-interface/lib/peer-identity.js +793 -0
  255. package/neural-interface/lib/pty-host/core.js +28 -1
  256. package/neural-interface/lib/pty-host/lifetime.js +12 -0
  257. package/neural-interface/lib/pty-host/manager.js +12 -1
  258. package/neural-interface/lib/remote-policy.js +1 -1
  259. package/neural-interface/lib/request-gate.js +20 -2
  260. package/neural-interface/lib/rulesets/api.js +7 -6
  261. package/neural-interface/lib/rulesets/fs-safe.js +1 -1
  262. package/neural-interface/lib/rulesets/installer.js +180 -36
  263. package/neural-interface/lib/rulesets/json-edit.js +1 -1
  264. package/neural-interface/lib/rulesets/render.js +1 -1
  265. package/neural-interface/lib/session-cache-builder.js +81 -31
  266. package/neural-interface/lib/session-title-generator.js +58 -36
  267. package/neural-interface/lib/skills/api-v2.js +495 -0
  268. package/neural-interface/lib/skills/bundle.js +418 -0
  269. package/neural-interface/lib/skills/catalog.js +298 -0
  270. package/neural-interface/lib/skills/creation-api.js +191 -0
  271. package/neural-interface/lib/skills/creation-brief.js +247 -0
  272. package/neural-interface/lib/skills/creation-sources.js +285 -0
  273. package/neural-interface/lib/skills/creation.js +843 -0
  274. package/neural-interface/lib/skills/deploy.js +569 -0
  275. package/neural-interface/lib/skills/digest.js +119 -0
  276. package/neural-interface/lib/skills/discover.js +111 -0
  277. package/neural-interface/lib/skills/draft-confinement.js +216 -0
  278. package/neural-interface/lib/skills/eval-confinement.js +399 -0
  279. package/neural-interface/lib/skills/eval-sandbox.js +280 -0
  280. package/neural-interface/lib/skills/eval-trace.js +135 -0
  281. package/neural-interface/lib/skills/evals-api.js +212 -0
  282. package/neural-interface/lib/skills/evals.js +1573 -0
  283. package/neural-interface/lib/skills/export.js +203 -0
  284. package/neural-interface/lib/skills/frontmatter.js +64 -0
  285. package/neural-interface/lib/skills/health.js +75 -0
  286. package/neural-interface/lib/skills/json-edit.js +165 -0
  287. package/neural-interface/lib/skills/known-bridge-digests.json +441 -0
  288. package/neural-interface/lib/skills/known-bridges.js +96 -0
  289. package/neural-interface/lib/skills/library.js +823 -0
  290. package/neural-interface/lib/skills/local-store.js +21 -0
  291. package/neural-interface/lib/skills/migration.js +433 -0
  292. package/neural-interface/lib/skills/operations.js +45 -0
  293. package/neural-interface/lib/skills/ownership.js +427 -0
  294. package/neural-interface/lib/skills/packages.js +88 -0
  295. package/neural-interface/lib/skills/reviews.js +212 -0
  296. package/neural-interface/lib/skills/revision.js +80 -0
  297. package/neural-interface/lib/skills/roots.js +269 -0
  298. package/neural-interface/lib/skills/runtime-checks.js +358 -0
  299. package/neural-interface/lib/skills/scan-assets.js +252 -0
  300. package/neural-interface/lib/skills/scan-context.js +26 -0
  301. package/neural-interface/lib/skills/scan-shell.js +324 -0
  302. package/neural-interface/lib/skills/scan.js +364 -0
  303. package/neural-interface/lib/skills/scanners.js +54 -0
  304. package/neural-interface/lib/skills/service.js +530 -0
  305. package/neural-interface/lib/skills/telemetry.js +119 -0
  306. package/neural-interface/lib/sqlite-integrity-worker.js +22 -0
  307. package/neural-interface/lib/synabun-version.js +1 -1
  308. package/neural-interface/lib/system-activity.js +1 -1
  309. package/neural-interface/lib/tool-lists.js +124 -0
  310. package/neural-interface/lib/whatsapp/brain.js +7 -3
  311. package/neural-interface/lib/whatsapp/bridge.js +6 -3
  312. package/neural-interface/lib/whatsapp/cards.js +22 -9
  313. package/neural-interface/lib/whatsapp/config.js +1 -1
  314. package/neural-interface/lib/worker-confinement.js +1268 -0
  315. package/neural-interface/lib/worker-guard-setting.js +56 -0
  316. package/neural-interface/lib/worker-mcp-channel.js +175 -0
  317. package/neural-interface/lib/worker-question.js +74 -0
  318. package/neural-interface/lib/worker-relay-ports.js +227 -0
  319. package/neural-interface/lib/worker-resume.js +238 -0
  320. package/neural-interface/lib/worker-sandbox.js +329 -0
  321. package/neural-interface/package-lock.json +34 -12
  322. package/neural-interface/package.json +3 -2
  323. package/neural-interface/public/index.html +3 -1
  324. package/neural-interface/public/index2d.html +19 -11
  325. package/neural-interface/public/onboarding.html +3 -3
  326. package/neural-interface/public/shared/account-menu.js +8 -5
  327. package/neural-interface/public/shared/agent-runtime-options.js +125 -31
  328. package/neural-interface/public/shared/agy/agy-bypass.js +47 -0
  329. package/neural-interface/public/shared/agy/agy-client.js +266 -0
  330. package/neural-interface/public/shared/agy/agy-commands.js +120 -0
  331. package/neural-interface/public/shared/agy/agy-copy.js +326 -0
  332. package/neural-interface/public/shared/agy/agy-diff.js +161 -0
  333. package/neural-interface/public/shared/agy/agy-events.js +469 -0
  334. package/neural-interface/public/shared/agy/agy-greeting.js +26 -0
  335. package/neural-interface/public/shared/agy/agy-options.js +232 -0
  336. package/neural-interface/public/shared/agy/agy-panel.js +2543 -0
  337. package/neural-interface/public/shared/agy/agy-render.js +392 -0
  338. package/neural-interface/public/shared/agy/agy-setup.js +149 -0
  339. package/neural-interface/public/shared/agy/agy-styles.js +604 -0
  340. package/neural-interface/public/shared/agy/agy-tabs-logic.js +181 -0
  341. package/neural-interface/public/shared/api.js +1527 -1336
  342. package/neural-interface/public/shared/app-frame.js +192 -0
  343. package/neural-interface/public/shared/assistant/asst-agents-dock.js +36 -6
  344. package/neural-interface/public/shared/assistant/asst-api.js +1 -1
  345. package/neural-interface/public/shared/assistant/asst-ask-styles.js +270 -0
  346. package/neural-interface/public/shared/assistant/asst-ask-tail.js +118 -0
  347. package/neural-interface/public/shared/assistant/asst-ask.js +397 -0
  348. package/neural-interface/public/shared/assistant/asst-brain-picker.js +105 -44
  349. package/neural-interface/public/shared/assistant/asst-budget.js +5 -4
  350. package/neural-interface/public/shared/assistant/asst-control.js +205 -26
  351. package/neural-interface/public/shared/assistant/asst-followups-card.js +383 -0
  352. package/neural-interface/public/shared/assistant/asst-followups.js +417 -0
  353. package/neural-interface/public/shared/assistant/asst-hosts.js +16 -7
  354. package/neural-interface/public/shared/assistant/asst-limit-dock.js +45 -0
  355. package/neural-interface/public/shared/assistant/asst-limit-wait.js +327 -0
  356. package/neural-interface/public/shared/assistant/asst-limit.js +168 -0
  357. package/neural-interface/public/shared/assistant/asst-mascot.js +49 -12
  358. package/neural-interface/public/shared/assistant/asst-menu.js +7 -6
  359. package/neural-interface/public/shared/assistant/asst-panel.js +151 -19
  360. package/neural-interface/public/shared/assistant/asst-rack-styles.js +66 -49
  361. package/neural-interface/public/shared/assistant/asst-render.js +445 -82
  362. package/neural-interface/public/shared/assistant/asst-route.js +304 -53
  363. package/neural-interface/public/shared/assistant/asst-routes-editor.js +9 -8
  364. package/neural-interface/public/shared/assistant/asst-scenes.js +56 -1
  365. package/neural-interface/public/shared/assistant/asst-sidepanel.js +117 -10
  366. package/neural-interface/public/shared/assistant/asst-slash.js +17 -9
  367. package/neural-interface/public/shared/assistant/asst-state.js +87 -24
  368. package/neural-interface/public/shared/assistant/asst-stop.js +127 -0
  369. package/neural-interface/public/shared/assistant/asst-styles.js +93 -21
  370. package/neural-interface/public/shared/assistant/asst-tool-kinds.js +190 -23
  371. package/neural-interface/public/shared/assistant/asst-usage.js +2 -1
  372. package/neural-interface/public/shared/automation-context.js +5 -2
  373. package/neural-interface/public/shared/cc-dropdown.js +89 -19
  374. package/neural-interface/public/shared/cdx/cdx-context-menu.js +10 -9
  375. package/neural-interface/public/shared/cdx/cdx-copy.js +16 -0
  376. package/neural-interface/public/shared/cdx/cdx-output-model.js +22 -1
  377. package/neural-interface/public/shared/cdx/cdx-output.js +34 -10
  378. package/neural-interface/public/shared/cdx/cdx-panel.js +59 -151
  379. package/neural-interface/public/shared/cdx/cdx-preview.js +12 -0
  380. package/neural-interface/public/shared/cdx/cdx-protocol.js +39 -11
  381. package/neural-interface/public/shared/cdx/cdx-render.js +57 -38
  382. package/neural-interface/public/shared/cdx/cdx-requests.js +14 -4
  383. package/neural-interface/public/shared/cdx/cdx-skill-hints.js +54 -0
  384. package/neural-interface/public/shared/cdx/cdx-styles.js +15 -3
  385. package/neural-interface/public/shared/cdx/cdx-tabs.js +127 -44
  386. package/neural-interface/public/shared/cdx/cdx-ws.js +0 -1
  387. package/neural-interface/public/shared/cli-install-controller.js +218 -0
  388. package/neural-interface/public/shared/cli-install-view.js +11 -12
  389. package/neural-interface/public/shared/cli-status.js +11 -10
  390. package/neural-interface/public/shared/constants.js +5 -4
  391. package/neural-interface/public/shared/context-menu-areas.js +34 -0
  392. package/neural-interface/public/shared/context-menu-logic.js +243 -0
  393. package/neural-interface/public/shared/context-menu-model.js +367 -0
  394. package/neural-interface/public/shared/context-menu.js +372 -0
  395. package/neural-interface/public/shared/cp/cp-context-menu.js +10 -9
  396. package/neural-interface/public/shared/cp/cp-restore.js +162 -0
  397. package/neural-interface/public/shared/cp/cp-tool-cards.js +10 -3
  398. package/neural-interface/public/shared/crash-notice-view.js +168 -0
  399. package/neural-interface/public/shared/desktop-bridge.js +17 -0
  400. package/neural-interface/public/shared/desktop-titlebar-view.js +12 -0
  401. package/neural-interface/public/shared/desktop-titlebar.js +13 -4
  402. package/neural-interface/public/shared/desktop-update-view.js +21 -0
  403. package/neural-interface/public/shared/editor/editor-panel-logic.js +2 -2
  404. package/neural-interface/public/shared/explorer/fx-api.js +4 -4
  405. package/neural-interface/public/shared/explorer/fx-links.js +3 -3
  406. package/neural-interface/public/shared/explorer/fx-logic.js +1 -1
  407. package/neural-interface/public/shared/explorer/fx-main.js +48 -16
  408. package/neural-interface/public/shared/explorer/fx-tree.js +1 -0
  409. package/neural-interface/public/shared/greeting/greeting-card.js +2 -2
  410. package/neural-interface/public/shared/greeting/greeting-view.js +1 -0
  411. package/neural-interface/public/shared/html-shell.js +30 -15
  412. package/neural-interface/public/shared/i18n.js +2 -0
  413. package/neural-interface/public/shared/ocp-v2/ocp-v2-approvals.js +7 -7
  414. package/neural-interface/public/shared/ocp-v2/ocp-v2-binding.js +4 -4
  415. package/neural-interface/public/shared/ocp-v2/ocp-v2-changes-logic.js +3 -101
  416. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +2 -0
  417. package/neural-interface/public/shared/ocp-v2/ocp-v2-compact-button.js +1 -3
  418. package/neural-interface/public/shared/ocp-v2/ocp-v2-composer-logic.js +2 -6
  419. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-menu.js +11 -11
  420. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-model.js +0 -3
  421. package/neural-interface/public/shared/ocp-v2/ocp-v2-events.js +8 -4
  422. package/neural-interface/public/shared/ocp-v2/ocp-v2-manager.js +7 -7
  423. package/neural-interface/public/shared/ocp-v2/ocp-v2-outcome-notifications.js +16 -0
  424. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +74 -259
  425. package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +1 -2
  426. package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +95 -202
  427. package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +13 -4
  428. package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +13 -22
  429. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +4 -4
  430. package/neural-interface/public/shared/ocp-v2/ocp-v2-session-actions.js +8 -61
  431. package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +2 -91
  432. package/neural-interface/public/shared/ocp-v2/ocp-v2-slash-hints.js +16 -15
  433. package/neural-interface/public/shared/ocp-v2/ocp-v2-state.js +8 -21
  434. package/neural-interface/public/shared/ocp-v2/ocp-v2-status-logic.js +1 -99
  435. package/neural-interface/public/shared/ocp-v2/ocp-v2-status.js +5 -35
  436. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +17 -21
  437. package/neural-interface/public/shared/ocp-v2/{ocp-v2-profile-inheritance.js → ocp-v2-tools-inheritance.js} +16 -16
  438. package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +60 -50
  439. package/neural-interface/public/shared/page-session.js +96 -0
  440. package/neural-interface/public/shared/provider-icons.js +4 -2
  441. package/neural-interface/public/shared/registry.js +5 -3
  442. package/neural-interface/public/shared/retired-2d.js +3 -0
  443. package/neural-interface/public/shared/schedules-view.js +195 -61
  444. package/neural-interface/public/shared/settings/settings-claude-hooks.js +135 -0
  445. package/neural-interface/public/shared/settings/settings-data.js +3 -1
  446. package/neural-interface/public/shared/settings/settings-ia.js +6 -6
  447. package/neural-interface/public/shared/settings/settings-opencode.js +89 -0
  448. package/neural-interface/public/shared/settings/settings-rules.js +2 -2
  449. package/neural-interface/public/shared/settings/settings-skill-folders-pane.js +265 -0
  450. package/neural-interface/public/shared/settings/settings-skill-folders.js +130 -0
  451. package/neural-interface/public/shared/settings/settings-worker-guard.js +72 -0
  452. package/neural-interface/public/shared/showcase-privacy.js +6 -1
  453. package/neural-interface/public/shared/sidepanel-session-status.js +3 -3
  454. package/neural-interface/public/shared/skills/ss-args.js +96 -0
  455. package/neural-interface/public/shared/skills/ss-creation.js +222 -0
  456. package/neural-interface/public/shared/skills/ss-dialog.js +133 -0
  457. package/neural-interface/public/shared/skills/ss-doc.js +173 -0
  458. package/neural-interface/public/shared/skills/ss-eval-adapters.js +269 -0
  459. package/neural-interface/public/shared/skills/ss-eval-grade.js +359 -0
  460. package/neural-interface/public/shared/skills/ss-eval-optimise.js +153 -0
  461. package/neural-interface/public/shared/skills/ss-eval-plan.js +315 -0
  462. package/neural-interface/public/shared/skills/ss-evals.js +417 -0
  463. package/neural-interface/public/shared/skills/ss-form.js +159 -0
  464. package/neural-interface/public/shared/skills/ss-frontmatter.js +376 -0
  465. package/neural-interface/public/shared/skills/ss-ids.js +32 -0
  466. package/neural-interface/public/shared/skills/ss-lint.js +149 -0
  467. package/neural-interface/public/shared/skills/ss-presets.js +117 -0
  468. package/neural-interface/public/shared/skills/ss-profiles.js +513 -0
  469. package/neural-interface/public/shared/skills/ss-resources.js +165 -0
  470. package/neural-interface/public/shared/skills/ss-review-view.js +190 -0
  471. package/neural-interface/public/shared/skills/ss-tabs.js +79 -0
  472. package/neural-interface/public/shared/skills/ss-unicode.js +135 -0
  473. package/neural-interface/public/shared/skills/studio/sx-actions.js +222 -0
  474. package/neural-interface/public/shared/skills/studio/sx-cm.js +101 -0
  475. package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +749 -0
  476. package/neural-interface/public/shared/skills/studio/sx-create-ai.js +237 -0
  477. package/neural-interface/public/shared/skills/studio/sx-create-view.js +254 -0
  478. package/neural-interface/public/shared/skills/studio/sx-create.js +126 -0
  479. package/neural-interface/public/shared/skills/studio/sx-diff-view.js +43 -0
  480. package/neural-interface/public/shared/skills/studio/sx-diff.js +133 -0
  481. package/neural-interface/public/shared/skills/studio/sx-docs.js +480 -0
  482. package/neural-interface/public/shared/skills/studio/sx-dom.js +230 -0
  483. package/neural-interface/public/shared/skills/studio/sx-edit-view.js +848 -0
  484. package/neural-interface/public/shared/skills/studio/sx-editor-model.js +193 -0
  485. package/neural-interface/public/shared/skills/studio/sx-errors.js +22 -0
  486. package/neural-interface/public/shared/skills/studio/sx-fixes-view.js +359 -0
  487. package/neural-interface/public/shared/skills/studio/sx-fixes.js +327 -0
  488. package/neural-interface/public/shared/skills/studio/sx-geometry.js +82 -0
  489. package/neural-interface/public/shared/skills/studio/sx-import.js +262 -0
  490. package/neural-interface/public/shared/skills/studio/sx-inspector.js +308 -0
  491. package/neural-interface/public/shared/skills/studio/sx-install-flow.js +282 -0
  492. package/neural-interface/public/shared/skills/studio/sx-install.js +313 -0
  493. package/neural-interface/public/shared/skills/studio/sx-library-view.js +748 -0
  494. package/neural-interface/public/shared/skills/studio/sx-library.js +479 -0
  495. package/neural-interface/public/shared/skills/studio/sx-main.js +690 -0
  496. package/neural-interface/public/shared/skills/studio/sx-operations-view.js +98 -0
  497. package/neural-interface/public/shared/skills/studio/sx-operations.js +11 -0
  498. package/neural-interface/public/shared/skills/studio/sx-plan.js +158 -0
  499. package/neural-interface/public/shared/skills/studio/sx-publish-view.js +621 -0
  500. package/neural-interface/public/shared/skills/studio/sx-review-view.js +369 -0
  501. package/neural-interface/public/shared/skills/studio/sx-review.js +148 -0
  502. package/neural-interface/public/shared/skills/studio/sx-scan.js +35 -0
  503. package/neural-interface/public/shared/skills/studio/sx-snippets.js +96 -0
  504. package/neural-interface/public/shared/skills/studio/sx-subject.js +249 -0
  505. package/neural-interface/public/shared/skills/studio/sx-test-view.js +994 -0
  506. package/neural-interface/public/shared/skills/studio/sx-test.js +328 -0
  507. package/neural-interface/public/shared/skills/studio/sx-versions-view.js +241 -0
  508. package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +426 -0
  509. package/neural-interface/public/shared/state.js +1 -1
  510. package/neural-interface/public/shared/streaming-markdown.js +58 -0
  511. package/neural-interface/public/shared/styleguide/sg-panel.js +4 -2
  512. package/neural-interface/public/shared/styles.css +1822 -1756
  513. package/neural-interface/public/shared/synabun-mascot.js +1115 -9
  514. package/neural-interface/public/shared/text-cache.js +29 -0
  515. package/neural-interface/public/shared/tool-list-picker.js +55 -0
  516. package/neural-interface/public/shared/tool-list-storage.js +24 -0
  517. package/neural-interface/public/shared/tool-list-view.js +112 -0
  518. package/neural-interface/public/shared/topright-overflow-logic.js +54 -0
  519. package/neural-interface/public/shared/tour/tour-actor.js +268 -0
  520. package/neural-interface/public/shared/tour/tour-beats.js +336 -0
  521. package/neural-interface/public/shared/tour/tour-engine.js +884 -0
  522. package/neural-interface/public/shared/tour/tour-ink.js +390 -0
  523. package/neural-interface/public/shared/tour/tour-stage.js +440 -0
  524. package/neural-interface/public/shared/tour/tour-state.js +40 -0
  525. package/neural-interface/public/shared/tour/tour-tips.js +99 -0
  526. package/neural-interface/public/shared/tour/tour.css +144 -0
  527. package/neural-interface/public/shared/ui-antigravity-panel.js +19 -0
  528. package/neural-interface/public/shared/ui-assistant.js +2 -0
  529. package/neural-interface/public/shared/ui-automation-studio.js +111 -140
  530. package/neural-interface/public/shared/ui-claude-panel.js +376 -82
  531. package/neural-interface/public/shared/ui-cli-banner.js +23 -167
  532. package/neural-interface/public/shared/ui-command-runner.js +6 -3
  533. package/neural-interface/public/shared/ui-context-menu.js +295 -0
  534. package/neural-interface/public/shared/ui-cost-widget.js +57 -59
  535. package/neural-interface/public/shared/ui-crash-notice.js +187 -0
  536. package/neural-interface/public/shared/ui-detail.js +15 -3
  537. package/neural-interface/public/shared/ui-file-explorer.js +48 -6
  538. package/neural-interface/public/shared/ui-file-links.js +2 -2
  539. package/neural-interface/public/shared/ui-games.js +2 -2
  540. package/neural-interface/public/shared/ui-image-gallery.js +50 -47
  541. package/neural-interface/public/shared/ui-judgments.js +1 -1
  542. package/neural-interface/public/shared/ui-keybinds.js +33 -2
  543. package/neural-interface/public/shared/ui-link.js +3 -3
  544. package/neural-interface/public/shared/ui-menubar.js +10 -20
  545. package/neural-interface/public/shared/ui-native-loop-router-state.js +5 -0
  546. package/neural-interface/public/shared/ui-native-loop-router.js +11 -1
  547. package/neural-interface/public/shared/ui-navbar.js +49 -24
  548. package/neural-interface/public/shared/ui-notifications.js +1 -0
  549. package/neural-interface/public/shared/ui-panels.js +96 -65
  550. package/neural-interface/public/shared/ui-resume.js +9 -7
  551. package/neural-interface/public/shared/ui-schedules-studio.js +546 -431
  552. package/neural-interface/public/shared/ui-scroll-follow.js +16 -5
  553. package/neural-interface/public/shared/ui-sessions.js +27 -15
  554. package/neural-interface/public/shared/ui-settings.js +683 -526
  555. package/neural-interface/public/shared/ui-sidepanel-session-entry.js +9 -2
  556. package/neural-interface/public/shared/ui-sidepanel-sessions.js +4 -4
  557. package/neural-interface/public/shared/ui-sidepanel-state.js +23 -12
  558. package/neural-interface/public/shared/ui-sidepanel-tray.js +48 -7
  559. package/neural-interface/public/shared/ui-sidepanel-windows.js +18 -13
  560. package/neural-interface/public/shared/ui-skills.js +33 -2830
  561. package/neural-interface/public/shared/ui-styleguide.js +5 -2
  562. package/neural-interface/public/shared/ui-sync.js +15 -5
  563. package/neural-interface/public/shared/ui-terminal.js +270 -190
  564. package/neural-interface/public/shared/ui-tool-updates.js +6 -4
  565. package/neural-interface/public/shared/ui-tooltip.js +81 -51
  566. package/neural-interface/public/shared/ui-topright-overflow.js +233 -0
  567. package/neural-interface/public/shared/ui-trash.js +6 -4
  568. package/neural-interface/public/shared/ui-tutorial-layout.js +3 -117
  569. package/neural-interface/public/shared/ui-tutorial-preview.js +103 -0
  570. package/neural-interface/public/shared/ui-tutorial-steps.js +3 -65
  571. package/neural-interface/public/shared/ui-tutorial.css +47 -100
  572. package/neural-interface/public/shared/ui-tutorial.js +285 -509
  573. package/neural-interface/public/shared/ui-update.js +38 -2
  574. package/neural-interface/public/shared/ui-whiteboard.js +312 -59
  575. package/neural-interface/public/shared/ui-worker-end.js +5 -1
  576. package/neural-interface/public/shared/ui-workspaces.js +3 -2
  577. package/neural-interface/public/shared/view-variant.js +66 -0
  578. package/neural-interface/public/shared/whatsapp/wa-view.js +3 -3
  579. package/neural-interface/public/shared/whiteboard-list.js +172 -0
  580. package/neural-interface/public/shared/worker-end.js +10 -3
  581. package/neural-interface/public/shared/worker-questions.js +34 -0
  582. package/neural-interface/public/shared/worker-restart.js +12 -0
  583. package/neural-interface/public/sidepanel-session.html +2 -2
  584. package/neural-interface/public/variant/2d/background.js +2 -1
  585. package/neural-interface/public/variant/2d/context-menu.js +8 -2
  586. package/neural-interface/public/variant/2d/graph.js +42 -20
  587. package/neural-interface/public/variant/2d/hulls.js +14 -9
  588. package/neural-interface/public/variant/2d/lasso.js +11 -7
  589. package/neural-interface/public/variant/2d/main.js +32 -1
  590. package/neural-interface/public/variant/2d/minimap.js +11 -13
  591. package/neural-interface/public/variant/3d/main.js +69 -6
  592. package/neural-interface/public/variant/3d/map-controls.js +24 -9
  593. package/neural-interface/public/vendor/caveat/OFL.txt +93 -0
  594. package/neural-interface/public/vendor/caveat/caveat-latin-400-normal.woff2 +0 -0
  595. package/neural-interface/public/vendor/caveat/caveat-latin-700-normal.woff2 +0 -0
  596. package/neural-interface/public/vendor/caveat/caveat.css +17 -0
  597. package/neural-interface/public/vendor/caveat/manifest.json +12 -0
  598. package/neural-interface/public/vendor/yaml/LICENSE +13 -0
  599. package/neural-interface/public/vendor/yaml/manifest.json +4 -0
  600. package/neural-interface/public/vendor/yaml/yaml-2.9.1.min.js +137 -0
  601. package/neural-interface/scripts/build-vendor.mjs +32 -0
  602. package/neural-interface/server.js +4553 -2855
  603. package/neural-interface/templates/rulesets/README.md +1 -1
  604. package/neural-interface/templates/rulesets/core.md +1 -1
  605. package/neural-interface/templates/rulesets/legacy-hashes.json +23 -5
  606. package/neural-interface/templates/rulesets/manifest.json +8 -8
  607. package/npm-shrinkwrap.json +34 -12
  608. package/package.json +17 -3
  609. package/postinstall.js +9 -4
  610. package/preuninstall.js +1 -1
  611. package/setup.js +97 -322
  612. package/skills/skill-forge/SKILL.md +177 -0
  613. package/skills/skill-forge/evals/evals.json +54 -0
  614. package/skills/skill-forge/references/package.md +105 -0
  615. package/skills/skill-forge/references/review-and-recovery.md +63 -0
  616. package/skills/skill-forge/references/runtime-profiles.md +20 -0
  617. package/skills/skill-forge/references/sources-and-capabilities.md +51 -0
  618. package/skills/synabun/SKILL.md +10 -7
  619. package/skills/synabun/modules/audit.md +1 -5
  620. package/skills/synabun/modules/changelog.md +1 -5
  621. package/skills/synabun/modules/idea.md +1 -1
  622. package/skills/synabun/modules/memorize.md +6 -9
  623. package/skills/synabun/modules/schedule.md +6 -6
  624. package/mcp-server/dist/services/profiles.d.ts +0 -120
  625. package/mcp-server/dist/services/profiles.d.ts.map +0 -1
  626. package/mcp-server/dist/services/profiles.js +0 -387
  627. package/mcp-server/dist/services/profiles.js.map +0 -1
  628. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +0 -97
  629. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +0 -1
  630. package/mcp-server/dist/tools/leonardo-browser-tools.js +0 -228
  631. package/mcp-server/dist/tools/leonardo-browser-tools.js.map +0 -1
  632. package/mcp-server/dist/tools/leonardo.d.ts +0 -13
  633. package/mcp-server/dist/tools/leonardo.d.ts.map +0 -1
  634. package/mcp-server/dist/tools/leonardo.js +0 -21
  635. package/mcp-server/dist/tools/leonardo.js.map +0 -1
  636. package/mcp-server/dist/tools/profile.d.ts +0 -17
  637. package/mcp-server/dist/tools/profile.d.ts.map +0 -1
  638. package/mcp-server/dist/tools/profile.js +0 -114
  639. package/mcp-server/dist/tools/profile.js.map +0 -1
  640. package/mcp-server/src/services/profiles.ts +0 -428
  641. package/mcp-server/src/tools/leonardo-browser-tools.ts +0 -291
  642. package/mcp-server/src/tools/leonardo.ts +0 -30
  643. package/mcp-server/src/tools/profile.ts +0 -122
  644. package/neural-interface/lib/assistant-brains/opencode-browser-policy.js +0 -47
  645. package/neural-interface/lib/assistant-brains/opencode-route-gate.js +0 -62
  646. package/neural-interface/lib/mcp-profile-servers.js +0 -120
  647. package/neural-interface/public/shared/ui-tutorial-draw.js +0 -311
  648. package/skills/leonardo/SKILL.md +0 -168
  649. package/skills/leonardo/icon.svg +0 -1
  650. package/skills/leonardo/modules/browser-guide.md +0 -378
  651. package/skills/leonardo/modules/image-prompter.md +0 -283
  652. package/skills/leonardo/modules/model-advisor.md +0 -100
  653. package/skills/leonardo/modules/prompt-library.md +0 -110
  654. package/skills/leonardo/modules/style-guide.md +0 -186
  655. package/skills/leonardo/modules/video-prompter.md +0 -317
  656. /package/neural-interface/templates/rulesets/{gemini.md → antigravity.md} +0 -0
@@ -1,6 +1,8 @@
1
- import { resolve } from 'node:path';
1
+ import { accessSync, constants, statSync } from 'node:fs';
2
+ import { homedir, tmpdir } from 'node:os';
3
+ import { isAbsolute, join, resolve, sep } from 'node:path';
2
4
  import { PACKAGE_ROOT } from './paths.js';
3
- import { durableEntry, packagedRuntime } from './packaged-runtime.js';
5
+ import { durableEntry, isReadOnlyVolumePath, isTransientPath, packagedRuntime } from './packaged-runtime.js';
4
6
 
5
7
  // Handler identity must be byte-for-byte identical across settings scopes.
6
8
  // Claude Code deduplicates matching settings handlers before executing them.
@@ -27,10 +29,10 @@ export function hookDefinitionsForEvent(event) {
27
29
  return HOOK_SCRIPTS.filter(def => events.includes(def.event));
28
30
  }
29
31
 
30
- // No shell-specific environment expansion, install paths, or downloads. Walk
31
- // up from the project/cwd for checkout-only installs, then use the installed
32
- // root. Single quotes inside JS work inside the command's double quotes on
33
- // both cmd.exe and POSIX shells. Keep this versioned literal stable.
32
+ // No install paths or downloads. Walk up from the project/cwd for checkout-only
33
+ // installs, then use the installed root. Single quotes inside JS work inside
34
+ // the command's double quotes on both cmd.exe and POSIX shells. Keep this
35
+ // versioned literal stable.
34
36
  const BOOTSTRAP = "const f=require('node:fs'),p=require('node:path'),u=require('node:url'),s=process.argv[1];let r;const ok=d=>{try{return JSON.parse(f.readFileSync(p.join(d,'package.json'),'utf8')).name==='synabun'&&f.existsSync(p.join(d,'hooks','claude-code',s))}catch{return false}};for(let d=p.resolve(process.env.CLAUDE_PROJECT_DIR||process.cwd());;d=p.dirname(d)){if(ok(d)){r=d;break}if(d===p.dirname(d))break}if(!r&&process.env.SYNABUN_HOOK_ROOT&&ok(process.env.SYNABUN_HOOK_ROOT))r=process.env.SYNABUN_HOOK_ROOT;if(!r)throw Error('SynaBun hook root unavailable; repair the hook installation');import(u.pathToFileURL(p.join(r,'hooks','claude-code',s)).href)";
35
37
 
36
38
  /**
@@ -49,23 +51,48 @@ function quoteHookEntry(entry) {
49
51
  return `"${entry.replace(/[\\"$`]/g, '\\$&')}"`;
50
52
  }
51
53
 
54
+ // Windows: cmd.exe, PowerShell and Git Bash all run this, and a Windows program
55
+ // gets the user's PATH from the registry whoever starts it.
52
56
  const nodeHookCommand = scriptName => `node -e "${BOOTSTRAP}" ${scriptName}`;
53
57
 
58
+ /**
59
+ * Where a hook started without the login PATH looks for Node after `node` on
60
+ * PATH: the official installer's and Homebrew's folders and Volta's shim (the
61
+ * Node a terminal finds, as a rule), then SYNABUN_NODE. The same names on every
62
+ * machine.
63
+ */
64
+ export const HOOK_NODE_FOLDERS = Object.freeze(['/usr/local/bin/node', '/opt/homebrew/bin/node', '$HOME/.volta/bin/node']);
65
+
66
+ // macOS and Linux: Claude Code runs a settings hook with /bin/sh in its own
67
+ // environment. Started from a terminal that has the login PATH; started from
68
+ // the Dock, Finder, a desktop app or launchd it is /usr/bin:/bin:/usr/sbin:/sbin,
69
+ // where `node` is not found and every hook exits 127. So: `node` on PATH, as a
70
+ // terminal finds it, then the usual folders, then the Node the installer named
71
+ // in the user's settings (SYNABUN_NODE: nvm and the like have no usual folder).
72
+ // Nothing in it names this machine, so the tracked template and the projects'
73
+ // settings carry it as they are.
74
+ const POSIX_NODE_FINDER = `n=$(command -v node) || for n in ${HOOK_NODE_FOLDERS.map(p => (p.startsWith('$') ? `"${p}"` : p)).join(' ')} "$SYNABUN_NODE"; do [ -f "$n" ] && [ -x "$n" ] && break; n=node; done; `;
75
+ const posixHookCommand = scriptName => `${POSIX_NODE_FINDER}exec "$n" -e "${BOOTSTRAP}" ${scriptName}`;
76
+
54
77
  // Whatever entry wrote it: an application that moved must still find, and
55
78
  // repair, its own handlers.
56
79
  const PACKAGED_HOOK_COMMAND = new RegExp(`^"(?:[^"\\\\]|\\\\.)+"\\s+${PACKAGED_HOOK_MODE}\\s+(\\S+)$`);
57
80
 
58
- export function hookCommandString(scriptName, _targetProjectPath, runtime = packagedRuntime()) {
81
+ export function hookCommandString(scriptName, _targetProjectPath, runtime = packagedRuntime(), platform = process.platform) {
59
82
  if (!HOOK_SCRIPTS.some(h => h.script === scriptName)) throw new Error('Unknown SynaBun hook');
60
83
  const entry = durableEntry(runtime);
61
- return entry ? `${quoteHookEntry(entry)} ${PACKAGED_HOOK_MODE} ${scriptName}` : nodeHookCommand(scriptName);
84
+ if (entry) return `${quoteHookEntry(entry)} ${PACKAGED_HOOK_MODE} ${scriptName}`;
85
+ return platform === 'win32' ? nodeHookCommand(scriptName) : posixHookCommand(scriptName);
62
86
  }
63
87
 
64
88
  export function isSynaBunHookCommand(command, scriptName) {
65
89
  if (typeof command !== 'string') return false;
66
- // Both canonical forms, whichever kind of install is reading: moving between
67
- // an npm install and the application must not leave two handlers behind.
68
- if (command === nodeHookCommand(scriptName)) return true;
90
+ // Every canonical form, whichever kind of install and system is reading:
91
+ // moving between an npm install and the application, or a settings file
92
+ // shared between Windows and macOS, must not leave two handlers behind.
93
+ if (command === nodeHookCommand(scriptName) || command === posixHookCommand(scriptName)) return true;
94
+ // Any version of the POSIX finder in front of the same bootstrap.
95
+ if (command.startsWith('n=$(command -v node)') && command.endsWith(` -e "${BOOTSTRAP}" ${scriptName}`)) return true;
69
96
  const packaged = command.trim().match(PACKAGED_HOOK_COMMAND);
70
97
  if (packaged) return packaged[1] === scriptName;
71
98
  // Recognize only the old direct-node path forms, including cross-OS installs.
@@ -98,25 +125,47 @@ export function hookInstallPlan({ target, registered = false, hook } = {}, runti
98
125
  return target === 'project' && !registered && !hook ? 'register-only' : 'refuse';
99
126
  }
100
127
 
101
- export function ensureHookRoot(settings, targetProjectPath, packageRoot = PACKAGE_ROOT, runtime = packagedRuntime()) {
128
+ /**
129
+ * The Node a hook falls back to when Claude Code was started without the login
130
+ * PATH (SYNABUN_NODE): the one running SynaBun, which is known to run its hooks,
131
+ * when its path outlives this run. null on Windows (its programs get the user's
132
+ * PATH) and for a Node in a temporary place.
133
+ */
134
+ export function hookNodePin({ execPath = process.execPath, platform = process.platform, env = process.env, writable } = {}) {
135
+ if (platform === 'win32' || typeof execPath !== 'string' || !isAbsolute(execPath)) return null;
136
+ if (isTransientPath(execPath, env) || isReadOnlyVolumePath(execPath, { platform, writable })) return null;
137
+ const temporary = [tmpdir(), '/tmp', '/private/tmp', '/private/var/folders', '/var/folders'];
138
+ if (temporary.some(dir => resolve(execPath).startsWith(`${resolve(dir)}${sep}`))) return null;
139
+ return execPath;
140
+ }
141
+
142
+ export function ensureHookRoot(settings, targetProjectPath, packageRoot = PACKAGE_ROOT, runtime = packagedRuntime(), { node = hookNodePin() } = {}) {
102
143
  // A packaged application's command finds its own handlers, and its package
103
144
  // root can be a mount that ends with the run.
104
145
  if (runtime) return false;
105
146
  // The checked-in template must not acquire a machine-specific env path.
106
147
  if (targetProjectPath && resolve(targetProjectPath) === resolve(packageRoot)) return false;
107
- if (settings.env?.SYNABUN_HOOK_ROOT === resolve(packageRoot)) return false;
108
- settings.env = { ...settings.env, SYNABUN_HOOK_ROOT: resolve(packageRoot) };
109
- return true;
148
+ let changed = false;
149
+ if (settings.env?.SYNABUN_HOOK_ROOT !== resolve(packageRoot)) {
150
+ settings.env = { ...settings.env, SYNABUN_HOOK_ROOT: resolve(packageRoot) };
151
+ changed = true;
152
+ }
153
+ // The user's own settings only (this machine's file): every session gets its env.
154
+ if (!targetProjectPath && node && settings.env?.SYNABUN_NODE !== node) {
155
+ settings.env = { ...settings.env, SYNABUN_NODE: node };
156
+ changed = true;
157
+ }
158
+ return changed;
110
159
  }
111
160
 
112
- export function sweepSettingsHooks(settings, targetProjectPath, stats = {}, packageRoot = PACKAGE_ROOT, runtime = packagedRuntime()) {
161
+ export function sweepSettingsHooks(settings, targetProjectPath, stats = {}, packageRoot = PACKAGE_ROOT, runtime = packagedRuntime(), { platform = process.platform, node = hookNodePin({ platform }) } = {}) {
113
162
  if (!settings?.hooks || hookInstallBlocker(runtime)) return false;
114
163
  let changed = false;
115
164
  let ownsHooks = false;
116
165
  for (const def of HOOK_SCRIPTS) {
117
166
  const entries = settings.hooks[def.event];
118
167
  if (!Array.isArray(entries)) continue;
119
- const command = hookCommandString(def.script, targetProjectPath, runtime);
168
+ const command = hookCommandString(def.script, targetProjectPath, runtime, platform);
120
169
  const matches = entries.flatMap(e => (e.hooks || []).filter(h => isSynaBunHookCommand(h.command, def.script)).map(h => ({ entry: e, hook: h })));
121
170
  if (!matches.length) continue;
122
171
  ownsHooks = true;
@@ -133,6 +182,111 @@ export function sweepSettingsHooks(settings, targetProjectPath, stats = {}, pack
133
182
  settings.hooks[def.event] = [...rest, { matcher: def.matcher || '', hooks: [{ type: 'command', command, timeout: def.timeout }] }];
134
183
  changed = true;
135
184
  }
136
- if (ownsHooks && ensureHookRoot(settings, targetProjectPath, packageRoot, runtime)) changed = true;
185
+ if (ownsHooks && ensureHookRoot(settings, targetProjectPath, packageRoot, runtime, { node })) changed = true;
137
186
  return changed;
138
187
  }
188
+
189
+ // ── What is really installed (Settings → Automations → Claude Code hooks) ────
190
+
191
+ /**
192
+ * What one settings file holds of SynaBun's handlers. `handlers`: one per
193
+ * HOOK_SCRIPTS entry, with `copies` (SynaBun handlers for that script in any
194
+ * form) and `current` (one of them is this machine's command, matcher and
195
+ * timeout); `events`: every handler of the event present; `installed` /
196
+ * `current` / `total` count handlers, `duplicates` the extra copies (each runs).
197
+ */
198
+ export function hookInstallState(settings, { targetProjectPath, runtime = packagedRuntime(), platform = process.platform } = {}) {
199
+ const handlers = HOOK_SCRIPTS.map((def) => {
200
+ const entries = Array.isArray(settings?.hooks?.[def.event]) ? settings.hooks[def.event] : [];
201
+ const owned = entries.flatMap(entry => (Array.isArray(entry?.hooks) ? entry.hooks : [])
202
+ .filter(hook => isSynaBunHookCommand(hook?.command, def.script)).map(hook => ({ entry, hook })));
203
+ const command = hookCommandString(def.script, targetProjectPath, runtime, platform);
204
+ const current = owned.some(({ entry, hook }) => hook.command === command && (entry.matcher || '') === (def.matcher || '') && hook.timeout === def.timeout);
205
+ return { event: def.event, script: def.script, copies: owned.length, current };
206
+ });
207
+ const events = {};
208
+ for (const h of handlers) events[h.event] = (events[h.event] ?? true) && h.copies > 0;
209
+ return {
210
+ handlers,
211
+ events,
212
+ installed: handlers.filter(h => h.copies > 0).length,
213
+ current: handlers.filter(h => h.current).length,
214
+ duplicates: handlers.reduce((sum, h) => sum + Math.max(0, h.copies - 1), 0),
215
+ total: handlers.length,
216
+ };
217
+ }
218
+
219
+ /** The commands of SynaBun's handlers in a settings file, script by script (to compare two scopes). */
220
+ export function hookCommandsOf(settings) {
221
+ const out = {};
222
+ for (const def of HOOK_SCRIPTS) {
223
+ const entries = Array.isArray(settings?.hooks?.[def.event]) ? settings.hooks[def.event] : [];
224
+ const commands = entries.flatMap(entry => (Array.isArray(entry?.hooks) ? entry.hooks : []))
225
+ .map(hook => hook?.command).filter(command => isSynaBunHookCommand(command, def.script));
226
+ out[`${def.event}:${def.script}`] = [...new Set(commands)].sort();
227
+ }
228
+ return out;
229
+ }
230
+
231
+ /**
232
+ * Whether a project's SynaBun handlers run once next to the user's: Claude Code
233
+ * runs one copy of identical handlers from both files, and both of different
234
+ * ones. 'same' (nothing of SynaBun's there, or the same commands), 'different'.
235
+ */
236
+ export function projectHooksAgree(userSettings, projectSettings) {
237
+ const user = hookCommandsOf(userSettings);
238
+ const project = hookCommandsOf(projectSettings);
239
+ for (const [key, commands] of Object.entries(project)) {
240
+ if (!commands.length) continue;
241
+ const mine = user[key] || [];
242
+ if (!mine.length) continue; // only the project runs it: once
243
+ if (commands.some(command => !mine.includes(command))) return 'different';
244
+ }
245
+ return 'same';
246
+ }
247
+
248
+ /** Claude Code's own switches that stop SynaBun's handlers, in one settings file: the first that applies, or null. */
249
+ export function hooksSwitchedOff(settings, { managed = false } = {}) {
250
+ if (!settings || typeof settings !== 'object') return null;
251
+ if (settings.disableAllHooks === true) return 'disableAllHooks';
252
+ // Only managed settings can keep user and project hooks from running.
253
+ if (managed && settings.allowManagedHooksOnly === true) return 'allowManagedHooksOnly';
254
+ return null;
255
+ }
256
+
257
+ /** Where Claude Code reads managed (organization) settings on this system. */
258
+ export function managedClaudeSettingsPath(platform = process.platform) {
259
+ if (platform === 'darwin') return '/Library/Application Support/ClaudeCode/managed-settings.json';
260
+ if (platform === 'win32') return 'C:\\Program Files\\ClaudeCode\\managed-settings.json';
261
+ return '/etc/claude-code/managed-settings.json';
262
+ }
263
+
264
+ /** The PATH macOS gives a program it starts from the Dock, Finder or launchd. */
265
+ export const LAUNCHD_PATH = Object.freeze(['/usr/bin', '/bin', '/usr/sbin', '/sbin']);
266
+
267
+ function runnableFile(path) {
268
+ try {
269
+ if (!statSync(path).isFile()) return false;
270
+ accessSync(path, constants.X_OK);
271
+ return true;
272
+ } catch { return false; }
273
+ }
274
+
275
+ /**
276
+ * The Node a SynaBun hook would run with in a Claude Code started without the
277
+ * login PATH (the Dock, Finder, a desktop app, launchd): what the POSIX command
278
+ * tries after PATH, in its order. { path, via: 'SYNABUN_NODE' | 'folder' } or
279
+ * null (such a session would fail every hook). Windows: not asked (null).
280
+ */
281
+ export function hookNodeWithoutPath({ env = {}, home = homedir(), platform = process.platform, runnable = runnableFile } = {}) {
282
+ if (platform === 'win32') return null;
283
+ // `command -v node` on the PATH such a launch has (a Linux distribution's own Node).
284
+ for (const dir of LAUNCHD_PATH) if (runnable(`${dir}/node`)) return { path: `${dir}/node`, via: 'PATH' };
285
+ for (const folder of HOOK_NODE_FOLDERS) {
286
+ const path = folder.startsWith('$HOME/') ? join(home, folder.slice('$HOME/'.length)) : folder;
287
+ if (runnable(path)) return { path, via: 'folder' };
288
+ }
289
+ const pinned = typeof env.SYNABUN_NODE === 'string' ? env.SYNABUN_NODE : '';
290
+ if (pinned && runnable(pinned)) return { path: pinned, via: 'SYNABUN_NODE' };
291
+ return null;
292
+ }
@@ -15,12 +15,20 @@ import {
15
15
  import { dirname, join, resolve } from 'node:path';
16
16
  import { homedir } from 'node:os';
17
17
  import {
18
- mergeGeminiMcpConfig,
19
- mergeOpenCodeMcpConfig,
18
+ mergeAntigravityMcpConfig,
19
+ parseAntigravityMcpConfig,
20
20
  } from '../neural-interface/lib/mcp-client-config.js';
21
+ import {
22
+ mcpServersOf,
23
+ opencodeConfigDir,
24
+ opencodeConfigFilePath,
25
+ opencodeMcpServerEntry,
26
+ setMcpServer,
27
+ } from '../neural-interface/lib/opencode-config.js';
21
28
  import {
22
29
  inspectCodexConfig,
23
30
  upsertCodexMcpConfig,
31
+ upsertCodexMcpContent,
24
32
  } from '../mcp-server/dist/services/codex-config-heal.js';
25
33
  import { mcpStdioCommand } from './packaged-runtime.js';
26
34
 
@@ -60,11 +68,12 @@ export function auditAndRepairClientConfigs({
60
68
  } = {}) {
61
69
  if (!dataHome || !packageRoot) throw new Error('dataHome and packageRoot are required');
62
70
  const definition = buildCanonicalMcpDefinition({ dataHome, packageRoot });
71
+ // Codex loads every SynaBun tool (its deferred catalog); a Codex runtime's own list is only its focus.
63
72
  const codexDefinition = {
64
73
  ...definition,
65
74
  env: {
66
75
  ...definition.env,
67
- SYNABUN_PROFILE: 'full',
76
+ SYNABUN_TOOLS: 'all',
68
77
  SYNABUN_TOOL_CATALOG_MODE: 'deferred',
69
78
  },
70
79
  };
@@ -94,22 +103,26 @@ export function auditAndRepairClientConfigs({
94
103
  results.claude = { exists: existsSync(claudePath), connected: false, changed: false, path: claudePath };
95
104
  }
96
105
 
97
- const geminiPath = join(home, '.gemini', 'settings.json');
98
- const gemini = readJson(geminiPath);
99
- if (gemini?.mcpServers?.SynaBun) {
100
- const next = mergeGeminiMcpConfig(gemini, definition);
101
- const changed = jsonChanged(gemini, next);
102
- if (apply && changed) writeJsonAtomic(geminiPath, next);
103
- results.gemini = { exists: true, connected: true, changed, path: geminiPath };
106
+ // Google Antigravity (the `agy` CLI and the app share it): ~/.gemini/config/mcp_config.json, mcpServers.SynaBun.
107
+ // The file Antigravity creates is empty until a server is added; one that is not JSON is left alone.
108
+ const antigravityPath = join(home, '.gemini', 'config', 'mcp_config.json');
109
+ let antigravity = null;
110
+ try { antigravity = parseAntigravityMcpConfig(readFileSync(antigravityPath, 'utf-8')); } catch { antigravity = null; }
111
+ if (antigravity?.mcpServers?.SynaBun) {
112
+ const next = mergeAntigravityMcpConfig(antigravity, definition);
113
+ const changed = jsonChanged(antigravity, next);
114
+ if (apply && changed) writeJsonAtomic(antigravityPath, next);
115
+ results.antigravity = { exists: true, connected: true, changed, path: antigravityPath };
104
116
  } else {
105
- results.gemini = { exists: existsSync(geminiPath), connected: false, changed: false, path: geminiPath };
117
+ results.antigravity = { exists: existsSync(antigravityPath), connected: false, changed: false, path: antigravityPath };
106
118
  }
107
119
 
108
- const xdgConfigHome = process.env.XDG_CONFIG_HOME || join(home, '.config');
109
- const openCodePath = join(xdgConfigHome, 'opencode', 'config.json');
120
+ // OpenCode 2's global opencode.json (it never reads the config.json of OpenCode 1), its mcp.servers.SynaBun:
121
+ // the folder the rest of SynaBun writes (OPENCODE_CONFIG_DIR, else XDG_CONFIG_HOME's, else ~/.config/opencode).
122
+ const openCodePath = opencodeConfigFilePath(opencodeConfigDir({ home }));
110
123
  const openCode = readJson(openCodePath);
111
- if (openCode?.mcp?.SynaBun) {
112
- const next = mergeOpenCodeMcpConfig(openCode, 'SynaBun', definition);
124
+ if (mcpServersOf(openCode).SynaBun) {
125
+ const next = setMcpServer(structuredClone(openCode), 'SynaBun', opencodeMcpServerEntry(definition));
113
126
  const changed = jsonChanged(openCode, next);
114
127
  if (apply && changed) writeJsonAtomic(openCodePath, next);
115
128
  results.opencode = { exists: true, connected: true, changed, path: openCodePath };
@@ -126,9 +139,9 @@ export function auditAndRepairClientConfigs({
126
139
  upsertCodexMcpConfig(codexPath, codexDefinition);
127
140
  changed = before !== readFileSync(codexPath, 'utf-8');
128
141
  } else {
142
+ // What the repair would write, compared with what is there: a value like "all" is in most files anyway.
129
143
  const content = readFileSync(codexPath, 'utf-8');
130
- changed = ![codexDefinition.command, ...codexDefinition.args].every(value => content.includes(value))
131
- || !Object.values(codexDefinition.env).every(value => content.includes(value));
144
+ changed = upsertCodexMcpContent(content, codexDefinition) !== content;
132
145
  }
133
146
  results.codex = { exists: true, connected: true, changed, path: codexPath, health: codexHealth };
134
147
  } else {
@@ -193,9 +193,15 @@ export async function runAppBackend({
193
193
  // 3. Start, through the launcher (lock, supervisor record, background start).
194
194
  let launcherPid = null;
195
195
  let lastPhase = null;
196
+ let lastStep = null;
197
+ // A phase is said when it begins; the snapshot also says how far it is (its step, the bytes done), for the
198
+ // window's progress bar.
196
199
  const reportPhase = (current) => {
197
- if (!current?.phase || current.phase === lastPhase) return;
200
+ if (!current?.phase) return;
201
+ const step = current.phase === 'snapshot' ? `${current.detail?.step ?? ''}:${current.detail?.done ?? ''}:${current.detail?.state ?? ''}` : null;
202
+ if (current.phase === lastPhase && step === lastStep) return;
198
203
  lastPhase = current.phase;
204
+ lastStep = step;
199
205
  emit({ type: 'supervisor', phase: current.phase, detail: current.detail || null });
200
206
  };
201
207
  const reporter = () => ({
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * SynaBun — external tools stay external
3
3
  *
4
- * Claude Code, Codex, OpenCode and Gemini CLI are programs of their own. The
4
+ * Claude Code, Codex, OpenCode and the Antigravity CLI are programs of their own. The
5
5
  * user installs them; SynaBun finds what is installed (Settings, PATH and the
6
6
  * OS PATH, the folders of every install method:
7
7
  * neural-interface/lib/cli-resolver.js) and talks to it, through a thin
@@ -66,14 +66,15 @@ export const EXTERNAL_TOOLS = Object.freeze([
66
66
  label: 'OpenCode',
67
67
  command: 'opencode',
68
68
  packages: Object.freeze(['opencode-ai']),
69
- // (@opencode-ai/sdk is the JavaScript client and is not matched.)
69
+ // (No OpenCode client package ships: SynaBun speaks to OpenCode 2's serve itself, neural-interface/lib/opencode2-client.js.)
70
70
  patterns: Object.freeze([new RegExp(`^opencode-${PLATFORMS}-`)]),
71
71
  }),
72
72
  Object.freeze({
73
- id: 'gemini',
74
- label: 'Gemini CLI',
75
- command: 'gemini',
76
- packages: Object.freeze(['@google/gemini-cli', '@google/gemini-cli-core']),
73
+ // Google ships the Antigravity CLI as a signed binary (no npm package): only its command is matched.
74
+ id: 'antigravity',
75
+ label: 'Antigravity CLI',
76
+ command: 'agy',
77
+ packages: Object.freeze([]),
77
78
  patterns: Object.freeze([]),
78
79
  }),
79
80
  ]);
@@ -11,6 +11,16 @@
11
11
  // The launcher also leaves its stop message in the server's stderr log
12
12
  // (recordLauncherFailure), because a detached launch has no terminal: the
13
13
  // updater's relaunch reads it back to tell the user why SynaBun did not start.
14
+ //
15
+ // The snapshot is the backup service's upgrade snapshot (createUpgradeSnapshot):
16
+ // a consistent copy of each database (a clone where the file system clones)
17
+ // that passed SQLite's integrity check, stored uncompressed, checksummed as it
18
+ // is written and read back once. The desktop app takes it itself before it
19
+ // replaces its own files (lib/update-snapshot.js) and hands it over; this start
20
+ // uses it only when the data home is still what it was taken from
21
+ // (checkUpgradeSnapshotFreshness), whatever process wrote since: an AI tool's
22
+ // own MCP server may have saved a memory while the app swapped itself. Then it
23
+ // takes a new one, here, before the server and so any migration runs.
14
24
 
15
25
  import { appendFileSync, existsSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
16
26
  import { resolve } from 'node:path';
@@ -31,19 +41,41 @@ function readJson(path, fallback) {
31
41
  /**
32
42
  * Why the snapshot an in-app update handed over cannot stand in for a fresh
33
43
  * one, or null when it can. It can only when the updater recorded that it
34
- * installed exactly the version now launching, and the archive still passes
35
- * verification. A `prepared` update is not enough: its updater may never have
36
- * run while the old server went on changing data.
44
+ * installed exactly the version now launching, the archive passes verification
45
+ * and its database copy passed SQLite's integrity check, and (the desktop app's
46
+ * snapshot, which records what it was taken from) nothing it protects changed
47
+ * since it was taken. A `prepared` update is not enough: its updater may never
48
+ * have run while the old server went on changing data.
37
49
  */
38
- async function handoffSnapshotProblem({ handoff, version, backupService }) {
50
+ async function handoffSnapshotProblem({ handoff, version, backupService, dataHome }) {
39
51
  if (handoff.status !== 'installed') return 'that update was prepared but never recorded as installed';
40
52
  if (typeof handoff.target !== 'string' || handoff.target !== version) return 'it belongs to an update to another version';
41
53
  if (typeof handoff.snapshotPath !== 'string' || !handoff.snapshotPath) return 'it names no snapshot';
42
54
  if (!existsSync(handoff.snapshotPath)) return 'its snapshot file is gone';
43
55
  try {
44
56
  const service = await backupService();
45
- const archive = await service.verifyBackupArchive(handoff.snapshotPath);
46
- if (archive?.kind !== 'pre-update') return 'its file is not a pre-update snapshot';
57
+ let manifest;
58
+ // The desktop app read its snapshot back once, right after writing it, and
59
+ // recorded which file that was. The very same file, untouched since (device,
60
+ // inode, size, modification time), is not read a second time: only its
61
+ // manifest. Any other file is read in full.
62
+ if (handoff.verifiedStamp && typeof service.sameBackupFile === 'function' && typeof service.readBackupArchiveManifest === 'function'
63
+ && service.sameBackupFile(handoff.snapshotPath, handoff.verifiedStamp)) {
64
+ manifest = await service.readBackupArchiveManifest(handoff.snapshotPath);
65
+ if (manifest?.verified !== true) return 'its file is not a verified snapshot';
66
+ } else {
67
+ manifest = await service.verifyBackupArchive(handoff.snapshotPath);
68
+ }
69
+ if (manifest?.kind !== 'pre-update') return 'its file is not a pre-update snapshot';
70
+ // The restore runs SQLite's integrity check on the database it puts back: a copy that never passed it is no copy.
71
+ if (manifest.database && manifest.database.integrity !== 'ok') return 'its database copy was not checked with SQLite\'s integrity check';
72
+ // The data as it is now, before anything of this version touches it. The desktop app's snapshot says what it was
73
+ // taken from; the npm updater's (taken by the old server right before it stopped) does not, and is used as before.
74
+ if (handoff.source === 'desktop' || manifest.inputs) {
75
+ if (typeof service.checkUpgradeSnapshotFreshness !== 'function') return 'this version cannot tell whether the data changed since';
76
+ const freshness = await service.checkUpgradeSnapshotFreshness({ dataHome, manifest, databasePath: resolve(dataHome, 'mcp-data', 'memory.db') });
77
+ if (!freshness?.fresh) return `the data changed after it was taken (${freshness?.reason || 'unknown'})`;
78
+ }
47
79
  } catch (error) {
48
80
  return `its snapshot did not pass verification (${error?.message || error})`;
49
81
  }
@@ -94,7 +126,10 @@ export async function protectFirstLaunchAfterUpdate({
94
126
  let snapshotPath = null;
95
127
  if (pendingHandoff) {
96
128
  info('Checking the snapshot taken by the updater...');
97
- const problem = await handoffSnapshotProblem({ handoff, version, backupService });
129
+ // The desktop app's splash says it: the copy made before the update is compared with the data (supervisor phase
130
+ // `snapshot`, step `check`).
131
+ progress({ step: 'check' });
132
+ const problem = await handoffSnapshotProblem({ handoff, version, backupService, dataHome });
98
133
  if (problem) info(`The updater's snapshot is not used: ${problem}. Taking a new one.`);
99
134
  else {
100
135
  snapshotPath = handoff.snapshotPath;
@@ -106,11 +141,16 @@ export async function protectFirstLaunchAfterUpdate({
106
141
  if (!snapshotPath) {
107
142
  const folderPath = resolve(dataHome, 'backups', 'updates');
108
143
  let service;
144
+ let lastPhase = null;
109
145
  try {
110
146
  info(`Protecting user state before first launch of v${version}...`);
111
147
  progress({});
112
148
  service = await backupService();
113
- const snapshot = await service.createVerifiedBackup({
149
+ // The upgrade snapshot where the service has it (every SynaBun since 2026-10-21); the full backup otherwise.
150
+ const takeSnapshot = typeof service.createUpgradeSnapshot === 'function'
151
+ ? options => service.createUpgradeSnapshot(options)
152
+ : options => service.createVerifiedBackup(options);
153
+ const snapshot = await takeSnapshot({
114
154
  dataHome,
115
155
  databasePath: resolve(dataHome, 'mcp-data', 'memory.db'),
116
156
  folderPath,
@@ -118,17 +158,22 @@ export async function protectFirstLaunchAfterUpdate({
118
158
  appVersion: manifest.lastAppVersion || null,
119
159
  // Without this the checksum and archive phases run silently for minutes
120
160
  // on a large data home, which users read as a hang and kill.
121
- onProgress: ({ phase, files, bytes, skippedFiles, skippedBytes }) => {
122
- progress({ step: phase, files, bytes, skippedFiles });
161
+ onProgress: ({ phase, files, bytes, skippedFiles, skippedBytes, done, total, method, state }) => {
162
+ progress({ step: phase, files, bytes, skippedFiles, done, total, ...(state ? { state } : {}) });
163
+ // Each phase is said once, when it begins; the steps within it only reach the progress bar.
164
+ if (phase === lastPhase) return;
165
+ lastPhase = phase;
123
166
  const size = bytes ? ` (${(bytes / 1024 / 1024).toFixed(0)} MB)` : '';
124
167
  if (phase === 'collect') {
125
168
  info(` ${files} files to protect${size}`);
126
169
  if (skippedFiles) {
127
170
  info(` Skipping ${skippedFiles} generated media files (${(skippedBytes / 1024 / 1024).toFixed(0)} MB) — an upgrade never touches them`);
128
171
  }
129
- } else if (phase === 'checksum') info(` Checksumming ${files} files...`);
130
- else if (phase === 'archive') info(` Compressing${size}...`);
172
+ } else if (phase === 'copy') info(` Copying the databases${method === 'clone' ? ' (a file system clone)' : ''}...`);
173
+ else if (phase === 'checksum') info(` Checksumming ${files} files...`);
174
+ else if (phase === 'archive') info(total ? ` Writing the archive (${(total / 1024 / 1024).toFixed(0)} MB)...` : ` Compressing${size}...`);
131
175
  else if (phase === 'verify') info(' Verifying archive integrity...');
176
+ else if (phase === 'integrity') info(' Finishing SQLite\'s integrity check of the database copies...');
132
177
  },
133
178
  });
134
179
  snapshotPath = snapshot.path;