synabun 1.3.0 → 2.0.0-beta

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 (1153) hide show
  1. package/CHANGELOG.md +197 -662
  2. package/LICENSE-COMMERCIAL.md +33 -0
  3. package/NOTICE +17 -0
  4. package/README.md +175 -853
  5. package/THIRD-PARTY-LICENSES.md +131 -0
  6. package/benchmarks/browser-live-results.json +79 -0
  7. package/benchmarks/browser-v2-results.json +258 -0
  8. package/benchmarks/fixtures/browser/README.md +57 -0
  9. package/benchmarks/fixtures/browser/page-state.json +132 -0
  10. package/benchmarks/fixtures/browser/social.json +92 -0
  11. package/benchmarks/fixtures/browser/target.json +319 -0
  12. package/benchmarks/fixtures/desktop/README.md +58 -0
  13. package/benchmarks/fixtures/desktop/abstention.json +59 -0
  14. package/benchmarks/fixtures/desktop/adversarial.json +22 -0
  15. package/benchmarks/fixtures/desktop/forbidden.json +93 -0
  16. package/benchmarks/fixtures/desktop/generate.mjs +1023 -0
  17. package/benchmarks/fixtures/desktop/target.json +136 -0
  18. package/bin/synabun.js +30 -0
  19. package/docs/browser-v2.md +109 -0
  20. package/docs/hook-integrity.md +89 -0
  21. package/docs/judgments.md +182 -0
  22. package/docs/style-guide.md +246 -0
  23. package/docs/whatsapp.md +325 -0
  24. package/hooks/claude-code/post-plan.mjs +613 -391
  25. package/hooks/claude-code/post-remember.mjs +246 -122
  26. package/hooks/claude-code/pre-compact.mjs +171 -110
  27. package/hooks/claude-code/pre-task.mjs +133 -0
  28. package/hooks/claude-code/pre-websearch.mjs +15 -4
  29. package/hooks/claude-code/prompt-origin.mjs +94 -0
  30. package/hooks/claude-code/prompt-submit.mjs +1244 -861
  31. package/hooks/claude-code/session-start.mjs +114 -156
  32. package/hooks/claude-code/shared.mjs +1228 -368
  33. package/hooks/claude-code/state.mjs +167 -0
  34. package/hooks/claude-code/stop.mjs +515 -140
  35. package/hooks/claude-code/subagent-start.mjs +154 -0
  36. package/hooks/claude-code/subagent-stop.mjs +102 -0
  37. package/hooks/claude-code/task-gate.mjs +150 -0
  38. package/lib/claude-hooks.js +84 -0
  39. package/lib/claude-usage-audit.js +141 -0
  40. package/lib/client-config-repair.js +144 -0
  41. package/lib/data-home-migration.js +498 -0
  42. package/lib/first-launch-protection.js +240 -0
  43. package/lib/paths.d.ts +21 -0
  44. package/lib/paths.js +103 -0
  45. package/mcp-server/dist/config.d.ts +22 -0
  46. package/mcp-server/dist/config.d.ts.map +1 -0
  47. package/mcp-server/dist/config.js +109 -0
  48. package/mcp-server/dist/config.js.map +1 -0
  49. package/mcp-server/dist/http.d.ts +30 -0
  50. package/mcp-server/dist/http.d.ts.map +1 -0
  51. package/mcp-server/dist/http.js +276 -0
  52. package/mcp-server/dist/http.js.map +1 -0
  53. package/mcp-server/dist/index.d.ts +48 -0
  54. package/mcp-server/dist/index.d.ts.map +1 -0
  55. package/mcp-server/dist/index.js +538 -0
  56. package/mcp-server/dist/index.js.map +1 -0
  57. package/mcp-server/dist/preload-http.d.ts +3 -0
  58. package/mcp-server/dist/preload-http.d.ts.map +1 -0
  59. package/mcp-server/dist/preload-http.js +28 -0
  60. package/mcp-server/dist/preload-http.js.map +1 -0
  61. package/mcp-server/dist/preload.d.ts +3 -0
  62. package/mcp-server/dist/preload.d.ts.map +1 -0
  63. package/mcp-server/dist/preload.js +32 -0
  64. package/mcp-server/dist/preload.js.map +1 -0
  65. package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.d.ts +19 -0
  66. package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.d.ts.map +1 -0
  67. package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.js +403 -0
  68. package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.js.map +1 -0
  69. package/mcp-server/dist/scripts/setup-embeddings.d.ts +3 -0
  70. package/mcp-server/dist/scripts/setup-embeddings.d.ts.map +1 -0
  71. package/mcp-server/dist/scripts/setup-embeddings.js +15 -0
  72. package/mcp-server/dist/scripts/setup-embeddings.js.map +1 -0
  73. package/mcp-server/dist/services/assistant-judgments.d.ts +79 -0
  74. package/mcp-server/dist/services/assistant-judgments.d.ts.map +1 -0
  75. package/mcp-server/dist/services/assistant-judgments.js +128 -0
  76. package/mcp-server/dist/services/assistant-judgments.js.map +1 -0
  77. package/mcp-server/dist/services/browser-assist-gate.d.ts +314 -0
  78. package/mcp-server/dist/services/browser-assist-gate.d.ts.map +1 -0
  79. package/mcp-server/dist/services/browser-assist-gate.js +344 -0
  80. package/mcp-server/dist/services/browser-assist-gate.js.map +1 -0
  81. package/mcp-server/dist/services/browser-assist.d.ts +104 -0
  82. package/mcp-server/dist/services/browser-assist.d.ts.map +1 -0
  83. package/mcp-server/dist/services/browser-assist.js +282 -0
  84. package/mcp-server/dist/services/browser-assist.js.map +1 -0
  85. package/mcp-server/dist/services/browser-bench.d.ts +772 -0
  86. package/mcp-server/dist/services/browser-bench.d.ts.map +1 -0
  87. package/mcp-server/dist/services/browser-bench.js +424 -0
  88. package/mcp-server/dist/services/browser-bench.js.map +1 -0
  89. package/mcp-server/dist/services/browser-judgments.d.ts +196 -0
  90. package/mcp-server/dist/services/browser-judgments.d.ts.map +1 -0
  91. package/mcp-server/dist/services/browser-judgments.js +363 -0
  92. package/mcp-server/dist/services/browser-judgments.js.map +1 -0
  93. package/mcp-server/dist/services/browser-risk.d.ts +166 -0
  94. package/mcp-server/dist/services/browser-risk.d.ts.map +1 -0
  95. package/mcp-server/dist/services/browser-risk.js +458 -0
  96. package/mcp-server/dist/services/browser-risk.js.map +1 -0
  97. package/mcp-server/dist/services/categories.d.ts +61 -0
  98. package/mcp-server/dist/services/categories.d.ts.map +1 -0
  99. package/mcp-server/dist/services/categories.js +377 -0
  100. package/mcp-server/dist/services/categories.js.map +1 -0
  101. package/mcp-server/dist/services/codex-config-heal.d.ts +49 -0
  102. package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -0
  103. package/mcp-server/dist/services/codex-config-heal.js +346 -0
  104. package/mcp-server/dist/services/codex-config-heal.js.map +1 -0
  105. package/mcp-server/dist/services/desktop-assist-gate.d.ts +198 -0
  106. package/mcp-server/dist/services/desktop-assist-gate.d.ts.map +1 -0
  107. package/mcp-server/dist/services/desktop-assist-gate.js +202 -0
  108. package/mcp-server/dist/services/desktop-assist-gate.js.map +1 -0
  109. package/mcp-server/dist/services/desktop-assist.d.ts +104 -0
  110. package/mcp-server/dist/services/desktop-assist.d.ts.map +1 -0
  111. package/mcp-server/dist/services/desktop-assist.js +266 -0
  112. package/mcp-server/dist/services/desktop-assist.js.map +1 -0
  113. package/mcp-server/dist/services/desktop-bench.d.ts +553 -0
  114. package/mcp-server/dist/services/desktop-bench.d.ts.map +1 -0
  115. package/mcp-server/dist/services/desktop-bench.js +311 -0
  116. package/mcp-server/dist/services/desktop-bench.js.map +1 -0
  117. package/mcp-server/dist/services/desktop-client.d.ts +23 -0
  118. package/mcp-server/dist/services/desktop-client.d.ts.map +1 -0
  119. package/mcp-server/dist/services/desktop-client.js +79 -0
  120. package/mcp-server/dist/services/desktop-client.js.map +1 -0
  121. package/mcp-server/dist/services/desktop-judgments.d.ts +125 -0
  122. package/mcp-server/dist/services/desktop-judgments.d.ts.map +1 -0
  123. package/mcp-server/dist/services/desktop-judgments.js +177 -0
  124. package/mcp-server/dist/services/desktop-judgments.js.map +1 -0
  125. package/mcp-server/dist/services/desktop-risk.d.ts +283 -0
  126. package/mcp-server/dist/services/desktop-risk.d.ts.map +1 -0
  127. package/mcp-server/dist/services/desktop-risk.js +605 -0
  128. package/mcp-server/dist/services/desktop-risk.js.map +1 -0
  129. package/mcp-server/dist/services/discord.d.ts +112 -0
  130. package/mcp-server/dist/services/discord.d.ts.map +1 -0
  131. package/mcp-server/dist/services/discord.js +477 -0
  132. package/mcp-server/dist/services/discord.js.map +1 -0
  133. package/mcp-server/dist/services/edit-stale.d.ts +81 -0
  134. package/mcp-server/dist/services/edit-stale.d.ts.map +1 -0
  135. package/mcp-server/dist/services/edit-stale.js +358 -0
  136. package/mcp-server/dist/services/edit-stale.js.map +1 -0
  137. package/mcp-server/dist/services/embedding-service.d.ts +16 -0
  138. package/mcp-server/dist/services/embedding-service.d.ts.map +1 -0
  139. package/mcp-server/dist/services/embedding-service.js +126 -0
  140. package/mcp-server/dist/services/embedding-service.js.map +1 -0
  141. package/mcp-server/dist/services/embedding-worker.d.ts +2 -0
  142. package/mcp-server/dist/services/embedding-worker.d.ts.map +1 -0
  143. package/mcp-server/dist/services/embedding-worker.js +52 -0
  144. package/mcp-server/dist/services/embedding-worker.js.map +1 -0
  145. package/mcp-server/dist/services/fb-regions.d.ts +71 -0
  146. package/mcp-server/dist/services/fb-regions.d.ts.map +1 -0
  147. package/mcp-server/dist/services/fb-regions.js +211 -0
  148. package/mcp-server/dist/services/fb-regions.js.map +1 -0
  149. package/mcp-server/dist/services/file-checksums.d.ts +22 -0
  150. package/mcp-server/dist/services/file-checksums.d.ts.map +1 -0
  151. package/mcp-server/dist/services/file-checksums.js +55 -0
  152. package/mcp-server/dist/services/file-checksums.js.map +1 -0
  153. package/mcp-server/dist/services/file-excerpt.d.ts +24 -0
  154. package/mcp-server/dist/services/file-excerpt.d.ts.map +1 -0
  155. package/mcp-server/dist/services/file-excerpt.js +65 -0
  156. package/mcp-server/dist/services/file-excerpt.js.map +1 -0
  157. package/mcp-server/dist/services/identity.d.ts +124 -0
  158. package/mcp-server/dist/services/identity.d.ts.map +1 -0
  159. package/mcp-server/dist/services/identity.js +241 -0
  160. package/mcp-server/dist/services/identity.js.map +1 -0
  161. package/mcp-server/dist/services/local-embeddings.d.ts +2 -0
  162. package/mcp-server/dist/services/local-embeddings.d.ts.map +1 -0
  163. package/mcp-server/dist/services/local-embeddings.js +3 -0
  164. package/mcp-server/dist/services/local-embeddings.js.map +1 -0
  165. package/mcp-server/dist/services/memory-client.d.ts +4 -0
  166. package/mcp-server/dist/services/memory-client.d.ts.map +1 -0
  167. package/mcp-server/dist/services/memory-client.js +27 -0
  168. package/mcp-server/dist/services/memory-client.js.map +1 -0
  169. package/mcp-server/dist/services/memory-judge-backfill.d.ts +135 -0
  170. package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -0
  171. package/mcp-server/dist/services/memory-judge-backfill.js +510 -0
  172. package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -0
  173. package/mcp-server/dist/services/memory-judgments.d.ts +362 -0
  174. package/mcp-server/dist/services/memory-judgments.d.ts.map +1 -0
  175. package/mcp-server/dist/services/memory-judgments.js +674 -0
  176. package/mcp-server/dist/services/memory-judgments.js.map +1 -0
  177. package/mcp-server/dist/services/memory-maintenance.d.ts +108 -0
  178. package/mcp-server/dist/services/memory-maintenance.d.ts.map +1 -0
  179. package/mcp-server/dist/services/memory-maintenance.js +403 -0
  180. package/mcp-server/dist/services/memory-maintenance.js.map +1 -0
  181. package/mcp-server/dist/services/memory-retrieval.d.ts +66 -0
  182. package/mcp-server/dist/services/memory-retrieval.d.ts.map +1 -0
  183. package/mcp-server/dist/services/memory-retrieval.js +412 -0
  184. package/mcp-server/dist/services/memory-retrieval.js.map +1 -0
  185. package/mcp-server/dist/services/memory-schema.d.ts +16 -0
  186. package/mcp-server/dist/services/memory-schema.d.ts.map +1 -0
  187. package/mcp-server/dist/services/memory-schema.js +282 -0
  188. package/mcp-server/dist/services/memory-schema.js.map +1 -0
  189. package/mcp-server/dist/services/memory-sessions.d.ts +24 -0
  190. package/mcp-server/dist/services/memory-sessions.d.ts.map +1 -0
  191. package/mcp-server/dist/services/memory-sessions.js +110 -0
  192. package/mcp-server/dist/services/memory-sessions.js.map +1 -0
  193. package/mcp-server/dist/services/memory-triage.d.ts +60 -0
  194. package/mcp-server/dist/services/memory-triage.d.ts.map +1 -0
  195. package/mcp-server/dist/services/memory-triage.js +189 -0
  196. package/mcp-server/dist/services/memory-triage.js.map +1 -0
  197. package/mcp-server/dist/services/memory-verification.d.ts +24 -0
  198. package/mcp-server/dist/services/memory-verification.d.ts.map +1 -0
  199. package/mcp-server/dist/services/memory-verification.js +92 -0
  200. package/mcp-server/dist/services/memory-verification.js.map +1 -0
  201. package/mcp-server/dist/services/memory-writer.d.ts +26 -0
  202. package/mcp-server/dist/services/memory-writer.d.ts.map +1 -0
  203. package/mcp-server/dist/services/memory-writer.js +126 -0
  204. package/mcp-server/dist/services/memory-writer.js.map +1 -0
  205. package/mcp-server/dist/services/neural-interface.d.ts +439 -0
  206. package/mcp-server/dist/services/neural-interface.d.ts.map +1 -0
  207. package/mcp-server/dist/services/neural-interface.js +1135 -0
  208. package/mcp-server/dist/services/neural-interface.js.map +1 -0
  209. package/mcp-server/dist/services/profiles.d.ts +120 -0
  210. package/mcp-server/dist/services/profiles.d.ts.map +1 -0
  211. package/mcp-server/dist/services/profiles.js +387 -0
  212. package/mcp-server/dist/services/profiles.js.map +1 -0
  213. package/mcp-server/dist/services/secret-gate.d.ts +29 -0
  214. package/mcp-server/dist/services/secret-gate.d.ts.map +1 -0
  215. package/mcp-server/dist/services/secret-gate.js +43 -0
  216. package/mcp-server/dist/services/secret-gate.js.map +1 -0
  217. package/mcp-server/dist/services/server-instructions.d.ts +10 -0
  218. package/mcp-server/dist/services/server-instructions.d.ts.map +1 -0
  219. package/mcp-server/dist/services/server-instructions.js +101 -0
  220. package/mcp-server/dist/services/server-instructions.js.map +1 -0
  221. package/mcp-server/dist/services/sqlite.d.ts +235 -0
  222. package/mcp-server/dist/services/sqlite.d.ts.map +1 -0
  223. package/mcp-server/dist/services/sqlite.js +1185 -0
  224. package/mcp-server/dist/services/sqlite.js.map +1 -0
  225. package/mcp-server/dist/services/typesafe-bench.d.ts +99 -0
  226. package/mcp-server/dist/services/typesafe-bench.d.ts.map +1 -0
  227. package/mcp-server/dist/services/typesafe-bench.js +218 -0
  228. package/mcp-server/dist/services/typesafe-bench.js.map +1 -0
  229. package/mcp-server/dist/services/typesafe-config.d.ts +342 -0
  230. package/mcp-server/dist/services/typesafe-config.d.ts.map +1 -0
  231. package/mcp-server/dist/services/typesafe-config.js +746 -0
  232. package/mcp-server/dist/services/typesafe-config.js.map +1 -0
  233. package/mcp-server/dist/services/typesafe.d.ts +213 -0
  234. package/mcp-server/dist/services/typesafe.d.ts.map +1 -0
  235. package/mcp-server/dist/services/typesafe.js +330 -0
  236. package/mcp-server/dist/services/typesafe.js.map +1 -0
  237. package/mcp-server/dist/services/vector-cache.d.ts +68 -0
  238. package/mcp-server/dist/services/vector-cache.d.ts.map +1 -0
  239. package/mcp-server/dist/services/vector-cache.js +271 -0
  240. package/mcp-server/dist/services/vector-cache.js.map +1 -0
  241. package/mcp-server/dist/services/whiteboard-geometry.d.ts +305 -0
  242. package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -0
  243. package/mcp-server/dist/services/whiteboard-geometry.js +666 -0
  244. package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -0
  245. package/mcp-server/dist/tools/agents.d.ts +212 -0
  246. package/mcp-server/dist/tools/agents.d.ts.map +1 -0
  247. package/mcp-server/dist/tools/agents.js +407 -0
  248. package/mcp-server/dist/tools/agents.js.map +1 -0
  249. package/mcp-server/dist/tools/bluesky.d.ts +39 -0
  250. package/mcp-server/dist/tools/bluesky.d.ts.map +1 -0
  251. package/mcp-server/dist/tools/bluesky.js +1144 -0
  252. package/mcp-server/dist/tools/bluesky.js.map +1 -0
  253. package/mcp-server/dist/tools/browser-advanced.d.ts +58 -0
  254. package/mcp-server/dist/tools/browser-advanced.d.ts.map +1 -0
  255. package/mcp-server/dist/tools/browser-advanced.js +106 -0
  256. package/mcp-server/dist/tools/browser-advanced.js.map +1 -0
  257. package/mcp-server/dist/tools/browser-batch.d.ts +99 -0
  258. package/mcp-server/dist/tools/browser-batch.d.ts.map +1 -0
  259. package/mcp-server/dist/tools/browser-batch.js +187 -0
  260. package/mcp-server/dist/tools/browser-batch.js.map +1 -0
  261. package/mcp-server/dist/tools/browser-cheatsheet.d.ts +21 -0
  262. package/mcp-server/dist/tools/browser-cheatsheet.d.ts.map +1 -0
  263. package/mcp-server/dist/tools/browser-cheatsheet.js +144 -0
  264. package/mcp-server/dist/tools/browser-cheatsheet.js.map +1 -0
  265. package/mcp-server/dist/tools/browser-interact.d.ts +239 -0
  266. package/mcp-server/dist/tools/browser-interact.d.ts.map +1 -0
  267. package/mcp-server/dist/tools/browser-interact.js +300 -0
  268. package/mcp-server/dist/tools/browser-interact.js.map +1 -0
  269. package/mcp-server/dist/tools/browser-navigate.d.ts +90 -0
  270. package/mcp-server/dist/tools/browser-navigate.d.ts.map +1 -0
  271. package/mcp-server/dist/tools/browser-navigate.js +142 -0
  272. package/mcp-server/dist/tools/browser-navigate.js.map +1 -0
  273. package/mcp-server/dist/tools/browser-observe.d.ts +561 -0
  274. package/mcp-server/dist/tools/browser-observe.d.ts.map +1 -0
  275. package/mcp-server/dist/tools/browser-observe.js +2009 -0
  276. package/mcp-server/dist/tools/browser-observe.js.map +1 -0
  277. package/mcp-server/dist/tools/browser.d.ts +34 -0
  278. package/mcp-server/dist/tools/browser.d.ts.map +1 -0
  279. package/mcp-server/dist/tools/browser.js +112 -0
  280. package/mcp-server/dist/tools/browser.js.map +1 -0
  281. package/mcp-server/dist/tools/card-tools.d.ts +82 -0
  282. package/mcp-server/dist/tools/card-tools.d.ts.map +1 -0
  283. package/mcp-server/dist/tools/card-tools.js +137 -0
  284. package/mcp-server/dist/tools/card-tools.js.map +1 -0
  285. package/mcp-server/dist/tools/card.d.ts +8 -0
  286. package/mcp-server/dist/tools/card.d.ts.map +1 -0
  287. package/mcp-server/dist/tools/card.js +16 -0
  288. package/mcp-server/dist/tools/card.js.map +1 -0
  289. package/mcp-server/dist/tools/category.d.ts +32 -0
  290. package/mcp-server/dist/tools/category.d.ts.map +1 -0
  291. package/mcp-server/dist/tools/category.js +290 -0
  292. package/mcp-server/dist/tools/category.js.map +1 -0
  293. package/mcp-server/dist/tools/choice.d.ts +160 -0
  294. package/mcp-server/dist/tools/choice.d.ts.map +1 -0
  295. package/mcp-server/dist/tools/choice.js +80 -0
  296. package/mcp-server/dist/tools/choice.js.map +1 -0
  297. package/mcp-server/dist/tools/computer.d.ts +71 -0
  298. package/mcp-server/dist/tools/computer.d.ts.map +1 -0
  299. package/mcp-server/dist/tools/computer.js +174 -0
  300. package/mcp-server/dist/tools/computer.js.map +1 -0
  301. package/mcp-server/dist/tools/discord-channel.d.ts +44 -0
  302. package/mcp-server/dist/tools/discord-channel.d.ts.map +1 -0
  303. package/mcp-server/dist/tools/discord-channel.js +236 -0
  304. package/mcp-server/dist/tools/discord-channel.js.map +1 -0
  305. package/mcp-server/dist/tools/discord-guild.d.ts +20 -0
  306. package/mcp-server/dist/tools/discord-guild.d.ts.map +1 -0
  307. package/mcp-server/dist/tools/discord-guild.js +138 -0
  308. package/mcp-server/dist/tools/discord-guild.js.map +1 -0
  309. package/mcp-server/dist/tools/discord-member.d.ts +26 -0
  310. package/mcp-server/dist/tools/discord-member.d.ts.map +1 -0
  311. package/mcp-server/dist/tools/discord-member.js +122 -0
  312. package/mcp-server/dist/tools/discord-member.js.map +1 -0
  313. package/mcp-server/dist/tools/discord-message.d.ts +36 -0
  314. package/mcp-server/dist/tools/discord-message.d.ts.map +1 -0
  315. package/mcp-server/dist/tools/discord-message.js +184 -0
  316. package/mcp-server/dist/tools/discord-message.js.map +1 -0
  317. package/mcp-server/dist/tools/discord-onboarding.d.ts +32 -0
  318. package/mcp-server/dist/tools/discord-onboarding.d.ts.map +1 -0
  319. package/mcp-server/dist/tools/discord-onboarding.js +179 -0
  320. package/mcp-server/dist/tools/discord-onboarding.js.map +1 -0
  321. package/mcp-server/dist/tools/discord-role.d.ts +34 -0
  322. package/mcp-server/dist/tools/discord-role.d.ts.map +1 -0
  323. package/mcp-server/dist/tools/discord-role.js +178 -0
  324. package/mcp-server/dist/tools/discord-role.js.map +1 -0
  325. package/mcp-server/dist/tools/discord-thread.d.ts +28 -0
  326. package/mcp-server/dist/tools/discord-thread.d.ts.map +1 -0
  327. package/mcp-server/dist/tools/discord-thread.js +88 -0
  328. package/mcp-server/dist/tools/discord-thread.js.map +1 -0
  329. package/mcp-server/dist/tools/discord-webhook.d.ts +32 -0
  330. package/mcp-server/dist/tools/discord-webhook.d.ts.map +1 -0
  331. package/mcp-server/dist/tools/discord-webhook.js +154 -0
  332. package/mcp-server/dist/tools/discord-webhook.js.map +1 -0
  333. package/mcp-server/dist/tools/discord.d.ts +7 -0
  334. package/mcp-server/dist/tools/discord.d.ts.map +1 -0
  335. package/mcp-server/dist/tools/discord.js +25 -0
  336. package/mcp-server/dist/tools/discord.js.map +1 -0
  337. package/mcp-server/dist/tools/fb-groups.d.ts +98 -0
  338. package/mcp-server/dist/tools/fb-groups.d.ts.map +1 -0
  339. package/mcp-server/dist/tools/fb-groups.js +369 -0
  340. package/mcp-server/dist/tools/fb-groups.js.map +1 -0
  341. package/mcp-server/dist/tools/forget.d.ts +14 -0
  342. package/mcp-server/dist/tools/forget.d.ts.map +1 -0
  343. package/mcp-server/dist/tools/forget.js +26 -0
  344. package/mcp-server/dist/tools/forget.js.map +1 -0
  345. package/mcp-server/dist/tools/git-tools.d.ts +24 -0
  346. package/mcp-server/dist/tools/git-tools.d.ts.map +1 -0
  347. package/mcp-server/dist/tools/git-tools.js +107 -0
  348. package/mcp-server/dist/tools/git-tools.js.map +1 -0
  349. package/mcp-server/dist/tools/git.d.ts +7 -0
  350. package/mcp-server/dist/tools/git.d.ts.map +1 -0
  351. package/mcp-server/dist/tools/git.js +11 -0
  352. package/mcp-server/dist/tools/git.js.map +1 -0
  353. package/mcp-server/dist/tools/gsc/experience.d.ts +135 -0
  354. package/mcp-server/dist/tools/gsc/experience.d.ts.map +1 -0
  355. package/mcp-server/dist/tools/gsc/experience.js +351 -0
  356. package/mcp-server/dist/tools/gsc/experience.js.map +1 -0
  357. package/mcp-server/dist/tools/gsc/helpers.d.ts +78 -0
  358. package/mcp-server/dist/tools/gsc/helpers.d.ts.map +1 -0
  359. package/mcp-server/dist/tools/gsc/helpers.js +258 -0
  360. package/mcp-server/dist/tools/gsc/helpers.js.map +1 -0
  361. package/mcp-server/dist/tools/gsc/indexing.d.ts +121 -0
  362. package/mcp-server/dist/tools/gsc/indexing.d.ts.map +1 -0
  363. package/mcp-server/dist/tools/gsc/indexing.js +357 -0
  364. package/mcp-server/dist/tools/gsc/indexing.js.map +1 -0
  365. package/mcp-server/dist/tools/gsc/inspect.d.ts +78 -0
  366. package/mcp-server/dist/tools/gsc/inspect.d.ts.map +1 -0
  367. package/mcp-server/dist/tools/gsc/inspect.js +321 -0
  368. package/mcp-server/dist/tools/gsc/inspect.js.map +1 -0
  369. package/mcp-server/dist/tools/gsc/navigate.d.ts +44 -0
  370. package/mcp-server/dist/tools/gsc/navigate.d.ts.map +1 -0
  371. package/mcp-server/dist/tools/gsc/navigate.js +197 -0
  372. package/mcp-server/dist/tools/gsc/navigate.js.map +1 -0
  373. package/mcp-server/dist/tools/gsc/performance.d.ts +84 -0
  374. package/mcp-server/dist/tools/gsc/performance.d.ts.map +1 -0
  375. package/mcp-server/dist/tools/gsc/performance.js +274 -0
  376. package/mcp-server/dist/tools/gsc/performance.js.map +1 -0
  377. package/mcp-server/dist/tools/gsc/settings.d.ts +153 -0
  378. package/mcp-server/dist/tools/gsc/settings.d.ts.map +1 -0
  379. package/mcp-server/dist/tools/gsc/settings.js +425 -0
  380. package/mcp-server/dist/tools/gsc/settings.js.map +1 -0
  381. package/mcp-server/dist/tools/gsc.d.ts +7 -0
  382. package/mcp-server/dist/tools/gsc.d.ts.map +1 -0
  383. package/mcp-server/dist/tools/gsc.js +51 -0
  384. package/mcp-server/dist/tools/gsc.js.map +1 -0
  385. package/mcp-server/dist/tools/image-tools.d.ts +24 -0
  386. package/mcp-server/dist/tools/image-tools.d.ts.map +1 -0
  387. package/mcp-server/dist/tools/image-tools.js +80 -0
  388. package/mcp-server/dist/tools/image-tools.js.map +1 -0
  389. package/mcp-server/dist/tools/image.d.ts +10 -0
  390. package/mcp-server/dist/tools/image.d.ts.map +1 -0
  391. package/mcp-server/dist/tools/image.js +14 -0
  392. package/mcp-server/dist/tools/image.js.map +1 -0
  393. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +97 -0
  394. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +1 -0
  395. package/mcp-server/dist/tools/leonardo-browser-tools.js +228 -0
  396. package/mcp-server/dist/tools/leonardo-browser-tools.js.map +1 -0
  397. package/mcp-server/dist/tools/leonardo.d.ts +13 -0
  398. package/mcp-server/dist/tools/leonardo.d.ts.map +1 -0
  399. package/mcp-server/dist/tools/leonardo.js +21 -0
  400. package/mcp-server/dist/tools/leonardo.js.map +1 -0
  401. package/mcp-server/dist/tools/loop.d.ts +30 -0
  402. package/mcp-server/dist/tools/loop.d.ts.map +1 -0
  403. package/mcp-server/dist/tools/loop.js +401 -0
  404. package/mcp-server/dist/tools/loop.js.map +1 -0
  405. package/mcp-server/dist/tools/memories.d.ts +56 -0
  406. package/mcp-server/dist/tools/memories.d.ts.map +1 -0
  407. package/mcp-server/dist/tools/memories.js +171 -0
  408. package/mcp-server/dist/tools/memories.js.map +1 -0
  409. package/mcp-server/dist/tools/morelogin.d.ts +24 -0
  410. package/mcp-server/dist/tools/morelogin.d.ts.map +1 -0
  411. package/mcp-server/dist/tools/morelogin.js +79 -0
  412. package/mcp-server/dist/tools/morelogin.js.map +1 -0
  413. package/mcp-server/dist/tools/profile.d.ts +17 -0
  414. package/mcp-server/dist/tools/profile.d.ts.map +1 -0
  415. package/mcp-server/dist/tools/profile.js +114 -0
  416. package/mcp-server/dist/tools/profile.js.map +1 -0
  417. package/mcp-server/dist/tools/recall.d.ts +71 -0
  418. package/mcp-server/dist/tools/recall.d.ts.map +1 -0
  419. package/mcp-server/dist/tools/recall.js +147 -0
  420. package/mcp-server/dist/tools/recall.js.map +1 -0
  421. package/mcp-server/dist/tools/reflect.d.ts +56 -0
  422. package/mcp-server/dist/tools/reflect.d.ts.map +1 -0
  423. package/mcp-server/dist/tools/reflect.js +157 -0
  424. package/mcp-server/dist/tools/reflect.js.map +1 -0
  425. package/mcp-server/dist/tools/remember.d.ts +62 -0
  426. package/mcp-server/dist/tools/remember.d.ts.map +1 -0
  427. package/mcp-server/dist/tools/remember.js +201 -0
  428. package/mcp-server/dist/tools/remember.js.map +1 -0
  429. package/mcp-server/dist/tools/response.d.ts +23 -0
  430. package/mcp-server/dist/tools/response.d.ts.map +1 -0
  431. package/mcp-server/dist/tools/response.js +24 -0
  432. package/mcp-server/dist/tools/response.js.map +1 -0
  433. package/mcp-server/dist/tools/restore.d.ts +14 -0
  434. package/mcp-server/dist/tools/restore.d.ts.map +1 -0
  435. package/mcp-server/dist/tools/restore.js +23 -0
  436. package/mcp-server/dist/tools/restore.js.map +1 -0
  437. package/mcp-server/dist/tools/style-guide-tools.d.ts +51 -0
  438. package/mcp-server/dist/tools/style-guide-tools.d.ts.map +1 -0
  439. package/mcp-server/dist/tools/style-guide-tools.js +231 -0
  440. package/mcp-server/dist/tools/style-guide-tools.js.map +1 -0
  441. package/mcp-server/dist/tools/style-guide.d.ts +8 -0
  442. package/mcp-server/dist/tools/style-guide.d.ts.map +1 -0
  443. package/mcp-server/dist/tools/style-guide.js +12 -0
  444. package/mcp-server/dist/tools/style-guide.js.map +1 -0
  445. package/mcp-server/dist/tools/sync.d.ts +20 -0
  446. package/mcp-server/dist/tools/sync.d.ts.map +1 -0
  447. package/mcp-server/dist/tools/sync.js +156 -0
  448. package/mcp-server/dist/tools/sync.js.map +1 -0
  449. package/mcp-server/dist/tools/tictactoe-tools.d.ts +18 -0
  450. package/mcp-server/dist/tools/tictactoe-tools.d.ts.map +1 -0
  451. package/mcp-server/dist/tools/tictactoe-tools.js +78 -0
  452. package/mcp-server/dist/tools/tictactoe-tools.js.map +1 -0
  453. package/mcp-server/dist/tools/tictactoe.d.ts +7 -0
  454. package/mcp-server/dist/tools/tictactoe.d.ts.map +1 -0
  455. package/mcp-server/dist/tools/tictactoe.js +11 -0
  456. package/mcp-server/dist/tools/tictactoe.js.map +1 -0
  457. package/mcp-server/dist/tools/utils.d.ts +19 -0
  458. package/mcp-server/dist/tools/utils.d.ts.map +1 -0
  459. package/mcp-server/dist/tools/utils.js +54 -0
  460. package/mcp-server/dist/tools/utils.js.map +1 -0
  461. package/mcp-server/dist/tools/whiteboard-format.d.ts +88 -0
  462. package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -0
  463. package/mcp-server/dist/tools/whiteboard-format.js +337 -0
  464. package/mcp-server/dist/tools/whiteboard-format.js.map +1 -0
  465. package/mcp-server/dist/tools/whiteboard-tools.d.ts +326 -0
  466. package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -0
  467. package/mcp-server/dist/tools/whiteboard-tools.js +222 -0
  468. package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -0
  469. package/mcp-server/dist/tools/whiteboard.d.ts +8 -0
  470. package/mcp-server/dist/tools/whiteboard.d.ts.map +1 -0
  471. package/mcp-server/dist/tools/whiteboard.js +16 -0
  472. package/mcp-server/dist/tools/whiteboard.js.map +1 -0
  473. package/mcp-server/dist/tools/youtube/analytics.d.ts +46 -0
  474. package/mcp-server/dist/tools/youtube/analytics.d.ts.map +1 -0
  475. package/mcp-server/dist/tools/youtube/analytics.js +83 -0
  476. package/mcp-server/dist/tools/youtube/analytics.js.map +1 -0
  477. package/mcp-server/dist/tools/youtube/dedup.d.ts +35 -0
  478. package/mcp-server/dist/tools/youtube/dedup.d.ts.map +1 -0
  479. package/mcp-server/dist/tools/youtube/dedup.js +56 -0
  480. package/mcp-server/dist/tools/youtube/dedup.js.map +1 -0
  481. package/mcp-server/dist/tools/youtube/download.d.ts +31 -0
  482. package/mcp-server/dist/tools/youtube/download.d.ts.map +1 -0
  483. package/mcp-server/dist/tools/youtube/download.js +30 -0
  484. package/mcp-server/dist/tools/youtube/download.js.map +1 -0
  485. package/mcp-server/dist/tools/youtube/helpers.d.ts +66 -0
  486. package/mcp-server/dist/tools/youtube/helpers.d.ts.map +1 -0
  487. package/mcp-server/dist/tools/youtube/helpers.js +143 -0
  488. package/mcp-server/dist/tools/youtube/helpers.js.map +1 -0
  489. package/mcp-server/dist/tools/youtube/media.d.ts +43 -0
  490. package/mcp-server/dist/tools/youtube/media.d.ts.map +1 -0
  491. package/mcp-server/dist/tools/youtube/media.js +97 -0
  492. package/mcp-server/dist/tools/youtube/media.js.map +1 -0
  493. package/mcp-server/dist/tools/youtube/metadata.d.ts +33 -0
  494. package/mcp-server/dist/tools/youtube/metadata.d.ts.map +1 -0
  495. package/mcp-server/dist/tools/youtube/metadata.js +106 -0
  496. package/mcp-server/dist/tools/youtube/metadata.js.map +1 -0
  497. package/mcp-server/dist/tools/youtube/navigate.d.ts +30 -0
  498. package/mcp-server/dist/tools/youtube/navigate.d.ts.map +1 -0
  499. package/mcp-server/dist/tools/youtube/navigate.js +71 -0
  500. package/mcp-server/dist/tools/youtube/navigate.js.map +1 -0
  501. package/mcp-server/dist/tools/youtube/playlist.d.ts +29 -0
  502. package/mcp-server/dist/tools/youtube/playlist.d.ts.map +1 -0
  503. package/mcp-server/dist/tools/youtube/playlist.js +128 -0
  504. package/mcp-server/dist/tools/youtube/playlist.js.map +1 -0
  505. package/mcp-server/dist/tools/youtube/schedule.d.ts +31 -0
  506. package/mcp-server/dist/tools/youtube/schedule.d.ts.map +1 -0
  507. package/mcp-server/dist/tools/youtube/schedule.js +147 -0
  508. package/mcp-server/dist/tools/youtube/schedule.js.map +1 -0
  509. package/mcp-server/dist/tools/youtube/source.d.ts +36 -0
  510. package/mcp-server/dist/tools/youtube/source.d.ts.map +1 -0
  511. package/mcp-server/dist/tools/youtube/source.js +85 -0
  512. package/mcp-server/dist/tools/youtube/source.js.map +1 -0
  513. package/mcp-server/dist/tools/youtube/upload.d.ts +53 -0
  514. package/mcp-server/dist/tools/youtube/upload.d.ts.map +1 -0
  515. package/mcp-server/dist/tools/youtube/upload.js +255 -0
  516. package/mcp-server/dist/tools/youtube/upload.js.map +1 -0
  517. package/mcp-server/dist/tools/youtube.d.ts +12 -0
  518. package/mcp-server/dist/tools/youtube.d.ts.map +1 -0
  519. package/mcp-server/dist/tools/youtube.js +38 -0
  520. package/mcp-server/dist/tools/youtube.js.map +1 -0
  521. package/mcp-server/dist/tui.d.ts +3 -0
  522. package/mcp-server/dist/tui.d.ts.map +1 -0
  523. package/mcp-server/dist/tui.js +806 -0
  524. package/mcp-server/dist/tui.js.map +1 -0
  525. package/mcp-server/dist/types.d.ts +77 -0
  526. package/mcp-server/dist/types.d.ts.map +1 -0
  527. package/mcp-server/dist/types.js +2 -0
  528. package/mcp-server/dist/types.js.map +1 -0
  529. package/mcp-server/package-lock.json +4798 -0
  530. package/mcp-server/package.json +55 -38
  531. package/mcp-server/run.mjs +12 -2
  532. package/mcp-server/src/config.ts +48 -3
  533. package/mcp-server/src/http.ts +296 -93
  534. package/mcp-server/src/index.ts +546 -203
  535. package/mcp-server/src/preload-http.ts +19 -18
  536. package/mcp-server/src/preload.ts +19 -18
  537. package/mcp-server/src/scripts/setup-embeddings.ts +9 -0
  538. package/mcp-server/src/services/assistant-judgments.ts +157 -0
  539. package/mcp-server/src/services/browser-assist-gate.ts +383 -0
  540. package/mcp-server/src/services/browser-assist.ts +267 -0
  541. package/mcp-server/src/services/browser-bench.ts +477 -0
  542. package/mcp-server/src/services/browser-judgments.ts +414 -0
  543. package/mcp-server/src/services/browser-risk.ts +484 -0
  544. package/mcp-server/src/services/categories.ts +36 -19
  545. package/mcp-server/src/services/codex-config-heal.ts +403 -0
  546. package/mcp-server/src/services/desktop-assist-gate.ts +251 -0
  547. package/mcp-server/src/services/desktop-assist.ts +308 -0
  548. package/mcp-server/src/services/desktop-bench.ts +372 -0
  549. package/mcp-server/src/services/desktop-client.ts +76 -0
  550. package/mcp-server/src/services/desktop-judgments.ts +218 -0
  551. package/mcp-server/src/services/desktop-risk.ts +743 -0
  552. package/mcp-server/src/services/edit-stale.ts +299 -0
  553. package/mcp-server/src/services/embedding-service.ts +108 -0
  554. package/mcp-server/src/services/embedding-worker.ts +46 -0
  555. package/mcp-server/src/services/fb-regions.ts +221 -0
  556. package/mcp-server/src/services/file-checksums.ts +26 -9
  557. package/mcp-server/src/services/file-excerpt.ts +59 -0
  558. package/mcp-server/src/services/identity.ts +291 -0
  559. package/mcp-server/src/services/local-embeddings.ts +2 -77
  560. package/mcp-server/src/services/memory-client.ts +23 -0
  561. package/mcp-server/src/services/memory-judge-backfill.ts +462 -0
  562. package/mcp-server/src/services/memory-judgments.ts +901 -0
  563. package/mcp-server/src/services/memory-maintenance.ts +360 -0
  564. package/mcp-server/src/services/memory-retrieval.ts +349 -0
  565. package/mcp-server/src/services/memory-schema.ts +280 -0
  566. package/mcp-server/src/services/memory-sessions.ts +87 -0
  567. package/mcp-server/src/services/memory-triage.ts +182 -0
  568. package/mcp-server/src/services/memory-verification.ts +68 -0
  569. package/mcp-server/src/services/memory-writer.ts +125 -0
  570. package/mcp-server/src/services/neural-interface.ts +1217 -73
  571. package/mcp-server/src/services/profiles.ts +428 -0
  572. package/mcp-server/src/services/secret-gate.ts +52 -0
  573. package/mcp-server/src/services/server-instructions.ts +122 -0
  574. package/mcp-server/src/services/sqlite.ts +1456 -823
  575. package/mcp-server/src/services/typesafe-bench.ts +247 -0
  576. package/mcp-server/src/services/typesafe-config.ts +790 -0
  577. package/mcp-server/src/services/typesafe.ts +390 -0
  578. package/mcp-server/src/services/vector-cache.ts +255 -0
  579. package/mcp-server/src/services/whiteboard-geometry.ts +711 -0
  580. package/mcp-server/src/tools/agents.ts +539 -0
  581. package/mcp-server/src/tools/bluesky.ts +1186 -0
  582. package/mcp-server/src/tools/browser-advanced.ts +15 -6
  583. package/mcp-server/src/tools/browser-batch.ts +178 -0
  584. package/mcp-server/src/tools/browser-cheatsheet.ts +155 -0
  585. package/mcp-server/src/tools/browser-interact.ts +362 -255
  586. package/mcp-server/src/tools/browser-navigate.ts +164 -77
  587. package/mcp-server/src/tools/browser-observe.ts +2222 -1330
  588. package/mcp-server/src/tools/browser.ts +181 -107
  589. package/mcp-server/src/tools/card.ts +7 -5
  590. package/mcp-server/src/tools/choice.ts +103 -0
  591. package/mcp-server/src/tools/computer.ts +190 -0
  592. package/mcp-server/src/tools/discord.ts +10 -23
  593. package/mcp-server/src/tools/fb-groups.ts +387 -0
  594. package/mcp-server/src/tools/forget.ts +1 -1
  595. package/mcp-server/src/tools/git.ts +3 -1
  596. package/mcp-server/src/tools/gsc/experience.ts +440 -0
  597. package/mcp-server/src/tools/gsc/helpers.ts +288 -0
  598. package/mcp-server/src/tools/gsc/indexing.ts +495 -0
  599. package/mcp-server/src/tools/gsc/inspect.ts +391 -0
  600. package/mcp-server/src/tools/gsc/navigate.ts +236 -0
  601. package/mcp-server/src/tools/gsc/performance.ts +352 -0
  602. package/mcp-server/src/tools/gsc/settings.ts +564 -0
  603. package/mcp-server/src/tools/gsc.ts +95 -0
  604. package/mcp-server/src/tools/image.ts +3 -1
  605. package/mcp-server/src/tools/leonardo-browser-tools.ts +47 -37
  606. package/mcp-server/src/tools/leonardo.ts +7 -5
  607. package/mcp-server/src/tools/loop.ts +118 -25
  608. package/mcp-server/src/tools/memories.ts +65 -5
  609. package/mcp-server/src/tools/morelogin.ts +81 -0
  610. package/mcp-server/src/tools/profile.ts +122 -0
  611. package/mcp-server/src/tools/recall.ts +105 -261
  612. package/mcp-server/src/tools/reflect.ts +171 -145
  613. package/mcp-server/src/tools/remember.ts +223 -115
  614. package/mcp-server/src/tools/style-guide-tools.ts +250 -0
  615. package/mcp-server/src/tools/style-guide.ts +16 -0
  616. package/mcp-server/src/tools/sync.ts +66 -9
  617. package/mcp-server/src/tools/tictactoe.ts +3 -1
  618. package/mcp-server/src/tools/utils.ts +22 -0
  619. package/mcp-server/src/tools/whiteboard-format.ts +394 -0
  620. package/mcp-server/src/tools/whiteboard-tools.ts +191 -183
  621. package/mcp-server/src/tools/whiteboard.ts +7 -5
  622. package/mcp-server/src/tools/youtube/analytics.ts +106 -0
  623. package/mcp-server/src/tools/youtube/dedup.ts +57 -0
  624. package/mcp-server/src/tools/youtube/download.ts +41 -0
  625. package/mcp-server/src/tools/youtube/helpers.ts +183 -0
  626. package/mcp-server/src/tools/youtube/media.ts +109 -0
  627. package/mcp-server/src/tools/youtube/metadata.ts +112 -0
  628. package/mcp-server/src/tools/youtube/navigate.ts +81 -0
  629. package/mcp-server/src/tools/youtube/playlist.ts +134 -0
  630. package/mcp-server/src/tools/youtube/schedule.ts +158 -0
  631. package/mcp-server/src/tools/youtube/source.ts +101 -0
  632. package/mcp-server/src/tools/youtube/upload.ts +296 -0
  633. package/mcp-server/src/tools/youtube.ts +47 -0
  634. package/mcp-server/src/tui.ts +8 -9
  635. package/neural-interface/games/TicTacToe/1.svg +1 -0
  636. package/neural-interface/games/TicTacToe/2.svg +1 -0
  637. package/neural-interface/games/TicTacToe/3.svg +1 -0
  638. package/neural-interface/games/TicTacToe/4.svg +1 -0
  639. package/neural-interface/games/TicTacToe/5.svg +1 -0
  640. package/neural-interface/games/TicTacToe/6.svg +1 -0
  641. package/neural-interface/games/TicTacToe/7.svg +1 -0
  642. package/neural-interface/games/TicTacToe/8.svg +1 -0
  643. package/neural-interface/games/TicTacToe/9.svg +1 -0
  644. package/neural-interface/games/TicTacToe/Board.svg +1 -0
  645. package/neural-interface/games/TicTacToe/Circle.svg +1 -0
  646. package/neural-interface/games/TicTacToe/Cross.svg +1 -0
  647. package/neural-interface/i18n/en.json +6983 -0
  648. package/neural-interface/i18n/pt-BR.json +6987 -0
  649. package/neural-interface/lib/assistant-api.js +1005 -0
  650. package/neural-interface/lib/assistant-attachments.js +121 -0
  651. package/neural-interface/lib/assistant-brains/claude.js +207 -0
  652. package/neural-interface/lib/assistant-brains/codex-browser-policy-hook.mjs +43 -0
  653. package/neural-interface/lib/assistant-brains/codex-route-gate-hook.mjs +56 -0
  654. package/neural-interface/lib/assistant-brains/codex.js +213 -0
  655. package/neural-interface/lib/assistant-brains/opencode-browser-policy.js +47 -0
  656. package/neural-interface/lib/assistant-brains/opencode-route-gate.js +62 -0
  657. package/neural-interface/lib/assistant-brains/opencode.js +320 -0
  658. package/neural-interface/lib/assistant-budget.js +318 -0
  659. package/neural-interface/lib/assistant-catalog.js +731 -0
  660. package/neural-interface/lib/assistant-clarify.js +664 -0
  661. package/neural-interface/lib/assistant-config.js +232 -0
  662. package/neural-interface/lib/assistant-dispatch.js +2744 -0
  663. package/neural-interface/lib/assistant-envelope.js +579 -0
  664. package/neural-interface/lib/assistant-evidence.js +236 -0
  665. package/neural-interface/lib/assistant-hidden-models.js +272 -0
  666. package/neural-interface/lib/assistant-jev.js +117 -0
  667. package/neural-interface/lib/assistant-judgments.js +111 -0
  668. package/neural-interface/lib/assistant-media.js +335 -0
  669. package/neural-interface/lib/assistant-memory.js +398 -0
  670. package/neural-interface/lib/assistant-persona.js +444 -0
  671. package/neural-interface/lib/assistant-plan-permissions.js +448 -0
  672. package/neural-interface/lib/assistant-playbooks/design.md +87 -0
  673. package/neural-interface/lib/assistant-playbooks.js +72 -0
  674. package/neural-interface/lib/assistant-pricing.js +159 -0
  675. package/neural-interface/lib/assistant-route-gate-codex.js +163 -0
  676. package/neural-interface/lib/assistant-route-gate.js +212 -0
  677. package/neural-interface/lib/assistant-router.js +1324 -0
  678. package/neural-interface/lib/assistant-runtime.js +3337 -0
  679. package/neural-interface/lib/assistant-task-prompt.js +472 -0
  680. package/neural-interface/lib/assistant-usage.js +1688 -0
  681. package/neural-interface/lib/augmented-path.js +50 -0
  682. package/neural-interface/lib/automation-storage-migration.js +54 -0
  683. package/neural-interface/lib/backup-service.js +851 -0
  684. package/neural-interface/lib/backup-zip-reader.js +262 -0
  685. package/neural-interface/lib/browser-assist-api.js +41 -0
  686. package/neural-interface/lib/browser-console.js +176 -0
  687. package/neural-interface/lib/browser-execution.js +241 -0
  688. package/neural-interface/lib/browser-extraction.js +191 -0
  689. package/neural-interface/lib/browser-screenshot.js +399 -0
  690. package/neural-interface/lib/browser-semantic-context.js +639 -0
  691. package/neural-interface/lib/browser-snapshots.js +192 -0
  692. package/neural-interface/lib/browser-tab-recovery.js +119 -0
  693. package/neural-interface/lib/browser-targets.js +70 -0
  694. package/neural-interface/lib/browser-tool-policy.js +926 -0
  695. package/neural-interface/lib/claude-accounts.js +230 -0
  696. package/neural-interface/lib/claude-agent-bridge.js +3296 -0
  697. package/neural-interface/lib/claude-bypass-policy.js +99 -0
  698. package/neural-interface/lib/claude-history.js +429 -0
  699. package/neural-interface/lib/claude-model-catalog.js +483 -0
  700. package/neural-interface/lib/claude-panel-requests.js +165 -0
  701. package/neural-interface/lib/claude-panel-session.js +272 -0
  702. package/neural-interface/lib/claude-permission-rules.js +153 -0
  703. package/neural-interface/lib/claude-session-cleanup.js +71 -0
  704. package/neural-interface/lib/claude-session-list.js +82 -0
  705. package/neural-interface/lib/claude-session-ops.js +140 -0
  706. package/neural-interface/lib/claude-settings-view.js +51 -0
  707. package/neural-interface/lib/claude-skin-connect.js +79 -0
  708. package/neural-interface/lib/claude-stall-policy.js +7 -0
  709. package/neural-interface/lib/claude-temporary.js +435 -0
  710. package/neural-interface/lib/cli-update-planner.js +312 -0
  711. package/neural-interface/lib/codex-capabilities.d.ts +41 -0
  712. package/neural-interface/lib/codex-capabilities.js +148 -0
  713. package/neural-interface/lib/codex-collaboration-mode.js +17 -0
  714. package/neural-interface/lib/codex-compat-rpc.js +241 -0
  715. package/neural-interface/lib/codex-mcp-approvals.js +56 -0
  716. package/neural-interface/lib/codex-mcp-apps.js +47 -0
  717. package/neural-interface/lib/codex-model-context.js +202 -0
  718. package/neural-interface/lib/codex-plan-store.js +71 -0
  719. package/neural-interface/lib/codex-request-journal.js +242 -0
  720. package/neural-interface/lib/codex-runtime-path.js +213 -0
  721. package/neural-interface/lib/codex-session-catalog.js +231 -0
  722. package/neural-interface/lib/codex-session-settings.js +46 -0
  723. package/neural-interface/lib/codex-sidepanel-permissions.js +110 -0
  724. package/neural-interface/lib/codex-thread-history.js +165 -0
  725. package/neural-interface/lib/codex-user-verification.js +34 -0
  726. package/neural-interface/lib/codex-writer-lifecycle.js +152 -0
  727. package/neural-interface/lib/confined-fs.js +256 -0
  728. package/neural-interface/lib/db.js +922 -0
  729. package/neural-interface/lib/design-md.js +9 -0
  730. package/neural-interface/lib/desktop/api.js +92 -0
  731. package/neural-interface/lib/desktop/audit.js +62 -0
  732. package/neural-interface/lib/desktop/build.js +423 -0
  733. package/neural-interface/lib/desktop/config.js +606 -0
  734. package/neural-interface/lib/desktop/coords.js +76 -0
  735. package/neural-interface/lib/desktop/fake-helper.js +1192 -0
  736. package/neural-interface/lib/desktop/frames.js +77 -0
  737. package/neural-interface/lib/desktop/grants.js +84 -0
  738. package/neural-interface/lib/desktop/guards.js +170 -0
  739. package/neural-interface/lib/desktop/helper/SynabunDesktop.swift +3056 -0
  740. package/neural-interface/lib/desktop/lease.js +51 -0
  741. package/neural-interface/lib/desktop/manager.js +545 -0
  742. package/neural-interface/lib/desktop/press-contexts.js +103 -0
  743. package/neural-interface/lib/desktop/protocol.js +495 -0
  744. package/neural-interface/lib/desktop/service.js +1202 -0
  745. package/neural-interface/lib/effort-levels.js +148 -0
  746. package/neural-interface/lib/event-loop-monitor.js +67 -0
  747. package/neural-interface/lib/exec-loop-command.js +209 -0
  748. package/neural-interface/lib/folder-picker.ps1 +77 -0
  749. package/neural-interface/lib/http-guards.js +287 -0
  750. package/neural-interface/lib/jsonl-lines.js +94 -0
  751. package/neural-interface/lib/loop-logger.js +127 -0
  752. package/neural-interface/lib/mcp-client-config.js +133 -0
  753. package/neural-interface/lib/mcp-installer.js +487 -0
  754. package/neural-interface/lib/mcp-profile-refresh-coordinator.js +78 -0
  755. package/neural-interface/lib/mcp-profile-servers.js +120 -0
  756. package/neural-interface/lib/memo-cache.js +84 -0
  757. package/neural-interface/lib/memory-api.js +758 -0
  758. package/neural-interface/lib/memory-map-api.js +1150 -0
  759. package/neural-interface/lib/memory-map-layout.js +872 -0
  760. package/neural-interface/lib/memory-map-worker.js +165 -0
  761. package/neural-interface/lib/memory-session-capture.js +81 -0
  762. package/neural-interface/lib/memory-timers.js +62 -0
  763. package/neural-interface/lib/morelogin.js +301 -0
  764. package/neural-interface/lib/native-binary-runtime.js +650 -0
  765. package/neural-interface/lib/native-loop-goal.js +33 -0
  766. package/neural-interface/lib/native-loop-providers.js +1016 -0
  767. package/neural-interface/lib/native-loop-runtime.js +747 -0
  768. package/neural-interface/lib/opencode-hidden-models.js +113 -0
  769. package/neural-interface/lib/opencode-history.js +253 -0
  770. package/neural-interface/lib/opencode-runtime-config.js +58 -0
  771. package/neural-interface/lib/opencode-v2-client.js +486 -0
  772. package/neural-interface/lib/opencode-v2-ws-requests.js +955 -0
  773. package/neural-interface/lib/path-confine.js +213 -0
  774. package/neural-interface/lib/plugin-installer.js +264 -0
  775. package/neural-interface/lib/project-storage.js +766 -0
  776. package/neural-interface/lib/pty-host/core.js +603 -0
  777. package/neural-interface/lib/pty-host/flow.js +43 -0
  778. package/neural-interface/lib/pty-host/host.js +47 -0
  779. package/neural-interface/lib/pty-host/manager.js +360 -0
  780. package/neural-interface/lib/pty-host/protocol.js +81 -0
  781. package/neural-interface/lib/pty-host/snapshot.js +133 -0
  782. package/neural-interface/lib/remote-policy.js +582 -0
  783. package/neural-interface/lib/rulesets/api.js +175 -0
  784. package/neural-interface/lib/rulesets/fs-safe.js +245 -0
  785. package/neural-interface/lib/rulesets/installer.js +1453 -0
  786. package/neural-interface/lib/rulesets/json-edit.js +186 -0
  787. package/neural-interface/lib/rulesets/lock.js +170 -0
  788. package/neural-interface/lib/rulesets/managed-text.js +314 -0
  789. package/neural-interface/lib/rulesets/normalise.js +24 -0
  790. package/neural-interface/lib/rulesets/render.js +84 -0
  791. package/neural-interface/lib/schedule-launch-intent.js +40 -0
  792. package/neural-interface/lib/session-cache-builder.js +524 -0
  793. package/neural-interface/lib/session-chunker.js +344 -0
  794. package/neural-interface/lib/session-indexer.js +327 -0
  795. package/neural-interface/lib/session-title-generator.js +227 -0
  796. package/neural-interface/lib/skill-prompt-bridge.js +11 -0
  797. package/neural-interface/lib/style-guide/api.js +375 -0
  798. package/neural-interface/lib/style-guide/color.js +352 -0
  799. package/neural-interface/lib/style-guide/export-css.js +99 -0
  800. package/neural-interface/lib/style-guide/export-dtcg.js +209 -0
  801. package/neural-interface/lib/style-guide/export-tailwind.js +102 -0
  802. package/neural-interface/lib/style-guide/fonts.json +227 -0
  803. package/neural-interface/lib/style-guide/import.js +1268 -0
  804. package/neural-interface/lib/style-guide/pointers.js +103 -0
  805. package/neural-interface/lib/style-guide/presets.js +232 -0
  806. package/neural-interface/lib/style-guide/render-design-md.js +319 -0
  807. package/neural-interface/lib/style-guide/schema.js +848 -0
  808. package/neural-interface/lib/style-guide/security.js +43 -0
  809. package/neural-interface/lib/style-guide/store.js +491 -0
  810. package/neural-interface/lib/style-guide/summary.js +106 -0
  811. package/neural-interface/lib/style-guide/tokens.js +170 -0
  812. package/neural-interface/lib/synabun-update-plan.js +305 -0
  813. package/neural-interface/lib/synabun-version.js +179 -0
  814. package/neural-interface/lib/system-restore.js +99 -0
  815. package/neural-interface/lib/terminal-env.js +86 -0
  816. package/neural-interface/lib/ui-blob-store.js +106 -0
  817. package/neural-interface/lib/vector-cache.js +2 -0
  818. package/neural-interface/lib/virtual-socket.js +60 -0
  819. package/neural-interface/lib/whatsapp/api.js +146 -0
  820. package/neural-interface/lib/whatsapp/auth-store.js +389 -0
  821. package/neural-interface/lib/whatsapp/baileys-adapter.js +457 -0
  822. package/neural-interface/lib/whatsapp/brain.js +128 -0
  823. package/neural-interface/lib/whatsapp/bridge.js +1499 -0
  824. package/neural-interface/lib/whatsapp/cards.js +519 -0
  825. package/neural-interface/lib/whatsapp/commands.js +92 -0
  826. package/neural-interface/lib/whatsapp/config.js +291 -0
  827. package/neural-interface/lib/whatsapp/connector/entry.mjs +25 -0
  828. package/neural-interface/lib/whatsapp/connector/manifest.json +6 -0
  829. package/neural-interface/lib/whatsapp/connector/npm-shrinkwrap.json +717 -0
  830. package/neural-interface/lib/whatsapp/connector/package.json +8 -0
  831. package/neural-interface/lib/whatsapp/fake-baileys.js +444 -0
  832. package/neural-interface/lib/whatsapp/format.js +552 -0
  833. package/neural-interface/lib/whatsapp/host-core.js +1225 -0
  834. package/neural-interface/lib/whatsapp/host.js +119 -0
  835. package/neural-interface/lib/whatsapp/identity.js +288 -0
  836. package/neural-interface/lib/whatsapp/inbound.js +149 -0
  837. package/neural-interface/lib/whatsapp/installer.js +562 -0
  838. package/neural-interface/lib/whatsapp/manager.js +638 -0
  839. package/neural-interface/lib/whatsapp/paths.js +81 -0
  840. package/neural-interface/lib/whatsapp/protocol.js +327 -0
  841. package/neural-interface/lib/whatsapp/qr-svg.js +57 -0
  842. package/neural-interface/lib/whatsapp/redact.js +130 -0
  843. package/neural-interface/lib/whatsapp/service.js +1305 -0
  844. package/neural-interface/lib/whatsapp/vendor/qrcodegen.js +848 -0
  845. package/neural-interface/package-lock.json +4682 -0
  846. package/neural-interface/package.json +58 -27
  847. package/neural-interface/public/apple-touch-icon.png +0 -0
  848. package/neural-interface/public/category-logos/synabun.png +0 -0
  849. package/neural-interface/public/claude.svg +1 -0
  850. package/neural-interface/public/favicon-16x16.png +0 -0
  851. package/neural-interface/public/favicon-32x32.png +0 -0
  852. package/neural-interface/public/icon-192.png +0 -0
  853. package/neural-interface/public/icon-512.png +0 -0
  854. package/neural-interface/public/index.html +32 -182
  855. package/neural-interface/public/index2d.html +2 -2
  856. package/neural-interface/public/logo-synabun.png +0 -0
  857. package/neural-interface/public/logoHD.png +0 -0
  858. package/neural-interface/public/mcp.svg +4 -0
  859. package/neural-interface/public/offline.html +335 -299
  860. package/neural-interface/public/onboarding.html +692 -155
  861. package/neural-interface/public/opencode-logo-dark-square.svg +1 -0
  862. package/neural-interface/public/shared/agent-runtime-options.js +596 -0
  863. package/neural-interface/public/shared/api.js +339 -28
  864. package/neural-interface/public/shared/assistant/asst-accounts.js +318 -0
  865. package/neural-interface/public/shared/assistant/asst-agents-dock.js +296 -0
  866. package/neural-interface/public/shared/assistant/asst-api.js +270 -0
  867. package/neural-interface/public/shared/assistant/asst-brain-picker.js +744 -0
  868. package/neural-interface/public/shared/assistant/asst-budget.js +333 -0
  869. package/neural-interface/public/shared/assistant/asst-composer.js +656 -0
  870. package/neural-interface/public/shared/assistant/asst-computer.js +803 -0
  871. package/neural-interface/public/shared/assistant/asst-control.js +1018 -0
  872. package/neural-interface/public/shared/assistant/asst-hosts.js +262 -0
  873. package/neural-interface/public/shared/assistant/asst-mascot.js +311 -0
  874. package/neural-interface/public/shared/assistant/asst-menu.js +375 -0
  875. package/neural-interface/public/shared/assistant/asst-panel.js +1845 -0
  876. package/neural-interface/public/shared/assistant/asst-rack-styles.js +589 -0
  877. package/neural-interface/public/shared/assistant/asst-render.js +3296 -0
  878. package/neural-interface/public/shared/assistant/asst-route.js +1653 -0
  879. package/neural-interface/public/shared/assistant/asst-roving.js +75 -0
  880. package/neural-interface/public/shared/assistant/asst-sanitize.js +117 -0
  881. package/neural-interface/public/shared/assistant/asst-sidepanel-styles.js +488 -0
  882. package/neural-interface/public/shared/assistant/asst-sidepanel.js +675 -0
  883. package/neural-interface/public/shared/assistant/asst-slash.js +258 -0
  884. package/neural-interface/public/shared/assistant/asst-state.js +727 -0
  885. package/neural-interface/public/shared/assistant/asst-styles.js +1684 -0
  886. package/neural-interface/public/shared/assistant/asst-tool-kinds.js +1017 -0
  887. package/neural-interface/public/shared/assistant/asst-usage.js +444 -0
  888. package/neural-interface/public/shared/assistant/asst-ws.js +175 -0
  889. package/neural-interface/public/shared/automation-context.js +75 -0
  890. package/neural-interface/public/shared/blob-store.js +99 -0
  891. package/neural-interface/public/shared/cdx/cdx-capabilities.js +118 -0
  892. package/neural-interface/public/shared/cdx/cdx-cards.js +37 -0
  893. package/neural-interface/public/shared/cdx/cdx-commands.js +171 -0
  894. package/neural-interface/public/shared/cdx/cdx-context-menu.js +402 -0
  895. package/neural-interface/public/shared/cdx/cdx-context-model.js +220 -0
  896. package/neural-interface/public/shared/cdx/cdx-features.js +408 -0
  897. package/neural-interface/public/shared/cdx/cdx-icons.js +89 -0
  898. package/neural-interface/public/shared/cdx/cdx-mcp-app-host.js +414 -0
  899. package/neural-interface/public/shared/cdx/cdx-mcp-app-proxy.html +6 -0
  900. package/neural-interface/public/shared/cdx/cdx-mcp-app-proxy.js +56 -0
  901. package/neural-interface/public/shared/cdx/cdx-mcp-app.js +178 -0
  902. package/neural-interface/public/shared/cdx/cdx-model-catalog.js +120 -0
  903. package/neural-interface/public/shared/cdx/cdx-output-model.js +261 -0
  904. package/neural-interface/public/shared/cdx/cdx-output.js +382 -0
  905. package/neural-interface/public/shared/cdx/cdx-panel.js +1372 -0
  906. package/neural-interface/public/shared/cdx/cdx-plan.js +266 -0
  907. package/neural-interface/public/shared/cdx/cdx-protocol.js +682 -0
  908. package/neural-interface/public/shared/cdx/cdx-render.js +3381 -0
  909. package/neural-interface/public/shared/cdx/cdx-requests.js +1136 -0
  910. package/neural-interface/public/shared/cdx/cdx-styles.js +3251 -0
  911. package/neural-interface/public/shared/cdx/cdx-tabs.js +7992 -0
  912. package/neural-interface/public/shared/cdx/cdx-ws.js +363 -0
  913. package/neural-interface/public/shared/cli-status.js +169 -0
  914. package/neural-interface/public/shared/constants.js +22 -5
  915. package/neural-interface/public/shared/cp/cp-agents.js +186 -0
  916. package/neural-interface/public/shared/cp/cp-bash.js +252 -0
  917. package/neural-interface/public/shared/cp/cp-compose.js +159 -0
  918. package/neural-interface/public/shared/cp/cp-context-menu.js +309 -0
  919. package/neural-interface/public/shared/cp/cp-context-model.js +157 -0
  920. package/neural-interface/public/shared/cp/cp-context-window.js +80 -0
  921. package/neural-interface/public/shared/cp/cp-ctx.js +11 -0
  922. package/neural-interface/public/shared/cp/cp-diff.js +255 -0
  923. package/neural-interface/public/shared/cp/cp-event-rows.js +637 -0
  924. package/neural-interface/public/shared/cp/cp-events.js +846 -0
  925. package/neural-interface/public/shared/cp/cp-markdown.js +104 -0
  926. package/neural-interface/public/shared/cp/cp-permission-model.js +905 -0
  927. package/neural-interface/public/shared/cp/cp-permissions.js +626 -0
  928. package/neural-interface/public/shared/cp/cp-rehydrate.js +113 -0
  929. package/neural-interface/public/shared/cp/cp-restore.js +224 -0
  930. package/neural-interface/public/shared/cp/cp-session-model.js +338 -0
  931. package/neural-interface/public/shared/cp/cp-session-settings.js +254 -0
  932. package/neural-interface/public/shared/cp/cp-sessions.js +227 -0
  933. package/neural-interface/public/shared/cp/cp-statusline.js +153 -0
  934. package/neural-interface/public/shared/cp/cp-styles.js +349 -0
  935. package/neural-interface/public/shared/cp/cp-tasks-model.js +282 -0
  936. package/neural-interface/public/shared/cp/cp-tasks.js +107 -0
  937. package/neural-interface/public/shared/cp/cp-temporary-view.js +56 -0
  938. package/neural-interface/public/shared/cp/cp-temporary.js +231 -0
  939. package/neural-interface/public/shared/cp/cp-tool-cards.js +326 -0
  940. package/neural-interface/public/shared/cp/cp-tool-results.js +618 -0
  941. package/neural-interface/public/shared/cp/cp-usage-model.js +124 -0
  942. package/neural-interface/public/shared/graph-activity.js +68 -0
  943. package/neural-interface/public/shared/html-shell.js +107 -12
  944. package/neural-interface/public/shared/i18n.js +132 -34
  945. package/neural-interface/public/shared/node-positions-store.js +44 -0
  946. package/neural-interface/public/shared/ocp-hidden-models.js +116 -0
  947. package/neural-interface/public/shared/ocp-v2/ocp-v2-approvals.js +355 -0
  948. package/neural-interface/public/shared/ocp-v2/ocp-v2-autoaccept-button.js +35 -0
  949. package/neural-interface/public/shared/ocp-v2/ocp-v2-automation-ownership.js +72 -0
  950. package/neural-interface/public/shared/ocp-v2/ocp-v2-binding.js +280 -0
  951. package/neural-interface/public/shared/ocp-v2/ocp-v2-caps.js +67 -0
  952. package/neural-interface/public/shared/ocp-v2/ocp-v2-changes-logic.js +179 -0
  953. package/neural-interface/public/shared/ocp-v2/ocp-v2-changes.js +164 -0
  954. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +725 -0
  955. package/neural-interface/public/shared/ocp-v2/ocp-v2-compact-button.js +75 -0
  956. package/neural-interface/public/shared/ocp-v2/ocp-v2-composer-logic.js +1204 -0
  957. package/neural-interface/public/shared/ocp-v2/ocp-v2-confirm-logic.js +117 -0
  958. package/neural-interface/public/shared/ocp-v2/ocp-v2-confirm.js +59 -0
  959. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-gauge.js +252 -0
  960. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-menu.js +478 -0
  961. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-model.js +179 -0
  962. package/neural-interface/public/shared/ocp-v2/ocp-v2-events.js +233 -0
  963. package/neural-interface/public/shared/ocp-v2/ocp-v2-icons.js +30 -0
  964. package/neural-interface/public/shared/ocp-v2/ocp-v2-manager.js +1065 -0
  965. package/neural-interface/public/shared/ocp-v2/ocp-v2-mention-hints.js +182 -0
  966. package/neural-interface/public/shared/ocp-v2/ocp-v2-modelpicker.js +655 -0
  967. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +2636 -0
  968. package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +601 -0
  969. package/neural-interface/public/shared/ocp-v2/ocp-v2-profile-inheritance.js +78 -0
  970. package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +649 -0
  971. package/neural-interface/public/shared/ocp-v2/ocp-v2-providers.js +35 -0
  972. package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +357 -0
  973. package/neural-interface/public/shared/ocp-v2/ocp-v2-render-logic.js +189 -0
  974. package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +1869 -0
  975. package/neural-interface/public/shared/ocp-v2/ocp-v2-select.js +42 -0
  976. package/neural-interface/public/shared/ocp-v2/ocp-v2-send-logic.js +117 -0
  977. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +1714 -0
  978. package/neural-interface/public/shared/ocp-v2/ocp-v2-session-actions.js +468 -0
  979. package/neural-interface/public/shared/ocp-v2/ocp-v2-session-widgets.js +63 -0
  980. package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +366 -0
  981. package/neural-interface/public/shared/ocp-v2/ocp-v2-settings-link.js +19 -0
  982. package/neural-interface/public/shared/ocp-v2/ocp-v2-slash-hints.js +343 -0
  983. package/neural-interface/public/shared/ocp-v2/ocp-v2-state.js +746 -0
  984. package/neural-interface/public/shared/ocp-v2/ocp-v2-status-logic.js +347 -0
  985. package/neural-interface/public/shared/ocp-v2/ocp-v2-status.js +338 -0
  986. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +3543 -0
  987. package/neural-interface/public/shared/ocp-v2/ocp-v2-subagents-logic.js +482 -0
  988. package/neural-interface/public/shared/ocp-v2/ocp-v2-tools-logic.js +351 -0
  989. package/neural-interface/public/shared/ocp-v2/ocp-v2-tools.js +168 -0
  990. package/neural-interface/public/shared/ocp-v2/ocp-v2-variantpicker.js +315 -0
  991. package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +545 -0
  992. package/neural-interface/public/shared/provider-icons.js +30 -0
  993. package/neural-interface/public/shared/session-title.js +100 -0
  994. package/neural-interface/public/shared/settings/settings-ia.js +389 -0
  995. package/neural-interface/public/shared/settings/settings-kit.js +234 -0
  996. package/neural-interface/public/shared/settings/settings-search.js +463 -0
  997. package/neural-interface/public/shared/settings/settings-shell.js +570 -0
  998. package/neural-interface/public/shared/state.js +5 -0
  999. package/neural-interface/public/shared/storage.js +50 -7
  1000. package/neural-interface/public/shared/styleguide/sg-agents.js +42 -0
  1001. package/neural-interface/public/shared/styleguide/sg-brand.js +4 -0
  1002. package/neural-interface/public/shared/styleguide/sg-color-client.js +388 -0
  1003. package/neural-interface/public/shared/styleguide/sg-colors.js +148 -0
  1004. package/neural-interface/public/shared/styleguide/sg-components.js +35 -0
  1005. package/neural-interface/public/shared/styleguide/sg-history.js +41 -0
  1006. package/neural-interface/public/shared/styleguide/sg-icons-logo.js +38 -0
  1007. package/neural-interface/public/shared/styleguide/sg-imagery.js +4 -0
  1008. package/neural-interface/public/shared/styleguide/sg-import-export.js +47 -0
  1009. package/neural-interface/public/shared/styleguide/sg-kit.js +281 -0
  1010. package/neural-interface/public/shared/styleguide/sg-labels.js +318 -0
  1011. package/neural-interface/public/shared/styleguide/sg-layout.js +4 -0
  1012. package/neural-interface/public/shared/styleguide/sg-motion.js +5 -0
  1013. package/neural-interface/public/shared/styleguide/sg-panel.js +229 -0
  1014. package/neural-interface/public/shared/styleguide/sg-preview.js +138 -0
  1015. package/neural-interface/public/shared/styleguide/sg-rules.js +9 -0
  1016. package/neural-interface/public/shared/styleguide/sg-shape.js +24 -0
  1017. package/neural-interface/public/shared/styleguide/sg-state.js +132 -0
  1018. package/neural-interface/public/shared/styleguide/sg-typography.js +124 -0
  1019. package/neural-interface/public/shared/styles.css +7883 -1155
  1020. package/neural-interface/public/shared/synabun-mascot.js +1625 -0
  1021. package/neural-interface/public/shared/synabun-ticker.js +376 -0
  1022. package/neural-interface/public/shared/term-renderer.js +343 -0
  1023. package/neural-interface/public/shared/ui-assistant-panel.js +10 -0
  1024. package/neural-interface/public/shared/ui-assistant.js +77 -0
  1025. package/neural-interface/public/shared/ui-automation-studio.js +5105 -3573
  1026. package/neural-interface/public/shared/ui-claude-panel.js +11685 -6333
  1027. package/neural-interface/public/shared/ui-codex-panel.js +12 -0
  1028. package/neural-interface/public/shared/ui-cost-widget.js +55 -34
  1029. package/neural-interface/public/shared/ui-detail.js +77 -14
  1030. package/neural-interface/public/shared/ui-explorer.js +360 -181
  1031. package/neural-interface/public/shared/ui-file-explorer.js +485 -107
  1032. package/neural-interface/public/shared/ui-help.js +2 -2
  1033. package/neural-interface/public/shared/ui-image-gallery.js +45 -21
  1034. package/neural-interface/public/shared/ui-judgments.js +1346 -0
  1035. package/neural-interface/public/shared/ui-keybinds.js +3 -2
  1036. package/neural-interface/public/shared/ui-link.js +105 -51
  1037. package/neural-interface/public/shared/ui-loading.js +4 -4
  1038. package/neural-interface/public/shared/ui-memory-maintenance.js +111 -0
  1039. package/neural-interface/public/shared/ui-menubar.js +89 -4
  1040. package/neural-interface/public/shared/ui-native-loop-router-state.js +94 -0
  1041. package/neural-interface/public/shared/ui-native-loop-router.js +493 -0
  1042. package/neural-interface/public/shared/ui-native-window-id.js +7 -0
  1043. package/neural-interface/public/shared/ui-navbar.js +357 -222
  1044. package/neural-interface/public/shared/ui-notifications.js +58 -12
  1045. package/neural-interface/public/shared/ui-opencode-panel-v2.js +17 -0
  1046. package/neural-interface/public/shared/ui-panels.js +15 -7
  1047. package/neural-interface/public/shared/ui-resume.js +823 -653
  1048. package/neural-interface/public/shared/ui-schedule-queue.js +172 -0
  1049. package/neural-interface/public/shared/ui-schedules-studio.js +1882 -0
  1050. package/neural-interface/public/shared/ui-scroll-follow.js +194 -0
  1051. package/neural-interface/public/shared/ui-sessions.js +789 -34
  1052. package/neural-interface/public/shared/ui-settings.js +5793 -2190
  1053. package/neural-interface/public/shared/ui-sidepanel-layout.js +109 -0
  1054. package/neural-interface/public/shared/ui-sidepanel-runtime.js +19 -0
  1055. package/neural-interface/public/shared/ui-sidepanel-session-entry.js +40 -0
  1056. package/neural-interface/public/shared/ui-sidepanel-sessions.js +221 -0
  1057. package/neural-interface/public/shared/ui-sidepanel-state.js +131 -0
  1058. package/neural-interface/public/shared/ui-sidepanel-tray.js +547 -0
  1059. package/neural-interface/public/shared/ui-sidepanel-windows.js +387 -0
  1060. package/neural-interface/public/shared/ui-skills.js +18 -32
  1061. package/neural-interface/public/shared/ui-styleguide.js +35 -0
  1062. package/neural-interface/public/shared/ui-sync.js +87 -0
  1063. package/neural-interface/public/shared/ui-terminal.js +7877 -6385
  1064. package/neural-interface/public/shared/ui-tool-updates.js +292 -0
  1065. package/neural-interface/public/shared/ui-tooltip.js +156 -15
  1066. package/neural-interface/public/shared/ui-tutorial-draw.js +119 -683
  1067. package/neural-interface/public/shared/ui-tutorial-layout.js +135 -0
  1068. package/neural-interface/public/shared/ui-tutorial-steps.js +59 -2209
  1069. package/neural-interface/public/shared/ui-tutorial.css +102 -0
  1070. package/neural-interface/public/shared/ui-tutorial.js +557 -1076
  1071. package/neural-interface/public/shared/ui-update.js +420 -68
  1072. package/neural-interface/public/shared/ui-whatsapp.js +941 -0
  1073. package/neural-interface/public/shared/ui-whiteboard.js +1076 -233
  1074. package/neural-interface/public/shared/ui-workspaces.js +2 -1
  1075. package/neural-interface/public/shared/utils.js +58 -0
  1076. package/neural-interface/public/shared/vterm-buffer.js +15 -5
  1077. package/neural-interface/public/shared/whatsapp/wa-phone.js +65 -0
  1078. package/neural-interface/public/shared/whatsapp/wa-view.js +411 -0
  1079. package/neural-interface/public/sidepanel-session.html +18 -0
  1080. package/neural-interface/public/sw.js +8 -2
  1081. package/neural-interface/public/synabun.png +0 -0
  1082. package/neural-interface/public/variant/2d/graph.js +1707 -1635
  1083. package/neural-interface/public/variant/2d/lasso.js +2 -1
  1084. package/neural-interface/public/variant/2d/layout.js +595 -594
  1085. package/neural-interface/public/variant/2d/main.js +556 -521
  1086. package/neural-interface/public/variant/2d/settings-gfx.js +18 -24
  1087. package/neural-interface/public/variant/3d/main.js +516 -500
  1088. package/neural-interface/public/variant/3d/map-controls.js +144 -0
  1089. package/neural-interface/public/variant/3d/map-data.js +251 -0
  1090. package/neural-interface/public/variant/3d/map-labels.js +241 -0
  1091. package/neural-interface/public/variant/3d/map-pick.js +90 -0
  1092. package/neural-interface/public/variant/3d/map-renderer.js +521 -0
  1093. package/neural-interface/public/variant/3d/map-shaders.js +158 -0
  1094. package/neural-interface/public/variant/3d/map-view.js +618 -0
  1095. package/neural-interface/public/vendor/three/manifest.json +3 -0
  1096. package/neural-interface/public/vendor/three/three-0.169.0.min.js +3844 -0
  1097. package/neural-interface/public/vendor/xterm/manifest.json +3 -0
  1098. package/neural-interface/public/vendor/xterm/xterm-6.0.0.css +285 -0
  1099. package/neural-interface/public/vendor/xterm/xterm-6.0.0.min.js +192 -0
  1100. package/neural-interface/scripts/build-vendor.mjs +64 -0
  1101. package/neural-interface/scripts/codex-protocol-fixture.mjs +83 -0
  1102. package/neural-interface/scripts/rebuild-pty.js +37 -23
  1103. package/neural-interface/scripts/vendor-three-entry.js +24 -0
  1104. package/neural-interface/scripts/vendor-xterm-entry.js +8 -0
  1105. package/neural-interface/server.js +33948 -15000
  1106. package/neural-interface/skins/default/skin.css +90 -0
  1107. package/neural-interface/skins/default/skin.json +8 -0
  1108. package/neural-interface/templates/rulesets/README.md +9 -0
  1109. package/neural-interface/templates/rulesets/claude.md +3 -0
  1110. package/neural-interface/templates/rulesets/codex.md +2 -0
  1111. package/neural-interface/templates/rulesets/coexistence.md +6 -0
  1112. package/neural-interface/templates/rulesets/core.md +26 -0
  1113. package/neural-interface/templates/rulesets/cursor.md +2 -0
  1114. package/neural-interface/templates/rulesets/gemini.md +2 -0
  1115. package/neural-interface/templates/rulesets/legacy-hashes.json +227 -0
  1116. package/neural-interface/templates/rulesets/manifest.json +12 -0
  1117. package/neural-interface/templates/rulesets/opencode.md +2 -0
  1118. package/package.json +119 -53
  1119. package/postinstall.js +125 -26
  1120. package/preuninstall.js +187 -0
  1121. package/scripts/audit-claude-hook-usage.mjs +12 -0
  1122. package/scripts/audit-memory-duplicates.mjs +44 -0
  1123. package/scripts/measure-claude-hook-overhead.mjs +77 -0
  1124. package/scripts/recover-user-config.mjs +254 -0
  1125. package/scripts/restore-data-home-from-backup.mjs +239 -0
  1126. package/setup.js +804 -260
  1127. package/skills/leonardo/SKILL.md +19 -10
  1128. package/skills/leonardo/modules/image-prompter.md +18 -12
  1129. package/skills/leonardo/modules/video-prompter.md +19 -13
  1130. package/skills/synabun/SKILL.md +209 -185
  1131. package/skills/synabun/icon.png +0 -0
  1132. package/skills/synabun/modules/audit.md +380 -374
  1133. package/skills/synabun/modules/changelog.md +15 -6
  1134. package/skills/synabun/modules/idea.md +148 -144
  1135. package/skills/synabun/modules/memorize.md +13 -4
  1136. package/skills/synabun/modules/schedule.md +198 -0
  1137. package/skills/synabun/synabunicon.png +0 -0
  1138. package/updater.cmd +31 -0
  1139. package/updater.mjs +382 -0
  1140. package/updater.sh +29 -0
  1141. package/hooks/claude-code/test-user-learning.mjs +0 -531
  1142. package/neural-interface/public/claude-chat.css +0 -878
  1143. package/neural-interface/public/claude-chat.html +0 -92
  1144. package/neural-interface/public/claude-chat.js +0 -1168
  1145. package/neural-interface/public/index-legacy.html +0 -14677
  1146. package/neural-interface/public/index2d-legacy.html +0 -8193
  1147. package/neural-interface/public/shared/html-term-renderer.js +0 -1022
  1148. package/neural-interface/public/variant/3d/background.js +0 -884
  1149. package/neural-interface/public/variant/3d/camera.js +0 -661
  1150. package/neural-interface/public/variant/3d/gfx.js +0 -116
  1151. package/neural-interface/public/variant/3d/graph.js +0 -2399
  1152. package/neural-interface/public/variant/3d/settings-gfx.js +0 -228
  1153. package/neural-interface/templates/CLAUDE-template.md +0 -211
@@ -0,0 +1,851 @@
1
+ import {
2
+ accessSync,
3
+ copyFileSync,
4
+ constants as FS_CONSTANTS,
5
+ createReadStream,
6
+ existsSync,
7
+ lstatSync,
8
+ mkdtempSync,
9
+ mkdirSync,
10
+ readFileSync,
11
+ readdirSync,
12
+ renameSync,
13
+ rmSync,
14
+ statSync,
15
+ statfsSync,
16
+ unlinkSync,
17
+ writeFileSync,
18
+ } from 'node:fs';
19
+ import { createHash } from 'node:crypto';
20
+ import { basename, dirname, extname, join, parse as parsePath, relative, resolve, sep } from 'node:path';
21
+ import { DatabaseSync } from 'node:sqlite';
22
+ import archiver from 'archiver';
23
+ import { openZipArchive, readZipEntry, verifyBackupChecksums } from './backup-zip-reader.js';
24
+ import { LOCK_FILE_NAME } from './rulesets/lock.js';
25
+
26
+ export const BACKUP_MANIFEST_VERSION = 3;
27
+ export const BACKUP_PREFIX = 'synabun-auto-backup';
28
+ export const BACKUP_FREE_SPACE_RESERVE_BYTES = 512 * 1024 * 1024;
29
+ export const DEFAULT_BACKUP_RETENTION = Object.freeze({
30
+ recentHours: 24,
31
+ dailyDays: 30,
32
+ weeklyWeeks: 12,
33
+ maxBytes: 10 * 1024 * 1024 * 1024,
34
+ });
35
+
36
+ /** The DATA_HOME folders every backup copies (createVerifiedBackup); DATA_HOME/.env goes too, as a file. */
37
+ export const BACKUP_DATA_DIRS = Object.freeze(['data', 'mcp-data']);
38
+
39
+ /**
40
+ * Every folder a backup copies from: BACKUP_DATA_DIRS under `dataHome`, then
41
+ * the folders of the caller's `additionalEntries` (server.js: skills, agents,
42
+ * skins). A secret that must never be archived (the WhatsApp session keys)
43
+ * has to live outside all of them.
44
+ */
45
+ export function backupRoots(dataHome, additionalEntries = []) {
46
+ const roots = BACKUP_DATA_DIRS.map((dir) => resolve(dataHome, dir));
47
+ for (const entry of Array.isArray(additionalEntries) ? additionalEntries : []) {
48
+ const diskPath = typeof entry === 'string' ? entry : entry?.diskPath;
49
+ if (diskPath) roots.push(resolve(diskPath));
50
+ }
51
+ return [...new Set(roots)];
52
+ }
53
+
54
+ const TRANSIENT_DATA_NAMES = new Set([
55
+ 'server-stdout.log',
56
+ 'server-stderr.log',
57
+ 'restart-requested',
58
+ 'opencode-managed.pid',
59
+ ]);
60
+
61
+ /**
62
+ * Files in a data folder that are operating-system locks, not data: the rules
63
+ * installer's writer lock (lib/rulesets/lock.js). A backup never opens, reads
64
+ * or copies one (closing any descriptor on the file drops this process's lock
65
+ * on it), and a restore never extracts one over the live file (that would put
66
+ * two servers on two different files): system-restore.js reads this list.
67
+ */
68
+ export const LOCK_ONLY_DATA_FILES = Object.freeze([LOCK_FILE_NAME]);
69
+ const SQLITE_SIDE_FILES = ['', '-journal', '-wal', '-shm'];
70
+
71
+ /** True for a lock-only file and for the journal, WAL and shm names SQLite could put beside it. Case does not count. */
72
+ export function isLockOnlyDataFile(name) {
73
+ const lower = String(name).toLowerCase();
74
+ return LOCK_ONLY_DATA_FILES.some(file => SQLITE_SIDE_FILES.some(suffix => lower === `${file}${suffix}`));
75
+ }
76
+
77
+ const IMMUTABLE_BACKUP_EXTENSIONS = new Set([
78
+ '.avif', '.gif', '.ico', '.jpeg', '.jpg', '.mov', '.mp3', '.mp4', '.ogg',
79
+ '.pdf', '.png', '.svg', '.webm', '.webp', '.woff', '.woff2', '.zip',
80
+ ]);
81
+
82
+ // Re-downloadable bulk media under data/. These are pipeline caches, not user
83
+ // state: including them made a pre-update snapshot spend minutes deflating
84
+ // hundreds of MB of video with no progress output, which reads as a hang and
85
+ // gets killed. A restore re-fetches them.
86
+ const EXCLUDED_DATA_DIRS = new Set([
87
+ 'youtube-downloads',
88
+ ]);
89
+
90
+ // Payloads that are already compressed. DEFLATE spends full CPU on every byte
91
+ // of these for no meaningful size gain, so they are stored verbatim instead.
92
+ const INCOMPRESSIBLE_EXTENSIONS = new Set([
93
+ '.avif', '.gif', '.ico', '.jpeg', '.jpg', '.mov', '.mp3', '.mp4', '.ogg',
94
+ '.png', '.webm', '.webp', '.woff', '.woff2', '.zip',
95
+ ]);
96
+
97
+ // Generated media. An upgrade snapshot exists to roll back *state* if a new
98
+ // version misbehaves; it never rewrites these, and they survive a rollback on
99
+ // disk regardless. Archiving them put multi-GB data homes through several
100
+ // minutes of compression on the npm update path, so upgrade snapshots skip
101
+ // them. Scheduled and manual backups still capture everything.
102
+ const BULK_MEDIA_EXTENSIONS = new Set([
103
+ '.avif', '.bmp', '.gif', '.heic', '.jpeg', '.jpg', '.m4a', '.m4v', '.mkv',
104
+ '.mov', '.mp3', '.mp4', '.ogg', '.png', '.tiff', '.wav', '.webm', '.webp',
105
+ ]);
106
+
107
+ // Snapshot kinds taken while the user is blocked on a version change.
108
+ const UPGRADE_BACKUP_KINDS = new Set(['pre-update', 'pre-migration']);
109
+
110
+ // Irreplaceable state: the memory database, UI state databases, and the JSON
111
+ // that configures them. Everything a rollback actually needs lives here.
112
+ const ESSENTIAL_STATE_EXTENSIONS = new Set(['.db', '.sqlite', '.sqlite3', '.json']);
113
+
114
+ // Above this, an upgrade snapshot stops trying to be comprehensive and keeps
115
+ // only irreplaceable state. Dropping media is not enough on its own — a data
116
+ // home can reach multiple GB in ordinary files, and compressing that on the
117
+ // npm update path is what made upgrades look broken.
118
+ const UPGRADE_SNAPSHOT_SOFT_LIMIT_BYTES = 1024 * 1024 * 1024;
119
+
120
+ function fileBytes(path) {
121
+ try { return statSync(path).size; } catch { return 0; }
122
+ }
123
+
124
+ /**
125
+ * Pick what an upgrade snapshot archives. Generated media always goes; if the
126
+ * remainder is still oversized, fall back to irreplaceable state only. Returns
127
+ * the kept files plus what was dropped, so the caller can say so out loud.
128
+ */
129
+ function selectUpgradeSnapshotFiles(files, { softLimitBytes = UPGRADE_SNAPSHOT_SOFT_LIMIT_BYTES } = {}) {
130
+ const excluded = { reason: 'generated-media', files: 0, bytes: 0 };
131
+ const kept = [];
132
+ for (const file of files) {
133
+ if (BULK_MEDIA_EXTENSIONS.has(extname(file.archivePath).toLowerCase())) {
134
+ excluded.files += 1;
135
+ excluded.bytes += fileBytes(file.diskPath);
136
+ continue;
137
+ }
138
+ kept.push(file);
139
+ }
140
+
141
+ const keptBytes = kept.reduce((total, file) => total + fileBytes(file.diskPath), 0);
142
+ if (keptBytes <= softLimitBytes) return { files: kept, excluded };
143
+
144
+ const essential = [];
145
+ for (const file of kept) {
146
+ const isEnv = file.archivePath === 'env.bak';
147
+ const isMcpState = file.archivePath.startsWith('mcp-data/');
148
+ const isStateFile = ESSENTIAL_STATE_EXTENSIONS.has(extname(file.archivePath).toLowerCase());
149
+ if (isEnv || isMcpState || isStateFile) { essential.push(file); continue; }
150
+ excluded.files += 1;
151
+ excluded.bytes += fileBytes(file.diskPath);
152
+ }
153
+ return { files: essential, excluded: { ...excluded, reason: 'oversized-data-home' } };
154
+ }
155
+
156
+ export class BackupStorageError extends Error {
157
+ constructor({ availableBytes, requiredBytes, folderPath }) {
158
+ const availableMiB = Math.floor(availableBytes / 1024 / 1024);
159
+ const requiredMiB = Math.ceil(requiredBytes / 1024 / 1024);
160
+ super(`Insufficient disk space for backup: ${availableMiB} MB available, ${requiredMiB} MB required`);
161
+ this.name = 'BackupStorageError';
162
+ this.code = 'ENOSPC';
163
+ this.availableBytes = availableBytes;
164
+ this.requiredBytes = requiredBytes;
165
+ this.folderPath = folderPath;
166
+ this.retryable = true;
167
+ }
168
+ }
169
+
170
+ function safeTimestamp(date) {
171
+ return date.toISOString().replace(/[:.]/g, '-');
172
+ }
173
+
174
+ function archiveNameFor(kind, createdAt) {
175
+ return `synabun-${kind}-${safeTimestamp(createdAt)}.zip`;
176
+ }
177
+
178
+ function hashFile(path) {
179
+ return new Promise((resolveHash, reject) => {
180
+ const digest = createHash('sha256');
181
+ const stream = createReadStream(path);
182
+ stream.on('data', chunk => digest.update(chunk));
183
+ stream.on('error', reject);
184
+ stream.on('end', () => resolveHash(digest.digest('hex')));
185
+ });
186
+ }
187
+
188
+ function escapeSqliteString(value) {
189
+ return String(value).replace(/'/g, "''");
190
+ }
191
+
192
+ function createConsistentSqliteSnapshot(sourcePath, snapshotPath) {
193
+ if (!existsSync(sourcePath)) return null;
194
+ try { if (existsSync(snapshotPath)) unlinkSync(snapshotPath); } catch {}
195
+ let source;
196
+ let snapshot;
197
+ try {
198
+ source = new DatabaseSync(sourcePath);
199
+ source.exec('PRAGMA busy_timeout = 10000');
200
+ source.exec(`VACUUM INTO '${escapeSqliteString(snapshotPath)}'`);
201
+ snapshot = new DatabaseSync(snapshotPath, { readOnly: true });
202
+ const integrityRow = snapshot.prepare('PRAGMA integrity_check').get();
203
+ const integrity = integrityRow?.integrity_check || integrityRow?.integrity || 'unknown';
204
+ if (integrity !== 'ok') throw new Error(`SQLite snapshot integrity check returned: ${integrity}`);
205
+ let memoryCount = null;
206
+ try { memoryCount = Number(snapshot.prepare('SELECT COUNT(*) AS count FROM memories').get()?.count || 0); } catch {}
207
+ return { path: snapshotPath, integrity, memoryCount, sizeBytes: statSync(snapshotPath).size };
208
+ } finally {
209
+ try { snapshot?.close(); } catch {}
210
+ try { source?.close(); } catch {}
211
+ }
212
+ }
213
+
214
+ // SQLite rollback journals, including the ones left beside migration copies
215
+ // (memory.db.pre-v4-….bak-journal). They are only meaningful next to the file
216
+ // they belonged to, and that file is snapshotted consistently or not at all.
217
+ const SQLITE_JOURNAL_RE = /\.(?:db|bak)-journal$/i;
218
+
219
+ function shouldSkipDataPath(relativePath) {
220
+ const normalized = relativePath.replace(/\\/g, '/');
221
+ const parts = normalized.split('/');
222
+ const name = parts.at(-1);
223
+ if (parts[0] === 'updater') return true;
224
+ if (parts[0] === 'logs') return true;
225
+ if (parts.length > 1 && EXCLUDED_DATA_DIRS.has(parts[0])) return true;
226
+ if (TRANSIENT_DATA_NAMES.has(name)) return true;
227
+ if (isLockOnlyDataFile(name)) return true;
228
+ if (name.endsWith('.tmp') || name.endsWith('.pid')) return true;
229
+ if (/\.db-(?:wal|shm)$/i.test(name)) return true;
230
+ if (SQLITE_JOURNAL_RE.test(name)) return true;
231
+ return false;
232
+ }
233
+
234
+ /**
235
+ * mcp-data holds full copies of memory.db written by schema migrations and
236
+ * manual repairs (memory.db.pre-v7-….bak, memory.db.backup-….bak). Each is as
237
+ * large as the live database, and the archive already carries a consistent
238
+ * snapshot of that, so six of them grew a 1.3 GB data home into a 3 GB archive.
239
+ */
240
+ export function isDatabaseCopyArtifact(relativePath) {
241
+ const name = relativePath.replace(/\\/g, '/').split('/').at(-1);
242
+ return /^memory\.db\../i.test(name) || SQLITE_JOURNAL_RE.test(name);
243
+ }
244
+
245
+ /**
246
+ * A destination on a removable drive that is not mounted. mkdir -p would try
247
+ * to create the mount point itself and fail with a baffling
248
+ * `EACCES: mkdir '/Volumes/<drive>'` (or, worse, succeed as root and fill the
249
+ * system disk), so it is reported as the drive being absent instead.
250
+ */
251
+ export function missingBackupVolume(folderPath, { volumesRoot = '/Volumes' } = {}) {
252
+ if (!folderPath) return null;
253
+ const target = resolve(folderPath);
254
+ const root = parsePath(target).root;
255
+ // Windows: an unplugged drive letter has no root at all.
256
+ if (root && !existsSync(root)) return { name: root.replace(/[\\/]+$/, ''), mountPoint: root };
257
+ const volumes = resolve(volumesRoot);
258
+ if (!target.startsWith(volumes + sep)) return null;
259
+ const name = target.slice(volumes.length + 1).split(sep)[0];
260
+ if (!name) return null;
261
+ const mountPoint = join(volumes, name);
262
+ return existsSync(mountPoint) ? null : { name, mountPoint };
263
+ }
264
+
265
+ export class BackupDestinationUnavailableError extends Error {
266
+ constructor({ name, mountPoint, folderPath }) {
267
+ super(`Backup drive "${name}" is not connected (${mountPoint}). Connect it or choose another backup folder.`);
268
+ this.name = 'BackupDestinationUnavailableError';
269
+ this.code = 'EBACKUPDRIVE';
270
+ this.mountPoint = mountPoint;
271
+ this.folderPath = folderPath;
272
+ this.retryable = true;
273
+ }
274
+ }
275
+
276
+ export function assertBackupDestinationMounted(folderPath, options) {
277
+ const missing = missingBackupVolume(folderPath, options);
278
+ if (missing) throw new BackupDestinationUnavailableError({ ...missing, folderPath });
279
+ }
280
+
281
+ function collectFiles(root, archiveRoot, { filter = () => true } = {}) {
282
+ const files = [];
283
+ function walk(current) {
284
+ if (!existsSync(current)) return;
285
+ let stat;
286
+ try { stat = lstatSync(current); }
287
+ catch (error) {
288
+ if (error?.code === 'ENOENT') return;
289
+ throw error;
290
+ }
291
+ if (stat.isSymbolicLink()) return;
292
+ if (stat.isFile()) {
293
+ const rel = relative(root, current).replace(/\\/g, '/');
294
+ if (filter(rel, current)) files.push({ diskPath: current, archivePath: `${archiveRoot}/${rel}` });
295
+ return;
296
+ }
297
+ if (!stat.isDirectory()) return;
298
+ let entries;
299
+ try { entries = readdirSync(current).sort(); }
300
+ catch (error) {
301
+ if (error?.code === 'ENOENT') return;
302
+ throw error;
303
+ }
304
+ for (const entry of entries) walk(join(current, entry));
305
+ }
306
+ walk(root);
307
+ return files;
308
+ }
309
+
310
+ function backupFileSize(file) {
311
+ try { return statSync(file.diskPath).size; }
312
+ catch (error) {
313
+ if (error?.code === 'ENOENT') return 0;
314
+ throw error;
315
+ }
316
+ }
317
+
318
+ function isSqliteBackupInput(file) {
319
+ return /\.(?:db|sqlite|sqlite3)$/i.test(file.archivePath);
320
+ }
321
+
322
+ function isMutableBackupInput(file) {
323
+ if (isSqliteBackupInput(file)) return false;
324
+ return !IMMUTABLE_BACKUP_EXTENSIONS.has(extname(file.archivePath).toLowerCase());
325
+ }
326
+
327
+ export function backupAvailableBytes(folderPath) {
328
+ let probe = resolve(folderPath);
329
+ while (!existsSync(probe) && dirname(probe) !== probe) probe = dirname(probe);
330
+ const stats = statfsSync(probe);
331
+ return Number(stats.bavail) * Number(stats.bsize);
332
+ }
333
+
334
+ export function assertBackupWorkingSpace({
335
+ folderPath,
336
+ files = [],
337
+ databasePath = null,
338
+ expectedArchiveBytes = 0,
339
+ freeSpaceReserveBytes = BACKUP_FREE_SPACE_RESERVE_BYTES,
340
+ getAvailableBytes = backupAvailableBytes,
341
+ } = {}) {
342
+ const primaryDatabaseBytes = databasePath && existsSync(databasePath) ? statSync(databasePath).size : 0;
343
+ const inputBytes = files.reduce((sum, file) => sum + backupFileSize(file), primaryDatabaseBytes);
344
+ const stagedMutableBytes = files
345
+ .filter(isMutableBackupInput)
346
+ .reduce((sum, file) => sum + backupFileSize(file), 0);
347
+ const sqliteSnapshotBytes = files
348
+ .filter(isSqliteBackupInput)
349
+ .reduce((sum, file) => sum + backupFileSize(file), primaryDatabaseBytes);
350
+ const archiveBytes = Math.max(Number(expectedArchiveBytes) || 0, inputBytes);
351
+ const requiredBytes = Math.max(0, Number(freeSpaceReserveBytes) || 0)
352
+ + stagedMutableBytes
353
+ + sqliteSnapshotBytes
354
+ + archiveBytes;
355
+ const availableBytes = Number(getAvailableBytes(folderPath));
356
+ if (Number.isFinite(availableBytes) && availableBytes < requiredBytes) {
357
+ throw new BackupStorageError({ availableBytes, requiredBytes, folderPath });
358
+ }
359
+ return {
360
+ availableBytes,
361
+ requiredBytes,
362
+ archiveBytes,
363
+ stagedMutableBytes,
364
+ sqliteSnapshotBytes,
365
+ };
366
+ }
367
+
368
+ /**
369
+ * Remove archive temps, SQLite temps, and stage dirs abandoned by an earlier
370
+ * run. A backup interrupted with Ctrl-C never reaches its own catch/finally,
371
+ * so its partial archive is orphaned forever — a killed pre-update snapshot
372
+ * left hundreds of MB behind with nothing to reclaim it.
373
+ */
374
+ export function cleanupStaleBackupArtifacts(folderPath, { maxAgeMs = 60 * 60 * 1000, now = Date.now } = {}) {
375
+ if (!existsSync(folderPath)) return [];
376
+ const removed = [];
377
+ let entries;
378
+ try { entries = readdirSync(folderPath); }
379
+ catch { return removed; }
380
+ for (const name of entries) {
381
+ const isArchiveTemp = /\.zip\.\d+\.tmp$/.test(name);
382
+ const isSqliteTemp = /^\.synabun-(?:db|extra-db)-.*\.tmp$/.test(name);
383
+ const isStageDir = /^\.synabun-files-/.test(name);
384
+ if (!isArchiveTemp && !isSqliteTemp && !isStageDir) continue;
385
+ const path = resolve(folderPath, name);
386
+ try {
387
+ if (now() - statSync(path).mtimeMs < maxAgeMs) continue;
388
+ rmSync(path, { recursive: true, force: true });
389
+ removed.push(name);
390
+ } catch { /* another process may be mid-cleanup; leave it */ }
391
+ }
392
+ return removed;
393
+ }
394
+
395
+ function snapshotMutableBackupFiles(files, folderPath) {
396
+ if (!files.some(isMutableBackupInput)) return { files, stageDir: null };
397
+ const stageDir = mkdtempSync(resolve(folderPath, `.synabun-files-${process.pid}-`));
398
+ const snapshots = [];
399
+ try {
400
+ for (let index = 0; index < files.length; index++) {
401
+ const file = files[index];
402
+ if (!isMutableBackupInput(file)) {
403
+ snapshots.push(file);
404
+ continue;
405
+ }
406
+ const diskPath = resolve(stageDir, String(index));
407
+ try {
408
+ copyFileSync(file.diskPath, diskPath);
409
+ snapshots.push({ ...file, diskPath });
410
+ } catch (error) {
411
+ // A runtime file deleted between enumeration and snapshotting is no
412
+ // longer part of the state being backed up. Other failures are fatal.
413
+ if (error?.code !== 'ENOENT') throw error;
414
+ }
415
+ }
416
+ return { files: snapshots, stageDir };
417
+ } catch (error) {
418
+ try { rmSync(stageDir, { recursive: true, force: true }); } catch {}
419
+ throw error;
420
+ }
421
+ }
422
+
423
+ function normalizeAdditionalEntries(entries = []) {
424
+ const result = [];
425
+ for (const entry of entries) {
426
+ if (!entry?.diskPath || !entry?.archivePath || !existsSync(entry.diskPath)) continue;
427
+ let stat;
428
+ try { stat = lstatSync(entry.diskPath); }
429
+ catch (error) {
430
+ if (error?.code === 'ENOENT') continue;
431
+ throw error;
432
+ }
433
+ if (stat.isSymbolicLink()) continue;
434
+ if (stat.isDirectory()) result.push(...collectFiles(entry.diskPath, entry.archivePath));
435
+ else if (stat.isFile()) result.push({ diskPath: entry.diskPath, archivePath: entry.archivePath });
436
+ }
437
+ return result;
438
+ }
439
+
440
+ async function writeArchive({ tempPath, files, manifest, level = 6 }) {
441
+ const { createWriteStream } = await import('node:fs');
442
+ await new Promise((resolveWrite, reject) => {
443
+ const output = createWriteStream(tempPath, { flags: 'wx' });
444
+ const archive = archiver('zip', { zlib: { level } });
445
+ output.on('close', resolveWrite);
446
+ output.on('error', reject);
447
+ archive.on('warning', error => error.code === 'ENOENT' ? null : reject(error));
448
+ archive.on('error', reject);
449
+ archive.pipe(output);
450
+ for (const file of files) {
451
+ const store = INCOMPRESSIBLE_EXTENSIONS.has(extname(file.archivePath).toLowerCase());
452
+ archive.file(file.diskPath, { name: `${BACKUP_PREFIX}/${file.archivePath}`, store });
453
+ }
454
+ archive.append(JSON.stringify(manifest, null, 2), { name: `${BACKUP_PREFIX}/manifest.json` });
455
+ archive.finalize().catch(reject);
456
+ });
457
+ }
458
+
459
+ /**
460
+ * Reopen a finished archive and stream every manifest-listed entry through
461
+ * sha256. Streaming matters: reading the archive into memory failed every
462
+ * backup over 2 GiB, which is when a backup matters most.
463
+ */
464
+ export async function verifyBackupArchive(path) {
465
+ const zip = await openZipArchive(path);
466
+ try {
467
+ const manifestEntry = zip.getEntry(`${BACKUP_PREFIX}/manifest.json`);
468
+ if (!manifestEntry) throw new Error('Backup verification failed: manifest is missing');
469
+ const manifest = JSON.parse((await readZipEntry(zip, manifestEntry)).toString('utf-8'));
470
+ await verifyBackupChecksums(zip, { prefix: BACKUP_PREFIX, manifest });
471
+ return manifest;
472
+ } finally {
473
+ await zip.close();
474
+ }
475
+ }
476
+
477
+ /** Create, reopen, checksum-verify, and atomically publish one immutable ZIP. */
478
+ export async function createVerifiedBackup({
479
+ dataHome,
480
+ databasePath = resolve(dataHome, 'mcp-data', 'memory.db'),
481
+ folderPath,
482
+ kind = 'scheduled',
483
+ appVersion = null,
484
+ dataSchemaVersion = 1,
485
+ sourceFingerprint = null,
486
+ additionalEntries = [],
487
+ expectedArchiveBytes = 0,
488
+ freeSpaceReserveBytes = BACKUP_FREE_SPACE_RESERVE_BYTES,
489
+ getAvailableBytes = backupAvailableBytes,
490
+ onBeforeArchive = null,
491
+ onProgress = null,
492
+ upgradeSoftLimitBytes = UPGRADE_SNAPSHOT_SOFT_LIMIT_BYTES,
493
+ now = () => new Date(),
494
+ } = {}) {
495
+ // A large data home spends minutes in checksum/archive with no output. Phase
496
+ // reporting is what stops that from reading as a hang to the caller.
497
+ const report = typeof onProgress === 'function' ? onProgress : () => {};
498
+ if (!dataHome || !folderPath) throw new Error('dataHome and folderPath are required');
499
+ const createdAt = now();
500
+ assertBackupDestinationMounted(folderPath);
501
+ mkdirSync(folderPath, { recursive: true });
502
+ cleanupStaleBackupArtifacts(folderPath);
503
+ const destination = resolve(folderPath, archiveNameFor(kind, createdAt));
504
+ const tempPath = `${destination}.${process.pid}.tmp`;
505
+ const sqliteTemp = resolve(folderPath, `.synabun-db-${process.pid}-${Date.now()}.tmp`);
506
+ const extraSqliteTemps = [];
507
+ if (existsSync(destination)) throw new Error(`Backup already exists: ${destination}`);
508
+
509
+ let sqliteSnapshot = null;
510
+ let stageDir = null;
511
+ try {
512
+ const files = [];
513
+ const envPath = resolve(dataHome, '.env');
514
+ if (existsSync(envPath)) files.push({ diskPath: envPath, archivePath: 'env.bak' });
515
+ // BACKUP_DATA_DIRS is the list other modules read (backupRoots): every folder copied here is on it.
516
+ const dataDirFilters = {
517
+ data: rel => !shouldSkipDataPath(rel),
518
+ 'mcp-data': rel => !shouldSkipDataPath(rel)
519
+ && !isDatabaseCopyArtifact(rel)
520
+ && !/^memory\.db(?:-wal|-shm)?$/i.test(rel)
521
+ && !/\.db-(?:wal|shm)$/i.test(rel),
522
+ };
523
+ for (const dir of BACKUP_DATA_DIRS) files.push(...collectFiles(resolve(dataHome, dir), dir, { filter: dataDirFilters[dir] }));
524
+ files.push(...normalizeAdditionalEntries(additionalEntries));
525
+
526
+ // De-duplicate before estimating work space so explicit additional entries
527
+ // cannot inflate the preflight or create ambiguous ZIP members.
528
+ const deduped = [...new Map(files.map(file => [
529
+ file.archivePath.replace(/\\/g, '/'),
530
+ file,
531
+ ])).values()];
532
+
533
+ // Keep the upgrade path bounded: state is archived, generated media is not.
534
+ const leanSnapshot = UPGRADE_BACKUP_KINDS.has(kind);
535
+ const selection = leanSnapshot
536
+ ? selectUpgradeSnapshotFiles(deduped, { softLimitBytes: upgradeSoftLimitBytes })
537
+ : { files: deduped, excluded: null };
538
+ const sourceFiles = selection.files;
539
+ const excluded = selection.excluded;
540
+
541
+ const workingSpace = assertBackupWorkingSpace({
542
+ folderPath,
543
+ files: sourceFiles,
544
+ databasePath,
545
+ expectedArchiveBytes,
546
+ freeSpaceReserveBytes,
547
+ getAvailableBytes,
548
+ });
549
+ report({
550
+ phase: 'collect',
551
+ files: sourceFiles.length,
552
+ bytes: workingSpace.archiveBytes,
553
+ skippedFiles: excluded?.files ?? 0,
554
+ skippedBytes: excluded?.bytes ?? 0,
555
+ skippedReason: excluded?.reason ?? null,
556
+ });
557
+
558
+ sqliteSnapshot = createConsistentSqliteSnapshot(databasePath, sqliteTemp);
559
+ files.length = 0;
560
+ files.push(...sourceFiles);
561
+ if (sqliteSnapshot) files.push({ diskPath: sqliteSnapshot.path, archivePath: 'database/memory.db' });
562
+
563
+ // UI blob/state databases also use WAL. Snapshot every additional SQLite
564
+ // file rather than pairing an arbitrary main file with a moving WAL.
565
+ for (let index = 0; index < files.length; index++) {
566
+ const file = files[index];
567
+ if (!/\.db$/i.test(file.archivePath) || file.archivePath === 'database/memory.db') continue;
568
+ const temp = resolve(folderPath, `.synabun-extra-db-${process.pid}-${Date.now()}-${index}.tmp`);
569
+ const consistent = createConsistentSqliteSnapshot(file.diskPath, temp);
570
+ if (!consistent) continue;
571
+ extraSqliteTemps.push(temp);
572
+ files[index] = { ...file, diskPath: temp };
573
+ }
574
+
575
+ // De-duplicate archive paths so explicit additional entries cannot create
576
+ // ambiguous ZIP members.
577
+ const unique = new Map(files.map(file => [file.archivePath.replace(/\\/g, '/'), file]));
578
+ const stableInputs = snapshotMutableBackupFiles([...unique.values()], folderPath);
579
+ stageDir = stableInputs.stageDir;
580
+ const finalFiles = stableInputs.files.sort((a, b) => a.archivePath.localeCompare(b.archivePath));
581
+ report({ phase: 'checksum', files: finalFiles.length });
582
+ const checksums = {};
583
+ for (const file of finalFiles) checksums[file.archivePath] = `sha256:${await hashFile(file.diskPath)}`;
584
+
585
+ const manifest = {
586
+ version: BACKUP_MANIFEST_VERSION,
587
+ created: createdAt.toISOString(),
588
+ kind,
589
+ appVersion,
590
+ dataSchemaVersion,
591
+ sourceFingerprint,
592
+ storage: 'sqlite',
593
+ database: sqliteSnapshot ? {
594
+ file: 'database/memory.db',
595
+ sizeBytes: sqliteSnapshot.sizeBytes,
596
+ memoryCount: sqliteSnapshot.memoryCount,
597
+ integrity: sqliteSnapshot.integrity,
598
+ } : null,
599
+ files: finalFiles.map(file => file.archivePath),
600
+ checksums,
601
+ // A lean snapshot is not a whole-data-home backup. Recording that here
602
+ // keeps a restore from silently presenting it as one.
603
+ scope: leanSnapshot ? 'state-only' : 'complete',
604
+ excluded,
605
+ verified: true,
606
+ verification: { algorithm: 'sha256', publication: 'verify-before-atomic-rename' },
607
+ };
608
+ if (typeof onBeforeArchive === 'function') await onBeforeArchive({ files: finalFiles, manifest });
609
+ report({ phase: 'archive', files: finalFiles.length, bytes: workingSpace.archiveBytes });
610
+ // Level 1 on the blocking upgrade path: the remaining payload is mostly
611
+ // SQLite and JSON, where fast deflate still shrinks well.
612
+ await writeArchive({ tempPath, files: finalFiles, manifest, level: leanSnapshot ? 1 : 6 });
613
+ report({ phase: 'verify', files: finalFiles.length });
614
+ const publishedManifest = await verifyBackupArchive(tempPath);
615
+ renameSync(tempPath, destination);
616
+ return {
617
+ path: destination,
618
+ name: basename(destination),
619
+ kind,
620
+ createdAt: createdAt.toISOString(),
621
+ sizeBytes: statSync(destination).size,
622
+ manifest: publishedManifest,
623
+ };
624
+ } catch (error) {
625
+ try { if (existsSync(tempPath)) unlinkSync(tempPath); } catch {}
626
+ throw error;
627
+ } finally {
628
+ try { if (existsSync(sqliteTemp)) unlinkSync(sqliteTemp); } catch {}
629
+ for (const path of extraSqliteTemps) {
630
+ try { if (existsSync(path)) unlinkSync(path); } catch {}
631
+ }
632
+ if (stageDir) {
633
+ try { rmSync(stageDir, { recursive: true, force: true }); } catch {}
634
+ }
635
+ }
636
+ }
637
+
638
+ function dateFromSnapshotName(name, stat) {
639
+ const match = name.match(/^synabun-[a-z-]+-(\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}Z)\.zip$/i);
640
+ if (!match) return stat.mtime;
641
+ const iso = match[1].replace(/T(\d{2})-(\d{2})-(\d{2})-(\d{3})Z$/, 'T$1:$2:$3.$4Z');
642
+ const value = new Date(iso);
643
+ return Number.isNaN(value.getTime()) ? stat.mtime : value;
644
+ }
645
+
646
+ function kindFromName(name) {
647
+ const match = name.match(/^synabun-(scheduled|pre-update|pre-migration|manual)-/i);
648
+ return match?.[1]?.toLowerCase() || (name === 'synabun-auto-backup.zip' ? 'legacy' : 'unknown');
649
+ }
650
+
651
+ export function listBackupSnapshots(folderPath) {
652
+ if (!folderPath || !existsSync(folderPath)) return [];
653
+ return readdirSync(folderPath)
654
+ .filter(name => name.endsWith('.zip') && (name.startsWith('synabun-') || name === 'synabun-auto-backup.zip'))
655
+ .map(name => {
656
+ const path = resolve(folderPath, name);
657
+ const stat = statSync(path);
658
+ const created = dateFromSnapshotName(name, stat);
659
+ return {
660
+ name,
661
+ path,
662
+ kind: kindFromName(name),
663
+ pinned: name === 'synabun-auto-backup.zip',
664
+ createdAt: created.toISOString(),
665
+ createdMs: created.getTime(),
666
+ sizeBytes: stat.size,
667
+ };
668
+ })
669
+ .sort((a, b) => b.createdMs - a.createdMs);
670
+ }
671
+
672
+ function utcDay(dateMs) {
673
+ return new Date(dateMs).toISOString().slice(0, 10);
674
+ }
675
+
676
+ function utcWeek(dateMs) {
677
+ const date = new Date(dateMs);
678
+ const day = date.getUTCDay() || 7;
679
+ date.setUTCDate(date.getUTCDate() - day + 1);
680
+ return date.toISOString().slice(0, 10);
681
+ }
682
+
683
+ export function applyBackupRetention({
684
+ folderPath,
685
+ retention = DEFAULT_BACKUP_RETENTION,
686
+ incomingBytes = 0,
687
+ now = () => new Date(),
688
+ remove = path => unlinkSync(path),
689
+ } = {}) {
690
+ const policy = { ...DEFAULT_BACKUP_RETENTION, ...(retention || {}) };
691
+ const snapshots = listBackupSnapshots(folderPath);
692
+ const currentMs = now().getTime();
693
+ const recentCutoff = currentMs - policy.recentHours * 60 * 60 * 1000;
694
+ const dailyCutoff = currentMs - policy.dailyDays * 24 * 60 * 60 * 1000;
695
+ const weeklyCutoff = currentMs - policy.weeklyWeeks * 7 * 24 * 60 * 60 * 1000;
696
+ const keep = new Set(snapshots.filter(item => item.pinned).map(item => item.path));
697
+ const protectedPaths = new Set(keep);
698
+ const scheduled = snapshots.filter(item => item.kind === 'scheduled');
699
+ if (scheduled[0]) {
700
+ keep.add(scheduled[0].path);
701
+ protectedPaths.add(scheduled[0].path);
702
+ }
703
+ const latestPreUpdate = snapshots.find(item => item.kind === 'pre-update');
704
+ if (latestPreUpdate) {
705
+ keep.add(latestPreUpdate.path);
706
+ protectedPaths.add(latestPreUpdate.path);
707
+ }
708
+ for (const item of snapshots.filter(item => ['pre-update', 'pre-migration'].includes(item.kind)).slice(0, 5)) keep.add(item.path);
709
+
710
+ const daily = new Set();
711
+ const weekly = new Set();
712
+ for (const item of scheduled) {
713
+ if (item.createdMs >= recentCutoff) {
714
+ keep.add(item.path);
715
+ } else if (item.createdMs >= dailyCutoff) {
716
+ const bucket = utcDay(item.createdMs);
717
+ if (!daily.has(bucket)) { daily.add(bucket); keep.add(item.path); }
718
+ } else if (item.createdMs >= weeklyCutoff) {
719
+ const bucket = utcWeek(item.createdMs);
720
+ if (!weekly.has(bucket)) { weekly.add(bucket); keep.add(item.path); }
721
+ }
722
+ }
723
+
724
+ const removed = [];
725
+ for (const item of snapshots) {
726
+ if (keep.has(item.path) || item.kind === 'manual' || item.kind === 'unknown') continue;
727
+ remove(item.path);
728
+ removed.push(item.path);
729
+ }
730
+
731
+ let retained = listBackupSnapshots(folderPath);
732
+ let totalBytes = retained.reduce((sum, item) => sum + item.sizeBytes, 0);
733
+ const normalizedIncomingBytes = Math.max(0, Number(incomingBytes) || 0);
734
+ const targetBytes = Math.max(0, policy.maxBytes - normalizedIncomingBytes);
735
+ if (totalBytes > targetBytes) {
736
+ const removable = [...retained]
737
+ .filter(item => !protectedPaths.has(item.path) && item.kind !== 'manual' && item.kind !== 'unknown')
738
+ .sort((a, b) => a.createdMs - b.createdMs);
739
+ for (const item of removable) {
740
+ if (totalBytes <= targetBytes) break;
741
+ remove(item.path);
742
+ removed.push(item.path);
743
+ totalBytes -= item.sizeBytes;
744
+ }
745
+ retained = listBackupSnapshots(folderPath);
746
+ }
747
+ return {
748
+ retention: policy,
749
+ retained,
750
+ removed,
751
+ incomingBytes: normalizedIncomingBytes,
752
+ projectedTotalBytes: retained.reduce((sum, item) => sum + item.sizeBytes, normalizedIncomingBytes),
753
+ totalBytes: retained.reduce((sum, item) => sum + item.sizeBytes, 0),
754
+ capExceeded: retained.reduce((sum, item) => sum + item.sizeBytes, normalizedIncomingBytes) > policy.maxBytes,
755
+ };
756
+ }
757
+
758
+ export function normalizeBackupConfig(value = {}) {
759
+ const config = value && typeof value === 'object' ? value : {};
760
+ const lastVerifiedBackup = config.lastVerifiedBackup
761
+ || (!config.lastBackupError ? config.lastBackup : null)
762
+ || null;
763
+ return {
764
+ version: 2,
765
+ configured: config.configured !== false,
766
+ enabled: config.enabled === true,
767
+ intervalMinutes: Number.isFinite(config.intervalMinutes) && config.intervalMinutes >= 1 ? config.intervalMinutes : 360,
768
+ folderPath: typeof config.folderPath === 'string' ? config.folderPath : '',
769
+ retention: { ...DEFAULT_BACKUP_RETENTION, ...(config.retention || {}) },
770
+ lastAttemptAt: config.lastAttemptAt || config.lastBackup || null,
771
+ lastVerifiedBackup,
772
+ lastBackup: lastVerifiedBackup,
773
+ lastBackupPath: config.lastBackupPath || null,
774
+ lastBackupSize: Number(config.lastBackupSize || 0),
775
+ lastBackupError: config.lastBackupError || null,
776
+ retentionWarning: config.retentionWarning || null,
777
+ };
778
+ }
779
+
780
+ /**
781
+ * When the scheduler fires next. After a failure it waits one interval from
782
+ * the failed attempt, not from the last success; health reads this same
783
+ * function so it cannot advertise a due date weeks in the past.
784
+ */
785
+ export function nextBackupDueMs(configValue, { lastAttemptMs = 0, now = () => new Date() } = {}) {
786
+ const config = normalizeBackupConfig(configValue);
787
+ const intervalMs = config.intervalMinutes * 60 * 1000;
788
+ const baseline = config.lastBackupError
789
+ ? new Date(config.lastAttemptAt || 0).getTime()
790
+ : new Date(config.lastVerifiedBackup || 0).getTime();
791
+ const effective = Math.max(Number.isFinite(baseline) ? baseline : 0, Number(lastAttemptMs) || 0);
792
+ return effective > 0 ? effective + intervalMs : now().getTime();
793
+ }
794
+
795
+ export function getBackupHealth(configValue, { now = () => new Date(), snapshots = null } = {}) {
796
+ const config = normalizeBackupConfig(configValue);
797
+ const lastMs = config.lastVerifiedBackup ? new Date(config.lastVerifiedBackup).getTime() : null;
798
+ const nextDueMs = nextBackupDueMs(config, { now });
799
+ let status = 'healthy';
800
+ let reason = null;
801
+ let destinationError = null;
802
+ const missingVolume = config.folderPath ? missingBackupVolume(config.folderPath) : null;
803
+ if (missingVolume) {
804
+ destinationError = new BackupDestinationUnavailableError({ ...missingVolume, folderPath: config.folderPath }).message;
805
+ } else if (config.folderPath) {
806
+ try {
807
+ let probe = resolve(config.folderPath);
808
+ while (!existsSync(probe) && dirname(probe) !== probe) probe = dirname(probe);
809
+ if (existsSync(config.folderPath) && !statSync(config.folderPath).isDirectory()) {
810
+ throw new Error('Backup destination is not a directory.');
811
+ }
812
+ accessSync(probe, FS_CONSTANTS.W_OK);
813
+ } catch (error) {
814
+ destinationError = error.message;
815
+ }
816
+ }
817
+ if (!config.configured) { status = 'unconfigured'; reason = 'Backups have not been configured yet.'; }
818
+ else if (!config.enabled) { status = 'disabled'; reason = 'Scheduled backups are disabled.'; }
819
+ else if (!config.folderPath) { status = 'unconfigured'; reason = 'No backup destination is configured.'; }
820
+ else if (destinationError) { status = 'destination-unavailable'; reason = destinationError; }
821
+ else if (config.lastBackupError) { status = 'failed'; reason = config.lastBackupError; }
822
+ else if (config.retentionWarning) { status = 'cap-exceeded'; reason = config.retentionWarning; }
823
+ else if (!lastMs || now().getTime() >= nextDueMs) { status = 'overdue'; reason = 'A scheduled backup is due.'; }
824
+ return {
825
+ status,
826
+ reason,
827
+ nextDueAt: config.enabled && config.folderPath ? new Date(nextDueMs).toISOString() : null,
828
+ latestVerifiedAt: config.lastVerifiedBackup,
829
+ retainedCount: snapshots?.length ?? null,
830
+ totalBytes: snapshots?.reduce((sum, item) => sum + item.sizeBytes, 0) ?? null,
831
+ };
832
+ }
833
+
834
+ export function loadBackupConfig(path) {
835
+ try { return normalizeBackupConfig({ ...JSON.parse(readFileSync(path, 'utf-8')), configured: true }); }
836
+ catch { return normalizeBackupConfig({ configured: false }); }
837
+ }
838
+
839
+ export function saveBackupConfig(path, value) {
840
+ mkdirSync(dirname(path), { recursive: true });
841
+ const config = normalizeBackupConfig({ ...value, configured: true });
842
+ const temp = `${path}.${process.pid}.tmp`;
843
+ try {
844
+ writeFileSync(temp, JSON.stringify(config, null, 2) + '\n', 'utf-8');
845
+ renameSync(temp, path);
846
+ } catch (error) {
847
+ try { if (existsSync(temp)) unlinkSync(temp); } catch {}
848
+ throw error;
849
+ }
850
+ return config;
851
+ }