synabun 2.0.10 → 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 (517) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/README.md +25 -2
  3. package/THIRD-PARTY-LICENSES.md +22 -0
  4. package/bin/synabun.js +71 -24
  5. package/docs/whatsapp.md +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/lib/claude-hooks.js +172 -18
  10. package/lib/client-config-repair.js +17 -8
  11. package/lib/desktop-app.js +7 -1
  12. package/lib/external-tools.js +1 -1
  13. package/lib/first-launch-protection.js +57 -12
  14. package/lib/mcp-dist.js +176 -0
  15. package/lib/release-npm-ci.mjs +138 -0
  16. package/lib/release-publish.mjs +91 -0
  17. package/lib/release-scan.mjs +50 -0
  18. package/lib/server-crash-record.js +123 -0
  19. package/lib/server-exit.js +318 -0
  20. package/lib/server-supervisor.js +508 -0
  21. package/lib/start-launcher.js +37 -4
  22. package/lib/tools-cli.js +45 -0
  23. package/lib/update-snapshot.js +228 -0
  24. package/lib/virustotal.mjs +192 -0
  25. package/lib/windows-crash-event.js +269 -0
  26. package/mcp-server/dist/http.d.ts +20 -1
  27. package/mcp-server/dist/http.d.ts.map +1 -1
  28. package/mcp-server/dist/http.js +59 -12
  29. package/mcp-server/dist/http.js.map +1 -1
  30. package/mcp-server/dist/index.d.ts +33 -27
  31. package/mcp-server/dist/index.d.ts.map +1 -1
  32. package/mcp-server/dist/index.js +128 -143
  33. package/mcp-server/dist/index.js.map +1 -1
  34. package/mcp-server/dist/preload.js +1 -1
  35. package/mcp-server/dist/preload.js.map +1 -1
  36. package/mcp-server/dist/services/codex-config-heal.d.ts +6 -2
  37. package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
  38. package/mcp-server/dist/services/codex-config-heal.js +81 -28
  39. package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
  40. package/mcp-server/dist/services/memory-judge-backfill.d.ts +6 -0
  41. package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -1
  42. package/mcp-server/dist/services/memory-judge-backfill.js +7 -1
  43. package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -1
  44. package/mcp-server/dist/services/neural-interface.d.ts +16 -10
  45. package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
  46. package/mcp-server/dist/services/neural-interface.js +67 -11
  47. package/mcp-server/dist/services/neural-interface.js.map +1 -1
  48. package/mcp-server/dist/services/server-instructions.d.ts +7 -2
  49. package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
  50. package/mcp-server/dist/services/server-instructions.js +20 -62
  51. package/mcp-server/dist/services/server-instructions.js.map +1 -1
  52. package/mcp-server/dist/services/tool-catalog.d.ts +120 -0
  53. package/mcp-server/dist/services/tool-catalog.d.ts.map +1 -0
  54. package/mcp-server/dist/services/tool-catalog.js +339 -0
  55. package/mcp-server/dist/services/tool-catalog.js.map +1 -0
  56. package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts +12 -0
  57. package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts.map +1 -0
  58. package/mcp-server/dist/services/tool-list-refresh-barrier.js +40 -0
  59. package/mcp-server/dist/services/tool-list-refresh-barrier.js.map +1 -0
  60. package/mcp-server/dist/services/tool-list.d.ts +108 -0
  61. package/mcp-server/dist/services/tool-list.d.ts.map +1 -0
  62. package/mcp-server/dist/services/tool-list.js +334 -0
  63. package/mcp-server/dist/services/tool-list.js.map +1 -0
  64. package/mcp-server/dist/services/tool-runtime.d.ts +161 -0
  65. package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -0
  66. package/mcp-server/dist/services/tool-runtime.js +400 -0
  67. package/mcp-server/dist/services/tool-runtime.js.map +1 -0
  68. package/mcp-server/dist/services/whiteboard-geometry.d.ts +26 -2
  69. package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -1
  70. package/mcp-server/dist/services/whiteboard-geometry.js +91 -8
  71. package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -1
  72. package/mcp-server/dist/tools/agents.d.ts +10 -10
  73. package/mcp-server/dist/tools/agents.d.ts.map +1 -1
  74. package/mcp-server/dist/tools/agents.js +22 -13
  75. package/mcp-server/dist/tools/agents.js.map +1 -1
  76. package/mcp-server/dist/tools/browser-batch.d.ts +3 -3
  77. package/mcp-server/dist/tools/image-tools.d.ts +1 -1
  78. package/mcp-server/dist/tools/image-tools.js +1 -1
  79. package/mcp-server/dist/tools/skill-tools.d.ts +505 -0
  80. package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -0
  81. package/mcp-server/dist/tools/skill-tools.js +639 -0
  82. package/mcp-server/dist/tools/skill-tools.js.map +1 -0
  83. package/mcp-server/dist/tools/skill.d.ts +7 -0
  84. package/mcp-server/dist/tools/skill.d.ts.map +1 -0
  85. package/mcp-server/dist/tools/skill.js +11 -0
  86. package/mcp-server/dist/tools/skill.js.map +1 -0
  87. package/mcp-server/dist/tools/tool-groups.d.ts +68 -0
  88. package/mcp-server/dist/tools/tool-groups.d.ts.map +1 -0
  89. package/mcp-server/dist/tools/tool-groups.js +147 -0
  90. package/mcp-server/dist/tools/tool-groups.js.map +1 -0
  91. package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -1
  92. package/mcp-server/dist/tools/whiteboard-format.js +7 -4
  93. package/mcp-server/dist/tools/whiteboard-format.js.map +1 -1
  94. package/mcp-server/dist/tools/whiteboard-tools.d.ts +64 -13
  95. package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -1
  96. package/mcp-server/dist/tools/whiteboard-tools.js +30 -5
  97. package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -1
  98. package/mcp-server/package-lock.json +2 -2
  99. package/mcp-server/package.json +1 -1
  100. package/mcp-server/src/http.ts +75 -12
  101. package/mcp-server/src/index.ts +147 -154
  102. package/mcp-server/src/preload.ts +12 -12
  103. package/mcp-server/src/services/codex-config-heal.ts +80 -29
  104. package/mcp-server/src/services/memory-judge-backfill.ts +7 -1
  105. package/mcp-server/src/services/neural-interface.ts +79 -20
  106. package/mcp-server/src/services/server-instructions.ts +27 -63
  107. package/mcp-server/src/services/tool-catalog.ts +403 -0
  108. package/mcp-server/src/services/tool-list-refresh-barrier.ts +33 -0
  109. package/mcp-server/src/services/tool-list.ts +410 -0
  110. package/mcp-server/src/services/tool-runtime.ts +457 -0
  111. package/mcp-server/src/services/whiteboard-geometry.ts +94 -9
  112. package/mcp-server/src/tools/agents.ts +22 -14
  113. package/mcp-server/src/tools/image-tools.ts +1 -1
  114. package/mcp-server/src/tools/skill-tools.ts +589 -0
  115. package/mcp-server/src/tools/skill.ts +13 -0
  116. package/mcp-server/src/tools/tool-groups.ts +164 -0
  117. package/mcp-server/src/tools/whiteboard-format.ts +9 -3
  118. package/mcp-server/src/tools/whiteboard-tools.ts +39 -5
  119. package/neural-interface/i18n/en.json +3463 -200
  120. package/neural-interface/i18n/pt-BR.json +3411 -151
  121. package/neural-interface/lib/assistant-api.js +127 -28
  122. package/neural-interface/lib/assistant-brains/claude.js +4 -3
  123. package/neural-interface/lib/assistant-brains/codex-browser-policy-hook.mjs +12 -2
  124. package/neural-interface/lib/assistant-brains/codex-route-gate-hook.mjs +32 -9
  125. package/neural-interface/lib/assistant-brains/codex.js +9 -5
  126. package/neural-interface/lib/assistant-brains/opencode.js +120 -54
  127. package/neural-interface/lib/assistant-brains/opencode2-browser-policy/index.js +28 -13
  128. package/neural-interface/lib/assistant-brains/opencode2-route-gate/index.js +59 -19
  129. package/neural-interface/lib/assistant-catalog.js +6 -7
  130. package/neural-interface/lib/assistant-dispatch.js +871 -156
  131. package/neural-interface/lib/assistant-envelope.js +3 -1
  132. package/neural-interface/lib/assistant-persona.js +80 -11
  133. package/neural-interface/lib/assistant-plan-permissions.js +10 -9
  134. package/neural-interface/lib/assistant-route-gate-codex.js +3 -0
  135. package/neural-interface/lib/assistant-route-gate.js +6 -4
  136. package/neural-interface/lib/assistant-router.js +13 -8
  137. package/neural-interface/lib/assistant-runtime.js +56 -18
  138. package/neural-interface/lib/assistant-task-prompt.js +78 -14
  139. package/neural-interface/lib/assistant-tools.js +51 -0
  140. package/neural-interface/lib/backup-service.js +620 -3
  141. package/neural-interface/lib/backup-zip-reader.js +10 -5
  142. package/neural-interface/lib/backup-zip-writer.js +257 -0
  143. package/neural-interface/lib/browser-execution.js +10 -2
  144. package/neural-interface/lib/browser-guard-cdp.js +83 -0
  145. package/neural-interface/lib/browser-network-guard.js +284 -0
  146. package/neural-interface/lib/browser-policy-roots.js +64 -0
  147. package/neural-interface/lib/browser-tool-policy.js +186 -31
  148. package/neural-interface/lib/claude-agent-bridge.js +4 -2
  149. package/neural-interface/lib/claude-hooks-status.js +103 -0
  150. package/neural-interface/lib/claude-temporary.js +5 -11
  151. package/neural-interface/lib/cli-install.js +18 -138
  152. package/neural-interface/lib/cli-resolver.js +4 -1
  153. package/neural-interface/lib/cli-update-planner.js +32 -31
  154. package/neural-interface/lib/cloudflared/tunnel.js +42 -2
  155. package/neural-interface/lib/codex-mcp-approvals.js +11 -0
  156. package/neural-interface/lib/codex-worker-app-server.js +172 -0
  157. package/neural-interface/lib/confined-fs.js +30 -3
  158. package/neural-interface/lib/crash-notice-api.js +98 -0
  159. package/neural-interface/lib/editor-completion-opencode.js +68 -68
  160. package/neural-interface/lib/exec-loop-command.js +4 -8
  161. package/neural-interface/lib/http-guards.js +8 -2
  162. package/neural-interface/lib/install-details.js +4 -1
  163. package/neural-interface/lib/mcp-agent-servers.js +67 -0
  164. package/neural-interface/lib/mcp-client-config.js +0 -29
  165. package/neural-interface/lib/mcp-external-servers.js +323 -0
  166. package/neural-interface/lib/{mcp-profile-refresh-coordinator.js → mcp-tools-refresh-coordinator.js} +4 -4
  167. package/neural-interface/lib/morelogin.js +30 -0
  168. package/neural-interface/lib/native-loop-providers.js +547 -47
  169. package/neural-interface/lib/native-loop-runtime.js +268 -41
  170. package/neural-interface/lib/opencode-config.js +557 -0
  171. package/neural-interface/lib/opencode-db-schema.js +17 -34
  172. package/neural-interface/lib/opencode-history.js +48 -218
  173. package/neural-interface/lib/opencode-mcp-ready.js +108 -0
  174. package/neural-interface/lib/opencode-native-boundary.js +44 -0
  175. package/neural-interface/lib/opencode-protocol.js +249 -112
  176. package/neural-interface/lib/opencode-runtime-config.js +32 -22
  177. package/neural-interface/lib/opencode-serve-records.js +39 -21
  178. package/neural-interface/lib/opencode-v2-client.js +48 -153
  179. package/neural-interface/lib/opencode-v2-ws-requests.js +36 -210
  180. package/neural-interface/lib/opencode-worker-data.js +27 -0
  181. package/neural-interface/lib/opencode2-client.js +73 -37
  182. package/neural-interface/lib/opencode2-proxy.js +23 -63
  183. package/neural-interface/lib/opencode2-translate.js +51 -2
  184. package/neural-interface/lib/owner-authority.js +249 -0
  185. package/neural-interface/lib/page-session.js +275 -0
  186. package/neural-interface/lib/peer-identity.js +763 -0
  187. package/neural-interface/lib/request-gate.js +17 -2
  188. package/neural-interface/lib/rulesets/api.js +1 -1
  189. package/neural-interface/lib/rulesets/fs-safe.js +1 -1
  190. package/neural-interface/lib/rulesets/installer.js +92 -27
  191. package/neural-interface/lib/rulesets/json-edit.js +1 -1
  192. package/neural-interface/lib/session-cache-builder.js +17 -30
  193. package/neural-interface/lib/session-title-generator.js +58 -36
  194. package/neural-interface/lib/skills/api-v2.js +495 -0
  195. package/neural-interface/lib/skills/bundle.js +418 -0
  196. package/neural-interface/lib/skills/catalog.js +294 -0
  197. package/neural-interface/lib/skills/creation-api.js +191 -0
  198. package/neural-interface/lib/skills/creation-brief.js +247 -0
  199. package/neural-interface/lib/skills/creation-sources.js +267 -0
  200. package/neural-interface/lib/skills/creation.js +843 -0
  201. package/neural-interface/lib/skills/deploy.js +564 -0
  202. package/neural-interface/lib/skills/digest.js +119 -0
  203. package/neural-interface/lib/skills/discover.js +111 -0
  204. package/neural-interface/lib/skills/draft-confinement.js +214 -0
  205. package/neural-interface/lib/skills/eval-confinement.js +397 -0
  206. package/neural-interface/lib/skills/eval-sandbox.js +280 -0
  207. package/neural-interface/lib/skills/eval-trace.js +119 -0
  208. package/neural-interface/lib/skills/evals-api.js +212 -0
  209. package/neural-interface/lib/skills/evals.js +1573 -0
  210. package/neural-interface/lib/skills/export.js +200 -0
  211. package/neural-interface/lib/skills/frontmatter.js +64 -0
  212. package/neural-interface/lib/skills/health.js +75 -0
  213. package/neural-interface/lib/skills/json-edit.js +165 -0
  214. package/neural-interface/lib/skills/known-bridge-digests.json +387 -0
  215. package/neural-interface/lib/skills/known-bridges.js +96 -0
  216. package/neural-interface/lib/skills/library.js +823 -0
  217. package/neural-interface/lib/skills/local-store.js +21 -0
  218. package/neural-interface/lib/skills/migration.js +433 -0
  219. package/neural-interface/lib/skills/operations.js +45 -0
  220. package/neural-interface/lib/skills/ownership.js +427 -0
  221. package/neural-interface/lib/skills/packages.js +88 -0
  222. package/neural-interface/lib/skills/reviews.js +212 -0
  223. package/neural-interface/lib/skills/revision.js +80 -0
  224. package/neural-interface/lib/skills/roots.js +262 -0
  225. package/neural-interface/lib/skills/runtime-checks.js +355 -0
  226. package/neural-interface/lib/skills/scan-assets.js +252 -0
  227. package/neural-interface/lib/skills/scan-context.js +26 -0
  228. package/neural-interface/lib/skills/scan-shell.js +324 -0
  229. package/neural-interface/lib/skills/scan.js +364 -0
  230. package/neural-interface/lib/skills/scanners.js +54 -0
  231. package/neural-interface/lib/skills/service.js +522 -0
  232. package/neural-interface/lib/skills/telemetry.js +113 -0
  233. package/neural-interface/lib/sqlite-integrity-worker.js +22 -0
  234. package/neural-interface/lib/tool-lists.js +124 -0
  235. package/neural-interface/lib/whatsapp/bridge.js +6 -3
  236. package/neural-interface/lib/worker-confinement.js +1192 -0
  237. package/neural-interface/lib/worker-guard-setting.js +56 -0
  238. package/neural-interface/lib/worker-mcp-channel.js +175 -0
  239. package/neural-interface/lib/worker-relay-ports.js +227 -0
  240. package/neural-interface/lib/worker-resume.js +229 -0
  241. package/neural-interface/lib/worker-sandbox.js +299 -0
  242. package/neural-interface/package-lock.json +18 -12
  243. package/neural-interface/package.json +2 -2
  244. package/neural-interface/public/index.html +3 -1
  245. package/neural-interface/public/index2d.html +19 -11
  246. package/neural-interface/public/onboarding.html +2 -2
  247. package/neural-interface/public/shared/account-menu.js +8 -5
  248. package/neural-interface/public/shared/agent-runtime-options.js +35 -19
  249. package/neural-interface/public/shared/api.js +1527 -1336
  250. package/neural-interface/public/shared/app-frame.js +192 -0
  251. package/neural-interface/public/shared/assistant/asst-agents-dock.js +33 -2
  252. package/neural-interface/public/shared/assistant/asst-ask-styles.js +270 -0
  253. package/neural-interface/public/shared/assistant/asst-ask-tail.js +118 -0
  254. package/neural-interface/public/shared/assistant/asst-ask.js +397 -0
  255. package/neural-interface/public/shared/assistant/asst-brain-picker.js +49 -35
  256. package/neural-interface/public/shared/assistant/asst-control.js +157 -26
  257. package/neural-interface/public/shared/assistant/asst-followups-card.js +383 -0
  258. package/neural-interface/public/shared/assistant/asst-followups.js +417 -0
  259. package/neural-interface/public/shared/assistant/asst-limit-dock.js +40 -0
  260. package/neural-interface/public/shared/assistant/asst-limit-wait.js +294 -0
  261. package/neural-interface/public/shared/assistant/asst-limit.js +168 -0
  262. package/neural-interface/public/shared/assistant/asst-mascot.js +49 -12
  263. package/neural-interface/public/shared/assistant/asst-menu.js +7 -6
  264. package/neural-interface/public/shared/assistant/asst-panel.js +106 -11
  265. package/neural-interface/public/shared/assistant/asst-rack-styles.js +66 -49
  266. package/neural-interface/public/shared/assistant/asst-render.js +401 -77
  267. package/neural-interface/public/shared/assistant/asst-route.js +83 -12
  268. package/neural-interface/public/shared/assistant/asst-scenes.js +2 -0
  269. package/neural-interface/public/shared/assistant/asst-sidepanel.js +67 -4
  270. package/neural-interface/public/shared/assistant/asst-slash.js +9 -7
  271. package/neural-interface/public/shared/assistant/asst-state.js +11 -15
  272. package/neural-interface/public/shared/assistant/asst-stop.js +127 -0
  273. package/neural-interface/public/shared/assistant/asst-styles.js +59 -21
  274. package/neural-interface/public/shared/assistant/asst-tool-kinds.js +156 -16
  275. package/neural-interface/public/shared/automation-context.js +5 -2
  276. package/neural-interface/public/shared/cc-dropdown.js +89 -19
  277. package/neural-interface/public/shared/cdx/cdx-context-menu.js +10 -9
  278. package/neural-interface/public/shared/cdx/cdx-copy.js +16 -0
  279. package/neural-interface/public/shared/cdx/cdx-output-model.js +22 -1
  280. package/neural-interface/public/shared/cdx/cdx-output.js +8 -7
  281. package/neural-interface/public/shared/cdx/cdx-panel.js +45 -149
  282. package/neural-interface/public/shared/cdx/cdx-protocol.js +28 -1
  283. package/neural-interface/public/shared/cdx/cdx-render.js +47 -29
  284. package/neural-interface/public/shared/cdx/cdx-requests.js +3 -3
  285. package/neural-interface/public/shared/cdx/cdx-skill-hints.js +54 -0
  286. package/neural-interface/public/shared/cdx/cdx-styles.js +11 -3
  287. package/neural-interface/public/shared/cdx/cdx-tabs.js +52 -39
  288. package/neural-interface/public/shared/cdx/cdx-ws.js +0 -1
  289. package/neural-interface/public/shared/cli-install-view.js +4 -8
  290. package/neural-interface/public/shared/cli-status.js +2 -2
  291. package/neural-interface/public/shared/constants.js +2 -2
  292. package/neural-interface/public/shared/context-menu-areas.js +34 -0
  293. package/neural-interface/public/shared/context-menu-logic.js +243 -0
  294. package/neural-interface/public/shared/context-menu-model.js +366 -0
  295. package/neural-interface/public/shared/context-menu.js +372 -0
  296. package/neural-interface/public/shared/cp/cp-context-menu.js +10 -9
  297. package/neural-interface/public/shared/crash-notice-view.js +168 -0
  298. package/neural-interface/public/shared/desktop-update-view.js +20 -0
  299. package/neural-interface/public/shared/editor/editor-panel-logic.js +2 -2
  300. package/neural-interface/public/shared/html-shell.js +9 -11
  301. package/neural-interface/public/shared/i18n.js +2 -0
  302. package/neural-interface/public/shared/ocp-v2/ocp-v2-approvals.js +7 -7
  303. package/neural-interface/public/shared/ocp-v2/ocp-v2-binding.js +4 -4
  304. package/neural-interface/public/shared/ocp-v2/ocp-v2-changes-logic.js +3 -101
  305. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +2 -0
  306. package/neural-interface/public/shared/ocp-v2/ocp-v2-compact-button.js +1 -3
  307. package/neural-interface/public/shared/ocp-v2/ocp-v2-composer-logic.js +2 -6
  308. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-menu.js +11 -11
  309. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-model.js +0 -3
  310. package/neural-interface/public/shared/ocp-v2/ocp-v2-events.js +8 -4
  311. package/neural-interface/public/shared/ocp-v2/ocp-v2-manager.js +7 -7
  312. package/neural-interface/public/shared/ocp-v2/ocp-v2-outcome-notifications.js +16 -0
  313. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +47 -252
  314. package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +1 -2
  315. package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +95 -202
  316. package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +6 -21
  317. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +4 -4
  318. package/neural-interface/public/shared/ocp-v2/ocp-v2-session-actions.js +8 -61
  319. package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +2 -91
  320. package/neural-interface/public/shared/ocp-v2/ocp-v2-slash-hints.js +16 -15
  321. package/neural-interface/public/shared/ocp-v2/ocp-v2-state.js +8 -21
  322. package/neural-interface/public/shared/ocp-v2/ocp-v2-status-logic.js +1 -99
  323. package/neural-interface/public/shared/ocp-v2/ocp-v2-status.js +5 -35
  324. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +0 -21
  325. package/neural-interface/public/shared/ocp-v2/{ocp-v2-profile-inheritance.js → ocp-v2-tools-inheritance.js} +16 -16
  326. package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +14 -47
  327. package/neural-interface/public/shared/page-session.js +96 -0
  328. package/neural-interface/public/shared/registry.js +5 -3
  329. package/neural-interface/public/shared/retired-2d.js +3 -0
  330. package/neural-interface/public/shared/schedules-view.js +195 -61
  331. package/neural-interface/public/shared/settings/settings-claude-hooks.js +135 -0
  332. package/neural-interface/public/shared/settings/settings-data.js +3 -1
  333. package/neural-interface/public/shared/settings/settings-ia.js +6 -6
  334. package/neural-interface/public/shared/settings/settings-opencode.js +89 -0
  335. package/neural-interface/public/shared/settings/settings-skill-folders-pane.js +265 -0
  336. package/neural-interface/public/shared/settings/settings-skill-folders.js +130 -0
  337. package/neural-interface/public/shared/settings/settings-worker-guard.js +72 -0
  338. package/neural-interface/public/shared/skills/ss-args.js +96 -0
  339. package/neural-interface/public/shared/skills/ss-creation.js +219 -0
  340. package/neural-interface/public/shared/skills/ss-dialog.js +130 -0
  341. package/neural-interface/public/shared/skills/ss-doc.js +173 -0
  342. package/neural-interface/public/shared/skills/ss-eval-adapters.js +269 -0
  343. package/neural-interface/public/shared/skills/ss-eval-grade.js +359 -0
  344. package/neural-interface/public/shared/skills/ss-eval-optimise.js +153 -0
  345. package/neural-interface/public/shared/skills/ss-eval-plan.js +315 -0
  346. package/neural-interface/public/shared/skills/ss-evals.js +417 -0
  347. package/neural-interface/public/shared/skills/ss-form.js +159 -0
  348. package/neural-interface/public/shared/skills/ss-frontmatter.js +376 -0
  349. package/neural-interface/public/shared/skills/ss-ids.js +32 -0
  350. package/neural-interface/public/shared/skills/ss-lint.js +141 -0
  351. package/neural-interface/public/shared/skills/ss-presets.js +117 -0
  352. package/neural-interface/public/shared/skills/ss-profiles.js +475 -0
  353. package/neural-interface/public/shared/skills/ss-resources.js +165 -0
  354. package/neural-interface/public/shared/skills/ss-review-view.js +190 -0
  355. package/neural-interface/public/shared/skills/ss-tabs.js +79 -0
  356. package/neural-interface/public/shared/skills/ss-unicode.js +135 -0
  357. package/neural-interface/public/shared/skills/studio/sx-actions.js +222 -0
  358. package/neural-interface/public/shared/skills/studio/sx-cm.js +101 -0
  359. package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +749 -0
  360. package/neural-interface/public/shared/skills/studio/sx-create-ai.js +236 -0
  361. package/neural-interface/public/shared/skills/studio/sx-create-view.js +254 -0
  362. package/neural-interface/public/shared/skills/studio/sx-create.js +126 -0
  363. package/neural-interface/public/shared/skills/studio/sx-diff-view.js +43 -0
  364. package/neural-interface/public/shared/skills/studio/sx-diff.js +133 -0
  365. package/neural-interface/public/shared/skills/studio/sx-docs.js +480 -0
  366. package/neural-interface/public/shared/skills/studio/sx-dom.js +229 -0
  367. package/neural-interface/public/shared/skills/studio/sx-edit-view.js +848 -0
  368. package/neural-interface/public/shared/skills/studio/sx-editor-model.js +193 -0
  369. package/neural-interface/public/shared/skills/studio/sx-errors.js +22 -0
  370. package/neural-interface/public/shared/skills/studio/sx-geometry.js +82 -0
  371. package/neural-interface/public/shared/skills/studio/sx-import.js +262 -0
  372. package/neural-interface/public/shared/skills/studio/sx-inspector.js +308 -0
  373. package/neural-interface/public/shared/skills/studio/sx-install-flow.js +279 -0
  374. package/neural-interface/public/shared/skills/studio/sx-install.js +296 -0
  375. package/neural-interface/public/shared/skills/studio/sx-library-view.js +639 -0
  376. package/neural-interface/public/shared/skills/studio/sx-library.js +475 -0
  377. package/neural-interface/public/shared/skills/studio/sx-main.js +681 -0
  378. package/neural-interface/public/shared/skills/studio/sx-operations-view.js +98 -0
  379. package/neural-interface/public/shared/skills/studio/sx-operations.js +11 -0
  380. package/neural-interface/public/shared/skills/studio/sx-plan.js +158 -0
  381. package/neural-interface/public/shared/skills/studio/sx-publish-view.js +621 -0
  382. package/neural-interface/public/shared/skills/studio/sx-review-view.js +369 -0
  383. package/neural-interface/public/shared/skills/studio/sx-review.js +148 -0
  384. package/neural-interface/public/shared/skills/studio/sx-scan.js +35 -0
  385. package/neural-interface/public/shared/skills/studio/sx-snippets.js +96 -0
  386. package/neural-interface/public/shared/skills/studio/sx-subject.js +248 -0
  387. package/neural-interface/public/shared/skills/studio/sx-test-view.js +994 -0
  388. package/neural-interface/public/shared/skills/studio/sx-test.js +328 -0
  389. package/neural-interface/public/shared/skills/studio/sx-versions-view.js +241 -0
  390. package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +425 -0
  391. package/neural-interface/public/shared/styleguide/sg-panel.js +4 -2
  392. package/neural-interface/public/shared/styles.css +1525 -1779
  393. package/neural-interface/public/shared/synabun-mascot.js +1115 -9
  394. package/neural-interface/public/shared/tool-list-picker.js +55 -0
  395. package/neural-interface/public/shared/tool-list-storage.js +24 -0
  396. package/neural-interface/public/shared/tool-list-view.js +112 -0
  397. package/neural-interface/public/shared/tour/tour-actor.js +268 -0
  398. package/neural-interface/public/shared/tour/tour-beats.js +336 -0
  399. package/neural-interface/public/shared/tour/tour-engine.js +884 -0
  400. package/neural-interface/public/shared/tour/tour-ink.js +390 -0
  401. package/neural-interface/public/shared/tour/tour-stage.js +440 -0
  402. package/neural-interface/public/shared/tour/tour-state.js +40 -0
  403. package/neural-interface/public/shared/tour/tour-tips.js +99 -0
  404. package/neural-interface/public/shared/tour/tour.css +144 -0
  405. package/neural-interface/public/shared/ui-automation-studio.js +91 -128
  406. package/neural-interface/public/shared/ui-claude-panel.js +77 -5
  407. package/neural-interface/public/shared/ui-command-runner.js +6 -3
  408. package/neural-interface/public/shared/ui-context-menu.js +295 -0
  409. package/neural-interface/public/shared/ui-cost-widget.js +57 -59
  410. package/neural-interface/public/shared/ui-crash-notice.js +187 -0
  411. package/neural-interface/public/shared/ui-detail.js +15 -3
  412. package/neural-interface/public/shared/ui-image-gallery.js +50 -47
  413. package/neural-interface/public/shared/ui-keybinds.js +26 -1
  414. package/neural-interface/public/shared/ui-menubar.js +8 -18
  415. package/neural-interface/public/shared/ui-native-loop-router-state.js +5 -0
  416. package/neural-interface/public/shared/ui-native-loop-router.js +7 -1
  417. package/neural-interface/public/shared/ui-navbar.js +4 -24
  418. package/neural-interface/public/shared/ui-panels.js +96 -65
  419. package/neural-interface/public/shared/ui-schedules-studio.js +507 -423
  420. package/neural-interface/public/shared/ui-sessions.js +5 -3
  421. package/neural-interface/public/shared/ui-settings.js +594 -462
  422. package/neural-interface/public/shared/ui-sidepanel-sessions.js +1 -1
  423. package/neural-interface/public/shared/ui-sidepanel-state.js +23 -12
  424. package/neural-interface/public/shared/ui-sidepanel-windows.js +16 -11
  425. package/neural-interface/public/shared/ui-skills.js +33 -2830
  426. package/neural-interface/public/shared/ui-styleguide.js +5 -2
  427. package/neural-interface/public/shared/ui-sync.js +15 -5
  428. package/neural-interface/public/shared/ui-terminal.js +124 -180
  429. package/neural-interface/public/shared/ui-tool-updates.js +3 -1
  430. package/neural-interface/public/shared/ui-tooltip.js +10 -5
  431. package/neural-interface/public/shared/ui-trash.js +6 -4
  432. package/neural-interface/public/shared/ui-tutorial-layout.js +3 -117
  433. package/neural-interface/public/shared/ui-tutorial-preview.js +103 -0
  434. package/neural-interface/public/shared/ui-tutorial-steps.js +3 -65
  435. package/neural-interface/public/shared/ui-tutorial.css +47 -100
  436. package/neural-interface/public/shared/ui-tutorial.js +285 -509
  437. package/neural-interface/public/shared/ui-update.js +38 -2
  438. package/neural-interface/public/shared/ui-whiteboard.js +311 -58
  439. package/neural-interface/public/shared/ui-worker-end.js +4 -0
  440. package/neural-interface/public/shared/ui-workspaces.js +3 -2
  441. package/neural-interface/public/shared/view-variant.js +66 -0
  442. package/neural-interface/public/shared/whatsapp/wa-view.js +1 -1
  443. package/neural-interface/public/shared/whiteboard-list.js +172 -0
  444. package/neural-interface/public/shared/worker-end.js +10 -3
  445. package/neural-interface/public/shared/worker-restart.js +12 -0
  446. package/neural-interface/public/sidepanel-session.html +1 -1
  447. package/neural-interface/public/variant/2d/background.js +2 -1
  448. package/neural-interface/public/variant/2d/context-menu.js +8 -2
  449. package/neural-interface/public/variant/2d/graph.js +42 -20
  450. package/neural-interface/public/variant/2d/hulls.js +14 -9
  451. package/neural-interface/public/variant/2d/lasso.js +11 -7
  452. package/neural-interface/public/variant/2d/main.js +32 -1
  453. package/neural-interface/public/variant/2d/minimap.js +11 -13
  454. package/neural-interface/public/variant/3d/main.js +69 -6
  455. package/neural-interface/public/variant/3d/map-controls.js +24 -9
  456. package/neural-interface/public/vendor/caveat/OFL.txt +93 -0
  457. package/neural-interface/public/vendor/caveat/caveat-latin-400-normal.woff2 +0 -0
  458. package/neural-interface/public/vendor/caveat/caveat-latin-700-normal.woff2 +0 -0
  459. package/neural-interface/public/vendor/caveat/caveat.css +17 -0
  460. package/neural-interface/public/vendor/caveat/manifest.json +12 -0
  461. package/neural-interface/public/vendor/yaml/LICENSE +13 -0
  462. package/neural-interface/public/vendor/yaml/manifest.json +4 -0
  463. package/neural-interface/public/vendor/yaml/yaml-2.9.1.min.js +137 -0
  464. package/neural-interface/scripts/build-vendor.mjs +32 -0
  465. package/neural-interface/server.js +3934 -2454
  466. package/neural-interface/templates/rulesets/core.md +1 -1
  467. package/neural-interface/templates/rulesets/legacy-hashes.json +18 -0
  468. package/neural-interface/templates/rulesets/manifest.json +8 -8
  469. package/npm-shrinkwrap.json +18 -12
  470. package/package.json +16 -3
  471. package/postinstall.js +9 -4
  472. package/preuninstall.js +1 -1
  473. package/setup.js +97 -322
  474. package/skills/skill-forge/SKILL.md +177 -0
  475. package/skills/skill-forge/evals/evals.json +54 -0
  476. package/skills/skill-forge/references/package.md +105 -0
  477. package/skills/skill-forge/references/review-and-recovery.md +63 -0
  478. package/skills/skill-forge/references/runtime-profiles.md +20 -0
  479. package/skills/skill-forge/references/sources-and-capabilities.md +51 -0
  480. package/skills/synabun/SKILL.md +10 -7
  481. package/skills/synabun/modules/audit.md +1 -5
  482. package/skills/synabun/modules/changelog.md +1 -5
  483. package/skills/synabun/modules/idea.md +1 -1
  484. package/skills/synabun/modules/memorize.md +6 -9
  485. package/skills/synabun/modules/schedule.md +4 -4
  486. package/mcp-server/dist/services/profiles.d.ts +0 -120
  487. package/mcp-server/dist/services/profiles.d.ts.map +0 -1
  488. package/mcp-server/dist/services/profiles.js +0 -387
  489. package/mcp-server/dist/services/profiles.js.map +0 -1
  490. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +0 -97
  491. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +0 -1
  492. package/mcp-server/dist/tools/leonardo-browser-tools.js +0 -228
  493. package/mcp-server/dist/tools/leonardo-browser-tools.js.map +0 -1
  494. package/mcp-server/dist/tools/leonardo.d.ts +0 -13
  495. package/mcp-server/dist/tools/leonardo.d.ts.map +0 -1
  496. package/mcp-server/dist/tools/leonardo.js +0 -21
  497. package/mcp-server/dist/tools/leonardo.js.map +0 -1
  498. package/mcp-server/dist/tools/profile.d.ts +0 -17
  499. package/mcp-server/dist/tools/profile.d.ts.map +0 -1
  500. package/mcp-server/dist/tools/profile.js +0 -114
  501. package/mcp-server/dist/tools/profile.js.map +0 -1
  502. package/mcp-server/src/services/profiles.ts +0 -428
  503. package/mcp-server/src/tools/leonardo-browser-tools.ts +0 -291
  504. package/mcp-server/src/tools/leonardo.ts +0 -30
  505. package/mcp-server/src/tools/profile.ts +0 -122
  506. package/neural-interface/lib/assistant-brains/opencode-browser-policy.js +0 -47
  507. package/neural-interface/lib/assistant-brains/opencode-route-gate.js +0 -62
  508. package/neural-interface/lib/mcp-profile-servers.js +0 -120
  509. package/neural-interface/public/shared/ui-tutorial-draw.js +0 -311
  510. package/skills/leonardo/SKILL.md +0 -168
  511. package/skills/leonardo/icon.svg +0 -1
  512. package/skills/leonardo/modules/browser-guide.md +0 -378
  513. package/skills/leonardo/modules/image-prompter.md +0 -283
  514. package/skills/leonardo/modules/model-advisor.md +0 -100
  515. package/skills/leonardo/modules/prompt-library.md +0 -110
  516. package/skills/leonardo/modules/style-guide.md +0 -186
  517. package/skills/leonardo/modules/video-prompter.md +0 -317
@@ -0,0 +1,296 @@
1
+ // ═══════════════════════════════════════════
2
+ // SynaBun Neural Interface — Skills Studio 2.0: the simple install flow, as data
3
+ // ═══════════════════════════════════════════
4
+ //
5
+ // Installing an approved skill is one decision (where) and one press (Install). This module decides, without a
6
+ // page: the one status a library skill shows everywhere (the workspace header, its Library row, the banner), what
7
+ // is ticked when Publish opens (the review's targets, else where the skill already is, else Claude Code for every
8
+ // project: never everything), the simple picker (one tile per runtime in one scope; everything else, accounts,
9
+ // the shared folder, other projects, lives under Advanced and is only reported here), the version picked by
10
+ // default (the approved one when the latest was made by an agent and is not approved), the one line each target
11
+ // of a plan gets (what will happen there, as a code the view words), what an install must ask first (a folder
12
+ // SynaBun did not install or that changed since, the scan's findings) and never asks otherwise, the words of the
13
+ // one button, and the outcome of an install. The plan and the install themselves stay the service's
14
+ // (lib/skills/deploy.js) through sx-plan.js: nothing here changes what is sent, only what is asked and shown.
15
+ // No DOM; imports sx-subject.js and sx-plan.js only.
16
+
17
+ import { targetKey, targetState, defaultTargets, seenThrough } from './sx-subject.js';
18
+ import { installableRows, decisionsOf } from './sx-plan.js';
19
+
20
+ export const STATUS_CODES = Object.freeze(['draft', 'review', 'changes', 'approved', 'installed', 'outdated', 'none']);
21
+ export const LINE_CODES = Object.freeze(['create', 'replace-owned', 'replace-modified', 'replace-unowned', 'identical', 'blocked']);
22
+ // What a tile says of a runtime: the target's state, 'via-claude' when OpenCode sees the skill through Claude Code's
23
+ // folder (ticked, or holding it) and is not ticked itself, 'unavailable' when there is no folder for it here.
24
+ export const TILE_STATES = Object.freeze(['installed', 'outdated', 'present', 'bridge', 'none', 'off', 'unavailable', 'via-claude', 'not-installed']);
25
+
26
+ /** The runtimes that are installed on this computer (the status' `assistants.installed`), or null when not known. */
27
+ export function installedRuntimesOf(source) {
28
+ const list_ = source?.assistants?.installed ?? source?.installed ?? null;
29
+ return Array.isArray(list_) ? list_.filter((r) => typeof r === 'string') : null;
30
+ }
31
+
32
+ /**
33
+ * "Also install for Codex · OpenCode": the assistants in effect (user scope, default account) that do not have a
34
+ * skill that is installed somewhere already; empty when nothing is missing, when nothing is installed yet (Publish
35
+ * is the way), or when the skill is not a library skill. A runtime known not to be installed here is left out.
36
+ * @param {{ skill?: object|null, row?: object|null, targets: object[], assistants?: string[]|null, installed?: string[]|null }} o
37
+ * @returns {object[]} targets of installTargets()
38
+ */
39
+ export function alsoInstallTargets({ skill = null, row = null, targets = [], assistants = null, installed = null } = {}) {
40
+ if (!skill || row?.source === 'synabun' || !list(skill.installations).length) return [];
41
+ const wanted = Array.isArray(assistants) && assistants.length ? assistants : [];
42
+ return SIMPLE_RUNTIMES.filter((r) => wanted.includes(r) && !(Array.isArray(installed) && !installed.includes(r)))
43
+ .map((r) => list(targets).find((t) => t.key === keyIn(r, 'user')) || null)
44
+ .filter((t) => t && !t.off && !['installed', 'outdated', 'present'].includes(targetState(t, { skill, row }).state));
45
+ }
46
+
47
+ /**
48
+ * The version "Also install for …" sends: the one the installations hold (the one most of them hold when they
49
+ * differ; on a tie the approved one, then the latest), else the approved one, else the latest; null for none.
50
+ */
51
+ export function alsoInstallRevision(skill) {
52
+ const held = list(skill?.installations).map((i) => i?.sourceRevisionId).filter((r) => typeof r === 'string' && r);
53
+ const pointers = skill?.pointers || {};
54
+ if (!held.length) return pointers.approved || pointers.latest || null;
55
+ const count = new Map();
56
+ for (const r of held) count.set(r, (count.get(r) || 0) + 1);
57
+ const rank = (r) => (r === pointers.approved ? 2 : r === pointers.latest ? 1 : 0);
58
+ return [...count.entries()].sort((a, b) => b[1] - a[1] || rank(b[0]) - rank(a[0]) || held.indexOf(a[0]) - held.indexOf(b[0]))[0][0];
59
+ }
60
+ export const BUTTON_CODES = Object.freeze(['install', 'update', 'installed', 'checking', 'installing', 'nothing', 'blocked']);
61
+ export const SIMPLE_RUNTIMES = Object.freeze(['claude', 'codex', 'opencode']);
62
+ const APPROVED_STATES = ['approved', 'partial', 'publish_failed'];
63
+
64
+ const list = (v) => (Array.isArray(v) ? v : []);
65
+
66
+ /** Where an installation is, as a target (the view words it: "Claude Code · all projects"). */
67
+ export function whereOf(i) {
68
+ const scope = i?.scope === 'project' ? 'project' : 'user';
69
+ return { runtime: i?.runtime || 'claude', scope, projectPath: scope === 'project' ? i.projectPath || null : null, accountId: scope === 'user' ? i?.accountId || 'default' : 'default', outdated: !!i?.updateAvailable };
70
+ }
71
+
72
+ /**
73
+ * The one status of a library skill: draft (no version yet), in review, changes asked for, approved but not
74
+ * installed, installed (where), installed with an update available, or not installed. Null for what is not a
75
+ * library skill (a plugin's, SynaBun's own, a folder not adopted): those keep their source and health.
76
+ * @param {{ skill?: object|null, row?: object|null }} o the library summary (GET /skills) and its Library row
77
+ */
78
+ export function installStatus({ skill = null, row = null } = {}) {
79
+ if (!skill || row?.source === 'synabun') return null;
80
+ const installs = list(skill.installations);
81
+ const review = row?.review || null;
82
+ const reviewState = review?.state || null;
83
+ if (installs.length) {
84
+ const outdated = !row?.keptUpdate && installs.some((i) => !!i.updateAvailable);
85
+ return { code: outdated ? 'outdated' : 'installed', where: installs.map(whereOf), reviewState, reviewId: review?.reviewId || null };
86
+ }
87
+ if (reviewState === 'pending') return { code: 'review', where: [], reviewState, reviewId: review.reviewId };
88
+ if (reviewState === 'changes_requested') return { code: 'changes', where: [], reviewState, reviewId: review.reviewId };
89
+ if (APPROVED_STATES.includes(reviewState)) return { code: 'approved', where: [], reviewState, reviewId: review.reviewId };
90
+ if (!skill.revisions) return { code: 'draft', where: [], reviewState: null, reviewId: null };
91
+ return { code: 'none', where: [], reviewState: null, reviewId: null };
92
+ }
93
+
94
+ /**
95
+ * What is ticked when Publish opens: the targets the review named (those that exist and are on), else where the
96
+ * skill already is, else the owner's assistants (sx-subject.js defaultTargets: never everything, no second copy
97
+ * for a runtime that reads a ticked folder).
98
+ * @param {{ review?: object|null, targets: object[], skill?: object|null, row?: object|null, assistants?: string[]|null }} o targets: sx-subject.js installTargets()
99
+ * @returns {Set<string>} target keys
100
+ */
101
+ export function defaultSelection({ review = null, targets = [], skill = null, row = null, assistants = null } = {}) {
102
+ const named = list(review?.targets).filter((x) => x && typeof x.runtime === 'string');
103
+ const keys = new Set(named.map((x) => targetKey(x)));
104
+ const fromReview = targets.filter((x) => !x.off && keys.has(x.key)).map((x) => x.key);
105
+ if (fromReview.length) return new Set(fromReview);
106
+ // The review named targets and none of them is here (another computer's project, the shared folder off): nothing
107
+ // is ticked, and the view says what is missing; never a silent fallback to the assistants.
108
+ if (named.length) return new Set();
109
+ return defaultTargets(targets, { skill, row, assistants });
110
+ }
111
+
112
+ /** The assistants in effect (GET /v2/config or /status `assistants.effective`), or null when the server has none. */
113
+ export function assistantsOf(source) {
114
+ const list_ = source?.assistants?.effective ?? source?.effective ?? null;
115
+ return Array.isArray(list_) && list_.length ? list_.filter((r) => typeof r === 'string') : null;
116
+ }
117
+
118
+ /** The scope a selection sits in: 'user', 'project:<path>' when every ticked target is of one project, else null (mixed). */
119
+ export function scopeOf(checked, targets) {
120
+ const picked = list(targets).filter((t) => checked?.has?.(t.key));
121
+ const scopes = new Set(picked.map((t) => (t.scope === 'project' ? `project:${t.projectPath}` : 'user')));
122
+ if (scopes.size === 1) return [...scopes][0];
123
+ return scopes.size ? null : 'user';
124
+ }
125
+
126
+ /** The key of a runtime's target in a scope ('user' or 'project:<path>'), the default account. */
127
+ export const keyIn = (runtime, scope) => (scope && scope.startsWith('project:') ? `${runtime}:project:${scope.slice(8)}` : `${runtime}:user:default`);
128
+
129
+ /**
130
+ * The simple picker: one tile per runtime for the scope chosen (ticked or not, what is there now), and whatever
131
+ * else is ticked (another account, the shared folder, another project: changed under Advanced only).
132
+ * @param {{ targets: object[], checked: Set<string>, scope: string, skill?: object|null, row?: object|null, revisionId?: string|null }} o
133
+ */
134
+ export function simplePicker({ targets = [], checked = new Set(), scope = 'user', skill = null, row = null, revisionId = null, installed = null } = {}) {
135
+ const tiles = SIMPLE_RUNTIMES.map((runtime) => {
136
+ const key = keyIn(runtime, scope);
137
+ const target = list(targets).find((t) => t.key === key) || null;
138
+ const st = target ? targetState(target, { skill, row, revisionId }) : { state: 'none', path: null };
139
+ const on = !!target && checked.has(key);
140
+ const available = !!target && !target.off;
141
+ // A terminal OpenCode reads Claude Code's folder: with that one ticked (or holding the skill) and OpenCode not
142
+ // ticked, the tile says so; SynaBun's own OpenCode panel does not read it, so the tile also says a copy is needed.
143
+ const via = available && !on && st.state === 'none' ? seenThrough(runtime, list(targets), checked, { scope, skill, row }) : null;
144
+ // A runtime the resolver did not find on this computer: said on the tile (the folder can still be written for a
145
+ // later install of the runtime; nothing fails), never ticked by default (the detected assistants leave it out).
146
+ const notInstalled = Array.isArray(installed) && !installed.includes(runtime);
147
+ const tileState = !available ? 'unavailable' : notInstalled && st.state === 'none' ? 'not-installed' : via ? 'via-claude' : st.state;
148
+ return { runtime, key, target, on, available, state: target ? st.state : 'none', path: st.path || target?.path || null, via, notInstalled, tileState };
149
+ });
150
+ const own = new Set(tiles.map((x) => x.key));
151
+ // What is ticked beyond the tiles, and would be sent: a target that is off (the shared folder turned off in
152
+ // Settings) is never sent, so it is neither counted nor listed.
153
+ const extra = list(targets).filter((t) => checked.has(t.key) && !own.has(t.key) && !t.off);
154
+ return { tiles, extra };
155
+ }
156
+
157
+ /** The selection moved to another scope: each ticked tile of `from` is ticked in `to` instead; the rest stays. */
158
+ export function moveScope(checked, from, to) {
159
+ const next = new Set();
160
+ for (const key of checked || []) {
161
+ const runtime = SIMPLE_RUNTIMES.find((r) => key === keyIn(r, from));
162
+ next.add(runtime ? keyIn(runtime, to) : key);
163
+ }
164
+ return next;
165
+ }
166
+
167
+ /**
168
+ * The version Publish picks by default: the one asked for, else what SynaBun ships for its own skill, else the
169
+ * latest, unless the latest was made by an agent and is not the approved one (then the approved one: the latest
170
+ * would be refused until it is reviewed).
171
+ * @param {{ skill?: object|null, revisions?: object[], bundled?: boolean, asked?: string|null }} o
172
+ */
173
+ export function defaultRevisionId({ skill = null, revisions = [], bundled = false, asked = null } = {}) {
174
+ if (asked) return asked;
175
+ const p = skill?.pointers || {};
176
+ if (bundled) return p.upstream || p.approved || p.latest || null;
177
+ const latest = list(revisions).find((r) => r.revisionId === p.latest) || null;
178
+ const agentMade = !!latest && ['assistant', 'agent'].includes(latest.author?.kind);
179
+ if (agentMade && p.approved && p.approved !== p.latest) return p.approved;
180
+ return p.latest || p.approved || null;
181
+ }
182
+
183
+ /** The one plain label of a version in the install path (the rest, candidate and best, stay in Versions). */
184
+ export function plainLabel(labels) {
185
+ const l = list(labels);
186
+ if (l.includes('approved')) return 'approved';
187
+ if (l.includes('upstream')) return 'upstream';
188
+ if (l.includes('latest')) return 'latest';
189
+ return null;
190
+ }
191
+
192
+ /**
193
+ * One line per target of a plan (sx-plan.js planModel): what will happen there, as a code. `asks` says what the
194
+ * owner is asked before it goes (a folder to replace, the scan's findings); `notes` are secondary facts.
195
+ */
196
+ export function planLines(model) {
197
+ return list(model?.rows).map((row) => {
198
+ let code = 'create';
199
+ if (row.blocked.length) code = 'blocked';
200
+ else if (row.state === 'identical') code = 'identical';
201
+ else if (row.replace) code = row.replace.state === 'modified' ? 'replace-modified' : 'replace-unowned';
202
+ else if (row.state === 'owned') code = 'replace-owned';
203
+ return {
204
+ targetKey: row.targetKey, runtime: row.runtime, scope: row.scope, accountId: row.accountId, projectPath: row.projectPath,
205
+ code, destination: row.destination || null,
206
+ blocked: row.blocked, asks: { replace: !!row.replace, scan: !!row.scanAck },
207
+ alsoReadBy: row.affectedRuntimes.filter((r) => r !== row.runtime),
208
+ overlap: row.overlap, transforms: row.transforms, refresh: row.refresh, name: row.name || '',
209
+ // The runtimes whose own settings turn a skill of this name off here (the view offers "Enable for …").
210
+ disabledFor: Object.entries(row.eligibility || {}).filter(([, e]) => e.state === 'disabled').map(([runtime, e]) => ({ runtime, reason: e.reason })),
211
+ unknownFor: Object.entries(row.eligibility || {}).filter(([, e]) => e.state === 'unknown' && e.reason).map(([runtime, e]) => ({ runtime, reason: e.reason })),
212
+ };
213
+ });
214
+ }
215
+
216
+ /**
217
+ * What an install must ask first, and nothing else: the folders to replace (not SynaBun's, or changed since) and
218
+ * the scan findings to read; what is blocked is said, never asked; the rest goes without a question.
219
+ * @returns {{ replace: object[], scan: object[], blocked: object[], ready: object[], decisions: object }} decisions:
220
+ * what the install sends when the owner confirms everything asked (sx-plan.js decisionsOf)
221
+ */
222
+ export function confirmations(model) {
223
+ const rows = list(model?.rows);
224
+ const replace = rows.filter((r) => !r.blocked.length && r.replace);
225
+ const scan = rows.filter((r) => !r.blocked.length && r.scanAck);
226
+ const blocked = rows.filter((r) => r.blocked.length);
227
+ const keys = { replace: replace.map((r) => r.targetKey), scan: scan.map((r) => r.targetKey) };
228
+ return { replace, scan, blocked, ready: installableRows(model, keys), decisions: decisionsOf(model, keys) };
229
+ }
230
+
231
+ /**
232
+ * The one button: its code and whether it can be pressed.
233
+ * @param {{ picked: number, states?: string[], model?: object|null, checking?: boolean, busy?: boolean, error?: boolean }} o
234
+ * picked: how many targets are ticked; states: what each ticked target has now (targetState); model: the plan
235
+ */
236
+ export function installButton({ picked = 0, states = [], model = null, checking = false, busy = false, error = false } = {}) {
237
+ if (busy) return { code: 'installing', enabled: false };
238
+ if (!picked) return { code: 'nothing', enabled: false };
239
+ if (checking || (!model && !error)) return { code: 'checking', enabled: false };
240
+ if (error) return { code: 'install', enabled: false };
241
+ const rows = list(model?.rows);
242
+ if (rows.length && rows.every((r) => r.blocked.length)) return { code: 'blocked', enabled: false };
243
+ if (rows.length && rows.every((r) => r.blocked.length || r.state === 'identical')) return { code: 'installed', enabled: false };
244
+ return { code: states.includes('outdated') ? 'update' : 'install', enabled: true };
245
+ }
246
+
247
+ /** An install's outcome (sx-plan.js resultModel), summed up: where it went, where it did not, how sessions pick it up. */
248
+ export function installOutcome(results) {
249
+ const rows = list(results);
250
+ const ok = rows.filter((r) => r.status === 'committed');
251
+ const failed = rows.filter((r) => r.status !== 'committed');
252
+ const refresh = [];
253
+ for (const r of ok) for (const x of r.refresh) if (x.kind !== 'automatic' && !refresh.some((y) => y.runtime === x.runtime && y.kind === x.kind)) refresh.push({ runtime: x.runtime, kind: x.kind });
254
+ return { ok: ok.map((r) => r.targetKey), failed: failed.map((r) => ({ targetKey: r.targetKey, status: r.status, reason: r.error || r.reasons[0]?.message || '', ...(r.code || r.reasons[0]?.code ? { code: r.code || r.reasons[0].code } : {}) })), refresh, all: rows.length > 0 && !failed.length };
255
+ }
256
+
257
+ /** A target key back as a target ({ runtime, scope, accountId, projectPath }): the words the view gives it. */
258
+ export function parseTargetKey(key) {
259
+ const s = String(key || '');
260
+ const at = s.indexOf(':');
261
+ const runtime = at > 0 ? s.slice(0, at) : s;
262
+ const rest = at > 0 ? s.slice(at + 1) : '';
263
+ if (rest.startsWith('project:')) return { runtime, scope: 'project', projectPath: rest.slice(8), accountId: 'default' };
264
+ return { runtime, scope: 'user', projectPath: null, accountId: rest.startsWith('user:') ? rest.slice(5) || 'default' : 'default' };
265
+ }
266
+
267
+ /**
268
+ * Where a review's install goes, said whole, never a silent fallback: the targets the submission named that exist
269
+ * here and are on (`missing` names each one that does not, with why: no folder for it, or the shared folder turned
270
+ * off); when it named none, where the skill is already installed, else Claude Code for every project (`fallback`
271
+ * says which). When it named targets and none is available, nothing (`targets` empty): the caller refuses and
272
+ * says why, and never installs elsewhere.
273
+ * @param {{ review?: object|null, targets: object[], skill?: object|null, row?: object|null, assistants?: string[]|null }} o targets: installTargets()
274
+ * @returns {{ keys: Set<string>, targets: object[], named: object[], missing: { target: object, reason: 'off'|'missing' }[],
275
+ * fallback: 'installed'|'claude'|'assistants'|null, projects: string[] }}
276
+ */
277
+ export function reviewDestinations({ review = null, targets = [], skill = null, row = null, assistants = null } = {}) {
278
+ const named = list(review?.targets).filter((x) => x && typeof x.runtime === 'string');
279
+ const projects = [...new Set(named.filter((x) => x.scope === 'project' && x.projectPath).map((x) => x.projectPath))];
280
+ const all = list(targets);
281
+ if (named.length) {
282
+ const keys = new Set();
283
+ const missing = [];
284
+ for (const x of named) {
285
+ const key = targetKey(x);
286
+ const have = all.find((t) => t.key === key);
287
+ if (have && !have.off) keys.add(key);
288
+ else missing.push({ target: x, reason: have?.off ? 'off' : 'missing' });
289
+ }
290
+ return { keys, targets: all.filter((t) => keys.has(t.key)).map((t) => t.target), named, missing, fallback: null, projects };
291
+ }
292
+ const there = all.filter((t) => !t.off && ['installed', 'outdated', 'present'].includes(targetState(t, { skill, row }).state));
293
+ const keys = there.length ? new Set(there.map((t) => t.key)) : defaultTargets(all, { skill, row, assistants });
294
+ const onlyClaude = [...keys].every((k) => k === keyIn('claude', 'user'));
295
+ return { keys, targets: all.filter((t) => keys.has(t.key)).map((t) => t.target), named, missing: [], fallback: there.length ? 'installed' : (onlyClaude ? 'claude' : 'assistants'), projects };
296
+ }