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,223 @@
1
+ // ═══════════════════════════════════════════
2
+ // SynaBun Neural Interface — data cache
3
+ // ═══════════════════════════════════════════
4
+ // One cache for what windows, menus and dropdowns wait for when they open
5
+ // (model lists, provider lists, accounts, Settings' reads). In memory, per
6
+ // page: a kept answer is given at once and asked for again in the background
7
+ // once it is old (stale-while-revalidate); callers asking at the same time
8
+ // share one request; nothing is kept from a failed request. A change event
9
+ // ages an answer (markStale: still given, asked for again) or drops it
10
+ // (invalidate: the next read waits, `refetch` asks for it right away), and
11
+ // subscribers hear when a background read brought another answer, so an open
12
+ // window can update in place.
13
+ //
14
+ // `persist: true` also keeps the last answer in sessionStorage (this tab only,
15
+ // gone when it closes): a reload paints from it at once. An answer read back
16
+ // from there is always asked for again on its first read.
17
+ //
18
+ // No DOM, no imports: runs under node --test as well.
19
+
20
+ const STORAGE_PREFIX = 'synabun:data-cache:v1:';
21
+ const MAX_PERSIST_CHARS = 768 * 1024;
22
+
23
+ const registry = new Map(); // name → cache (invalidateDataCaches)
24
+
25
+ function sameJson(a, b) {
26
+ if (a === b) return true;
27
+ try { return JSON.stringify(a) === JSON.stringify(b); } catch { return false; }
28
+ }
29
+
30
+ function session() {
31
+ try { return typeof sessionStorage !== 'undefined' ? sessionStorage : null; } catch { return null; }
32
+ }
33
+
34
+ /**
35
+ * @param {string} name
36
+ * @param {object} o
37
+ * @param {(key:string, opts:{force:boolean})=>Promise<any>} o.load the request; throw on failure
38
+ * @param {number} [o.ttlMs] how long an answer is fresh
39
+ * @param {boolean} [o.persist] keep the last answer in sessionStorage too
40
+ * @param {(value:any, key:string)=>boolean} [o.accept] worth keeping (a failed or empty answer is not)
41
+ * @param {(a:any, b:any)=>boolean} [o.equals]
42
+ */
43
+ export function createDataCache(name, {
44
+ load,
45
+ ttlMs = 60_000,
46
+ persist = false,
47
+ accept = (value) => value !== undefined && value !== null,
48
+ equals = sameJson,
49
+ now = () => Date.now(),
50
+ } = {}) {
51
+ if (typeof load !== 'function') throw new Error(`data cache ${name}: load is required`);
52
+ const entries = new Map(); // key → { value, at, stale }
53
+ const inflight = new Map(); // key → promise
54
+ const generations = new Map(); // key → bumped by invalidate(): a request begun before it is not kept
55
+ const listeners = new Set();
56
+ const restored = new Set(); // keys looked up in sessionStorage already
57
+
58
+ const storageKey = (key) => `${STORAGE_PREFIX}${name}:${key}`;
59
+ const ok = (value, key) => { try { return accept(value, key) === true; } catch { return false; } };
60
+
61
+ function restore(key) {
62
+ if (!persist || restored.has(key)) return;
63
+ restored.add(key);
64
+ if (entries.has(key)) return;
65
+ try {
66
+ const raw = session()?.getItem(storageKey(key));
67
+ if (!raw) return;
68
+ const parsed = JSON.parse(raw);
69
+ if (parsed && parsed.value !== undefined && ok(parsed.value, key)) entries.set(key, { value: parsed.value, at: Number(parsed.at) || 0, stale: true });
70
+ } catch { /* unreadable: nothing kept */ }
71
+ }
72
+
73
+ function save(key, entry) {
74
+ if (!persist) return;
75
+ try {
76
+ const text = JSON.stringify({ at: entry.at, value: entry.value });
77
+ if (text.length > MAX_PERSIST_CHARS) { session()?.removeItem(storageKey(key)); return; }
78
+ session()?.setItem(storageKey(key), text);
79
+ } catch { /* full or unavailable: memory still has it */ }
80
+ }
81
+
82
+ function forget(key) {
83
+ if (!persist) return;
84
+ try { session()?.removeItem(storageKey(key)); } catch { /* unavailable */ }
85
+ }
86
+
87
+ function notify(key, value, previous) {
88
+ for (const listener of [...listeners]) {
89
+ try { listener(key, value, previous); } catch { /* a listener's failure is its own */ }
90
+ }
91
+ }
92
+
93
+ function store(key, value) {
94
+ const previous = entries.get(key);
95
+ const same = !!previous && equals(previous.value, value);
96
+ const entry = { value: same ? previous.value : value, at: now(), stale: false };
97
+ entries.set(key, entry);
98
+ save(key, entry);
99
+ if (!same) notify(key, entry.value, previous?.value);
100
+ return entry.value;
101
+ }
102
+
103
+ function fresh(entry) {
104
+ return !!entry && !entry.stale && now() - entry.at < ttlMs;
105
+ }
106
+
107
+ function request(key, force) {
108
+ if (inflight.has(key)) return inflight.get(key);
109
+ const generation = generations.get(key) || 0;
110
+ const job = (async () => {
111
+ try {
112
+ const value = await load(key, { force });
113
+ if (ok(value, key) && (generations.get(key) || 0) === generation) return { value: store(key, value), kept: true };
114
+ return { value, kept: false };
115
+ } finally {
116
+ if (inflight.get(key) === job) inflight.delete(key);
117
+ }
118
+ })();
119
+ inflight.set(key, job);
120
+ return job;
121
+ }
122
+
123
+ /** `{ value, cached, stale }`: a kept answer at once (asked for again when old), else the request's. */
124
+ async function read(key = '', { force = false } = {}) {
125
+ const id = String(key);
126
+ restore(id);
127
+ const entry = entries.get(id);
128
+ if (!force && entry) {
129
+ const stale = !fresh(entry);
130
+ if (stale) request(id, false).catch(() => {});
131
+ return { value: entry.value, cached: true, stale };
132
+ }
133
+ const result = await request(id, force);
134
+ return { value: result.value, cached: false, stale: false, kept: result.kept };
135
+ }
136
+
137
+ const cache = {
138
+ name,
139
+ read,
140
+ async get(key = '', options = {}) { return (await read(key, options)).value; },
141
+ /** The kept answer, or undefined: never waits. An old one (or one read back after a reload) is asked for again behind it. */
142
+ peek(key = '') {
143
+ const id = String(key);
144
+ restore(id);
145
+ const entry = entries.get(id);
146
+ if (entry && !fresh(entry)) request(id, false).catch(() => {});
147
+ return entry?.value;
148
+ },
149
+ has(key = '') { const id = String(key); restore(id); return entries.has(id); },
150
+ /** True while nothing was kept and a request is running (the one moment a spinner is right). */
151
+ loading(key = '') { const id = String(key); restore(id); return !entries.has(id) && inflight.has(id); },
152
+ /** Ask now unless a fresh answer is kept; resolves when done, never rejects. */
153
+ prefetch(key = '') {
154
+ const id = String(key);
155
+ restore(id);
156
+ if (fresh(entries.get(id))) return Promise.resolve(entries.get(id).value);
157
+ return request(id, false).then((result) => result.value, () => undefined);
158
+ },
159
+ /** Ask again now (one request for every caller); resolves to the answer, never rejects. */
160
+ refresh(key = '', { force = false } = {}) {
161
+ return request(String(key), force).then((result) => result.value, () => undefined);
162
+ },
163
+ /** Keep an answer obtained elsewhere (a save that returned the new state). */
164
+ set(key = '', value) { const id = String(key); if (ok(value, id)) store(id, value); },
165
+ /** The answer is due: still given, asked for again on the next read (`refetch`: now). */
166
+ markStale(key = null, { refetch = false } = {}) {
167
+ const ids = key === null ? [...entries.keys()] : [String(key)];
168
+ for (const id of ids) {
169
+ restore(id);
170
+ const entry = entries.get(id);
171
+ if (entry) entry.stale = true;
172
+ if (refetch) request(id, false).catch(() => {});
173
+ }
174
+ },
175
+ /** Drop the answer: the next read waits for a new one; a request already running is not kept (`refetch`: ask now). */
176
+ invalidate(key = null, { refetch = false } = {}) {
177
+ const ids = key === null ? [...new Set([...entries.keys(), ...inflight.keys()])] : [String(key)];
178
+ for (const id of ids) {
179
+ entries.delete(id);
180
+ restored.add(id);
181
+ forget(id);
182
+ generations.set(id, (generations.get(id) || 0) + 1);
183
+ // A request begun before this is not joined by later reads: its answer is from before the change.
184
+ inflight.delete(id);
185
+ if (refetch) request(id, false).catch(() => {});
186
+ }
187
+ },
188
+ /** `listener(key, value, previous)` whenever another answer is kept. Returns the function that stops it. */
189
+ subscribe(listener) {
190
+ if (typeof listener !== 'function') return () => {};
191
+ listeners.add(listener);
192
+ return () => { listeners.delete(listener); };
193
+ },
194
+ keys() { return [...entries.keys()]; },
195
+ };
196
+ registry.set(name, cache);
197
+ return cache;
198
+ }
199
+
200
+ /** The cache registered under `name`, or null. */
201
+ export function dataCache(name) {
202
+ return registry.get(name) || null;
203
+ }
204
+
205
+ /** Drop every answer of the named caches (or of all of them): a sign-out, a server that came back as another. */
206
+ export function invalidateDataCaches(names = null) {
207
+ for (const [name, cache] of registry) {
208
+ if (!names || names.includes(name)) cache.invalidate();
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Run `fn` when the page is idle (requestIdleCallback where there is one; Safari has none, so a short timer
214
+ * there), at most `timeout` ms later. Returns a function that cancels it.
215
+ */
216
+ export function whenIdle(fn, { timeout = 1500, fallbackMs = 120 } = {}) {
217
+ if (typeof window !== 'undefined' && typeof window.requestIdleCallback === 'function') {
218
+ const id = window.requestIdleCallback(() => fn(), { timeout });
219
+ return () => { try { window.cancelIdleCallback?.(id); } catch { /* gone */ } };
220
+ }
221
+ const id = setTimeout(fn, fallbackMs);
222
+ return () => clearTimeout(id);
223
+ }
@@ -25,6 +25,17 @@ export function isDesktopApp(win = globalThis.window) {
25
25
  return desktopBridge(win) !== null;
26
26
  }
27
27
 
28
+ /**
29
+ * The desktop app's own settings (Settings > App: packaging/desktop/src/app-prefs.mjs, login-item.mjs): state(),
30
+ * set(key, value), openFolder('data' | 'logs'), openLoginSettings(), relaunch(), onChange(listener).
31
+ * Null in a browser, and in an app from before Settings > App.
32
+ */
33
+ export function desktopApp(win = globalThis.window) {
34
+ const api = desktopBridge(win)?.app;
35
+ if (!api || typeof api !== 'object' || typeof api.state !== 'function' || typeof api.set !== 'function') return null;
36
+ return api;
37
+ }
38
+
28
39
  /**
29
40
  * The title bar of the desktop app's main window (packaging/desktop/src/titlebar.mjs): its facts
30
41
  * ({ style, platform, height, controls, appMenu }), its state, the app's menu and the caption buttons' colours.
@@ -8,7 +8,9 @@
8
8
  // its ends. desktop-titlebar.js does the page's part; this file decides, from
9
9
  // plain values: the colours the caption buttons get, whether the bar makes room
10
10
  // for them now, where they are when the page has no Window Controls Overlay API,
11
- // and whether something drawn over the bar has to get its clicks.
11
+ // whether something drawn over the bar has to get its clicks, and which changes
12
+ // of the page can put something there (changedClasses, styleChange,
13
+ // drawnUnderBar).
12
14
  //
13
15
  // No imports and no DOM: `node --test` loads this file as it is
14
16
  // (tests/desktop-titlebar-view.test.mjs).
@@ -120,3 +122,78 @@ export function barCovered(samples) {
120
122
 
121
123
  /** A stable key for a pair of colours: unchanged colours are never sent twice. */
122
124
  export const colorsKey = (colors) => (colors ? `${colors.color}/${colors.symbolColor}` : '');
125
+
126
+ /** The class names one of two class attributes has and the other has not (none: the same classes, in any order). */
127
+ export function changedClasses(before, after) {
128
+ const was = new Set(String(before ?? '').split(/\s+/).filter(Boolean));
129
+ const is = new Set(String(after ?? '').split(/\s+/).filter(Boolean));
130
+ return [...[...was].filter(name => !is.has(name)), ...[...is].filter(name => !was.has(name))];
131
+ }
132
+
133
+ // Inline style properties a tooltip that follows the pointer, a window being dragged or a panel being resized
134
+ // changes on every frame: they move, size or paint a box, and never show or hide one.
135
+ const MOVES_OR_PAINTS = /^(?:--.+|top|left|right|bottom|inset(?:-[a-z-]+)?|(?:min-|max-)?(?:width|height)|margin(?:-[a-z-]+)?|padding(?:-[a-z-]+)?|transform(?:-origin)?|translate|scale|rotate|opacity|color|background(?:-[a-z-]+)?|border(?:-[a-z-]+)?|box-shadow|outline(?:-[a-z-]+)?|filter|(?:-webkit-)?backdrop-filter|transition(?:-[a-z-]+)?|animation(?:-[a-z-]+)?|cursor|font(?:-[a-z-]+)?|line-height|letter-spacing|text-[a-z-]+|white-space)$/;
136
+
137
+ /** An inline style attribute as property → value. */
138
+ function declarations(text) {
139
+ const out = new Map();
140
+ for (const part of String(text ?? '').split(';')) {
141
+ const at = part.indexOf(':');
142
+ const name = at < 0 ? '' : part.slice(0, at).trim().toLowerCase();
143
+ if (name) out.set(name, part.slice(at + 1).trim());
144
+ }
145
+ return out;
146
+ }
147
+
148
+ /**
149
+ * What a change of an inline style attribute (`before` → `after`) did: 'none' (the same declarations), 'move' (only
150
+ * properties that move, size or paint a box: MOVES_OR_PAINTS) or 'other' (display, visibility, pointer-events,
151
+ * z-index, position or anything else, which can show, hide or restack it).
152
+ */
153
+ export function styleChange(before, after) {
154
+ const was = declarations(before);
155
+ const is = declarations(after);
156
+ let kind = 'none';
157
+ for (const name of new Set([...was.keys(), ...is.keys()])) {
158
+ if (was.get(name) === is.get(name)) continue;
159
+ if (!MOVES_OR_PAINTS.test(name)) return 'other';
160
+ kind = 'move';
161
+ }
162
+ return kind;
163
+ }
164
+
165
+ /** The z-index a box is stacked at from its computed style, when it is positioned and has one; null otherwise. */
166
+ export function stackLevel(style) {
167
+ const z = Number.parseInt(style?.zIndex, 10);
168
+ return style?.position && style.position !== 'static' && Number.isFinite(z) ? z : null;
169
+ }
170
+
171
+ const isSet = (value) => !!value && value !== 'none';
172
+
173
+ /**
174
+ * Whether nothing inside an element can be drawn over the bar, from the element's computed style, for an element
175
+ * that is the bar's sibling (both children of <body>, the bar stacked at `barLevel`): it draws nothing (display:
176
+ * none), or it is a stacking context of its own (a z-index on a positioned box, position fixed or sticky, a
177
+ * transform, a filter, opacity, isolation, a blend mode, paint or layout containment) stacked under the bar. Whatever
178
+ * its descendants' z-index, they are drawn inside it. Only the top layer escapes (a modal dialog, a popover), which
179
+ * the caller watches by itself; and a rule can restyle the element from what it holds (`:has()`), so the answer holds
180
+ * only until something inside it changes. Anything it cannot tell is false.
181
+ */
182
+ export function drawnUnderBar(style, barLevel) {
183
+ if (!style || !Number.isFinite(barLevel)) return false;
184
+ if (style.display === 'none') return true;
185
+ if (style.display === 'contents') return false;
186
+ const z = Number.parseInt(style.zIndex, 10);
187
+ const positioned = !!style.position && style.position !== 'static';
188
+ const ownContext = (positioned && Number.isFinite(z))
189
+ || style.position === 'fixed' || style.position === 'sticky'
190
+ || isSet(style.transform) || isSet(style.filter) || isSet(style.backdropFilter) || isSet(style.webkitBackdropFilter)
191
+ || Number.parseFloat(style.opacity) < 1
192
+ || style.isolation === 'isolate'
193
+ || (!!style.mixBlendMode && style.mixBlendMode !== 'normal')
194
+ || /\b(?:paint|layout|strict|content)\b/.test(String(style.contain || ''));
195
+ if (!ownContext) return false;
196
+ // A z-index on a box that is not positioned counts only on a flex or grid item: read as at least 0 there.
197
+ const level = Number.isFinite(z) ? (positioned ? z : Math.max(z, 0)) : 0;
198
+ return level < barLevel;
199
+ }
@@ -17,7 +17,8 @@
17
17
  // menu, the one the hidden menu bar had (its shortcuts still work)
18
18
  // clicks the bar's empty parts drag the window (the system double-clicks
19
19
  // them too); while something is drawn over the bar (a dialog, the
20
- // tour), that thing gets the clicks: body.desktop-titlebar-covered
20
+ // tour), that thing gets the clicks: body.desktop-titlebar-covered,
21
+ // checked only after a change that can put something there
21
22
  //
22
23
  // In a browser and in the installed PWA nothing here runs: initDesktopTitleBar()
23
24
  // returns null, and the PWA's own overlay handling (ui-navbar.js) is untouched.
@@ -26,11 +27,19 @@
26
27
 
27
28
  import { desktopWindow } from './desktop-bridge.js';
28
29
  import { colorSender, textTone } from './desktop-titlebar-page.js';
29
- import { barCovered, fallbackTitlebarArea, overlayColorsFor, titleBarActive } from './desktop-titlebar-view.js';
30
+ import { barCovered, changedClasses, drawnUnderBar, fallbackTitlebarArea, overlayColorsFor, stackLevel, styleChange, titleBarActive } from './desktop-titlebar-view.js';
30
31
  import { t } from './i18n.js';
31
32
 
32
33
  const MENU_ICON = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 7h16"/><path d="M4 12h16"/><path d="M4 17h16"/></svg>';
33
34
  const COLOR_DELAY_MS = 120;
35
+ // The cover check while the page keeps changing: at most one per COVER_INTERVAL_MS (four a second).
36
+ const COVER_INTERVAL_MS = 250;
37
+ // The classes of <body> this module writes itself: never a reason to check again.
38
+ const OWN_BODY_CLASSES = new Set(['desktop-titlebar-covered', 'wco-active']);
39
+ // What a change of the page can do to the cover.
40
+ const IGNORE = 0;
41
+ const SOON = 1;
42
+ const NOW = 2;
34
43
 
35
44
  /**
36
45
  * The map pages (index.html, index2d.html): #title-bar becomes the window's title bar. Returns the controller, or
@@ -69,24 +78,146 @@ export function initDesktopTitleBar({ doc = document, view = window } = {}) {
69
78
  }
70
79
 
71
80
  // ── Covered: something over the bar takes its clicks, so the bar stops dragging the window ──
81
+ // Chromium gives the page no mouse events over a drag region, so this has to be right before the pointer gets
82
+ // there. Measuring it costs a layout and the hit tests, so it runs only after a change that can put something over
83
+ // the bar or take it away (pageChange below): on the next frame (coverNow) for an overlay's root coming, going,
84
+ // shown or hidden, at most every COVER_INTERVAL_MS (coverSoon: at once when the page was quiet, then once more after
85
+ // the last change) for the rest, and never for text or for what the bar holds. A change inside a part of the page
86
+ // drawn under the bar (a side panel's transcript, a terminal's output) only has that part's style read again, in
87
+ // case a rule lifted it over the bar (the side panels' `:has(.…-dropdown.open)`); the bar is measured then only if
88
+ // one was.
89
+ const body = doc.body;
90
+ const clock = () => (typeof view.performance?.now === 'function' ? view.performance.now() : Date.now());
72
91
  let coverFrame = 0;
92
+ let coverTimer = null;
93
+ let measureNow = false; // the next check measures the bar
94
+ let soonPending = false; // work at the throttled pace is waiting: verdicts, and the bar's measure when soonMeasure
95
+ let soonMeasure = false;
96
+ let lastSoon = -Infinity; // when that work last ran
97
+ // Children of <body> drawn under the bar as a whole (drawnUnderBar), and those whose verdict the next check takes
98
+ // again: read during a check, when the page's style is current anyway, and never their layout.
99
+ const underBar = new Set();
100
+ const toJudge = new Set();
101
+ const judgeAgain = () => { for (const part of underBar) toJudge.add(part); };
102
+ /** Takes the verdicts asked for; true when a part that was drawn under the bar no longer is. */
103
+ const judgeParts = () => {
104
+ if (!toJudge.size) return false;
105
+ const level = bar.parentNode === body ? stackLevel(view.getComputedStyle(bar)) : null;
106
+ let lifted = false;
107
+ for (const part of toJudge) {
108
+ if (level !== null && part.parentNode === body && drawnUnderBar(view.getComputedStyle(part), level)) underBar.add(part);
109
+ else if (underBar.delete(part)) lifted = true;
110
+ }
111
+ toJudge.clear();
112
+ return lifted;
113
+ };
73
114
  const checkCover = () => {
74
115
  coverFrame = 0;
75
- if (!doc.body.classList.contains('wco-active')) { doc.body.classList.remove('desktop-titlebar-covered'); return; }
76
- const rect = bar.getBoundingClientRect();
77
- const area = wco && wco.visible ? wco.getTitlebarAreaRect() : null;
78
- const left = Math.max(rect.left, area ? area.x : rect.left) + 2;
79
- const right = Math.min(rect.right, area ? area.x + area.width : rect.right) - 2;
80
- if (!(right > left) || !(rect.height > 0)) { doc.body.classList.remove('desktop-titlebar-covered'); return; }
81
- const y = Math.round(rect.top + rect.height / 2);
82
- const samples = [];
83
- for (let i = 0; i <= 8; i++) {
84
- const el = doc.elementFromPoint(Math.round(left + ((right - left) * i) / 8), y);
85
- samples.push({ inBar: !!el && (el === bar || bar.contains(el)), page: !el || el === html || el === doc.body });
116
+ let measure = measureNow;
117
+ measureNow = false;
118
+ const now = clock();
119
+ if (soonPending && now - lastSoon >= COVER_INTERVAL_MS) {
120
+ soonPending = false;
121
+ lastSoon = now;
122
+ if (soonMeasure) measure = true;
123
+ soonMeasure = false;
124
+ }
125
+ // Reads in one go (the style, then one layout and the hit tests), then at most one write, and only of a change.
126
+ if (judgeParts()) measure = true;
127
+ if (measure) {
128
+ let covered = false;
129
+ if (body.classList.contains('wco-active')) {
130
+ const rect = bar.getBoundingClientRect();
131
+ const area = wco && wco.visible ? wco.getTitlebarAreaRect() : null;
132
+ const left = Math.max(rect.left, area ? area.x : rect.left) + 2;
133
+ const right = Math.min(rect.right, area ? area.x + area.width : rect.right) - 2;
134
+ if (right > left && rect.height > 0) {
135
+ const y = Math.round(rect.top + rect.height / 2);
136
+ for (let i = 0; i <= 8 && !covered; i++) {
137
+ const el = doc.elementFromPoint(Math.round(left + ((right - left) * i) / 8), y);
138
+ covered = barCovered([{ inBar: !!el && (el === bar || bar.contains(el)), page: !el || el === html || el === body }]);
139
+ }
140
+ }
141
+ }
142
+ if (body.classList.contains('desktop-titlebar-covered') !== covered) body.classList.toggle('desktop-titlebar-covered', covered);
86
143
  }
87
- doc.body.classList.toggle('desktop-titlebar-covered', barCovered(samples));
144
+ if (soonPending) armSoon();
145
+ };
146
+ /** The next check for the throttled work: the next frame once COVER_INTERVAL_MS has passed since it last ran. */
147
+ const armSoon = () => {
148
+ if (coverFrame || coverTimer) return;
149
+ const wait = lastSoon + COVER_INTERVAL_MS - clock();
150
+ if (wait <= 0) coverFrame = view.requestAnimationFrame(checkCover);
151
+ else coverTimer = setTimeout(() => { coverTimer = null; if (!coverFrame) coverFrame = view.requestAnimationFrame(checkCover); }, wait);
152
+ };
153
+ /** A check on the next frame; `measured` false: only the verdicts asked for, unless one changes. */
154
+ const coverNow = (measured = true) => {
155
+ if (measured) measureNow = true;
156
+ if (!coverFrame) coverFrame = view.requestAnimationFrame(checkCover);
157
+ };
158
+ /** A check at the throttled pace: at once after a quiet COVER_INTERVAL_MS, else when it is over (leading, trailing). */
159
+ const coverSoon = (measured = true) => {
160
+ soonPending = true;
161
+ if (measured) soonMeasure = true;
162
+ armSoon();
163
+ };
164
+
165
+ /** The child of <body> that holds `node` (the node itself when it is one); null for <body> or a node off the page. */
166
+ const partOf = (node) => {
167
+ for (let n = node; n; n = n.parentNode) if (n.parentNode === body) return n;
168
+ return null;
169
+ };
170
+ const hasElement = (nodes) => { for (const node of nodes || []) if (node?.nodeType === 1) return true; return false; };
171
+ // Each change → [IGNORE | SOON | NOW, whether the bar has to be measured].
172
+ const QUIET = [IGNORE, false];
173
+ const childListChange = (record) => {
174
+ if (!hasElement(record.addedNodes) && !hasElement(record.removedNodes)) return QUIET; // text
175
+ const target = record.target;
176
+ if (target === body) { judgeAgain(); return [NOW, true]; } // an overlay's root; a sibling selector may match anew
177
+ const part = partOf(target);
178
+ if (!part || part === bar) return QUIET; // off the page, or what the bar holds: that counts as the bar
179
+ toJudge.add(part);
180
+ if (target === part) return [NOW, true]; // an overlay's root got or lost a child (:empty, :has() can show it)
181
+ return [SOON, !underBar.has(part)];
182
+ };
183
+ const attributeChange = ({ target, name, before, after }) => {
184
+ // A modal dialog is drawn above everything, wherever it is in the page.
185
+ if (name === 'open' && target.nodeName === 'DIALOG') return [NOW, true];
186
+ if (target === body) {
187
+ if (name === 'class' && changedClasses(before, after).every(token => OWN_BODY_CLASSES.has(token))) return QUIET;
188
+ judgeAgain();
189
+ return [NOW, true];
190
+ }
191
+ const part = partOf(target);
192
+ if (!part) return QUIET;
193
+ if (part === bar) return target === bar ? [NOW, true] : QUIET;
194
+ toJudge.add(part);
195
+ // Shown, hidden or restacked: on the next frame; only moved, sized or repainted: at the throttled pace. Inside a
196
+ // part drawn under the bar only its style is read again (a class can lift the whole part).
197
+ const moveOnly = name === 'style' && styleChange(before, after) !== 'other';
198
+ return [moveOnly ? SOON : NOW, target === part || !underBar.has(part)];
199
+ };
200
+ /** What a batch of the page's changes can do to the cover; a record this cannot read counts as one that can. */
201
+ const pageChange = (records) => {
202
+ const { attributes, others } = foldRecords(records);
203
+ // The next frame's work and the throttled work, each with whether it measures the bar: kept apart, so that a
204
+ // verdict read on the next frame never takes a throttled measure along before its time.
205
+ let next = false;
206
+ let nextMeasured = false;
207
+ let soon = false;
208
+ let soonMeasured = false;
209
+ const add = ([level, measured]) => {
210
+ if (level === NOW) { next = true; if (measured) nextMeasured = true; }
211
+ else if (level === SOON) { soon = true; if (measured) soonMeasured = true; }
212
+ };
213
+ for (const record of others) {
214
+ if (record?.type === 'characterData') continue; // text
215
+ add(record?.type === 'childList' && record.target ? childListChange(record) : [NOW, true]);
216
+ }
217
+ for (const change of attributes) add(attributeChange(change));
218
+ if (next) coverNow(nextMeasured);
219
+ if (soon) coverSoon(soonMeasured);
88
220
  };
89
- const scheduleCover = () => { if (!coverFrame) coverFrame = view.requestAnimationFrame(checkCover); };
90
221
 
91
222
  // ── Colours: the bar as drawn where the buttons are, over whatever is under it there ──
92
223
  let colorTimer = null;
@@ -124,7 +255,7 @@ export function initDesktopTitleBar({ doc = document, view = window } = {}) {
124
255
  html.style.setProperty('--desktop-titlebar-width', `${area.width}px`);
125
256
  html.style.setProperty('--desktop-titlebar-height', `${area.height}px`);
126
257
  }
127
- scheduleCover();
258
+ coverNow();
128
259
  scheduleColors();
129
260
  };
130
261
  const setState = (next) => { if (next && typeof next === 'object') state = { ...state, ...next }; layout(); };
@@ -133,21 +264,76 @@ export function initDesktopTitleBar({ doc = document, view = window } = {}) {
133
264
  Promise.resolve(api.state()).then(setState).catch(() => {});
134
265
  if (typeof api.onState === 'function') api.onState(setState);
135
266
  wco?.addEventListener('geometrychange', layout);
136
- view.addEventListener('resize', () => { scheduleCover(); scheduleColors(); });
137
- bar.addEventListener('transitionend', scheduleColors);
267
+ view.addEventListener('resize', () => { coverNow(); scheduleColors(); });
268
+ // The bar's own transitions (its background, its left edge beside a sidebar); what it holds never colours the buttons.
269
+ bar.addEventListener('transitionend', (event) => { if (event?.target === bar) { scheduleColors(); coverSoon(); } });
270
+ if (typeof doc.addEventListener === 'function') {
271
+ // A popover is drawn above everything without a change of the page to see; an element in full screen too.
272
+ doc.addEventListener('toggle', (event) => { if (event?.target?.nodeName !== 'DETAILS') coverNow(); }, true);
273
+ doc.addEventListener('fullscreenchange', () => coverNow());
274
+ }
138
275
 
139
276
  // What changes the bar's colours: its own class and style (the Memory Explorer, a sidebar), the stylesheets (a
140
- // skin's <link>, which draws once it has loaded) and the interface settings (variables on <html>).
141
- new view.MutationObserver(scheduleColors).observe(bar, { attributes: true, attributeFilter: ['class', 'style'] });
142
- new view.MutationObserver((records) => {
143
- for (const record of records) {
144
- for (const node of record.addedNodes || []) if (node.tagName === 'LINK') node.addEventListener('load', scheduleColors, { once: true });
145
- }
277
+ // skin's <link>, which draws once it has loaded) and the interface settings (variables on <html>). A class flipped
278
+ // and back, a <title> or a <meta> changes nothing. A stylesheet or <html> can also restack the page: the cover too
279
+ // (a theme's class or a stylesheet that loaded at once, the rest at the throttled pace).
280
+ const restyled = (now) => {
281
+ judgeAgain();
146
282
  scheduleColors();
147
- }).observe(doc.head, { childList: true, subtree: true, attributes: true, attributeFilter: ['href', 'media', 'disabled'] });
148
- new view.MutationObserver(scheduleColors).observe(html, { attributes: true, attributeFilter: ['style', 'class'] });
149
- // What can come over the bar: anything added, shown or moved on the page.
150
- new view.MutationObserver(scheduleCover).observe(doc.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['class', 'style', 'hidden', 'open'] });
283
+ if (now) coverNow(); else coverSoon();
284
+ };
285
+ new view.MutationObserver((records) => {
286
+ const { attributes, others } = foldRecords(records);
287
+ if (attributes.length || others.length) scheduleColors();
288
+ }).observe(bar, { attributes: true, attributeOldValue: true, attributeFilter: ['class', 'style'] });
289
+ const onSheetLoad = () => restyled(true);
290
+ new view.MutationObserver((records) => {
291
+ const { attributes, others } = foldRecords(records);
292
+ for (const record of others) for (const node of record?.addedNodes || []) if (node.tagName === 'LINK') node.addEventListener('load', onSheetLoad, { once: true });
293
+ if (attributes.some(change => isStylesheet(change.target)) || others.some(sheetsChanged)) restyled(false);
294
+ }).observe(doc.head, { childList: true, subtree: true, attributes: true, attributeOldValue: true, attributeFilter: ['href', 'media', 'disabled'] });
295
+ new view.MutationObserver((records) => {
296
+ const { attributes, others } = foldRecords(records);
297
+ if (attributes.length || others.length) restyled(others.length > 0 || attributes.some(change => change.name === 'class'));
298
+ }).observe(html, { attributes: true, attributeOldValue: true, attributeFilter: ['style', 'class'] });
299
+ // What can come over the bar: anything added, shown or moved on the page (pageChange keeps what can matter).
300
+ new view.MutationObserver(pageChange).observe(body, { childList: true, subtree: true, attributes: true, attributeOldValue: true, attributeFilter: ['class', 'style', 'hidden', 'open'] });
151
301
 
152
302
  return { facts, menuButton, refresh: layout, state: () => ({ ...state }) };
153
303
  }
304
+
305
+ /**
306
+ * One MutationObserver batch with each attribute's records folded into its net change: { target, name, before,
307
+ * after } for an attribute whose value now differs from its value before the batch (a class removed and added back
308
+ * in the same frame is no change), and the other records as they came.
309
+ */
310
+ function foldRecords(records) {
311
+ const first = new Map();
312
+ const others = [];
313
+ for (const record of records || []) {
314
+ if (record?.type !== 'attributes' || !record.target || !record.attributeName) { others.push(record); continue; }
315
+ let names = first.get(record.target);
316
+ if (!names) first.set(record.target, (names = new Map()));
317
+ if (!names.has(record.attributeName)) names.set(record.attributeName, record.oldValue ?? null);
318
+ }
319
+ const attributes = [];
320
+ for (const [target, names] of first) {
321
+ for (const [name, before] of names) {
322
+ const after = target.getAttribute(name);
323
+ if (after !== before) attributes.push({ target, name, before, after });
324
+ }
325
+ }
326
+ return { attributes, others };
327
+ }
328
+
329
+ const isStylesheet = (node) => node?.nodeName === 'LINK' || node?.nodeName === 'STYLE';
330
+
331
+ /** Whether a record of <head> added or removed a stylesheet or changed one's text; a record this cannot read did. */
332
+ function sheetsChanged(record) {
333
+ if (record?.type !== 'childList') return true;
334
+ if (isStylesheet(record.target)) return true;
335
+ for (const nodes of [record.addedNodes, record.removedNodes]) {
336
+ for (const node of nodes || []) if (isStylesheet(node) || node?.querySelector?.('link, style')) return true;
337
+ }
338
+ return false;
339
+ }