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,681 @@
1
+ // ═══════════════════════════════════════════
2
+ // SynaBun Neural Interface — Skills Studio 2.0: the window and its places
3
+ // ═══════════════════════════════════════════
4
+ //
5
+ // The Studio's shell, in Automation Studio's manner (one view machine, one render switch): a window with a rail of
6
+ // three places (Library · Review · Create) and, from a place, one workspace for the skill, agent or command opened
7
+ // (Edit · Test · Versions · Publish). Built on the Skills Service (lib/skills/api-v2.js): the catalog of every
8
+ // runtime folder, the managed library, its drafts, revisions, install plans and the Review queue.
9
+ //
10
+ // The window is non-modal unless the owner dims the background (then the page under it waits, and the keyboard
11
+ // stays in the window); it can be docked beside the side panels so a conversation stays usable next to it; it
12
+ // opens where it was left, at the size it had. Keys reach it only while the focus is in it: Escape closes the
13
+ // topmost thing that is open (a question, a menu), leaves a text field, and only then closes the window, which
14
+ // asks first when something is unsaved. Every answer that arrives after the window closed (or another workspace
15
+ // opened) is dropped. Strings are `skillsStudio.*` (i18n/en.json, pt-BR.json).
16
+
17
+ import { studioErrorText } from './sx-errors.js';
18
+ import { t, tp, getLocale } from '../../i18n.js';
19
+ import { storage } from '../../storage.js';
20
+ import { emit } from '../../state.js';
21
+ import { isGuest, hasPermission, showGuestToast } from '../../ui-sync.js';
22
+ import { KEYS } from '../../constants.js';
23
+ import { createUnloadGuard } from '../../editor/editor-safety.js';
24
+ import { askInPanel, dialogOpen, closeDialog } from '../ss-dialog.js';
25
+ import { closeDropdowns } from '../../cc-dropdown.js';
26
+ import * as api from '../../api.js';
27
+ import { readWholeCatalog, buildRows, countRows, projectsOf, keepSelection } from './sx-library.js';
28
+ import { initialRect, parseOpen } from './sx-geometry.js';
29
+ import { frameRect } from '../../app-frame.js';
30
+ import { updateCards, reviewCount } from './sx-review.js';
31
+ import { newWorkspace, dirtyTabs, saveTab, dropDraft, backups, keptDrafts } from './sx-docs.js';
32
+ import { html, setHTML, ICONS, idempotencyKey, inTextField, focusableIn, trapIndex } from './sx-dom.js';
33
+ import { renderLibraryPlace, focusLibrary, leaveLibraryPlace } from './sx-library-view.js';
34
+ import { renderReviewPlace, leaveReviewPlace, forgetReviewOutcomes } from './sx-review-view.js';
35
+ import { renderCreatePlace, startImport, leaveCreatePlace, openCreation } from './sx-create-view.js';
36
+ import { importFile } from './sx-import.js';
37
+ import { renderWorkspace, closeWorkspaceMenus, workspaceShortcut, disposeWorkspace, disposeStudio, refreshWorkspaceChrome } from './sx-workspace-view.js';
38
+ import { refreshPublishBusy } from './sx-publish-view.js';
39
+ import { leaveTestTab } from './sx-test-view.js';
40
+ import { renderOperationsPlace, leaveOperationsPlace } from './sx-operations-view.js';
41
+ import { onInstallBusy } from './sx-install-flow.js';
42
+
43
+ const PANEL_ID = 'skills-studio-panel';
44
+ const DOCK_KEY = 'skills-studio-docked';
45
+ const DIM_KEY = 'skills-studio-dim';
46
+ const RAIL_KEY = 'skills-studio-rail-collapsed';
47
+ const KEPT_UPDATES_KEY = 'skills-studio-kept-updates';
48
+ const LIB_KEY = 'skills-studio-library-view';
49
+ const MAC = /Mac|iPhone|iPad/.test(globalThis.navigator?.platform || '');
50
+
51
+ // ── State ──
52
+
53
+ const S = {
54
+ panel: null, backdrop: null, gen: 0, life: null, unload: null, opener: null,
55
+ caps: null, capsFailed: false,
56
+ data: null, loading: null, loadError: null,
57
+ rows: [], counts: null, projects: [], updates: [],
58
+ place: 'library', ws: null, workspaces: new Map(),
59
+ lib: { view: 'all', kind: 'all', source: 'all', runtime: 'all', health: 'any', q: '', sort: 'attention', selected: new Set(), focus: null },
60
+ docked: false, dim: false, changeTimer: 0,
61
+ };
62
+ let _cache = null; // what was last read (a later opening paints from it, then reads again behind it)
63
+ let _capsPromise = null;
64
+
65
+ const guest = () => isGuest();
66
+
67
+ function readJson(key, fallback) {
68
+ try { const v = JSON.parse(storage.getItem(key) || 'null'); return v ?? fallback; } catch { return fallback; }
69
+ }
70
+
71
+ // ── Capabilities and data ──
72
+
73
+ /** What the service can do (GET /v2/capabilities), once per page; null while unknown. */
74
+ export function capabilities() {
75
+ if (S.caps) return Promise.resolve(S.caps);
76
+ if (!_capsPromise) {
77
+ _capsPromise = api.fetchSkillsCapabilities()
78
+ .then((res) => { S.caps = new Set(Array.isArray(res?.capabilities) ? res.capabilities.filter((c) => typeof c === 'string') : []); S.capsFailed = false; return S.caps; })
79
+ .catch((err) => { S.capsFailed = true; _capsPromise = null; throw err; });
80
+ }
81
+ return _capsPromise;
82
+ }
83
+
84
+ async function readCatalog() {
85
+ return readWholeCatalog(api.fetchSkillsCatalog);
86
+ }
87
+
88
+ /** What this app version ships of each bundled skill: its upstream revision and the digest of its SKILL.md. */
89
+ async function readUpstream(skills) {
90
+ const out = {};
91
+ for (const s of skills.filter((x) => x.origin?.kind === 'bundled' && x.pointers?.upstream)) {
92
+ try {
93
+ const rev = (await api.fetchSkillsRevision(s.pointers.upstream)).revision;
94
+ const head = (rev?.manifest?.files || []).find((f) => f.path === 'SKILL.md');
95
+ out[String(s.origin.name || s.name).toLowerCase()] = { revisionId: rev.revisionId, headDigest: head?.digest || null };
96
+ } catch { /* an update cannot be told for it: no card */ }
97
+ }
98
+ return out;
99
+ }
100
+
101
+ /** Read everything the Library shows (the catalog, the library, the status, the queue). */
102
+ export function loadData() {
103
+ if (S.loading) return S.loading;
104
+ const run = (async () => {
105
+ await capabilities();
106
+ const [catalog, skills, status, reviews, config, notice, archived] = await Promise.all([
107
+ readCatalog(),
108
+ api.fetchSkillsList().then((r) => r.skills || []),
109
+ api.fetchSkillsStatus().catch(() => null),
110
+ api.fetchSkillsReviews({}).then((r) => r.reviews || []).catch(() => []),
111
+ // The skills settings (the shared folder on or off): what a review's install goes to is decided with them.
112
+ api.fetchSkillsConfig().then((r) => r.config || {}).catch(() => ({ sharedAgentsRoot: false })),
113
+ // The start-up move of the old bridges, said once (a server from before it has no notice: nothing is shown).
114
+ S.caps?.has('auto-migration') ? api.fetchSkillsMigrationNotice().then((r) => r.notice || null).catch(() => null) : Promise.resolve(null),
115
+ // The skills deleted from the library (a server from before Restore lists none).
116
+ S.caps?.has('library-restore') ? api.fetchSkillsArchived().then((r) => (Array.isArray(r.archived) ? r.archived : [])).catch(() => []) : Promise.resolve([]),
117
+ ]);
118
+ const upstream = await readUpstream(skills);
119
+ _cache = { catalog, skills, status, reviews, upstream, config, notice, archived, at: Date.now() };
120
+ return _cache;
121
+ })();
122
+ S.loading = run;
123
+ // Settle the loading state before callers render the fulfilled/rejected request.
124
+ // A chained finally runs after an awaiting caller's catch and could leave the Library stuck on Loading.
125
+ run.then(() => { S.loadError = null; if (S.loading === run) S.loading = null; }, (err) => { S.loadError = err; if (S.loading === run) S.loading = null; });
126
+ return run;
127
+ }
128
+
129
+ function deriveRows() {
130
+ const d = _cache;
131
+ if (!d) { S.rows = []; S.counts = countRows([]); S.projects = []; S.updates = []; return; }
132
+ S.data = d;
133
+ // "Keep mine" is read here once for every place: the rows (health, attention, runtimes), the workspace banner, the
134
+ // Review cards and the rail's count all leave a kept update out.
135
+ const kept = readJson(KEPT_UPDATES_KEY, {});
136
+ S.rows = buildRows({ entries: d.catalog.items, skills: d.skills, status: d.status, reviews: d.reviews.filter((r) => ['pending', 'changes_requested', 'approved', 'partial', 'publish_failed'].includes(r.state)), upstream: d.upstream, kept });
137
+ S.counts = countRows(S.rows);
138
+ S.counts.views.archived = Array.isArray(d.archived) ? d.archived.length : 0;
139
+ S.projects = projectsOf(d.catalog.roots, S.rows);
140
+ S.updates = updateCards(S.rows, kept);
141
+ S.lib.selected = keepSelection(S.lib.selected, S.rows);
142
+ // An open workspace follows its row (a new library state, installations, a review).
143
+ for (const ws of S.workspaces.values()) {
144
+ const row = S.rows.find((r) => r.key === ws.key) || (ws.skill ? S.rows.find((r) => r.skill?.skillId === ws.skill.skillId) : null);
145
+ // The Library's summary is what was just read: its installations and pointers win over what the workspace read
146
+ // earlier (the earlier reading keeps only what the summary lacks, its log).
147
+ if (row) { ws.row = row; if (row.skill) ws.skill = { ...(ws.skill?.skillId === row.skill.skillId ? ws.skill : {}), ...row.skill }; }
148
+ }
149
+ }
150
+
151
+ /** Launch prefetch: the Library read once after the page painted, so the first opening paints at once. */
152
+ export function prefetchStudio() {
153
+ if (_cache || (guest() && !hasPermission('skills'))) return Promise.resolve();
154
+ return loadData().catch(() => {});
155
+ }
156
+
157
+ // ── Opening and closing ──
158
+
159
+ export const isStudioOpen = () => !!S.panel;
160
+
161
+ /**
162
+ * Open the Studio (or bring it forward), going where `detail` says (sx-geometry.js parseOpen).
163
+ * @param {object} [detail]
164
+ */
165
+ export async function openStudio(detail = {}) {
166
+ if (guest() && !hasPermission('skills')) { showGuestToast(t('skillsStudio.guestDisabled')); return; }
167
+ const want = parseOpen(detail);
168
+ if (S.panel) {
169
+ S.panel.focus({ preventScroll: true });
170
+ await navigateTo(want);
171
+ return;
172
+ }
173
+ S.gen++;
174
+ S.opener = document.activeElement instanceof HTMLElement ? document.activeElement : null;
175
+ S.docked = storage.getItem(DOCK_KEY) === 'true';
176
+ S.dim = storage.getItem(DIM_KEY) === 'true' && !S.docked;
177
+ S.lib = { ...S.lib, ...readJson(LIB_KEY, {}), selected: new Set(), focus: null, installNotice: null };
178
+ S.backdrop = document.createElement('div');
179
+ S.backdrop.className = `studio-backdrop sx-backdrop${S.dim ? '' : ' backdrop-hidden'}`;
180
+ document.body.appendChild(S.backdrop);
181
+ const panel = document.createElement('section');
182
+ panel.id = PANEL_ID;
183
+ panel.className = `skills-studio-panel sx glass resizable${S.docked ? ' sx-docked' : ''}`;
184
+ panel.tabIndex = -1;
185
+ panel.setAttribute('role', 'dialog');
186
+ panel.setAttribute('aria-labelledby', 'sx-title');
187
+ panel.setAttribute('aria-modal', S.dim ? 'true' : 'false');
188
+ if (storage.getItem(RAIL_KEY) === 'true') panel.classList.add('sx-rail-collapsed');
189
+ setHTML(panel, shellHTML());
190
+ document.body.appendChild(panel);
191
+ S.panel = panel;
192
+ // Docked, it holds the work area as the code editor does: the map's top-right toolbar steps aside.
193
+ document.body.classList.toggle('sx-studio-docked', S.docked);
194
+ placeWindow();
195
+ wireShell();
196
+ S.unload = createUnloadGuard({ target: window, isDirty: () => anyDirty(), beforeLeave: () => backups().flush({ leaving: true }) });
197
+ S.unload.install();
198
+ const gen = S.gen;
199
+ if (_cache) deriveRows();
200
+ S.place = want.place === 'library' && !want.skillId && !want.artifactId && !want.name ? 'library' : want.place;
201
+ render();
202
+ requestAnimationFrame(() => { S.backdrop?.classList.add('open'); S.panel?.classList.add('open'); });
203
+ panel.focus({ preventScroll: true });
204
+ try {
205
+ await loadData();
206
+ if (gen !== S.gen || !S.panel) return;
207
+ deriveRows();
208
+ render({ keepFocus: true });
209
+ await navigateTo(want, { first: true });
210
+ } catch (err) {
211
+ if (gen !== S.gen || !S.panel) return;
212
+ render({ keepFocus: true });
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Import a bundle file the menu's "Import…" picked before the Studio was loaded (the picker opens in the click that
218
+ * asked for it; the Studio is loaded while the file is chosen): open on Create, read what the server can do, import.
219
+ */
220
+ export async function openStudioWithImport(file) {
221
+ await openStudio({ place: 'create' });
222
+ if (!S.panel || !file) return;
223
+ await importFile(ctx(), file, capabilities);
224
+ }
225
+
226
+ function placeWindow() {
227
+ const panel = S.panel;
228
+ if (S.docked) { panel.style.left = ''; panel.style.top = ''; panel.style.width = ''; panel.style.height = ''; return; }
229
+ // Where the shared panel system saved it the last time it was moved or resized (ui-panels.js savePanelLayout).
230
+ let saved = null;
231
+ try { saved = JSON.parse(storage.getItem(`${KEYS.PANEL_PREFIX}${PANEL_ID}`) || 'null'); } catch { saved = null; }
232
+ const rect = initialRect({ vw: window.innerWidth, vh: window.innerHeight, saved, frame: frameRect() });
233
+ Object.assign(panel.style, { left: `${rect.left}px`, top: `${rect.top}px`, width: `${rect.width}px`, height: `${rect.height}px` });
234
+ }
235
+
236
+ function anyDirty() {
237
+ for (const ws of S.workspaces.values()) if (dirtyTabs(ws).length) return true;
238
+ return false;
239
+ }
240
+
241
+ /** Close the window. Unsaved documents are saved, kept for later (they come back), or discarded: the owner says. */
242
+ export async function requestCloseStudio() {
243
+ if (!S.panel || dialogOpen()) return;
244
+ const dirty = [];
245
+ for (const ws of S.workspaces.values()) for (const tab of dirtyTabs(ws)) dirty.push({ ws, tab });
246
+ if (dirty.length) {
247
+ const names = dirty.slice(0, 6).map(({ ws, tab }) => `• ${ws.label} › ${tab.label}`);
248
+ if (dirty.length > 6) names.push(`• ${t('skillsStudio.dialog.andMore', { count: dirty.length - 6 })}`);
249
+ const answer = await ask({
250
+ title: t('skillsStudio.dialog.unsavedTitle'),
251
+ lines: [tp('skillsStudio.dialog.unsavedFiles', dirty.length), ...names, t('skillsStudio.dialog.keepForLaterHelp')],
252
+ buttons: [{ id: 'cancel', label: t('skillsStudio.dialog.cancel') }, { id: 'discard', label: t('skillsStudio.dialog.discard'), kind: 'danger' }, { id: 'keep', label: t('skillsStudio.dialog.keepForLater') }, { id: 'save', label: t('skillsStudio.dialog.saveAll'), kind: 'primary' }],
253
+ });
254
+ if (answer === 'save') {
255
+ for (const { ws, tab } of dirty) {
256
+ try {
257
+ const res = await saveTab(ws, tab, api, { key: idempotencyKey });
258
+ if (res.status === 'conflict' || res.status === 'gone') { toast(t('skillsStudio.toast.saveConflict', { file: tab.label }), 'error'); return; }
259
+ } catch (err) { toast(t('skillsStudio.toast.saveFailed', { file: tab.label, error: studioErrorText(t, err) }), 'error'); return; }
260
+ }
261
+ } else if (answer === 'discard') {
262
+ for (const { ws, tab } of dirty) dropDraft(ws, tab);
263
+ } else if (answer === 'keep') {
264
+ backups().flush();
265
+ } else return;
266
+ }
267
+ closeStudio();
268
+ }
269
+
270
+ /** Close now (the owner already said what happens to unsaved text). */
271
+ export function closeStudio() {
272
+ if (!S.panel) return;
273
+ S.gen++; // every answer still on its way belongs to this opening: dropped
274
+ clearTimeout(S.changeTimer);
275
+ closeDialog();
276
+ closeWorkspaceMenus(null);
277
+ // The workspaces and the window's editor go now (the editor's view and listeners would outlive the panel).
278
+ disposeStudio(S.workspaces.values());
279
+ // The place drawn last ends its listeners, timers and follow-ups too (a creation's clock would tick on a removed panel).
280
+ leaveLibraryPlace(); leaveReviewPlace(); leaveCreatePlace(); leaveTestTab(); leaveOperationsPlace();
281
+ forgetReviewOutcomes();
282
+ S.life?.abort();
283
+ S.life = null;
284
+ S.unload?.remove();
285
+ S.unload = null;
286
+ S.backdrop?.remove();
287
+ S.backdrop = null;
288
+ S.panel.remove();
289
+ S.panel = null;
290
+ document.body.classList.remove('sx-studio-docked');
291
+ S.ws = null;
292
+ S.workspaces.clear();
293
+ S.place = 'library';
294
+ storage.setItem(LIB_KEY, JSON.stringify({ view: S.lib.view, kind: S.lib.kind, source: S.lib.source, runtime: S.lib.runtime, health: S.lib.health, sort: S.lib.sort }));
295
+ const back = S.opener;
296
+ S.opener = null;
297
+ if (back?.isConnected) back.focus({ preventScroll: true });
298
+ }
299
+
300
+ // ── The shell ──
301
+
302
+ function shellHTML() {
303
+ const handles = ['t', 'r', 'b', 'l', 'tl', 'tr', 'bl', 'br'].map((d) => html`<div class="resize-handle resize-handle-${d}" data-resize="${d}"></div>`);
304
+ return html`${handles}
305
+ <header class="sx-head${S.docked ? '' : ' drag-handle'}" data-drag="${PANEL_ID}">
306
+ <span class="sx-head-mark" aria-hidden="true">${ICONS.mark}</span>
307
+ <h2 class="sx-title" id="sx-title">${t('skillsStudio.title')}</h2>
308
+ <span class="sx-head-note" id="sx-head-note" role="status"></span>
309
+ <span class="sx-spacer"></span>
310
+ <button type="button" class="sx-icon-btn" data-act="toggle-rail" aria-pressed="false" aria-label="${t('skillsStudio.shell.collapseRail')}" title="${t('skillsStudio.shell.collapseRail')}">${ICONS.library}</button>
311
+ <button type="button" class="sx-icon-btn" data-act="dock" aria-pressed="${S.docked ? 'true' : 'false'}" aria-label="${t('skillsStudio.shell.dock')}" title="${t('skillsStudio.shell.dockHelp')}">${S.docked ? ICONS.undock : ICONS.dock}</button>
312
+ <button type="button" class="sx-icon-btn" data-act="dim" aria-pressed="${S.dim ? 'true' : 'false'}" aria-label="${t('skillsStudio.shell.dim')}" title="${t('skillsStudio.shell.dimHelp')}"${S.docked ? ' disabled' : ''}>${ICONS.dim}</button>
313
+ <button type="button" class="sx-icon-btn sx-close" data-act="close" aria-label="${t('skillsStudio.shell.close')}" title="${t('skillsStudio.shell.close')}">${ICONS.close}</button>
314
+ </header>
315
+ <div class="sx-body">
316
+ <nav class="sx-rail" id="sx-rail" aria-label="${t('skillsStudio.title')}"></nav>
317
+ <main class="sx-main" id="sx-main" aria-labelledby="sx-title"></main>
318
+ </div>
319
+ <p class="sx-sr" id="sx-live" role="status" aria-live="polite"></p>`;
320
+ }
321
+
322
+ function wireShell() {
323
+ S.life?.abort();
324
+ S.life = new AbortController();
325
+ const signal = S.life.signal;
326
+ S.panel.addEventListener('click', (e) => {
327
+ const el = e.target.closest?.('[data-act]');
328
+ if (!el || !S.panel.contains(el) || el.disabled) return;
329
+ const act = el.dataset.act;
330
+ if (act === 'close') requestCloseStudio();
331
+ else if (act === 'dock') toggleDock();
332
+ else if (act === 'dim') toggleDim();
333
+ else if (act === 'toggle-rail') toggleRail();
334
+ else if (act === 'place') goPlace(el.dataset.place);
335
+ else if (act === 'view') { S.lib.view = el.dataset.view; S.lib.focus = null; goPlace('library'); }
336
+ else if (act === 'runtime-filter') { S.lib.runtime = el.dataset.runtime; S.lib.view = 'all'; goPlace('library'); }
337
+ else if (act === 'runtime-fix') openSkillFolders();
338
+ }, { signal });
339
+ // Keys only while the focus is in the Studio: the window is not modal, and the page beside it keeps its own.
340
+ document.addEventListener('keydown', onKeydown, { signal });
341
+ window.addEventListener('resize', () => { if (S.docked) return; placeWithinViewport(); }, { signal });
342
+ }
343
+
344
+ function placeWithinViewport() {
345
+ if (!S.panel) return;
346
+ const r = initialRect({ vw: window.innerWidth, vh: window.innerHeight, frame: frameRect(), saved: { left: S.panel.style.left, top: S.panel.style.top, width: S.panel.style.width, height: S.panel.style.height } });
347
+ Object.assign(S.panel.style, { left: `${r.left}px`, top: `${r.top}px`, width: `${r.width}px`, height: `${r.height}px` });
348
+ }
349
+
350
+ /**
351
+ * Dimmed, the window is modal (aria-modal): Tab and Shift+Tab go round inside it, from the last control to the first
352
+ * and back, and bring the keyboard back in from the page under it. True when the key was taken.
353
+ */
354
+ function trapTab(e, inside) {
355
+ if (!S.dim || e.key !== 'Tab' || e.altKey || e.ctrlKey || e.metaKey) return false;
356
+ const items = focusableIn(S.panel);
357
+ const active = document.activeElement;
358
+ let pos = null;
359
+ if (inside) {
360
+ const at = items.indexOf(active);
361
+ pos = at >= 0 ? at : items.filter((el) => el.compareDocumentPosition(active) & Node.DOCUMENT_POSITION_FOLLOWING).length - 0.5;
362
+ }
363
+ const to = trapIndex(items.length, pos, { shift: e.shiftKey });
364
+ if (to === -1) return false;
365
+ e.preventDefault();
366
+ (to === -2 ? S.panel : items[to]).focus({ preventScroll: false });
367
+ return true;
368
+ }
369
+
370
+ function onKeydown(e) {
371
+ if (!S.panel || e.defaultPrevented || dialogOpen()) return;
372
+ const inside = S.panel.contains(e.target) || S.panel.contains(document.activeElement);
373
+ if (trapTab(e, inside)) return;
374
+ if (!inside) return;
375
+ const mod = MAC ? e.metaKey : e.ctrlKey;
376
+ if (e.key === 'Escape') {
377
+ // The topmost thing that is open, and nothing under it.
378
+ if (closeDropdowns(S.panel, { focus: true })) { e.preventDefault(); return; }
379
+ if (closeWorkspaceMenus(S.panel)) { e.preventDefault(); return; }
380
+ if (inTextField(e.target) && (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA')) {
381
+ if (e.target.type === 'search' && e.target.value) { e.target.value = ''; e.target.dispatchEvent(new Event('input', { bubbles: true })); }
382
+ else e.target.blur();
383
+ e.preventDefault();
384
+ return;
385
+ }
386
+ e.preventDefault();
387
+ requestCloseStudio();
388
+ return;
389
+ }
390
+ if (mod && !e.shiftKey && !e.altKey && e.key.toLowerCase() === 'p') { e.preventDefault(); goPlace('library'); focusLibrary(S.panel); return; }
391
+ if (S.place === 'workspace' && S.ws && workspaceShortcut(e, ctx())) { e.preventDefault(); return; }
392
+ }
393
+
394
+ function toggleDock() {
395
+ S.docked = !S.docked;
396
+ storage.setItem(DOCK_KEY, S.docked ? 'true' : 'false');
397
+ if (S.docked && S.dim) toggleDim(false);
398
+ S.panel.classList.toggle('sx-docked', S.docked);
399
+ document.body.classList.toggle('sx-studio-docked', S.docked);
400
+ const head = S.panel.querySelector('.sx-head');
401
+ head?.classList.toggle('drag-handle', !S.docked);
402
+ const btn = S.panel.querySelector('[data-act="dock"]');
403
+ if (btn) { btn.setAttribute('aria-pressed', S.docked ? 'true' : 'false'); setHTML(btn, S.docked ? ICONS.undock : ICONS.dock); }
404
+ const dim = S.panel.querySelector('[data-act="dim"]');
405
+ if (dim) dim.disabled = S.docked;
406
+ placeWindow();
407
+ announce(t(S.docked ? 'skillsStudio.shell.docked' : 'skillsStudio.shell.undocked'));
408
+ }
409
+
410
+ function toggleDim(force) {
411
+ S.dim = typeof force === 'boolean' ? force : !S.dim;
412
+ storage.setItem(DIM_KEY, S.dim ? 'true' : 'false');
413
+ S.backdrop?.classList.toggle('backdrop-hidden', !S.dim);
414
+ S.panel.setAttribute('aria-modal', S.dim ? 'true' : 'false');
415
+ const btn = S.panel.querySelector('[data-act="dim"]');
416
+ if (btn) btn.setAttribute('aria-pressed', S.dim ? 'true' : 'false');
417
+ announce(t(S.dim ? 'skillsStudio.shell.dimmed' : 'skillsStudio.shell.notDimmed'));
418
+ }
419
+
420
+ function toggleRail() {
421
+ const on = !S.panel.classList.contains('sx-rail-collapsed');
422
+ S.panel.classList.toggle('sx-rail-collapsed', on);
423
+ storage.setItem(RAIL_KEY, on ? 'true' : 'false');
424
+ S.panel.querySelector('[data-act="toggle-rail"]')?.setAttribute('aria-pressed', on ? 'true' : 'false');
425
+ }
426
+
427
+ // ── Navigation ──
428
+
429
+ function goPlace(place) {
430
+ if (!['library', 'review', 'create', 'discover', 'health'].includes(place)) return;
431
+ S.place = place;
432
+ render();
433
+ focusPlace();
434
+ }
435
+
436
+ /**
437
+ * Open a Library row in its workspace (the one it had, with its documents, when it was open before).
438
+ * `revisionId`, `reviewId` and `preset` open Publish for something named (a version, an approved submission, an
439
+ * update SynaBun ships, `preset(pub, targets)` ticking what it replaces): Publish starts over for it before it
440
+ * is drawn, its ticks and any plan of before dropped.
441
+ */
442
+ export async function openRow(key, { tab = null, file = null, line = null, revisionId = null, reviewId = null, preset = null } = {}) {
443
+ const row = S.rows.find((r) => r.key === key);
444
+ if (!row) return false;
445
+ let ws = S.workspaces.get(row.key);
446
+ if (!ws) { ws = newWorkspace(row, { guest: guest(), caps: S.caps || new Set() }); S.workspaces.set(row.key, ws); }
447
+ if (tab) ws.tab = tab;
448
+ if (revisionId || reviewId || preset) {
449
+ ws.pub = null;
450
+ ws.publishRevisionId = revisionId || null;
451
+ ws.publishReviewId = reviewId || null;
452
+ ws.pubPresetApply = typeof preset === 'function' ? preset : null;
453
+ }
454
+ if (file || line) ws.pendingReveal = { file, line };
455
+ S.ws = ws;
456
+ S.place = 'workspace';
457
+ render();
458
+ return true;
459
+ }
460
+
461
+ async function navigateTo(want, { first = false } = {}) {
462
+ if (!S.panel) return;
463
+ if (want.skillId || want.artifactId || want.name) {
464
+ const row = S.rows.find((r) => (want.skillId && r.skill?.skillId === want.skillId) || (want.artifactId && r.entries.some((e) => e.id === want.artifactId))
465
+ || (want.name && (r.folderName === want.name || r.name === want.name) && r.kind === 'skill'));
466
+ if (row) { await openRow(row.key, { tab: want.tab, file: want.file, line: want.line }); return; }
467
+ }
468
+ if (want.place === 'review') { S.place = 'review'; S.reviewFocus = want.reviewId; render(); focusPlace(); return; }
469
+ if (want.place === 'create') {
470
+ S.place = 'create';
471
+ // A link to an AI drafting opens it in Create's box (its progress, or what it made).
472
+ if (want.creationId) openCreation(want.creationId);
473
+ render();
474
+ if (want.create === 'import') startImport(ctx());
475
+ else focusPlace();
476
+ return;
477
+ }
478
+ if (!first || S.place === 'library') { S.place = 'library'; render(); }
479
+ }
480
+
481
+ function focusPlace() {
482
+ requestAnimationFrame(() => {
483
+ const target = S.panel?.querySelector('#sx-main [data-autofocus]') || S.panel?.querySelector('#sx-main h3, #sx-main h2');
484
+ if (target) { if (!target.hasAttribute('tabindex') && !/^(INPUT|TEXTAREA|BUTTON)$/.test(target.tagName)) target.tabIndex = -1; target.focus({ preventScroll: true }); }
485
+ });
486
+ }
487
+
488
+ // ── Rendering ──
489
+
490
+ function railHTML() {
491
+ const c = S.counts || countRows([]);
492
+ const waiting = reviewCount((S.data?.reviews || []), S.updates);
493
+ const place = S.place === 'workspace' ? 'library' : S.place;
494
+ const item = (id, icon, label, count, extra = '') => html`<li><button type="button" class="sx-rail-item" data-act="place" data-place="${id}"${place === id ? html` aria-current="page"` : ''} title="${label}">
495
+ <span class="sx-rail-icon">${icon}</span><span class="sx-rail-label">${label}</span>${count !== null ? html`<span class="sx-rail-count">${count}${extra ? html`<span class="sx-sr"> ${extra}</span>` : ''}</span>` : ''}</button></li>`;
496
+ const views = ['attention', 'mine', 'synabun', 'plugins', 'account', 'drafts', ...(S.caps?.has('library-restore') ? ['archived'] : [])].map((v) => html`<li><button type="button" class="sx-rail-view" data-act="view" data-view="${v}"${S.place === 'library' && S.lib.view === v ? html` aria-current="true"` : ''}>
497
+ <span class="sx-rail-label">${t(`skillsStudio.rail.views.${v}`)}</span><span class="sx-rail-count">${c.views[v] ?? 0}</span></button></li>`);
498
+ const projects = S.projects.map((p) => html`<li><button type="button" class="sx-rail-view" data-act="view" data-view="${`project:${p.path}`}"${S.place === 'library' && S.lib.view === `project:${p.path}` ? html` aria-current="true"` : ''} title="${p.path}">
499
+ <span class="sx-rail-label">${p.label}</span><span class="sx-rail-count">${p.count}</span></button></li>`);
500
+ return html`
501
+ <ul class="sx-rail-list">
502
+ ${item('library', ICONS.library, t('skillsStudio.rail.library'), c.total, '')}
503
+ ${item('review', ICONS.review, t('skillsStudio.rail.review'), waiting || null, t('skillsStudio.rail.waiting'))}
504
+ ${item('create', ICONS.create, t('skillsStudio.rail.create'), null)}
505
+ ${item('discover', ICONS.search, t('skillsStudio.operations.discover'), null)}
506
+ ${item('health', ICONS.history, t('skillsStudio.operations.health'), null)}
507
+ </ul>
508
+ <div class="sx-rail-groups">
509
+ <p class="sx-rail-group-label" id="sx-rail-views">${t('skillsStudio.rail.viewsTitle')}</p>
510
+ <ul class="sx-rail-list" aria-labelledby="sx-rail-views">${views}</ul>
511
+ ${S.projects.length ? html`<p class="sx-rail-group-label" id="sx-rail-projects">${t('skillsStudio.rail.projectsTitle')}</p><ul class="sx-rail-list" aria-labelledby="sx-rail-projects">${projects}</ul>` : ''}
512
+ </div>
513
+ ${runtimeFootHTML()}`;
514
+ }
515
+
516
+ /**
517
+ * Settings → Skills → Skill folders, where the old bridge files are moved to skill folders (Move). The settings
518
+ * module is loaded when asked for (never at the Studio's load: it is the page's, and heavy).
519
+ */
520
+ async function openSkillFolders() {
521
+ try {
522
+ const m = await import('../../ui-settings.js');
523
+ await m.openSettingsModal({ tab: 'tool-access', expand: ['stg-sec-skills'], scrollTo: 'stg-skill-folders' });
524
+ } catch { toast(t('skillsStudio.rail.runtimeFixFailed'), 'error'); }
525
+ }
526
+
527
+ /**
528
+ * The runtimes at the foot of the rail: ready, reached through old bridge files only (the old format: the row opens
529
+ * Settings → Skills → Skill folders, where Move gives each skill a folder of its own), empty, or not set up.
530
+ */
531
+ function runtimeFootHTML() {
532
+ const roots = S.data?.catalog?.roots || [];
533
+ const state = (runtime) => {
534
+ const family = runtime;
535
+ const own = roots.filter((r) => r.family === family && r.kind === 'skills' && r.scope === 'user' && r.sourceKind === 'native');
536
+ const bridged = S.rows.some((r) => r.bridges.some((b) => b.runtime === runtime));
537
+ if (bridged) return 'bridge';
538
+ if (own.some((r) => r.status === 'ok')) return 'ready';
539
+ return own.length ? 'empty' : 'unknown';
540
+ };
541
+ const rows = ['claude', 'codex', 'opencode'].map((rt) => {
542
+ const st = state(rt);
543
+ const name = t(`skillsStudio.runtime.${rt}`);
544
+ const label = st === 'bridge' ? t('skillsStudio.rail.runtimeFix', { runtime: name }) : `${name}: ${t(`skillsStudio.rail.runtimeState.${st}`)}`;
545
+ return html`<button type="button" class="sx-rt-row${st === 'bridge' ? ' sx-rt-row--fix' : ''}" data-act="${st === 'bridge' ? 'runtime-fix' : 'runtime-filter'}" data-runtime="${rt}" aria-label="${label}" title="${label}">
546
+ <span class="sx-rt-dot sx-rt-${st}" aria-hidden="true"></span><span class="sx-rt-name">${name}</span><span class="sx-rt-state">${t(`skillsStudio.rail.runtimeState.${st}`)}</span></button>`;
547
+ });
548
+ return html`<div class="sx-rail-foot" role="group" aria-label="${t('skillsStudio.rail.runtimesTitle')}">${rows}</div>`;
549
+ }
550
+
551
+ function headNote() {
552
+ const note = S.panel?.querySelector('#sx-head-note');
553
+ if (!note) return;
554
+ if (S.capsFailed) setHTML(note, html`<span class="sx-note-warn">${t('skillsStudio.shell.olderServer')}</span>`);
555
+ else if (S.loading && !_cache) setHTML(note, t('skillsStudio.shell.loading'));
556
+ else setHTML(note, '');
557
+ }
558
+
559
+ /** Draw the current place (keeping where the keyboard was when asked). */
560
+ export function render({ keepFocus = false } = {}) {
561
+ if (!S.panel) return;
562
+ const active = keepFocus ? document.activeElement : null;
563
+ const activeId = active && S.panel.contains(active) ? active.id || null : null;
564
+ setHTML(S.panel.querySelector('#sx-rail'), railHTML());
565
+ headNote();
566
+ const main = S.panel.querySelector('#sx-main');
567
+ const c = ctx();
568
+ main.dataset.place = S.place;
569
+ if (S.capsFailed && !_cache) { renderOlderServer(main); return; }
570
+ // Every place listens on the one main area: the one drawn before ends its listeners first (a Library listener left
571
+ // on would also answer inside a workspace: a dropdown opened and closed by the same click).
572
+ leaveLibraryPlace(); leaveReviewPlace(); leaveCreatePlace(); leaveTestTab(); leaveOperationsPlace();
573
+ if (S.place === 'library') renderLibraryPlace(main, c);
574
+ else if (S.place === 'review') renderReviewPlace(main, c);
575
+ else if (S.place === 'create') renderCreatePlace(main, c);
576
+ else if (S.place === 'discover' || S.place === 'health') renderOperationsPlace(main, c, S.place);
577
+ else if (S.place === 'workspace' && S.ws) renderWorkspace(main, c, S.ws);
578
+ else { S.place = 'library'; renderLibraryPlace(main, c); }
579
+ if (activeId) { const again = S.panel.querySelector(`#${CSS.escape(activeId)}`); if (again) again.focus({ preventScroll: true }); }
580
+ }
581
+
582
+ function renderOlderServer(main) {
583
+ setHTML(main, html`<div class="sx-empty" role="alert">
584
+ <h3 class="sx-empty-title" tabindex="-1" data-autofocus>${t('skillsStudio.shell.olderServerTitle')}</h3>
585
+ <p>${t('skillsStudio.shell.olderServerHelp')}</p>
586
+ <button type="button" class="sx-btn" id="sx-retry-caps">${t('skillsStudio.shell.retry')}</button>
587
+ </div>`);
588
+ main.querySelector('#sx-retry-caps')?.addEventListener('click', async () => {
589
+ try { await capabilities(); await loadData(); deriveRows(); } catch { /* still older */ }
590
+ render();
591
+ });
592
+ }
593
+
594
+ // ── Changes made elsewhere ──
595
+
596
+ // An install taken up or let go on any surface (sx-install-flow.js): the surfaces on screen draw it as on its way,
597
+ // or not, so no second one starts from a button that still looks free.
598
+ onInstallBusy(({ skillId }) => {
599
+ if (!S.panel) return;
600
+ if (S.place === 'review') { render({ keepFocus: true }); return; }
601
+ if (S.place === 'workspace' && S.ws && S.ws.skill?.skillId === skillId) {
602
+ const c = ctx();
603
+ refreshWorkspaceChrome(c, S.ws);
604
+ if (S.ws.tab === 'publish') refreshPublishBusy(c, S.ws);
605
+ }
606
+ });
607
+
608
+ /** A skill changed somewhere (another window, the Assistant, an install, a review): read again, a moment later. */
609
+ export function onSkillsChanged(event = {}) {
610
+ if (!S.panel) { _cache = null; return; }
611
+ clearTimeout(S.changeTimer);
612
+ const gen = S.gen;
613
+ S.changeTimer = setTimeout(async () => {
614
+ try {
615
+ await loadData();
616
+ if (gen !== S.gen || !S.panel) return;
617
+ deriveRows();
618
+ // A workspace that shows something being edited is not redrawn under the owner: its rail and its banners are.
619
+ if (S.place === 'workspace' && S.ws) {
620
+ setHTML(S.panel.querySelector('#sx-rail'), railHTML());
621
+ S.ws.onExternalChange?.(event);
622
+ } else render({ keepFocus: true });
623
+ } catch { /* what was read stays */ }
624
+ }, 300);
625
+ }
626
+
627
+ // ── Messages ──
628
+
629
+ export function toast(message, kind = 'info') {
630
+ const el = document.createElement('div');
631
+ el.className = `ss-toast ss-toast--${kind === 'error' ? 'error' : 'info'}`;
632
+ el.setAttribute('role', kind === 'error' ? 'alert' : 'status');
633
+ el.textContent = String(message ?? '');
634
+ document.body.appendChild(el);
635
+ requestAnimationFrame(() => el.classList.add('show'));
636
+ setTimeout(() => { el.classList.remove('show'); setTimeout(() => el.remove(), 300); }, kind === 'error' ? 6000 : 2800);
637
+ }
638
+
639
+ export function announce(message) {
640
+ const live = S.panel?.querySelector('#sx-live');
641
+ if (!live) return;
642
+ live.textContent = '';
643
+ requestAnimationFrame(() => { live.textContent = String(message ?? ''); });
644
+ }
645
+
646
+ const ask = (o) => askInPanel({ host: S.panel, ...o });
647
+
648
+ /** What the views are given: the state they read, and what they may do. */
649
+ function ctx() {
650
+ return {
651
+ t, tp, locale: getLocale(), mac: MAC, api, storage, emit,
652
+ guest: guest(),
653
+ caps: S.caps || new Set(),
654
+ // Whether the server has said what it can do: until then nothing is said to be missing from it.
655
+ capsKnown: !!S.caps,
656
+ panel: S.panel,
657
+ get data() { return S.data; },
658
+ get rows() { return S.rows; },
659
+ get counts() { return S.counts; },
660
+ get projects() { return S.projects; },
661
+ get updates() { return S.updates; },
662
+ get loading() { return !!S.loading && !_cache; },
663
+ get loadError() { return S.loadError; },
664
+ get reviewFocus() { return S.reviewFocus || null; },
665
+ clearReviewFocus() { S.reviewFocus = null; },
666
+ lib: S.lib,
667
+ gen: () => S.gen,
668
+ alive: (gen) => gen === S.gen && !!S.panel,
669
+ render, goPlace, openRow, toast, announce, ask,
670
+ // Review, with one submission brought forward (a finished AI draft's "Open in Review").
671
+ openReview: (reviewId) => { S.reviewFocus = reviewId || null; goPlace('review'); },
672
+ reload: async () => { const gen = S.gen; try { await loadData(); } catch (err) { if (gen === S.gen) toast(t('skillsStudio.toast.loadFailed', { error: studioErrorText(t, err) }), 'error'); } if (gen !== S.gen || !S.panel) return; deriveRows(); render({ keepFocus: true }); },
673
+ keepUpdate: (name, revisionId) => { const kept = readJson(KEPT_UPDATES_KEY, {}); kept[name] = revisionId; storage.setItem(KEPT_UPDATES_KEY, JSON.stringify(kept)); deriveRows(); },
674
+ saveLibraryView: () => storage.setItem(LIB_KEY, JSON.stringify({ view: S.lib.view, kind: S.lib.kind, source: S.lib.source, runtime: S.lib.runtime, health: S.lib.health, sort: S.lib.sort })),
675
+ keptDrafts: () => keptDrafts(),
676
+ workspaces: S.workspaces,
677
+ closeWorkspace: (ws) => { disposeWorkspace(ws); S.workspaces.delete(ws.key); if (S.ws === ws) { S.ws = null; S.place = 'library'; render(); } },
678
+ key: idempotencyKey,
679
+ capabilities,
680
+ };
681
+ }