synabun 2.0.9 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (679) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/README.md +25 -2
  3. package/THIRD-PARTY-LICENSES.md +68 -4
  4. package/bin/synabun.js +71 -24
  5. package/docs/whatsapp.md +2 -2
  6. package/hooks/claude-code/pre-websearch.mjs +12 -1
  7. package/hooks/claude-code/shared.mjs +5 -0
  8. package/hooks/claude-code/stop.mjs +1 -1
  9. package/launcher.mjs +9 -3
  10. package/lib/claude-hooks.js +172 -18
  11. package/lib/client-config-repair.js +17 -8
  12. package/lib/desktop-app.js +7 -1
  13. package/lib/external-tools.js +1 -1
  14. package/lib/first-launch-protection.js +57 -12
  15. package/lib/mcp-dist.js +176 -0
  16. package/lib/release-npm-ci.mjs +138 -0
  17. package/lib/release-publish.mjs +91 -0
  18. package/lib/release-scan.mjs +50 -0
  19. package/lib/server-crash-record.js +123 -0
  20. package/lib/server-exit.js +318 -0
  21. package/lib/server-supervisor.js +508 -0
  22. package/lib/start-launcher.js +43 -5
  23. package/lib/tools-cli.js +45 -0
  24. package/lib/update-snapshot.js +228 -0
  25. package/lib/virustotal.mjs +192 -0
  26. package/lib/windows-crash-event.js +269 -0
  27. package/mcp-server/dist/http.d.ts +20 -1
  28. package/mcp-server/dist/http.d.ts.map +1 -1
  29. package/mcp-server/dist/http.js +59 -12
  30. package/mcp-server/dist/http.js.map +1 -1
  31. package/mcp-server/dist/index.d.ts +33 -27
  32. package/mcp-server/dist/index.d.ts.map +1 -1
  33. package/mcp-server/dist/index.js +128 -143
  34. package/mcp-server/dist/index.js.map +1 -1
  35. package/mcp-server/dist/preload.js +1 -1
  36. package/mcp-server/dist/preload.js.map +1 -1
  37. package/mcp-server/dist/services/codex-config-heal.d.ts +6 -2
  38. package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
  39. package/mcp-server/dist/services/codex-config-heal.js +81 -28
  40. package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
  41. package/mcp-server/dist/services/memory-judge-backfill.d.ts +6 -0
  42. package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -1
  43. package/mcp-server/dist/services/memory-judge-backfill.js +7 -1
  44. package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -1
  45. package/mcp-server/dist/services/neural-interface.d.ts +16 -10
  46. package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
  47. package/mcp-server/dist/services/neural-interface.js +67 -11
  48. package/mcp-server/dist/services/neural-interface.js.map +1 -1
  49. package/mcp-server/dist/services/server-instructions.d.ts +7 -2
  50. package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
  51. package/mcp-server/dist/services/server-instructions.js +20 -62
  52. package/mcp-server/dist/services/server-instructions.js.map +1 -1
  53. package/mcp-server/dist/services/tool-catalog.d.ts +120 -0
  54. package/mcp-server/dist/services/tool-catalog.d.ts.map +1 -0
  55. package/mcp-server/dist/services/tool-catalog.js +339 -0
  56. package/mcp-server/dist/services/tool-catalog.js.map +1 -0
  57. package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts +12 -0
  58. package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts.map +1 -0
  59. package/mcp-server/dist/services/tool-list-refresh-barrier.js +40 -0
  60. package/mcp-server/dist/services/tool-list-refresh-barrier.js.map +1 -0
  61. package/mcp-server/dist/services/tool-list.d.ts +108 -0
  62. package/mcp-server/dist/services/tool-list.d.ts.map +1 -0
  63. package/mcp-server/dist/services/tool-list.js +334 -0
  64. package/mcp-server/dist/services/tool-list.js.map +1 -0
  65. package/mcp-server/dist/services/tool-runtime.d.ts +161 -0
  66. package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -0
  67. package/mcp-server/dist/services/tool-runtime.js +400 -0
  68. package/mcp-server/dist/services/tool-runtime.js.map +1 -0
  69. package/mcp-server/dist/services/whiteboard-geometry.d.ts +26 -2
  70. package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -1
  71. package/mcp-server/dist/services/whiteboard-geometry.js +91 -8
  72. package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -1
  73. package/mcp-server/dist/tools/agents.d.ts +10 -10
  74. package/mcp-server/dist/tools/agents.d.ts.map +1 -1
  75. package/mcp-server/dist/tools/agents.js +22 -13
  76. package/mcp-server/dist/tools/agents.js.map +1 -1
  77. package/mcp-server/dist/tools/browser-batch.d.ts +3 -3
  78. package/mcp-server/dist/tools/image-tools.d.ts +1 -1
  79. package/mcp-server/dist/tools/image-tools.js +1 -1
  80. package/mcp-server/dist/tools/skill-tools.d.ts +505 -0
  81. package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -0
  82. package/mcp-server/dist/tools/skill-tools.js +639 -0
  83. package/mcp-server/dist/tools/skill-tools.js.map +1 -0
  84. package/mcp-server/dist/tools/skill.d.ts +7 -0
  85. package/mcp-server/dist/tools/skill.d.ts.map +1 -0
  86. package/mcp-server/dist/tools/skill.js +11 -0
  87. package/mcp-server/dist/tools/skill.js.map +1 -0
  88. package/mcp-server/dist/tools/tool-groups.d.ts +68 -0
  89. package/mcp-server/dist/tools/tool-groups.d.ts.map +1 -0
  90. package/mcp-server/dist/tools/tool-groups.js +147 -0
  91. package/mcp-server/dist/tools/tool-groups.js.map +1 -0
  92. package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -1
  93. package/mcp-server/dist/tools/whiteboard-format.js +7 -4
  94. package/mcp-server/dist/tools/whiteboard-format.js.map +1 -1
  95. package/mcp-server/dist/tools/whiteboard-tools.d.ts +64 -13
  96. package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -1
  97. package/mcp-server/dist/tools/whiteboard-tools.js +30 -5
  98. package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -1
  99. package/mcp-server/package-lock.json +2 -2
  100. package/mcp-server/package.json +1 -1
  101. package/mcp-server/src/http.ts +75 -12
  102. package/mcp-server/src/index.ts +147 -154
  103. package/mcp-server/src/preload.ts +12 -12
  104. package/mcp-server/src/services/codex-config-heal.ts +80 -29
  105. package/mcp-server/src/services/memory-judge-backfill.ts +7 -1
  106. package/mcp-server/src/services/neural-interface.ts +79 -20
  107. package/mcp-server/src/services/server-instructions.ts +27 -63
  108. package/mcp-server/src/services/tool-catalog.ts +403 -0
  109. package/mcp-server/src/services/tool-list-refresh-barrier.ts +33 -0
  110. package/mcp-server/src/services/tool-list.ts +410 -0
  111. package/mcp-server/src/services/tool-runtime.ts +457 -0
  112. package/mcp-server/src/services/whiteboard-geometry.ts +94 -9
  113. package/mcp-server/src/tools/agents.ts +22 -14
  114. package/mcp-server/src/tools/image-tools.ts +1 -1
  115. package/mcp-server/src/tools/skill-tools.ts +589 -0
  116. package/mcp-server/src/tools/skill.ts +13 -0
  117. package/mcp-server/src/tools/tool-groups.ts +164 -0
  118. package/mcp-server/src/tools/whiteboard-format.ts +9 -3
  119. package/mcp-server/src/tools/whiteboard-tools.ts +39 -5
  120. package/neural-interface/i18n/en.json +3680 -206
  121. package/neural-interface/i18n/pt-BR.json +3628 -157
  122. package/neural-interface/lib/account-usage.js +5 -3
  123. package/neural-interface/lib/app-controls-api.js +161 -0
  124. package/neural-interface/lib/assistant-api.js +148 -35
  125. package/neural-interface/lib/assistant-brains/claude.js +4 -3
  126. package/neural-interface/lib/assistant-brains/codex-browser-policy-hook.mjs +12 -2
  127. package/neural-interface/lib/assistant-brains/codex-route-gate-hook.mjs +32 -9
  128. package/neural-interface/lib/assistant-brains/codex.js +9 -5
  129. package/neural-interface/lib/assistant-brains/opencode.js +122 -44
  130. package/neural-interface/lib/assistant-brains/opencode2-browser-policy/index.js +59 -0
  131. package/neural-interface/lib/assistant-brains/opencode2-route-gate/index.js +97 -0
  132. package/neural-interface/lib/assistant-catalog.js +23 -9
  133. package/neural-interface/lib/assistant-dispatch.js +874 -156
  134. package/neural-interface/lib/assistant-envelope.js +22 -2
  135. package/neural-interface/lib/assistant-persona.js +80 -11
  136. package/neural-interface/lib/assistant-plan-permissions.js +10 -9
  137. package/neural-interface/lib/assistant-route-gate-codex.js +3 -0
  138. package/neural-interface/lib/assistant-route-gate.js +6 -4
  139. package/neural-interface/lib/assistant-router.js +13 -8
  140. package/neural-interface/lib/assistant-runtime.js +183 -26
  141. package/neural-interface/lib/assistant-task-prompt.js +78 -14
  142. package/neural-interface/lib/assistant-tools.js +51 -0
  143. package/neural-interface/lib/backup-service.js +620 -3
  144. package/neural-interface/lib/backup-zip-reader.js +10 -5
  145. package/neural-interface/lib/backup-zip-writer.js +257 -0
  146. package/neural-interface/lib/browser-execution.js +10 -2
  147. package/neural-interface/lib/browser-guard-cdp.js +83 -0
  148. package/neural-interface/lib/browser-network-guard.js +284 -0
  149. package/neural-interface/lib/browser-policy-roots.js +64 -0
  150. package/neural-interface/lib/browser-tool-policy.js +186 -31
  151. package/neural-interface/lib/claude-agent-bridge.js +4 -2
  152. package/neural-interface/lib/claude-hooks-status.js +103 -0
  153. package/neural-interface/lib/claude-model-catalog.js +64 -14
  154. package/neural-interface/lib/claude-temporary.js +5 -11
  155. package/neural-interface/lib/cli-install.js +18 -138
  156. package/neural-interface/lib/cli-resolver.js +4 -1
  157. package/neural-interface/lib/cli-update-planner.js +32 -31
  158. package/neural-interface/lib/cloudflared/tunnel.js +42 -2
  159. package/neural-interface/lib/codex-mcp-approvals.js +11 -0
  160. package/neural-interface/lib/codex-settings-schema.js +109 -47
  161. package/neural-interface/lib/codex-worker-app-server.js +172 -0
  162. package/neural-interface/lib/confined-fs.js +30 -3
  163. package/neural-interface/lib/crash-notice-api.js +98 -0
  164. package/neural-interface/lib/editor-completion-opencode.js +164 -67
  165. package/neural-interface/lib/exec-loop-command.js +4 -1
  166. package/neural-interface/lib/http-guards.js +8 -2
  167. package/neural-interface/lib/install-details.js +4 -1
  168. package/neural-interface/lib/launch-cache.js +293 -0
  169. package/neural-interface/lib/login-start.js +524 -0
  170. package/neural-interface/lib/mcp-agent-servers.js +67 -0
  171. package/neural-interface/lib/mcp-client-config.js +0 -29
  172. package/neural-interface/lib/mcp-external-servers.js +323 -0
  173. package/neural-interface/lib/{mcp-profile-refresh-coordinator.js → mcp-tools-refresh-coordinator.js} +4 -4
  174. package/neural-interface/lib/morelogin.js +30 -0
  175. package/neural-interface/lib/native-loop-providers.js +565 -50
  176. package/neural-interface/lib/native-loop-runtime.js +287 -41
  177. package/neural-interface/lib/opencode-config.js +557 -0
  178. package/neural-interface/lib/opencode-db-schema.js +58 -0
  179. package/neural-interface/lib/opencode-history.js +49 -204
  180. package/neural-interface/lib/opencode-mcp-ready.js +108 -0
  181. package/neural-interface/lib/opencode-native-boundary.js +44 -0
  182. package/neural-interface/lib/opencode-protocol.js +310 -0
  183. package/neural-interface/lib/opencode-provider-view.js +81 -0
  184. package/neural-interface/lib/opencode-runtime-config.js +32 -15
  185. package/neural-interface/lib/opencode-serve-records.js +624 -0
  186. package/neural-interface/lib/opencode-v2-client.js +53 -131
  187. package/neural-interface/lib/opencode-v2-ws-requests.js +35 -195
  188. package/neural-interface/lib/opencode-worker-activity.js +229 -0
  189. package/neural-interface/lib/opencode-worker-data.js +27 -0
  190. package/neural-interface/lib/opencode2-client.js +796 -0
  191. package/neural-interface/lib/opencode2-proxy.js +76 -0
  192. package/neural-interface/lib/opencode2-translate.js +1057 -0
  193. package/neural-interface/lib/owner-authority.js +249 -0
  194. package/neural-interface/lib/page-session.js +275 -0
  195. package/neural-interface/lib/peer-identity.js +763 -0
  196. package/neural-interface/lib/process-identity.js +361 -0
  197. package/neural-interface/lib/request-gate.js +17 -2
  198. package/neural-interface/lib/rulesets/api.js +1 -1
  199. package/neural-interface/lib/rulesets/fs-safe.js +1 -1
  200. package/neural-interface/lib/rulesets/installer.js +92 -27
  201. package/neural-interface/lib/rulesets/json-edit.js +1 -1
  202. package/neural-interface/lib/session-cache-builder.js +18 -10
  203. package/neural-interface/lib/session-title-generator.js +58 -18
  204. package/neural-interface/lib/skills/api-v2.js +495 -0
  205. package/neural-interface/lib/skills/bundle.js +418 -0
  206. package/neural-interface/lib/skills/catalog.js +294 -0
  207. package/neural-interface/lib/skills/creation-api.js +191 -0
  208. package/neural-interface/lib/skills/creation-brief.js +247 -0
  209. package/neural-interface/lib/skills/creation-sources.js +267 -0
  210. package/neural-interface/lib/skills/creation.js +843 -0
  211. package/neural-interface/lib/skills/deploy.js +564 -0
  212. package/neural-interface/lib/skills/digest.js +119 -0
  213. package/neural-interface/lib/skills/discover.js +111 -0
  214. package/neural-interface/lib/skills/draft-confinement.js +214 -0
  215. package/neural-interface/lib/skills/eval-confinement.js +397 -0
  216. package/neural-interface/lib/skills/eval-sandbox.js +280 -0
  217. package/neural-interface/lib/skills/eval-trace.js +119 -0
  218. package/neural-interface/lib/skills/evals-api.js +212 -0
  219. package/neural-interface/lib/skills/evals.js +1573 -0
  220. package/neural-interface/lib/skills/export.js +200 -0
  221. package/neural-interface/lib/skills/frontmatter.js +64 -0
  222. package/neural-interface/lib/skills/health.js +75 -0
  223. package/neural-interface/lib/skills/json-edit.js +165 -0
  224. package/neural-interface/lib/skills/known-bridge-digests.json +387 -0
  225. package/neural-interface/lib/skills/known-bridges.js +96 -0
  226. package/neural-interface/lib/skills/library.js +823 -0
  227. package/neural-interface/lib/skills/local-store.js +21 -0
  228. package/neural-interface/lib/skills/migration.js +433 -0
  229. package/neural-interface/lib/skills/operations.js +45 -0
  230. package/neural-interface/lib/skills/ownership.js +427 -0
  231. package/neural-interface/lib/skills/packages.js +88 -0
  232. package/neural-interface/lib/skills/reviews.js +212 -0
  233. package/neural-interface/lib/skills/revision.js +80 -0
  234. package/neural-interface/lib/skills/roots.js +262 -0
  235. package/neural-interface/lib/skills/runtime-checks.js +355 -0
  236. package/neural-interface/lib/skills/scan-assets.js +252 -0
  237. package/neural-interface/lib/skills/scan-context.js +26 -0
  238. package/neural-interface/lib/skills/scan-shell.js +324 -0
  239. package/neural-interface/lib/skills/scan.js +364 -0
  240. package/neural-interface/lib/skills/scanners.js +54 -0
  241. package/neural-interface/lib/skills/service.js +522 -0
  242. package/neural-interface/lib/skills/telemetry.js +113 -0
  243. package/neural-interface/lib/sqlite-integrity-worker.js +22 -0
  244. package/neural-interface/lib/style-guide/api.js +4 -3
  245. package/neural-interface/lib/tool-lists.js +124 -0
  246. package/neural-interface/lib/untrusted-file-headers.js +27 -0
  247. package/neural-interface/lib/whatsapp/bridge.js +6 -3
  248. package/neural-interface/lib/worker-confinement.js +1192 -0
  249. package/neural-interface/lib/worker-guard-setting.js +56 -0
  250. package/neural-interface/lib/worker-mcp-channel.js +175 -0
  251. package/neural-interface/lib/worker-relay-ports.js +227 -0
  252. package/neural-interface/lib/worker-resume.js +229 -0
  253. package/neural-interface/lib/worker-sandbox.js +299 -0
  254. package/neural-interface/package-lock.json +1354 -50
  255. package/neural-interface/package.json +6 -2
  256. package/neural-interface/public/index.html +5 -3
  257. package/neural-interface/public/index2d.html +19 -11
  258. package/neural-interface/public/onboarding.html +2 -2
  259. package/neural-interface/public/shared/account-menu.js +8 -5
  260. package/neural-interface/public/shared/agent-runtime-options.js +76 -16
  261. package/neural-interface/public/shared/api.js +1527 -1336
  262. package/neural-interface/public/shared/app-frame.js +192 -0
  263. package/neural-interface/public/shared/assistant/asst-agents-dock.js +205 -19
  264. package/neural-interface/public/shared/assistant/asst-api.js +11 -3
  265. package/neural-interface/public/shared/assistant/asst-ask-styles.js +270 -0
  266. package/neural-interface/public/shared/assistant/asst-ask-tail.js +118 -0
  267. package/neural-interface/public/shared/assistant/asst-ask.js +397 -0
  268. package/neural-interface/public/shared/assistant/asst-brain-picker.js +241 -112
  269. package/neural-interface/public/shared/assistant/asst-composer.js +1 -1
  270. package/neural-interface/public/shared/assistant/asst-control.js +157 -26
  271. package/neural-interface/public/shared/assistant/asst-followups-card.js +383 -0
  272. package/neural-interface/public/shared/assistant/asst-followups.js +417 -0
  273. package/neural-interface/public/shared/assistant/asst-hosts.js +49 -2
  274. package/neural-interface/public/shared/assistant/asst-limit-dock.js +40 -0
  275. package/neural-interface/public/shared/assistant/asst-limit-wait.js +294 -0
  276. package/neural-interface/public/shared/assistant/asst-limit.js +168 -0
  277. package/neural-interface/public/shared/assistant/asst-mascot.js +49 -12
  278. package/neural-interface/public/shared/assistant/asst-menu.js +84 -12
  279. package/neural-interface/public/shared/assistant/asst-panel.js +303 -44
  280. package/neural-interface/public/shared/assistant/asst-rack-styles.js +93 -58
  281. package/neural-interface/public/shared/assistant/asst-redact.js +186 -0
  282. package/neural-interface/public/shared/assistant/asst-render.js +770 -100
  283. package/neural-interface/public/shared/assistant/asst-route.js +83 -12
  284. package/neural-interface/public/shared/assistant/asst-run-stage.js +231 -0
  285. package/neural-interface/public/shared/assistant/asst-sanitize.js +193 -3
  286. package/neural-interface/public/shared/assistant/asst-scene-styles.js +273 -0
  287. package/neural-interface/public/shared/assistant/asst-scenes.js +530 -0
  288. package/neural-interface/public/shared/assistant/asst-sidepanel-styles.js +3 -15
  289. package/neural-interface/public/shared/assistant/asst-sidepanel.js +67 -4
  290. package/neural-interface/public/shared/assistant/asst-slash.js +9 -7
  291. package/neural-interface/public/shared/assistant/asst-state.js +25 -15
  292. package/neural-interface/public/shared/assistant/asst-stop.js +127 -0
  293. package/neural-interface/public/shared/assistant/asst-styles.js +102 -21
  294. package/neural-interface/public/shared/assistant/asst-tool-kinds.js +165 -13
  295. package/neural-interface/public/shared/automation-context.js +5 -2
  296. package/neural-interface/public/shared/cc-dropdown.js +550 -0
  297. package/neural-interface/public/shared/cdx/cdx-context-menu.js +10 -9
  298. package/neural-interface/public/shared/cdx/cdx-copy.js +16 -0
  299. package/neural-interface/public/shared/cdx/cdx-output-model.js +22 -1
  300. package/neural-interface/public/shared/cdx/cdx-output.js +8 -7
  301. package/neural-interface/public/shared/cdx/cdx-panel.js +58 -150
  302. package/neural-interface/public/shared/cdx/cdx-protocol.js +28 -1
  303. package/neural-interface/public/shared/cdx/cdx-render.js +62 -32
  304. package/neural-interface/public/shared/cdx/cdx-requests.js +3 -3
  305. package/neural-interface/public/shared/cdx/cdx-skill-hints.js +54 -0
  306. package/neural-interface/public/shared/cdx/cdx-styles.js +15 -3
  307. package/neural-interface/public/shared/cdx/cdx-tabs.js +201 -74
  308. package/neural-interface/public/shared/cdx/cdx-ws.js +0 -1
  309. package/neural-interface/public/shared/cli-install-view.js +4 -8
  310. package/neural-interface/public/shared/cli-status.js +2 -2
  311. package/neural-interface/public/shared/constants.js +2 -2
  312. package/neural-interface/public/shared/context-menu-areas.js +34 -0
  313. package/neural-interface/public/shared/context-menu-logic.js +243 -0
  314. package/neural-interface/public/shared/context-menu-model.js +366 -0
  315. package/neural-interface/public/shared/context-menu.js +372 -0
  316. package/neural-interface/public/shared/cp/cp-context-menu.js +10 -9
  317. package/neural-interface/public/shared/cp/cp-markdown.js +4 -57
  318. package/neural-interface/public/shared/crash-notice-view.js +168 -0
  319. package/neural-interface/public/shared/data-cache.js +223 -0
  320. package/neural-interface/public/shared/desktop-bridge.js +11 -0
  321. package/neural-interface/public/shared/desktop-titlebar-view.js +78 -1
  322. package/neural-interface/public/shared/desktop-titlebar.js +214 -28
  323. package/neural-interface/public/shared/desktop-update-view.js +35 -5
  324. package/neural-interface/public/shared/editor/editor-panel-logic.js +2 -2
  325. package/neural-interface/public/shared/file-links.js +73 -8
  326. package/neural-interface/public/shared/html-shell.js +78 -86
  327. package/neural-interface/public/shared/i18n.js +2 -0
  328. package/neural-interface/public/shared/launch-prefetch.js +59 -0
  329. package/neural-interface/public/shared/ocp-v2/ocp-v2-approvals.js +7 -7
  330. package/neural-interface/public/shared/ocp-v2/ocp-v2-binding.js +4 -4
  331. package/neural-interface/public/shared/ocp-v2/ocp-v2-caps.js +3 -2
  332. package/neural-interface/public/shared/ocp-v2/ocp-v2-changes-logic.js +3 -101
  333. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +9 -2
  334. package/neural-interface/public/shared/ocp-v2/ocp-v2-compact-button.js +1 -3
  335. package/neural-interface/public/shared/ocp-v2/ocp-v2-composer-logic.js +2 -6
  336. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-menu.js +11 -11
  337. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-model.js +0 -3
  338. package/neural-interface/public/shared/ocp-v2/ocp-v2-events.js +8 -4
  339. package/neural-interface/public/shared/ocp-v2/ocp-v2-manager.js +7 -7
  340. package/neural-interface/public/shared/ocp-v2/ocp-v2-modelpicker.js +54 -17
  341. package/neural-interface/public/shared/ocp-v2/ocp-v2-outcome-notifications.js +16 -0
  342. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +140 -254
  343. package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +1 -2
  344. package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +97 -203
  345. package/neural-interface/public/shared/ocp-v2/ocp-v2-providers.js +11 -9
  346. package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +15 -4
  347. package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +7 -22
  348. package/neural-interface/public/shared/ocp-v2/ocp-v2-send-logic.js +401 -0
  349. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +20 -13
  350. package/neural-interface/public/shared/ocp-v2/ocp-v2-session-actions.js +8 -61
  351. package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +53 -82
  352. package/neural-interface/public/shared/ocp-v2/ocp-v2-slash-hints.js +16 -15
  353. package/neural-interface/public/shared/ocp-v2/ocp-v2-state.js +8 -21
  354. package/neural-interface/public/shared/ocp-v2/ocp-v2-status-logic.js +1 -99
  355. package/neural-interface/public/shared/ocp-v2/ocp-v2-status.js +5 -35
  356. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +48 -40
  357. package/neural-interface/public/shared/ocp-v2/{ocp-v2-profile-inheritance.js → ocp-v2-tools-inheritance.js} +16 -16
  358. package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +205 -62
  359. package/neural-interface/public/shared/opencode-providers.js +39 -0
  360. package/neural-interface/public/shared/page-session.js +96 -0
  361. package/neural-interface/public/shared/registry.js +5 -3
  362. package/neural-interface/public/shared/retired-2d.js +3 -0
  363. package/neural-interface/public/shared/schedules-view.js +452 -0
  364. package/neural-interface/public/shared/settings/settings-app-pane.js +335 -0
  365. package/neural-interface/public/shared/settings/settings-app.js +243 -0
  366. package/neural-interface/public/shared/settings/settings-claude-hooks.js +135 -0
  367. package/neural-interface/public/shared/settings/settings-data.js +90 -0
  368. package/neural-interface/public/shared/settings/settings-ia.js +23 -6
  369. package/neural-interface/public/shared/settings/settings-opencode.js +89 -0
  370. package/neural-interface/public/shared/settings/settings-skill-folders-pane.js +265 -0
  371. package/neural-interface/public/shared/settings/settings-skill-folders.js +130 -0
  372. package/neural-interface/public/shared/settings/settings-worker-guard.js +72 -0
  373. package/neural-interface/public/shared/sidepanel-session-status.js +49 -0
  374. package/neural-interface/public/shared/skills/ss-args.js +96 -0
  375. package/neural-interface/public/shared/skills/ss-creation.js +219 -0
  376. package/neural-interface/public/shared/skills/ss-dialog.js +130 -0
  377. package/neural-interface/public/shared/skills/ss-doc.js +173 -0
  378. package/neural-interface/public/shared/skills/ss-eval-adapters.js +269 -0
  379. package/neural-interface/public/shared/skills/ss-eval-grade.js +359 -0
  380. package/neural-interface/public/shared/skills/ss-eval-optimise.js +153 -0
  381. package/neural-interface/public/shared/skills/ss-eval-plan.js +315 -0
  382. package/neural-interface/public/shared/skills/ss-evals.js +417 -0
  383. package/neural-interface/public/shared/skills/ss-form.js +159 -0
  384. package/neural-interface/public/shared/skills/ss-frontmatter.js +376 -0
  385. package/neural-interface/public/shared/skills/ss-ids.js +32 -0
  386. package/neural-interface/public/shared/skills/ss-lint.js +141 -0
  387. package/neural-interface/public/shared/skills/ss-presets.js +117 -0
  388. package/neural-interface/public/shared/skills/ss-profiles.js +475 -0
  389. package/neural-interface/public/shared/skills/ss-resources.js +165 -0
  390. package/neural-interface/public/shared/skills/ss-review-view.js +190 -0
  391. package/neural-interface/public/shared/skills/ss-tabs.js +79 -0
  392. package/neural-interface/public/shared/skills/ss-unicode.js +135 -0
  393. package/neural-interface/public/shared/skills/studio/sx-actions.js +222 -0
  394. package/neural-interface/public/shared/skills/studio/sx-cm.js +101 -0
  395. package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +749 -0
  396. package/neural-interface/public/shared/skills/studio/sx-create-ai.js +236 -0
  397. package/neural-interface/public/shared/skills/studio/sx-create-view.js +254 -0
  398. package/neural-interface/public/shared/skills/studio/sx-create.js +126 -0
  399. package/neural-interface/public/shared/skills/studio/sx-diff-view.js +43 -0
  400. package/neural-interface/public/shared/skills/studio/sx-diff.js +133 -0
  401. package/neural-interface/public/shared/skills/studio/sx-docs.js +480 -0
  402. package/neural-interface/public/shared/skills/studio/sx-dom.js +229 -0
  403. package/neural-interface/public/shared/skills/studio/sx-edit-view.js +848 -0
  404. package/neural-interface/public/shared/skills/studio/sx-editor-model.js +193 -0
  405. package/neural-interface/public/shared/skills/studio/sx-errors.js +22 -0
  406. package/neural-interface/public/shared/skills/studio/sx-geometry.js +82 -0
  407. package/neural-interface/public/shared/skills/studio/sx-import.js +262 -0
  408. package/neural-interface/public/shared/skills/studio/sx-inspector.js +308 -0
  409. package/neural-interface/public/shared/skills/studio/sx-install-flow.js +279 -0
  410. package/neural-interface/public/shared/skills/studio/sx-install.js +296 -0
  411. package/neural-interface/public/shared/skills/studio/sx-library-view.js +639 -0
  412. package/neural-interface/public/shared/skills/studio/sx-library.js +475 -0
  413. package/neural-interface/public/shared/skills/studio/sx-main.js +681 -0
  414. package/neural-interface/public/shared/skills/studio/sx-operations-view.js +98 -0
  415. package/neural-interface/public/shared/skills/studio/sx-operations.js +11 -0
  416. package/neural-interface/public/shared/skills/studio/sx-plan.js +158 -0
  417. package/neural-interface/public/shared/skills/studio/sx-publish-view.js +621 -0
  418. package/neural-interface/public/shared/skills/studio/sx-review-view.js +369 -0
  419. package/neural-interface/public/shared/skills/studio/sx-review.js +148 -0
  420. package/neural-interface/public/shared/skills/studio/sx-scan.js +35 -0
  421. package/neural-interface/public/shared/skills/studio/sx-snippets.js +96 -0
  422. package/neural-interface/public/shared/skills/studio/sx-subject.js +248 -0
  423. package/neural-interface/public/shared/skills/studio/sx-test-view.js +994 -0
  424. package/neural-interface/public/shared/skills/studio/sx-test.js +328 -0
  425. package/neural-interface/public/shared/skills/studio/sx-versions-view.js +241 -0
  426. package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +425 -0
  427. package/neural-interface/public/shared/styleguide/sg-panel.js +4 -2
  428. package/neural-interface/public/shared/styles.css +2065 -2150
  429. package/neural-interface/public/shared/synabun-mascot.js +1115 -9
  430. package/neural-interface/public/shared/tool-list-picker.js +55 -0
  431. package/neural-interface/public/shared/tool-list-storage.js +24 -0
  432. package/neural-interface/public/shared/tool-list-view.js +112 -0
  433. package/neural-interface/public/shared/tour/tour-actor.js +268 -0
  434. package/neural-interface/public/shared/tour/tour-beats.js +336 -0
  435. package/neural-interface/public/shared/tour/tour-engine.js +884 -0
  436. package/neural-interface/public/shared/tour/tour-ink.js +390 -0
  437. package/neural-interface/public/shared/tour/tour-stage.js +440 -0
  438. package/neural-interface/public/shared/tour/tour-state.js +40 -0
  439. package/neural-interface/public/shared/tour/tour-tips.js +99 -0
  440. package/neural-interface/public/shared/tour/tour.css +144 -0
  441. package/neural-interface/public/shared/ui-assistant.js +27 -5
  442. package/neural-interface/public/shared/ui-automation-studio.js +155 -152
  443. package/neural-interface/public/shared/ui-bookmarks.js +2 -1
  444. package/neural-interface/public/shared/ui-claude-panel.js +153 -13
  445. package/neural-interface/public/shared/ui-codex-panel.js +1 -0
  446. package/neural-interface/public/shared/ui-command-runner.js +6 -3
  447. package/neural-interface/public/shared/ui-context-menu.js +295 -0
  448. package/neural-interface/public/shared/ui-cost-widget.js +57 -59
  449. package/neural-interface/public/shared/ui-crash-notice.js +187 -0
  450. package/neural-interface/public/shared/ui-detail.js +21 -9
  451. package/neural-interface/public/shared/ui-file-links.js +1 -0
  452. package/neural-interface/public/shared/ui-image-gallery.js +56 -52
  453. package/neural-interface/public/shared/ui-invite.js +18 -2
  454. package/neural-interface/public/shared/ui-keybinds.js +26 -1
  455. package/neural-interface/public/shared/ui-link.js +9 -9
  456. package/neural-interface/public/shared/ui-menubar.js +229 -40
  457. package/neural-interface/public/shared/ui-native-loop-router-state.js +5 -0
  458. package/neural-interface/public/shared/ui-native-loop-router.js +9 -1
  459. package/neural-interface/public/shared/ui-navbar.js +4 -24
  460. package/neural-interface/public/shared/ui-opencode-panel-v2.js +1 -0
  461. package/neural-interface/public/shared/ui-panels.js +96 -65
  462. package/neural-interface/public/shared/ui-schedules-studio.js +2267 -953
  463. package/neural-interface/public/shared/ui-sessions.js +20 -7
  464. package/neural-interface/public/shared/ui-settings.js +679 -496
  465. package/neural-interface/public/shared/ui-sidebar.js +4 -4
  466. package/neural-interface/public/shared/ui-sidepanel-session-entry.js +13 -0
  467. package/neural-interface/public/shared/ui-sidepanel-sessions.js +56 -5
  468. package/neural-interface/public/shared/ui-sidepanel-state.js +23 -12
  469. package/neural-interface/public/shared/ui-sidepanel-tray.js +84 -8
  470. package/neural-interface/public/shared/ui-sidepanel-windows.js +16 -11
  471. package/neural-interface/public/shared/ui-skills.js +42 -2781
  472. package/neural-interface/public/shared/ui-styleguide.js +5 -2
  473. package/neural-interface/public/shared/ui-sync.js +22 -5
  474. package/neural-interface/public/shared/ui-terminal.js +159 -199
  475. package/neural-interface/public/shared/ui-tool-updates.js +3 -1
  476. package/neural-interface/public/shared/ui-tooltip.js +10 -5
  477. package/neural-interface/public/shared/ui-trash.js +14 -5
  478. package/neural-interface/public/shared/ui-tutorial-layout.js +3 -117
  479. package/neural-interface/public/shared/ui-tutorial-preview.js +103 -0
  480. package/neural-interface/public/shared/ui-tutorial-steps.js +3 -61
  481. package/neural-interface/public/shared/ui-tutorial.css +47 -100
  482. package/neural-interface/public/shared/ui-tutorial.js +285 -499
  483. package/neural-interface/public/shared/ui-update.js +121 -16
  484. package/neural-interface/public/shared/ui-whiteboard.js +313 -59
  485. package/neural-interface/public/shared/ui-worker-end.js +4 -0
  486. package/neural-interface/public/shared/ui-workspaces.js +3 -2
  487. package/neural-interface/public/shared/view-variant.js +66 -0
  488. package/neural-interface/public/shared/whatsapp/wa-view.js +1 -1
  489. package/neural-interface/public/shared/whiteboard-list.js +172 -0
  490. package/neural-interface/public/shared/worker-end.js +10 -3
  491. package/neural-interface/public/shared/worker-restart.js +12 -0
  492. package/neural-interface/public/sidepanel-session.html +1 -1
  493. package/neural-interface/public/variant/2d/background.js +2 -1
  494. package/neural-interface/public/variant/2d/context-menu.js +8 -2
  495. package/neural-interface/public/variant/2d/graph.js +42 -20
  496. package/neural-interface/public/variant/2d/hulls.js +14 -9
  497. package/neural-interface/public/variant/2d/lasso.js +11 -7
  498. package/neural-interface/public/variant/2d/main.js +36 -2
  499. package/neural-interface/public/variant/2d/minimap.js +11 -13
  500. package/neural-interface/public/variant/3d/main.js +72 -6
  501. package/neural-interface/public/variant/3d/map-controls.js +24 -9
  502. package/neural-interface/public/vendor/caveat/OFL.txt +93 -0
  503. package/neural-interface/public/vendor/caveat/caveat-latin-400-normal.woff2 +0 -0
  504. package/neural-interface/public/vendor/caveat/caveat-latin-700-normal.woff2 +0 -0
  505. package/neural-interface/public/vendor/caveat/caveat.css +17 -0
  506. package/neural-interface/public/vendor/caveat/manifest.json +12 -0
  507. package/neural-interface/public/vendor/highlight/LICENSE +29 -0
  508. package/neural-interface/public/vendor/highlight/github-dark-dimmed-11.12.0.min.css +9 -0
  509. package/neural-interface/public/vendor/highlight/highlight-11.12.0.min.js +1262 -0
  510. package/neural-interface/public/vendor/highlight/manifest.json +5 -0
  511. package/neural-interface/public/vendor/html2canvas/LICENSE +22 -0
  512. package/neural-interface/public/vendor/html2canvas/html2canvas-1.4.1.min.js +20 -0
  513. package/neural-interface/public/vendor/html2canvas/manifest.json +4 -0
  514. package/neural-interface/public/vendor/marked/LICENSE.md +44 -0
  515. package/neural-interface/public/vendor/marked/manifest.json +4 -0
  516. package/neural-interface/public/vendor/marked/marked-14.1.4.esm.js +2502 -0
  517. package/neural-interface/public/vendor/mermaid/LICENSE +21 -0
  518. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/abnfDiagram-PAR5IXJI.mjs +1 -0
  519. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/architecture-7GRP2DOG-M7G3SWCO.mjs +1 -0
  520. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/architectureDiagram-2PNWDENW.mjs +36 -0
  521. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/blockDiagram-PUWGUBOA.mjs +129 -0
  522. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/c4Diagram-3NLNHZP5.mjs +38 -0
  523. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-2NMSUPJH.mjs +1 -0
  524. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-32MCUW2P.mjs +206 -0
  525. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-3NPNU5GP.mjs +1 -0
  526. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-3SMGFRGC.mjs +1 -0
  527. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-4CAJECRU.mjs +14 -0
  528. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-4OADUZ5Q.mjs +10 -0
  529. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5IMINLNL.mjs +1 -0
  530. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5IQCK5RY.mjs +3 -0
  531. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5MVFYWFU.mjs +1 -0
  532. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-AQ6EADP3.mjs +1 -0
  533. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-AZZRMDJM.mjs +15 -0
  534. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-CLS4B6BI.mjs +168 -0
  535. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-DZP67EKU.mjs +70 -0
  536. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-EICP7K5X.mjs +1 -0
  537. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-GDY2UAB4.mjs +1 -0
  538. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-H7VHZCWX.mjs +1 -0
  539. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-IJBDOHL6.mjs +1 -0
  540. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JFFVMJIA.mjs +1 -0
  541. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JQRUD6KW.mjs +1 -0
  542. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JZGDI5JK.mjs +1 -0
  543. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-KD6SPIPN.mjs +2 -0
  544. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-NF366YI6.mjs +231 -0
  545. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-NUDPKBEF.mjs +32 -0
  546. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-OJINMHTS.mjs +1 -0
  547. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-Q6NGPIAH.mjs +2 -0
  548. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-QJSWEUOL.mjs +132 -0
  549. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-R7JDMUKV.mjs +1 -0
  550. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-RCXAM2GK.mjs +1 -0
  551. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-RT4MAWR3.mjs +1 -0
  552. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-SFMINX4W.mjs +1 -0
  553. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-SLDQ463B.mjs +88 -0
  554. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-STOV2HOB.mjs +1 -0
  555. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-T5OCTHI4.mjs +1 -0
  556. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-TCEHX7R3.mjs +1 -0
  557. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VQC2EELJ.mjs +1 -0
  558. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VRZKL3EH.mjs +1 -0
  559. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VTHDQ7BV.mjs +1 -0
  560. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VY2OSTJR.mjs +2 -0
  561. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-WUBWJARI.mjs +1 -0
  562. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-YBMQ5JGJ.mjs +2 -0
  563. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-YDMLL4PJ.mjs +1 -0
  564. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-Z6V44ARX.mjs +62 -0
  565. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZJJ7VQJP.mjs +339 -0
  566. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZNLK7HRR.mjs +1 -0
  567. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZQN7UHIL.mjs +1 -0
  568. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZS6VBONO.mjs +174 -0
  569. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZUNWM646.mjs +1 -0
  570. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/classDiagram-FGAMPOII.mjs +1 -0
  571. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/classDiagram-v2-AI5RJEK4.mjs +1 -0
  572. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cose-bilkent-Q72C2OJ3.mjs +1 -0
  573. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cynefin-OW5HDTMX-6OCTWOGG.mjs +1 -0
  574. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cynefinDiagram-2OOWUY4M.mjs +62 -0
  575. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/dagre-MPVFI544.mjs +4 -0
  576. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-AE4NWXFW.mjs +24 -0
  577. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-BUJID5UG.mjs +41 -0
  578. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-C44CZ5NI.mjs +24 -0
  579. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-EYOLEXXS.mjs +30 -0
  580. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-P7B6PWOJ.mjs +3 -0
  581. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ebnfDiagram-FTPZ3PV6.mjs +1 -0
  582. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/erDiagram-H3ERR26V.mjs +99 -0
  583. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/eventmodeling-NTZA5JFV-WKSWQHFS.mjs +1 -0
  584. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/flowDiagram-YHGXBVSY.mjs +1 -0
  585. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ganttDiagram-RWFTB7ED.mjs +292 -0
  586. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/gitGraph-4MIJSDKK-JH2HKYUO.mjs +1 -0
  587. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/gitGraphDiagram-MAR6GKOP.mjs +106 -0
  588. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/info-A6RAGUB7-3TX3OFWW.mjs +1 -0
  589. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/infoDiagram-LV547AFH.mjs +2 -0
  590. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ishikawaDiagram-PUJQGNDS.mjs +70 -0
  591. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/journeyDiagram-EW5QJT4W.mjs +139 -0
  592. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/kanban-definition-JSQERAZB.mjs +89 -0
  593. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/katex-CZ4GXH2S.mjs +257 -0
  594. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/mindmap-definition-VBJCLQLM.mjs +96 -0
  595. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/packet-AYTQ26CC-MKII6P3Y.mjs +1 -0
  596. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pegDiagram-7WILOQTJ.mjs +1 -0
  597. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pie-WAS4IAKB-6B4OPMJ5.mjs +1 -0
  598. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pieDiagram-EFA7CBSB.mjs +39 -0
  599. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/quadrantDiagram-WARVYA7P.mjs +7 -0
  600. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/radar-RG4KPBEZ-UPTR3XUL.mjs +1 -0
  601. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-74A4TZTK-MEFUPFMS.mjs +1 -0
  602. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-abnf-HS5TGJTU-R5YG2S5D.mjs +1 -0
  603. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-ebnf-LZEXJU2U-G5QEX2L6.mjs +1 -0
  604. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-peg-WCYAUIDC-H5I2ZRY2.mjs +1 -0
  605. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroadDiagram-5NIQVNLQ.mjs +1 -0
  606. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/requirementDiagram-SXREGOKZ.mjs +84 -0
  607. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sankeyDiagram-VV74M2VP.mjs +40 -0
  608. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sequenceDiagram-52ZFIFDL.mjs +162 -0
  609. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sizeCapture-FGA5AGYP.mjs +1 -0
  610. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/stateDiagram-3QAKPIVI.mjs +1 -0
  611. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/stateDiagram-v2-HN2P4RDZ.mjs +1 -0
  612. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/swimlanes-QLVP42QD.mjs +1 -0
  613. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/swimlanesDiagram-JKPDBFCN.mjs +8 -0
  614. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/timeline-definition-GS45XAXW.mjs +120 -0
  615. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/treeView-Q6P3EWNA-ZRJGANNQ.mjs +1 -0
  616. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/treemap-WGGIJYW6-K64VN5AS.mjs +1 -0
  617. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/vennDiagram-QIQU2ZRJ.mjs +34 -0
  618. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/wardley-WFR3VGLG-D67OWCCH.mjs +1 -0
  619. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/wardleyDiagram-U6YNM66N.mjs +78 -0
  620. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/xychartDiagram-XJAZEDNM.mjs +7 -0
  621. package/neural-interface/public/vendor/mermaid/manifest.json +4 -0
  622. package/neural-interface/public/vendor/mermaid/mermaid-11.17.2.esm.min.mjs +14 -0
  623. package/neural-interface/public/vendor/yaml/LICENSE +13 -0
  624. package/neural-interface/public/vendor/yaml/manifest.json +4 -0
  625. package/neural-interface/public/vendor/yaml/yaml-2.9.1.min.js +137 -0
  626. package/neural-interface/scripts/build-vendor.mjs +116 -3
  627. package/neural-interface/server.js +4834 -2541
  628. package/neural-interface/templates/rulesets/core.md +1 -1
  629. package/neural-interface/templates/rulesets/legacy-hashes.json +18 -0
  630. package/neural-interface/templates/rulesets/manifest.json +8 -8
  631. package/npm-shrinkwrap.json +18 -12
  632. package/package.json +16 -3
  633. package/postinstall.js +9 -4
  634. package/preuninstall.js +1 -1
  635. package/setup.js +97 -322
  636. package/skills/skill-forge/SKILL.md +177 -0
  637. package/skills/skill-forge/evals/evals.json +54 -0
  638. package/skills/skill-forge/references/package.md +105 -0
  639. package/skills/skill-forge/references/review-and-recovery.md +63 -0
  640. package/skills/skill-forge/references/runtime-profiles.md +20 -0
  641. package/skills/skill-forge/references/sources-and-capabilities.md +51 -0
  642. package/skills/synabun/SKILL.md +10 -7
  643. package/skills/synabun/modules/audit.md +1 -5
  644. package/skills/synabun/modules/changelog.md +1 -5
  645. package/skills/synabun/modules/idea.md +1 -1
  646. package/skills/synabun/modules/memorize.md +6 -9
  647. package/skills/synabun/modules/schedule.md +5 -5
  648. package/mcp-server/dist/services/profiles.d.ts +0 -120
  649. package/mcp-server/dist/services/profiles.d.ts.map +0 -1
  650. package/mcp-server/dist/services/profiles.js +0 -387
  651. package/mcp-server/dist/services/profiles.js.map +0 -1
  652. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +0 -97
  653. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +0 -1
  654. package/mcp-server/dist/tools/leonardo-browser-tools.js +0 -228
  655. package/mcp-server/dist/tools/leonardo-browser-tools.js.map +0 -1
  656. package/mcp-server/dist/tools/leonardo.d.ts +0 -13
  657. package/mcp-server/dist/tools/leonardo.d.ts.map +0 -1
  658. package/mcp-server/dist/tools/leonardo.js +0 -21
  659. package/mcp-server/dist/tools/leonardo.js.map +0 -1
  660. package/mcp-server/dist/tools/profile.d.ts +0 -17
  661. package/mcp-server/dist/tools/profile.d.ts.map +0 -1
  662. package/mcp-server/dist/tools/profile.js +0 -114
  663. package/mcp-server/dist/tools/profile.js.map +0 -1
  664. package/mcp-server/src/services/profiles.ts +0 -428
  665. package/mcp-server/src/tools/leonardo-browser-tools.ts +0 -291
  666. package/mcp-server/src/tools/leonardo.ts +0 -30
  667. package/mcp-server/src/tools/profile.ts +0 -122
  668. package/neural-interface/lib/assistant-brains/opencode-browser-policy.js +0 -47
  669. package/neural-interface/lib/assistant-brains/opencode-route-gate.js +0 -62
  670. package/neural-interface/lib/mcp-profile-servers.js +0 -120
  671. package/neural-interface/public/shared/ui-tutorial-draw.js +0 -311
  672. package/skills/leonardo/SKILL.md +0 -168
  673. package/skills/leonardo/icon.svg +0 -1
  674. package/skills/leonardo/modules/browser-guide.md +0 -378
  675. package/skills/leonardo/modules/image-prompter.md +0 -283
  676. package/skills/leonardo/modules/model-advisor.md +0 -100
  677. package/skills/leonardo/modules/prompt-library.md +0 -110
  678. package/skills/leonardo/modules/style-guide.md +0 -186
  679. package/skills/leonardo/modules/video-prompter.md +0 -317
@@ -0,0 +1,624 @@
1
+ // ─────────────────────────────────────────────────────────────────────────────
2
+ // SynaBun's own OpenCode serves, on record, and what a crash left of them.
3
+ //
4
+ // Every `opencode serve` SynaBun starts is on record from its spawn until its
5
+ // process has ended: the shared serve (which the session title generator uses
6
+ // too), the isolated serves of panel sessions, loops and Assistant workers and
7
+ // brains, and the code editor's completion serve. One file per process,
8
+ // DATA_HOME/runtime/opencode-serves/<pid>.json (outside data/: process state
9
+ // of this machine, which no backup or restore carries):
10
+ // { v, kind, id, port, pid, startedAt, command, token, scope, owner, recordedAt }
11
+ // `pid`, `startedAt` and `command` are the process's identity as the OS reports
12
+ // it (lib/process-identity.js); `token` is the random token SynaBun put in the
13
+ // serve's environment when it spawned it (SERVE_TOKEN_ENV), which nothing else
14
+ // carries; `scope` is the machine, the user and the boot the record was written
15
+ // in; `owner` is the identity of the SynaBun server that started it. The
16
+ // spawned process is recorded at once (record()), and the process that answers
17
+ // on the port too when the spawned one started it, proved through the parent
18
+ // chain (answering()). No other process is ever recorded: another server that
19
+ // took the port is a start collision, left running and off record.
20
+ //
21
+ // SynaBun stops a recorded process only when it can prove that SynaBun spawned
22
+ // it, on this machine, for this user, in this boot, and that the SynaBun that
23
+ // started it has ended:
24
+ // • the record is whole (identity, port, token, scope, and a command line
25
+ // that serves on its port, read as the platform parses it) and was written
26
+ // on this machine, by this user, in this boot;
27
+ // • the OS still reports the very process recorded (verify()): the same pid
28
+ // and start time, a command line that serves on the port, the user's own,
29
+ // and the token in its environment (Windows, where no other process's
30
+ // environment can be read: the same command line, and a start time to the
31
+ // fraction of a second); read again right before each signal (SIGTERM,
32
+ // then SIGKILL when it stays);
33
+ // • its owner has positively ended: no process runs under the owner's pid,
34
+ // or one with another start time or command line. The running server
35
+ // stops its own serves itself (claimable()), never in the sweep.
36
+ // Anything unknown, unreadable or ambiguous is left running: an owner that was
37
+ // never recorded or cannot be read, a process whose identity, user or
38
+ // environment cannot be read, a record of another machine or user. A record is
39
+ // removed only once its process has provably ended (gone, its pid another
40
+ // process's, or an earlier boot); a record whose process cannot be read stays
41
+ // for the next look. Nothing else is looked for: the machine's processes are
42
+ // never listed and searched for OpenCode, and a process SynaBun did not record
43
+ // is never signalled.
44
+ //
45
+ // The same records keep SynaBun's quick tunnel (lib/cloudflared/tunnel.js): a
46
+ // second set of them, in DATA_HOME/runtime/tunnels, whose kind is 'quick' and
47
+ // whose command line is a cloudflared tunnel to this server's port
48
+ // (createServeRecords `kinds` / `matchesCommand`: lib/cloudflared/tunnel.js
49
+ // tunnelsToPort over commandArgs). A server that ends without its exit handlers (a native crash)
50
+ // leaves its cloudflared running, the public address still pointing at the port
51
+ // the next server takes: the next server ends it by these same rules.
52
+ // ─────────────────────────────────────────────────────────────────────────────
53
+
54
+ import { mkdirSync, readFileSync, readdirSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
55
+ import { join } from 'node:path';
56
+ import { spawn } from 'node:child_process';
57
+ import {
58
+ SERVE_TOKEN_ENV, listPortListenersAsync, newServeToken, pidExists, readEnvironmentHas, readEnvironmentHasAsync,
59
+ readHostScope, readHostScopeAsync, readProcessIdentity, readProcessIdentityAsync, readProcessParentAsync, sameProcess,
60
+ } from './process-identity.js';
61
+
62
+ /** The serves SynaBun starts. */
63
+ export const SERVE_KINDS = Object.freeze(['shared', 'isolated', 'completion']);
64
+ export const RECORD_VERSION = 2;
65
+
66
+ const RECORD_FILE = /^(\d+)\.json$/;
67
+ const TOKEN = /^[0-9a-f]{32}$/;
68
+ // A Windows start time to the fraction of a second (CIM's CreationDate, ISO 8601 with 7 digits).
69
+ const FINE_START = /T\d{2}:\d{2}:\d{2}\.\d{4,}/;
70
+ const isPid = (n) => Number.isInteger(n) && n > 0;
71
+ const isPort = (n) => Number.isInteger(n) && n > 0 && n <= 65535;
72
+ const str = (v) => (typeof v === 'string' ? v : '');
73
+
74
+ // ── Command lines, as the platform reads them ───────────────────────────────
75
+
76
+ /**
77
+ * A Windows command line split the way a program's C runtime splits it: whitespace parts the arguments, double
78
+ * quotes group them, backslashes are literal except before a quote, and "" inside quotes is a quote.
79
+ * @param {string} line
80
+ */
81
+ export function windowsArgv(line) {
82
+ const text = String(line ?? '');
83
+ const n = text.length;
84
+ const args = [];
85
+ let i = 0;
86
+ while (i < n && (text[i] === ' ' || text[i] === '\t')) i++;
87
+ if (i >= n) return args;
88
+ // The program's name: up to the next quote when it starts with one, else up to whitespace; no escapes in it.
89
+ let program = '';
90
+ if (text[i] === '"') { i++; while (i < n && text[i] !== '"') program += text[i++]; i++; }
91
+ else { while (i < n && text[i] !== ' ' && text[i] !== '\t') program += text[i++]; }
92
+ args.push(program);
93
+ for (;;) {
94
+ while (i < n && (text[i] === ' ' || text[i] === '\t')) i++;
95
+ if (i >= n) break;
96
+ let arg = '';
97
+ let quoted = false;
98
+ while (i < n) {
99
+ const c = text[i];
100
+ if (!quoted && (c === ' ' || c === '\t')) break;
101
+ if (c === '\\') {
102
+ let k = i;
103
+ while (k < n && text[k] === '\\') k++;
104
+ const count = k - i;
105
+ if (text[k] === '"') {
106
+ arg += '\\'.repeat(Math.floor(count / 2));
107
+ if (count % 2) { arg += '"'; i = k + 1; } else i = k;
108
+ } else { arg += '\\'.repeat(count); i = k; }
109
+ continue;
110
+ }
111
+ if (c === '"') {
112
+ if (quoted && text[i + 1] === '"') { arg += '"'; i += 2; continue; }
113
+ quoted = !quoted;
114
+ i++;
115
+ continue;
116
+ }
117
+ arg += c;
118
+ i++;
119
+ }
120
+ args.push(arg);
121
+ }
122
+ return args;
123
+ }
124
+
125
+ // cmd.exe's reading of the line after /c: a caret takes the next character as it is (an escaped quote opens
126
+ // nothing), quotes group, unescaped whitespace outside quotes parts the words. The words keep their quotes.
127
+ function cmdWords(line) {
128
+ const text = String(line ?? '');
129
+ const words = [];
130
+ let word = '';
131
+ let quoted = false;
132
+ let has = false;
133
+ for (let i = 0; i < text.length; i++) {
134
+ const c = text[i];
135
+ if (!quoted && (c === ' ' || c === '\t')) { if (has) { words.push(word); word = ''; has = false; } continue; }
136
+ has = true;
137
+ if (c === '"') { quoted = !quoted; word += c; continue; }
138
+ if (c === '^' && !quoted && i + 1 < text.length) { word += text[++i]; continue; }
139
+ word += c;
140
+ }
141
+ if (has) words.push(word);
142
+ return words;
143
+ }
144
+
145
+ // The text after cmd.exe's own switches up to /c (or /k), outer quotes taken off as /s does; null when there is none.
146
+ function cmdCommandText(line) {
147
+ const text = String(line ?? '');
148
+ let i = 0;
149
+ const n = text.length;
150
+ while (i < n && /\s/.test(text[i])) i++;
151
+ if (text[i] === '"') { i = text.indexOf('"', i + 1); if (i < 0) return null; i++; }
152
+ else while (i < n && !/\s/.test(text[i])) i++;
153
+ for (;;) {
154
+ while (i < n && /\s/.test(text[i])) i++;
155
+ if (text[i] !== '/') return null;
156
+ let j = i;
157
+ while (j < n && !/\s/.test(text[j])) j++;
158
+ const word = text.slice(i, j).toLowerCase();
159
+ i = j;
160
+ if (word === '/c' || word === '/k') break;
161
+ }
162
+ let rest = text.slice(i).trim();
163
+ if (rest.length >= 2 && rest.startsWith('"') && rest.endsWith('"')) rest = rest.slice(1, -1);
164
+ return rest;
165
+ }
166
+
167
+ const windowsBase = (path) => String(path ?? '').split(/[\\/]/).pop() || '';
168
+
169
+ /**
170
+ * The arguments a command line holds, as the platform reads it. Windows: the C runtime's split; a cmd.exe that
171
+ * runs a command (`cmd.exe /d /s /c "…"`, how a command file is started: lib/cli-resolver.js spawnArgsFor) is read
172
+ * through to what it runs: its carets once, and once more for a command file (.cmd, .bat), which reads its own
173
+ * arguments again. Elsewhere: the words `ps` prints.
174
+ * @param {string} command
175
+ * @param {string} [platform]
176
+ */
177
+ export function commandArgs(command, platform = process.platform) {
178
+ const text = str(command).trim();
179
+ if (!text) return [];
180
+ if (platform !== 'win32') return text.split(/\s+/);
181
+ const argv = windowsArgv(text);
182
+ if (!/^cmd(?:\.exe)?$/i.test(windowsBase(argv[0]))) return argv;
183
+ const inner = cmdCommandText(text);
184
+ if (inner == null) return argv;
185
+ const words = cmdWords(inner);
186
+ if (!words.length) return argv;
187
+ // The program cmd.exe runs: its first word, quotes only group it (an escaped space is part of it).
188
+ const target = words[0].replace(/"/g, '');
189
+ const rest = /\.(?:cmd|bat)$/i.test(target) ? words.slice(1).map((word) => cmdWords(word).join(' ')) : words.slice(1);
190
+ return [target, ...windowsArgv(`x ${rest.join(' ')}`).slice(1)];
191
+ }
192
+
193
+ /** Is `command` the command line of a serve on `port` (`… serve … --port <port>`), its arguments read as the platform reads them? */
194
+ export function servesOnPort(command, port, platform = process.platform) {
195
+ if (!isPort(Number(port))) return false;
196
+ const args = commandArgs(command, platform);
197
+ if (!args.includes('serve')) return false;
198
+ const p = String(Number(port));
199
+ return args.some((arg, i) => arg === `--port=${p}` || (arg === '--port' && args[i + 1] === p));
200
+ }
201
+
202
+ const wholeScope = (s) => !!s && typeof s === 'object' && !!str(s.machine) && !!str(s.uid) && !!str(s.boot);
203
+ const sameScope = (a, b) => wholeScope(a) && wholeScope(b) && a.machine === b.machine && a.uid === b.uid && a.boot === b.boot;
204
+
205
+ /**
206
+ * A record that proves which process it names: its identity whole, its port, the token of its spawn, where it was
207
+ * written (machine, user, boot), and a command line that serves on its port. `kinds` and `matches` are another set
208
+ * of records' own (the tunnel's: lib/cloudflared/tunnel.js tunnelsToPort).
209
+ */
210
+ export function wholeRecord(record, platform = process.platform, { kinds = SERVE_KINDS, matches = servesOnPort } = {}) {
211
+ if (!record || typeof record !== 'object') return false;
212
+ if (!kinds.includes(record.kind) || !isPid(record.pid) || !isPort(record.port)) return false;
213
+ if (!str(record.startedAt) || !str(record.command) || !TOKEN.test(str(record.token)) || !wholeScope(record.scope)) return false;
214
+ return matches(record.command, record.port, platform);
215
+ }
216
+
217
+ /** An owner that can be told apart from any other process: its pid, start time and command line. */
218
+ const wholeOwner = (owner) => !!owner && isPid(owner.pid) && !!str(owner.startedAt) && !!str(owner.command);
219
+
220
+ /**
221
+ * @param {object} o
222
+ * @param {string} o.dir the folder of the records (DATA_HOME/runtime/opencode-serves)
223
+ * @param {() => object | null} [o.self] the identity of the running SynaBun server (read once, when first needed)
224
+ * @param {() => object} [o.scope] `{ machine, uid, boot }` here (lib/process-identity.js readHostScope)
225
+ * @param {() => Promise<object>} [o.scopeAsync] the same, without holding the event loop
226
+ * @param {(pid: number) => object | null} [o.readIdentity] read right before a signal (lib/process-identity.js)
227
+ * @param {(pid: number) => Promise<object | null>} [o.readIdentityAsync] every other read
228
+ * @param {(pid: number, token: string, command: string) => boolean | null} [o.readToken] is the token in its environment?
229
+ * @param {(pid: number, token: string, command: string) => Promise<boolean | null>} [o.readTokenAsync]
230
+ * @param {(port: number) => Promise<number[] | null>} [o.listeners] who listens on a port (null: cannot be told)
231
+ * @param {(pid: number) => Promise<{ pid: number, ppid: number, startedAt: string } | null>} [o.parentOf]
232
+ * @param {(pid: number) => boolean | null} [o.exists] does a process run under the pid (null: cannot be told)
233
+ * @param {(pid: number, signal: string) => void} [o.kill] the signal itself (Windows: taskkill /T /F, any signal)
234
+ * @param {number} [o.selfPid] process.pid
235
+ * @param {string[]} [o.kinds] the kinds these records hold (SERVE_KINDS; the tunnel's: ['quick'])
236
+ * @param {(command: string, port: number, platform: string) => boolean} [o.matchesCommand] is a command line one of
237
+ * theirs on `port`? (servesOnPort; the tunnel's: lib/cloudflared/tunnel.js tunnelsToPort)
238
+ * @param {string} [o.noun] what one is called in the log ('serve', 'tunnel')
239
+ */
240
+ export function createServeRecords({
241
+ dir,
242
+ kinds = SERVE_KINDS,
243
+ matchesCommand = servesOnPort,
244
+ noun = 'serve',
245
+ selfPid = process.pid,
246
+ self = () => readProcessIdentity(selfPid),
247
+ scope = null,
248
+ scopeAsync = null,
249
+ readIdentity = readProcessIdentity,
250
+ readIdentityAsync = readProcessIdentityAsync,
251
+ readToken = (pid, token, command) => readEnvironmentHas(pid, SERVE_TOKEN_ENV, token, { command }),
252
+ readTokenAsync = (pid, token, command) => readEnvironmentHasAsync(pid, SERVE_TOKEN_ENV, token, { command }),
253
+ listeners = (port) => listPortListenersAsync(port),
254
+ parentOf = (pid) => readProcessParentAsync(pid),
255
+ exists = pidExists,
256
+ platform = process.platform,
257
+ kill = null,
258
+ newToken = newServeToken,
259
+ now = () => Date.now(),
260
+ sleep = (ms) => new Promise((done) => { const t = setTimeout(done, ms); t.unref?.(); }),
261
+ stopWaitMs = 6000,
262
+ killWaitMs = 3000,
263
+ pollMs = 100,
264
+ log = () => {},
265
+ } = {}) {
266
+ if (!dir) throw new Error('createServeRecords requires dir');
267
+ const whole = (record) => wholeRecord(record, platform, { kinds, matches: matchesCommand });
268
+ const readScope = scope || (() => readHostScope());
269
+ const readScopeAsync = scopeAsync || (scope ? async () => scope() : () => readHostScopeAsync());
270
+ const signal = kill || ((pid, sig) => {
271
+ if (platform === 'win32') {
272
+ // The serve and what it started: Windows has no signals to send.
273
+ spawn('taskkill', ['/pid', String(pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore' }).on('error', () => {});
274
+ return;
275
+ }
276
+ process.kill(pid, sig);
277
+ });
278
+
279
+ // Where this server runs: read once it is first needed, and again (at most once a minute) while the OS could not
280
+ // tell all three. Until then nothing is recorded and nothing is stopped.
281
+ let here = null;
282
+ let hereTriedAt = -Infinity;
283
+ const wholeOrNull = (s) => (wholeScope(s) ? { machine: s.machine, uid: s.uid, boot: s.boot } : null);
284
+ const asScope = (s) => wholeOrNull(s && { machine: s.machine == null ? '' : String(s.machine), uid: s.uid == null ? '' : String(s.uid), boot: s.boot == null ? '' : String(s.boot) });
285
+ function scopeNow() {
286
+ if (!here && now() - hereTriedAt >= 60_000) {
287
+ hereTriedAt = now();
288
+ try { here = asScope(readScope()); } catch { here = null; }
289
+ }
290
+ return here;
291
+ }
292
+ async function scopeLater() {
293
+ if (!here && now() - hereTriedAt >= 60_000) {
294
+ hereTriedAt = now();
295
+ try { here = asScope(await readScopeAsync()); } catch { here = null; }
296
+ }
297
+ return here;
298
+ }
299
+
300
+ // The running server's own identity: read once it is first needed, and again (at most once a minute) while the OS
301
+ // could not be asked. Until then the owner is its pid alone, which a later run never takes for proof.
302
+ let selfIdentity = null;
303
+ let selfTriedAt = -Infinity;
304
+ function owner() {
305
+ if (!selfIdentity && now() - selfTriedAt >= 60_000) {
306
+ selfTriedAt = now();
307
+ try { selfIdentity = self() || null; } catch { selfIdentity = null; }
308
+ }
309
+ return selfIdentity && selfIdentity.pid === selfPid ? selfIdentity : { pid: selfPid };
310
+ }
311
+ // The tokens of the records this server wrote: those serves are its own.
312
+ const issued = new Set();
313
+ /** Is this record the running server's own: one it wrote, or one whose owner is this very process, here? */
314
+ function ownedHere(record) {
315
+ if (!record || typeof record !== 'object') return false;
316
+ if (str(record.token) && issued.has(record.token)) return true;
317
+ const o = record.owner;
318
+ const me = owner();
319
+ return wholeOwner(o) && wholeOwner(me) && o.pid === selfPid && sameProcess(o, me) && sameScope(record.scope, scopeNow());
320
+ }
321
+
322
+ const fileOf = (pid) => join(dir, `${pid}.json`);
323
+ function readFile(name) {
324
+ try { return JSON.parse(readFileSync(join(dir, name), 'utf8')); } catch { return null; }
325
+ }
326
+ function unlink(name) {
327
+ try { unlinkSync(join(dir, name)); return true; } catch { return false; }
328
+ }
329
+ /** Every record on file, with its file name; `record` null for a file that is not a record. */
330
+ function entries() {
331
+ let names = [];
332
+ try { names = readdirSync(dir); } catch { return []; }
333
+ return names.filter((name) => RECORD_FILE.test(name)).map((name) => ({ name, record: readFile(name) }));
334
+ }
335
+
336
+ // ── Is it still that process? ──
337
+
338
+ // The record against where this server runs: 'here', 'gone' (an earlier boot of this machine, for this user:
339
+ // every process of it has ended) or 'unknown' (another machine's or user's, or where cannot be told).
340
+ function whereVerdict(record) {
341
+ const at = scopeNow();
342
+ const there = record?.scope;
343
+ if (!at || !wholeScope(there)) return 'unknown';
344
+ if (there.machine !== at.machine || there.uid !== at.uid) return 'unknown';
345
+ return there.boot === at.boot ? 'here' : 'gone';
346
+ }
347
+ // What the OS reports for the pid now, against the record: 'same', 'gone', 'unknown', or 'token' (the token in its
348
+ // environment decides); null when nothing could be read for the pid.
349
+ function identityVerdict(record, current) {
350
+ if (!current) return null;
351
+ if (String(current.startedAt) !== String(record.startedAt)) return 'gone';
352
+ if (platform === 'win32') {
353
+ if (String(current.command) !== String(record.command)) return 'gone';
354
+ return FINE_START.test(String(record.startedAt)) ? 'same' : 'unknown';
355
+ }
356
+ if (current.uid == null || current.uid === '') return 'unknown';
357
+ if (String(current.uid) !== record.scope.uid) return 'gone';
358
+ if (!matchesCommand(current.command, record.port, platform)) return 'gone';
359
+ return 'token';
360
+ }
361
+ const tokenVerdict = (has) => (has === true ? 'same' : has === false ? 'gone' : 'unknown');
362
+
363
+ /**
364
+ * Is the record's process still the very one recorded? 'same'; 'gone' (provably not: it has ended, its pid is
365
+ * another process's, or it was of an earlier boot); 'unknown' (it cannot be told: nothing is done on it, and its
366
+ * record stays). Read in full each time, right before a signal included.
367
+ */
368
+ function verifySync(record) {
369
+ if (!whole(record)) return 'unknown';
370
+ const where = whereVerdict(record);
371
+ if (where !== 'here') return where;
372
+ const current = readIdentity(record.pid);
373
+ const verdict = identityVerdict(record, current);
374
+ if (verdict === null) return exists(record.pid) === false ? 'gone' : 'unknown';
375
+ if (verdict !== 'token') return verdict;
376
+ return tokenVerdict(readToken(record.pid, record.token, current.command));
377
+ }
378
+ /** verifySync without holding the event loop while the OS answers. */
379
+ async function verify(record) {
380
+ if (!whole(record)) return 'unknown';
381
+ await scopeLater();
382
+ const where = whereVerdict(record);
383
+ if (where !== 'here') return where;
384
+ const current = await readIdentityAsync(record.pid);
385
+ const verdict = identityVerdict(record, current);
386
+ if (verdict === null) return exists(record.pid) === false ? 'gone' : 'unknown';
387
+ if (verdict !== 'token') return verdict;
388
+ return tokenVerdict(await readTokenAsync(record.pid, record.token, current.command));
389
+ }
390
+
391
+ // Has the record's owner ended? 'ended' (positively: no process under its pid, or the one there now has another
392
+ // start time or command line), 'running', or 'unknown' (no owner, a bare pid that runs, a read that failed).
393
+ function ownerVerdict(o, current, gone) {
394
+ if (current) return wholeOwner(o) ? (sameProcess(o, current) ? 'running' : 'ended') : 'unknown';
395
+ return gone ? 'ended' : 'unknown';
396
+ }
397
+ function ownerEndedSync(o) {
398
+ if (!o || !isPid(o.pid)) return 'unknown';
399
+ if (exists(o.pid) === false) return 'ended';
400
+ if (!wholeOwner(o)) return 'unknown';
401
+ const current = readIdentity(o.pid);
402
+ return ownerVerdict(o, current, !current && exists(o.pid) === false);
403
+ }
404
+ async function ownerEnded(o) {
405
+ if (!o || !isPid(o.pid)) return 'unknown';
406
+ if (exists(o.pid) === false) return 'ended';
407
+ if (!wholeOwner(o)) return 'unknown';
408
+ const current = await readIdentityAsync(o.pid);
409
+ return ownerVerdict(o, current, !current && exists(o.pid) === false);
410
+ }
411
+
412
+ /**
413
+ * May the running server stop this record's process (once verify() says it is still that process)? Only a whole
414
+ * record written here (this machine, user and boot) that is its own, or whose SynaBun has positively ended. Never
415
+ * another live SynaBun's, one whose owner was never recorded or cannot be read, one of another machine or user.
416
+ */
417
+ function claimable(record) {
418
+ if (!whole(record) || whereVerdict(record) !== 'here') return false;
419
+ return ownedHere(record) || ownerEndedSync(record.owner) === 'ended';
420
+ }
421
+
422
+ // ── On record ──
423
+
424
+ /**
425
+ * Record a process of a serve SynaBun started: the one it spawned, at once, and the one that answers on the port
426
+ * when the spawned one started it (answering()). Its identity is read now, so that a later run can tell it from
427
+ * whatever gets its pid afterwards. Nothing is recorded that could never be shown to be this start's: a process
428
+ * whose identity cannot be read, whose command line is not a serve on `port`, that is another user's, that does
429
+ * not carry this start's token (macOS, Linux), or whose start time is not to the fraction of a second (Windows);
430
+ * nor while the machine, the user or the boot cannot be told. A live record of another start under the same pid
431
+ * is never written over. Resolves the record or null.
432
+ */
433
+ async function record({ kind, id = null, port, pid, token } = {}) {
434
+ const n = Number(pid);
435
+ if (!kinds.includes(kind) || !isPid(n) || !isPort(Number(port)) || !TOKEN.test(str(token))) return null;
436
+ const at = await scopeLater();
437
+ if (!at) { log(`no record for the ${kind} ${noun} on port ${port}: the machine, the user or the boot could not be read`); return null; }
438
+ const identity = await readIdentityAsync(n);
439
+ if (!identity) { log(`no record for the ${kind} ${noun} on port ${port}: the identity of process ${n} could not be read`); return null; }
440
+ const entry = {
441
+ v: RECORD_VERSION, kind, id: id == null ? null : String(id), port: Number(port),
442
+ pid: n, startedAt: identity.startedAt, command: identity.command, token,
443
+ scope: { ...at }, owner: owner(), recordedAt: new Date(now()).toISOString(),
444
+ };
445
+ if (!whole(entry)) { log(`no record for the ${kind} ${noun} on port ${port}: process ${n} is not a ${noun} on that port (${identity.command})`); return null; }
446
+ if (platform === 'win32') {
447
+ if (!FINE_START.test(entry.startedAt)) { log(`no record for the ${kind} ${noun} on port ${port}: the start time of process ${n} is not precise enough to tell it apart`); return null; }
448
+ } else {
449
+ if (String(identity.uid ?? '') !== at.uid) { log(`no record for the ${kind} ${noun} on port ${port}: process ${n} is not this user's`); return null; }
450
+ if (await readTokenAsync(n, token, identity.command) !== true) { log(`no record for the ${kind} ${noun} on port ${port}: process ${n} does not carry this start's token`); return null; }
451
+ }
452
+ const onFile = readFile(`${n}.json`);
453
+ if (onFile && str(onFile.token) && onFile.token !== token && !issued.has(onFile.token) && await verify(onFile) === 'same') {
454
+ log(`no record for the ${kind} ${noun} on port ${port}: process ${n} is on record for another start`);
455
+ return null;
456
+ }
457
+ if (!write(entry)) return null;
458
+ issued.add(token);
459
+ return entry;
460
+ }
461
+
462
+ function write(entry) {
463
+ try {
464
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
465
+ const path = fileOf(entry.pid);
466
+ const tmp = `${path}.${process.pid}.tmp`;
467
+ writeFileSync(tmp, `${JSON.stringify(entry)}\n`, { encoding: 'utf8', mode: 0o600 });
468
+ renameSync(tmp, path);
469
+ return true;
470
+ } catch (error) {
471
+ log(`could not write the record of the ${entry.kind} ${noun} on port ${entry.port}: ${error?.message || error}`);
472
+ return false;
473
+ }
474
+ }
475
+
476
+ /** Remove a record: only that very one (its pid and its spawn's token), never another start's under the same pid. */
477
+ function remove(entry) {
478
+ if (!entry || !isPid(Number(entry.pid))) return false;
479
+ const name = `${Number(entry.pid)}.json`;
480
+ const onFile = readFile(name);
481
+ if (!onFile) return false;
482
+ const same = str(entry.token) ? onFile.token === entry.token : sameProcess(onFile, entry);
483
+ return same ? unlink(name) : false;
484
+ }
485
+
486
+ /** The whole records on file, the newest first. `kind` / `port` narrow them. */
487
+ function list({ kind = null, port = null } = {}) {
488
+ return entries()
489
+ .map(({ record: r }) => r)
490
+ .filter((r) => whole(r) && (!kind || r.kind === kind) && (port == null || r.port === Number(port)))
491
+ .sort((a, b) => String(b.recordedAt || '').localeCompare(String(a.recordedAt || '')));
492
+ }
493
+
494
+ // Did `ancestor` start `pid` (or a process that did)? true, false, or null (a link could not be read: nothing is
495
+ // proved). A parent never starts after its child: Windows keeps a parent's pid after that parent has ended, and
496
+ // the pid may be another process's by now.
497
+ async function descendsFrom(pid, ancestor) {
498
+ let at = await parentOf(pid);
499
+ for (let depth = 0; at && depth < 8; depth++) {
500
+ const ppid = Number(at.ppid);
501
+ if (!isPid(ppid) || ppid === 1) return false;
502
+ const up = await parentOf(ppid);
503
+ if (!up) return null;
504
+ if (platform === 'win32' && String(up.startedAt) > String(at.startedAt)) return false;
505
+ if (ppid === ancestor) return true;
506
+ at = up;
507
+ }
508
+ return at ? false : null;
509
+ }
510
+
511
+ /**
512
+ * Who answers on `port` for a start whose spawned process is `pid`: `{ state: 'ours', pid }` (the spawned process,
513
+ * or one it started, proved through the parent chain: the pid to record), `{ state: 'foreign' }` (another process
514
+ * holds the port, or the spawned one has ended: a start collision) or `{ state: 'unknown' }` (the OS could not say
515
+ * who listens: only the spawned process stays on record).
516
+ * @param {{ port: number, pid: number, exited?: () => boolean }} o
517
+ */
518
+ async function answering({ port, pid, exited = () => false } = {}) {
519
+ const n = Number(pid);
520
+ if (!isPid(n) || exited()) return { state: 'foreign' };
521
+ const pids = await listeners(Number(port));
522
+ if (exited()) return { state: 'foreign' };
523
+ if (!Array.isArray(pids)) return { state: 'unknown' };
524
+ if (!pids.length) return { state: 'foreign' };
525
+ let ours = null;
526
+ for (const listener of pids) {
527
+ if (listener !== n && await descendsFrom(listener, n) !== true) return { state: 'foreign', pids };
528
+ ours = listener === n ? n : (ours ?? listener);
529
+ }
530
+ return { state: 'ours', pid: ours };
531
+ }
532
+
533
+ // ── What a crash left running ──
534
+
535
+ // The signal, only while the OS still reports the very process recorded: read once more right before. 'signalled',
536
+ // 'gone' (it is provably not that process now) or 'unknown' (the read or the signal failed: nothing is known).
537
+ function signalIfSame(entry, sig) {
538
+ const verdict = verifySync(entry);
539
+ if (verdict !== 'same') return verdict;
540
+ try { signal(entry.pid, sig); return 'signalled'; } catch (error) { return error?.code === 'ESRCH' ? 'gone' : 'unknown'; }
541
+ }
542
+
543
+ async function goneWithin(entry, ms) {
544
+ const deadline = now() + ms;
545
+ for (;;) {
546
+ if (await verify(entry) === 'gone') return true;
547
+ if (now() >= deadline) return false;
548
+ await sleep(pollMs);
549
+ }
550
+ }
551
+
552
+ // Stop a leftover serve: SIGTERM, then SIGKILL when it stays. 'stopped', 'gone' (it was provably no longer that
553
+ // process when the signal was due), 'unknown' (it could not be read right before the signal: not signalled) or
554
+ // 'survived'.
555
+ async function stopLeftover(entry) {
556
+ const term = signalIfSame(entry, 'SIGTERM');
557
+ if (term !== 'signalled') return term;
558
+ if (await goneWithin(entry, stopWaitMs)) return 'stopped';
559
+ const hard = signalIfSame(entry, 'SIGKILL');
560
+ if (hard === 'gone') return 'stopped';
561
+ if (hard !== 'signalled') return 'survived';
562
+ return (await goneWithin(entry, killWaitMs)) ? 'stopped' : 'survived';
563
+ }
564
+
565
+ async function sweepOnce() {
566
+ const result = { stopped: [], dropped: [], kept: [] };
567
+ const files = entries();
568
+ const at = await scopeLater();
569
+ if (!at) {
570
+ if (files.length) log('the machine, the user or the boot could not be read: no leftover serve is looked at now');
571
+ for (const { name } of files) result.kept.push({ pid: Number(RECORD_FILE.exec(name)?.[1]), why: 'scope-unknown' });
572
+ return result;
573
+ }
574
+ for (const { name, record: entry } of files) {
575
+ const pid = Number(RECORD_FILE.exec(name)?.[1]);
576
+ const about = (why) => ({ pid, kind: entry.kind, port: entry.port, why });
577
+ if (!entry || typeof entry !== 'object') { unlink(name); result.dropped.push({ pid, why: 'not-a-record' }); continue; }
578
+ // Another machine's or another user's (a data home copied or shared): not this one's to judge, nor to tidy.
579
+ const there = entry.scope;
580
+ if (wholeScope(there) && there.machine !== at.machine) { result.kept.push(about('other-machine')); continue; }
581
+ if (wholeScope(there) && there.uid !== at.uid) { result.kept.push(about('other-user')); continue; }
582
+ // The running server's own serves: its own stops end them, and their exits remove their records.
583
+ if (ownedHere(entry)) continue;
584
+ // A file that is no whole record proves nothing: it goes, and nothing is signalled.
585
+ if (!whole(entry) || entry.pid !== pid) { unlink(name); result.dropped.push({ pid, why: 'not-a-record' }); continue; }
586
+ // An earlier boot ended every process it had: the record goes, and nothing is signalled.
587
+ if (there.boot !== at.boot) { remove(entry); result.dropped.push(about('earlier-boot')); continue; }
588
+ const serveNow = await verify(entry);
589
+ // Ended, or its pid is another program's by now: the record goes, and nothing is signalled.
590
+ if (serveNow === 'gone') { remove(entry); result.dropped.push(about('process-gone')); continue; }
591
+ if (serveNow !== 'same') { result.kept.push(about('identity-unknown')); continue; }
592
+ const ownerNow = await ownerEnded(entry.owner);
593
+ if (ownerNow !== 'ended') { result.kept.push(about(ownerNow === 'running' ? 'owner-running' : 'owner-unknown')); continue; }
594
+ // SynaBun's own serve, started by a SynaBun that has ended: nothing uses it any more.
595
+ log(`stopping a ${entry.kind} ${noun} an earlier SynaBun left running on port ${entry.port} (pid ${entry.pid})`);
596
+ const outcome = await stopLeftover(entry);
597
+ if (outcome === 'stopped') { remove(entry); result.stopped.push(about('leftover')); continue; }
598
+ if (outcome === 'gone') { remove(entry); result.dropped.push(about('process-gone')); continue; }
599
+ // Not seen to end, or not readable right before the signal: it stays on record for the next look.
600
+ result.kept.push(about(outcome === 'survived' ? 'survived' : 'identity-unknown'));
601
+ }
602
+ return result;
603
+ }
604
+
605
+ let sweeping = null;
606
+ /** Look for the serves an earlier SynaBun left running, and stop them (see above). One look at a time. */
607
+ function sweep() {
608
+ if (!sweeping) {
609
+ sweeping = sweepOnce()
610
+ .catch((error) => { log(`the look for leftover serves failed: ${error?.message || error}`); return { stopped: [], dropped: [], kept: [] }; })
611
+ .finally(() => { sweeping = null; });
612
+ }
613
+ return sweeping;
614
+ }
615
+
616
+ return {
617
+ dir, record, remove, list, verify, verifySync, claimable, ownedHere, answering, sweep,
618
+ /** A fresh token for one spawn, to put in its environment as SERVE_TOKEN_ENV (`tokenEnv`). */
619
+ newToken: () => newToken(),
620
+ tokenEnv: SERVE_TOKEN_ENV,
621
+ /** Where this server runs: `{ machine, uid, boot }`, or null while the OS cannot tell all three. */
622
+ scope: scopeNow,
623
+ };
624
+ }