@vellumai/assistant 0.4.26 → 0.4.30

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 (1360) hide show
  1. package/.env.example +2 -2
  2. package/AGENTS.md +5 -0
  3. package/ARCHITECTURE.md +207 -105
  4. package/Dockerfile +1 -1
  5. package/README.md +111 -113
  6. package/bun.lock +0 -3
  7. package/docs/architecture/integrations.md +0 -1
  8. package/docs/architecture/memory.md +100 -63
  9. package/docs/error-handling.md +71 -0
  10. package/docs/runbook-trusted-contacts.md +89 -52
  11. package/docs/trusted-contact-access.md +48 -46
  12. package/package.json +3 -3
  13. package/scripts/compare-benchmarks.sh +12 -5
  14. package/scripts/ipc/check-swift-decoder-drift.ts +5 -3
  15. package/scripts/test.sh +89 -5
  16. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +50 -37
  17. package/src/__tests__/access-request-decision.test.ts +0 -1
  18. package/src/__tests__/account-registry.test.ts +1 -1
  19. package/src/__tests__/actor-token-service.test.ts +40 -26
  20. package/src/__tests__/agent-loop-thinking.test.ts +29 -13
  21. package/src/__tests__/agent-loop.test.ts +2 -1
  22. package/src/__tests__/app-builder-tool-scripts.test.ts +1 -1
  23. package/src/__tests__/app-executors.test.ts +7 -17
  24. package/src/__tests__/approval-routes-http.test.ts +2 -2
  25. package/src/__tests__/asset-materialize-tool.test.ts +7 -7
  26. package/src/__tests__/asset-search-tool.test.ts +7 -7
  27. package/src/__tests__/assistant-feature-flags-integration.test.ts +18 -10
  28. package/src/__tests__/browser-fill-credential.test.ts +1 -1
  29. package/src/__tests__/browser-skill-endstate.test.ts +10 -1
  30. package/src/__tests__/bundled-skill-retrieval-guard.test.ts +218 -0
  31. package/src/__tests__/call-controller.test.ts +99 -69
  32. package/src/__tests__/call-start-guardian-guard.test.ts +1 -1
  33. package/src/__tests__/channel-approval-routes.test.ts +157 -114
  34. package/src/__tests__/channel-approval.test.ts +8 -0
  35. package/src/__tests__/channel-approvals.test.ts +39 -1
  36. package/src/__tests__/channel-guardian.test.ts +176 -275
  37. package/src/__tests__/channel-readiness-service.test.ts +6 -2
  38. package/src/__tests__/channel-reply-delivery.test.ts +33 -2
  39. package/src/__tests__/channel-retry-sweep.test.ts +14 -14
  40. package/src/__tests__/checker.test.ts +12 -31
  41. package/src/__tests__/claude-code-tool-profiles.test.ts +1 -1
  42. package/src/__tests__/commit-message-enrichment-service.test.ts +71 -59
  43. package/src/__tests__/compaction.benchmark.test.ts +6 -2
  44. package/src/__tests__/computer-use-tools.test.ts +1 -1
  45. package/src/__tests__/config-schema.test.ts +66 -7
  46. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +29 -29
  47. package/src/__tests__/contacts-tools.test.ts +63 -2
  48. package/src/__tests__/context-overflow-approval.test.ts +141 -0
  49. package/src/__tests__/context-overflow-policy.test.ts +171 -0
  50. package/src/__tests__/context-overflow-reducer.test.ts +533 -0
  51. package/src/__tests__/context-window-manager.test.ts +97 -0
  52. package/src/__tests__/conversation-attention-telegram.test.ts +38 -46
  53. package/src/__tests__/conversation-pairing.test.ts +2 -2
  54. package/src/__tests__/conversation-routes-guardian-reply.test.ts +214 -10
  55. package/src/__tests__/conversation-routes.test.ts +4 -7
  56. package/src/__tests__/credential-broker-browser-fill.test.ts +13 -2
  57. package/src/__tests__/credential-security-e2e.test.ts +1 -1
  58. package/src/__tests__/credential-security-invariants.test.ts +1 -1
  59. package/src/__tests__/credential-vault-unit.test.ts +1 -1
  60. package/src/__tests__/credential-vault.test.ts +11 -8
  61. package/src/__tests__/daemon-lifecycle.test.ts +2 -2
  62. package/src/__tests__/daemon-server-session-init.test.ts +6 -6
  63. package/src/__tests__/delete-managed-skill-tool.test.ts +1 -1
  64. package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -2
  65. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +9 -0
  66. package/src/__tests__/emit-signal-routing-intent.test.ts +4 -0
  67. package/src/__tests__/encrypted-store.test.ts +10 -7
  68. package/src/__tests__/ephemeral-permissions.test.ts +3 -3
  69. package/src/__tests__/file-edit-tool.test.ts +1 -1
  70. package/src/__tests__/file-read-tool.test.ts +1 -1
  71. package/src/__tests__/file-write-tool.test.ts +1 -1
  72. package/src/__tests__/fixtures/credential-security-fixtures.ts +87 -64
  73. package/src/__tests__/fixtures/media-reuse-fixtures.ts +37 -31
  74. package/src/__tests__/fixtures/mock-signup-server.ts +171 -115
  75. package/src/__tests__/fixtures/proxy-fixtures.ts +39 -39
  76. package/src/__tests__/followup-tools.test.ts +1 -1
  77. package/src/__tests__/gateway-only-guard.test.ts +4 -0
  78. package/src/__tests__/gemini-image-service.test.ts +2 -2
  79. package/src/__tests__/guardian-actions-endpoint.test.ts +543 -1
  80. package/src/__tests__/guardian-control-plane-policy.test.ts +15 -15
  81. package/src/__tests__/guardian-dispatch.test.ts +79 -1
  82. package/src/__tests__/guardian-grant-minting.test.ts +20 -20
  83. package/src/__tests__/guardian-outbound-http.test.ts +1 -2
  84. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -41
  85. package/src/__tests__/guardian-routing-invariants.test.ts +36 -16
  86. package/src/__tests__/guardian-routing-state.test.ts +36 -52
  87. package/src/__tests__/guardian-verification-intent-routing.test.ts +4 -6
  88. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +6 -8
  89. package/src/__tests__/handle-user-message-secret-resume.test.ts +39 -1
  90. package/src/__tests__/handlers-cu-observation-blob.test.ts +21 -10
  91. package/src/__tests__/handlers-telegram-config.test.ts +14 -14
  92. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +23 -2
  93. package/src/__tests__/headless-browser-interactions.test.ts +1 -1
  94. package/src/__tests__/headless-browser-navigate.test.ts +1 -1
  95. package/src/__tests__/headless-browser-read-tools.test.ts +1 -1
  96. package/src/__tests__/headless-browser-snapshot.test.ts +1 -1
  97. package/src/__tests__/heartbeat-service.test.ts +45 -2
  98. package/src/__tests__/host-file-edit-tool.test.ts +1 -1
  99. package/src/__tests__/host-file-read-tool.test.ts +1 -1
  100. package/src/__tests__/host-file-write-tool.test.ts +1 -1
  101. package/src/__tests__/host-shell-tool.test.ts +1 -1
  102. package/src/__tests__/inbound-invite-redemption.test.ts +17 -19
  103. package/src/__tests__/ingress-reconcile.test.ts +2 -2
  104. package/src/__tests__/integrations-cli.test.ts +232 -0
  105. package/src/__tests__/intent-routing.test.ts +7 -5
  106. package/src/__tests__/invite-redemption-service.test.ts +5 -4
  107. package/src/__tests__/{ingress-routes-http.test.ts → invite-routes-http.test.ts} +42 -321
  108. package/src/__tests__/ipc-snapshot.test.ts +32 -31
  109. package/src/__tests__/managed-skill-lifecycle.test.ts +1 -1
  110. package/src/__tests__/mcp-cli.test.ts +136 -57
  111. package/src/__tests__/mcp-client-auth.test.ts +95 -0
  112. package/src/__tests__/media-generate-image.test.ts +2 -2
  113. package/src/__tests__/media-reuse-story.e2e.test.ts +8 -8
  114. package/src/__tests__/memory-regressions.test.ts +6 -6
  115. package/src/__tests__/messaging-send-tool.test.ts +1 -1
  116. package/src/__tests__/migration-cross-version-compatibility.test.ts +1855 -0
  117. package/src/__tests__/migration-export-http.test.ts +540 -0
  118. package/src/__tests__/migration-import-commit-http.test.ts +823 -0
  119. package/src/__tests__/migration-import-preflight-http.test.ts +755 -0
  120. package/src/__tests__/migration-parity-persistence.test.ts +1854 -0
  121. package/src/__tests__/migration-transport.test.ts +904 -0
  122. package/src/__tests__/migration-validate-http.test.ts +698 -0
  123. package/src/__tests__/migration-wizard.test.ts +1289 -0
  124. package/src/__tests__/nl-approval-parser.test.ts +305 -0
  125. package/src/__tests__/non-member-access-request.test.ts +17 -17
  126. package/src/__tests__/notification-decision-strategy.test.ts +110 -2
  127. package/src/__tests__/notification-deep-link.test.ts +18 -0
  128. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  129. package/src/__tests__/oauth-provider-profiles.test.ts +34 -0
  130. package/src/__tests__/oauth2-gateway-transport.test.ts +1 -1
  131. package/src/__tests__/playbook-execution.test.ts +1 -1
  132. package/src/__tests__/playbook-tools.test.ts +1 -1
  133. package/src/__tests__/provider-error-scenarios.test.ts +68 -0
  134. package/src/__tests__/provider-streaming.benchmark.test.ts +3 -1
  135. package/src/__tests__/proxy-approval-callback.test.ts +1 -1
  136. package/src/__tests__/qdrant-manager.test.ts +40 -11
  137. package/src/__tests__/rebind-secrets-screen.test.ts +839 -0
  138. package/src/__tests__/recording-handler.test.ts +2 -2
  139. package/src/__tests__/recording-intent-handler.test.ts +3 -3
  140. package/src/__tests__/recording-state-machine.test.ts +2 -2
  141. package/src/__tests__/relay-server.test.ts +507 -228
  142. package/src/__tests__/reminder-store.test.ts +8 -0
  143. package/src/__tests__/reminder.test.ts +8 -0
  144. package/src/__tests__/{resolve-guardian-trust-class.test.ts → resolve-trust-class.test.ts} +11 -17
  145. package/src/__tests__/retry-after-extraction.test.ts +111 -0
  146. package/src/__tests__/scaffold-managed-skill-tool.test.ts +1 -1
  147. package/src/__tests__/schedule-tools.test.ts +1 -1
  148. package/src/__tests__/script-proxy-certs.test.ts +1 -1
  149. package/src/__tests__/script-proxy-connect-tunnel.test.ts +2 -3
  150. package/src/__tests__/script-proxy-decision-trace.test.ts +2 -2
  151. package/src/__tests__/script-proxy-http-forwarder.test.ts +1 -1
  152. package/src/__tests__/script-proxy-injection-runtime.test.ts +5 -5
  153. package/src/__tests__/script-proxy-mitm-handler.test.ts +4 -4
  154. package/src/__tests__/script-proxy-policy-runtime.test.ts +2 -2
  155. package/src/__tests__/script-proxy-policy.test.ts +2 -2
  156. package/src/__tests__/script-proxy-profile-template-fallback.test.ts +127 -0
  157. package/src/__tests__/script-proxy-session-manager.test.ts +4 -7
  158. package/src/__tests__/script-proxy-session-runtime.test.ts +1 -6
  159. package/src/__tests__/secret-onetime-send.test.ts +4 -4
  160. package/src/__tests__/secret-scanner-executor.test.ts +2 -2
  161. package/src/__tests__/send-endpoint-busy.test.ts +11 -9
  162. package/src/__tests__/send-notification-tool.test.ts +2 -2
  163. package/src/__tests__/session-abort-tool-results.test.ts +17 -2
  164. package/src/__tests__/session-agent-loop.test.ts +456 -35
  165. package/src/__tests__/session-confirmation-signals.test.ts +3 -2
  166. package/src/__tests__/session-conflict-gate.test.ts +20 -3
  167. package/src/__tests__/session-init.benchmark.test.ts +2 -2
  168. package/src/__tests__/session-load-history-repair.test.ts +7 -7
  169. package/src/__tests__/session-media-retry.test.ts +147 -0
  170. package/src/__tests__/session-pre-run-repair.test.ts +17 -2
  171. package/src/__tests__/session-profile-injection.test.ts +20 -3
  172. package/src/__tests__/session-provider-retry-repair.test.ts +86 -6
  173. package/src/__tests__/session-queue.test.ts +33 -18
  174. package/src/__tests__/session-runtime-assembly.test.ts +147 -1
  175. package/src/__tests__/session-runtime-workspace.test.ts +40 -0
  176. package/src/__tests__/session-slash-known.test.ts +21 -3
  177. package/src/__tests__/session-slash-queue.test.ts +17 -2
  178. package/src/__tests__/session-slash-unknown.test.ts +17 -2
  179. package/src/__tests__/session-surfaces-deselection.test.ts +208 -0
  180. package/src/__tests__/session-workspace-cache-state.test.ts +2 -2
  181. package/src/__tests__/session-workspace-injection.test.ts +17 -2
  182. package/src/__tests__/session-workspace-tool-tracking.test.ts +17 -2
  183. package/src/__tests__/shell-credential-ref.test.ts +1 -1
  184. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  185. package/src/__tests__/skill-feature-flags-integration.test.ts +9 -5
  186. package/src/__tests__/skill-feature-flags.test.ts +18 -12
  187. package/src/__tests__/skill-load-feature-flag.test.ts +5 -4
  188. package/src/__tests__/skill-load-tool.test.ts +1 -1
  189. package/src/__tests__/skill-script-runner-host.test.ts +1 -1
  190. package/src/__tests__/skill-script-runner-sandbox.test.ts +1 -1
  191. package/src/__tests__/skill-script-runner.test.ts +1 -1
  192. package/src/__tests__/skill-tool-factory.test.ts +1 -1
  193. package/src/__tests__/slack-block-formatting.test.ts +100 -0
  194. package/src/__tests__/slack-inbound-verification.test.ts +346 -0
  195. package/src/__tests__/slack-reaction-approvals.test.ts +77 -0
  196. package/src/__tests__/slack-skill.test.ts +4 -2
  197. package/src/__tests__/starter-task-flow.test.ts +0 -1
  198. package/src/__tests__/subagent-tools.test.ts +3 -3
  199. package/src/__tests__/swarm-recursion.test.ts +1 -1
  200. package/src/__tests__/swarm-session-integration.test.ts +1 -1
  201. package/src/__tests__/swarm-tool.test.ts +1 -1
  202. package/src/__tests__/task-management-tools.test.ts +1 -1
  203. package/src/__tests__/task-tools.test.ts +1 -1
  204. package/src/__tests__/terminal-tools.test.ts +1 -1
  205. package/src/__tests__/test-support/browser-skill-harness.ts +39 -27
  206. package/src/__tests__/test-support/computer-use-skill-harness.ts +14 -14
  207. package/src/__tests__/tool-approval-handler.test.ts +15 -15
  208. package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -1
  209. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
  210. package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
  211. package/src/__tests__/tool-executor-shell-integration.test.ts +1 -1
  212. package/src/__tests__/tool-executor.test.ts +23 -182
  213. package/src/__tests__/tool-grant-request-escalation.test.ts +11 -11
  214. package/src/__tests__/tool-permission-simulate-handler.test.ts +4 -4
  215. package/src/__tests__/transfer-progress-screen.test.ts +1180 -0
  216. package/src/__tests__/trust-context-guards.test.ts +25 -29
  217. package/src/__tests__/trusted-contact-approval-notifier.test.ts +23 -21
  218. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +37 -40
  219. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +29 -25
  220. package/src/__tests__/trusted-contact-multichannel.test.ts +25 -24
  221. package/src/__tests__/trusted-contact-verification.test.ts +64 -76
  222. package/src/__tests__/turn-commit.test.ts +18 -18
  223. package/src/__tests__/twilio-provider.test.ts +7 -7
  224. package/src/__tests__/validation-results-screen.test.ts +1107 -0
  225. package/src/__tests__/view-image-tool.test.ts +1 -1
  226. package/src/__tests__/voice-invite-redemption.test.ts +4 -3
  227. package/src/__tests__/voice-scoped-grant-consumer.test.ts +12 -12
  228. package/src/__tests__/voice-session-bridge.test.ts +24 -24
  229. package/src/agent/attachments.ts +3 -1
  230. package/src/agent/loop.ts +13 -13
  231. package/src/agent/message-types.ts +13 -7
  232. package/src/amazon/cart.ts +59 -32
  233. package/src/amazon/checkout.ts +25 -14
  234. package/src/amazon/client.ts +61 -58
  235. package/src/amazon/product-details.ts +3 -3
  236. package/src/amazon/request-extractor.ts +46 -31
  237. package/src/amazon/search.ts +6 -4
  238. package/src/amazon/session.ts +33 -24
  239. package/src/approvals/AGENTS.md +26 -0
  240. package/src/approvals/approval-primitive.ts +87 -64
  241. package/src/approvals/guardian-decision-primitive.ts +172 -81
  242. package/src/approvals/guardian-request-resolvers.ts +262 -155
  243. package/src/autonomy/autonomy-resolver.ts +7 -5
  244. package/src/autonomy/autonomy-store.ts +34 -19
  245. package/src/autonomy/disposition-mapper.ts +5 -5
  246. package/src/autonomy/index.ts +6 -6
  247. package/src/autonomy/types.ts +7 -3
  248. package/src/browser-extension-relay/client.ts +50 -19
  249. package/src/browser-extension-relay/protocol.ts +11 -11
  250. package/src/browser-extension-relay/server.ts +45 -20
  251. package/src/bundler/app-bundler.ts +75 -50
  252. package/src/bundler/bundle-scanner.ts +145 -41
  253. package/src/bundler/bundle-signer.ts +16 -14
  254. package/src/bundler/signature-verifier.ts +36 -33
  255. package/src/calls/call-constants.ts +10 -3
  256. package/src/calls/call-controller.ts +473 -214
  257. package/src/calls/call-conversation-messages.ts +25 -15
  258. package/src/calls/call-domain.ts +401 -148
  259. package/src/calls/call-pointer-message-composer.ts +26 -21
  260. package/src/calls/call-pointer-messages.ts +52 -28
  261. package/src/calls/call-recovery.ts +53 -37
  262. package/src/calls/call-state-machine.ts +37 -7
  263. package/src/calls/call-state.ts +35 -13
  264. package/src/calls/call-store.ts +165 -77
  265. package/src/calls/elevenlabs-client.ts +39 -20
  266. package/src/calls/guardian-action-sweep.ts +42 -24
  267. package/src/calls/guardian-dispatch.ts +79 -56
  268. package/src/calls/guardian-question-copy.ts +28 -23
  269. package/src/calls/relay-server.ts +1149 -532
  270. package/src/calls/speaker-identification.ts +21 -15
  271. package/src/calls/twilio-config.ts +34 -17
  272. package/src/calls/twilio-provider.ts +108 -55
  273. package/src/calls/twilio-rest.ts +212 -100
  274. package/src/calls/twilio-routes.ts +165 -92
  275. package/src/calls/types.ts +55 -7
  276. package/src/calls/voice-quality.ts +6 -4
  277. package/src/calls/voice-session-bridge.ts +181 -133
  278. package/src/channels/config.ts +18 -14
  279. package/src/channels/types.ts +38 -10
  280. package/src/cli/amazon.ts +333 -227
  281. package/src/cli/config-commands.ts +236 -146
  282. package/src/cli/core-commands.ts +403 -329
  283. package/src/cli/email-guardrails.ts +38 -19
  284. package/src/cli/email.ts +207 -153
  285. package/src/cli/influencer.ts +58 -56
  286. package/src/cli/integrations.ts +306 -0
  287. package/src/cli/ipc-client.ts +24 -19
  288. package/src/cli/map.ts +176 -129
  289. package/src/cli/mcp.ts +260 -152
  290. package/src/cli/sequence.ts +165 -107
  291. package/src/cli/twitter.ts +302 -218
  292. package/src/cli.ts +418 -279
  293. package/src/commands/cc-command-registry.ts +52 -27
  294. package/src/config/agent-schema.ts +217 -134
  295. package/src/config/assistant-feature-flags.ts +23 -18
  296. package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +19 -0
  297. package/src/config/bundled-skills/app-builder/SKILL.md +193 -1500
  298. package/src/config/bundled-skills/app-builder/TOOLS.json +70 -18
  299. package/src/config/bundled-skills/app-builder/tools/app-create.ts +7 -4
  300. package/src/config/bundled-skills/app-builder/tools/app-delete.ts +6 -3
  301. package/src/config/bundled-skills/app-builder/tools/app-file-edit.ts +7 -4
  302. package/src/config/bundled-skills/app-builder/tools/app-file-list.ts +6 -3
  303. package/src/config/bundled-skills/app-builder/tools/app-file-read.ts +6 -3
  304. package/src/config/bundled-skills/app-builder/tools/app-file-write.ts +7 -4
  305. package/src/config/bundled-skills/app-builder/tools/app-list.ts +6 -3
  306. package/src/config/bundled-skills/app-builder/tools/app-query.ts +6 -3
  307. package/src/config/bundled-skills/app-builder/tools/app-update.ts +6 -3
  308. package/src/config/bundled-skills/browser/TOOLS.json +59 -2
  309. package/src/config/bundled-skills/browser/tools/browser-click.ts +5 -2
  310. package/src/config/bundled-skills/browser/tools/browser-close.ts +5 -2
  311. package/src/config/bundled-skills/browser/tools/browser-extract.ts +5 -2
  312. package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +5 -2
  313. package/src/config/bundled-skills/browser/tools/browser-hover.ts +5 -2
  314. package/src/config/bundled-skills/browser/tools/browser-navigate.ts +5 -2
  315. package/src/config/bundled-skills/browser/tools/browser-press-key.ts +5 -2
  316. package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +5 -2
  317. package/src/config/bundled-skills/browser/tools/browser-scroll.ts +5 -2
  318. package/src/config/bundled-skills/browser/tools/browser-select-option.ts +5 -2
  319. package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +5 -2
  320. package/src/config/bundled-skills/browser/tools/browser-type.ts +5 -2
  321. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +13 -6
  322. package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +5 -2
  323. package/src/config/bundled-skills/chatgpt-import/TOOLS.json +4 -0
  324. package/src/config/bundled-skills/claude-code/TOOLS.json +4 -0
  325. package/src/config/bundled-skills/claude-code/tools/claude-code.ts +5 -2
  326. package/src/config/bundled-skills/computer-use/SKILL.md +2 -2
  327. package/src/config/bundled-skills/computer-use/TOOLS.json +50 -2
  328. package/src/config/bundled-skills/computer-use/tools/computer-use-click.ts +6 -3
  329. package/src/config/bundled-skills/computer-use/tools/computer-use-done.ts +6 -3
  330. package/src/config/bundled-skills/computer-use/tools/computer-use-double-click.ts +10 -3
  331. package/src/config/bundled-skills/computer-use/tools/computer-use-drag.ts +6 -3
  332. package/src/config/bundled-skills/computer-use/tools/computer-use-key.ts +6 -3
  333. package/src/config/bundled-skills/computer-use/tools/computer-use-open-app.ts +6 -3
  334. package/src/config/bundled-skills/computer-use/tools/computer-use-request-control.ts +10 -3
  335. package/src/config/bundled-skills/computer-use/tools/computer-use-respond.ts +6 -3
  336. package/src/config/bundled-skills/computer-use/tools/computer-use-right-click.ts +10 -3
  337. package/src/config/bundled-skills/computer-use/tools/computer-use-run-applescript.ts +10 -3
  338. package/src/config/bundled-skills/computer-use/tools/computer-use-scroll.ts +6 -3
  339. package/src/config/bundled-skills/computer-use/tools/computer-use-type-text.ts +6 -3
  340. package/src/config/bundled-skills/computer-use/tools/computer-use-wait.ts +6 -3
  341. package/src/config/bundled-skills/configure-settings/SKILL.md +28 -14
  342. package/src/config/bundled-skills/contacts/SKILL.md +453 -15
  343. package/src/config/bundled-skills/contacts/TOOLS.json +22 -2
  344. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +79 -20
  345. package/src/config/bundled-skills/contacts/tools/contact-search.ts +55 -18
  346. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +64 -19
  347. package/src/config/bundled-skills/document/TOOLS.json +8 -0
  348. package/src/config/bundled-skills/document/tools/document-create.ts +5 -2
  349. package/src/config/bundled-skills/document/tools/document-update.ts +5 -2
  350. package/src/config/bundled-skills/doordash/doordash-cli.ts +17 -7
  351. package/src/config/bundled-skills/email-setup/SKILL.md +12 -9
  352. package/src/config/bundled-skills/followups/TOOLS.json +12 -0
  353. package/src/config/bundled-skills/followups/tools/followup-create.ts +5 -2
  354. package/src/config/bundled-skills/followups/tools/followup-list.ts +5 -2
  355. package/src/config/bundled-skills/followups/tools/followup-resolve.ts +5 -2
  356. package/src/config/bundled-skills/google-calendar/TOOLS.json +124 -26
  357. package/src/config/bundled-skills/google-calendar/calendar-client.ts +44 -32
  358. package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +11 -5
  359. package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +13 -7
  360. package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +11 -5
  361. package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +13 -7
  362. package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +28 -12
  363. package/src/config/bundled-skills/google-calendar/tools/shared.ts +6 -4
  364. package/src/config/bundled-skills/google-calendar/types.ts +3 -3
  365. package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +88 -33
  366. package/src/config/bundled-skills/image-studio/TOOLS.json +12 -2
  367. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +48 -25
  368. package/src/config/bundled-skills/knowledge-graph/TOOLS.json +13 -3
  369. package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +60 -35
  370. package/src/config/bundled-skills/mcp-setup/SKILL.md +75 -0
  371. package/src/config/bundled-skills/media-processing/SKILL.md +55 -15
  372. package/src/config/bundled-skills/media-processing/TOOLS.json +48 -2
  373. package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +12 -10
  374. package/src/config/bundled-skills/media-processing/__tests__/cost-tracker.test.ts +34 -19
  375. package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +82 -66
  376. package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +148 -0
  377. package/src/config/bundled-skills/media-processing/services/concurrency-pool.ts +1 -1
  378. package/src/config/bundled-skills/media-processing/services/cost-tracker.ts +8 -3
  379. package/src/config/bundled-skills/media-processing/services/gemini-map.ts +117 -53
  380. package/src/config/bundled-skills/media-processing/services/gemini-video.ts +273 -0
  381. package/src/config/bundled-skills/media-processing/services/preprocess.ts +185 -97
  382. package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +32 -27
  383. package/src/config/bundled-skills/media-processing/services/reduce.ts +101 -24
  384. package/src/config/bundled-skills/media-processing/tools/analyze-keyframes.ts +121 -55
  385. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +58 -24
  386. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +198 -92
  387. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +98 -70
  388. package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +59 -19
  389. package/src/config/bundled-skills/media-processing/tools/media-status.ts +26 -10
  390. package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +29 -14
  391. package/src/config/bundled-skills/messaging/SKILL.md +7 -5
  392. package/src/config/bundled-skills/messaging/TOOLS.json +232 -186
  393. package/src/config/bundled-skills/messaging/tools/gmail-archive-by-query.ts +31 -13
  394. package/src/config/bundled-skills/messaging/tools/gmail-archive.ts +16 -10
  395. package/src/config/bundled-skills/messaging/tools/gmail-batch-label.ts +18 -9
  396. package/src/config/bundled-skills/messaging/tools/gmail-download-attachment.ts +23 -16
  397. package/src/config/bundled-skills/messaging/tools/gmail-draft.ts +28 -12
  398. package/src/config/bundled-skills/messaging/tools/gmail-filters.ts +41 -21
  399. package/src/config/bundled-skills/messaging/tools/gmail-follow-up.ts +44 -23
  400. package/src/config/bundled-skills/messaging/tools/gmail-forward.ts +73 -33
  401. package/src/config/bundled-skills/messaging/tools/gmail-label.ts +15 -9
  402. package/src/config/bundled-skills/messaging/tools/gmail-list-attachments.ts +22 -14
  403. package/src/config/bundled-skills/messaging/tools/gmail-outreach-scan.ts +99 -50
  404. package/src/config/bundled-skills/messaging/tools/gmail-send-draft.ts +14 -8
  405. package/src/config/bundled-skills/messaging/tools/gmail-send-with-attachments.ts +63 -44
  406. package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +90 -46
  407. package/src/config/bundled-skills/messaging/tools/gmail-summarize-thread.ts +43 -22
  408. package/src/config/bundled-skills/messaging/tools/gmail-trash.ts +15 -9
  409. package/src/config/bundled-skills/messaging/tools/gmail-triage.ts +51 -22
  410. package/src/config/bundled-skills/messaging/tools/gmail-unsubscribe.ts +62 -26
  411. package/src/config/bundled-skills/messaging/tools/gmail-vacation.ts +34 -19
  412. package/src/config/bundled-skills/messaging/tools/google-contacts.ts +32 -16
  413. package/src/config/bundled-skills/messaging/tools/messaging-analyze-activity.ts +10 -4
  414. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +91 -47
  415. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +21 -9
  416. package/src/config/bundled-skills/messaging/tools/messaging-auth-test.ts +9 -3
  417. package/src/config/bundled-skills/messaging/tools/messaging-draft.ts +30 -17
  418. package/src/config/bundled-skills/messaging/tools/messaging-list-conversations.ts +10 -4
  419. package/src/config/bundled-skills/messaging/tools/messaging-mark-read.ts +14 -6
  420. package/src/config/bundled-skills/messaging/tools/messaging-read.ts +16 -5
  421. package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +63 -36
  422. package/src/config/bundled-skills/messaging/tools/messaging-search.ts +10 -4
  423. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +30 -12
  424. package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +48 -29
  425. package/src/config/bundled-skills/messaging/tools/scan-result-store.ts +20 -6
  426. package/src/config/bundled-skills/messaging/tools/send-notification.ts +1 -1
  427. package/src/config/bundled-skills/messaging/tools/sequence-analytics.ts +59 -22
  428. package/src/config/bundled-skills/messaging/tools/sequence-cancel.ts +13 -7
  429. package/src/config/bundled-skills/messaging/tools/sequence-create.ts +27 -12
  430. package/src/config/bundled-skills/messaging/tools/sequence-delete.ts +14 -6
  431. package/src/config/bundled-skills/messaging/tools/sequence-enroll.ts +30 -11
  432. package/src/config/bundled-skills/messaging/tools/sequence-enrollment-list.ts +16 -8
  433. package/src/config/bundled-skills/messaging/tools/sequence-get.ts +31 -13
  434. package/src/config/bundled-skills/messaging/tools/sequence-import.ts +38 -22
  435. package/src/config/bundled-skills/messaging/tools/sequence-list.ts +16 -7
  436. package/src/config/bundled-skills/messaging/tools/sequence-pause.ts +29 -10
  437. package/src/config/bundled-skills/messaging/tools/sequence-resume.ts +16 -8
  438. package/src/config/bundled-skills/messaging/tools/sequence-update.ts +35 -16
  439. package/src/config/bundled-skills/messaging/tools/shared.ts +26 -12
  440. package/src/config/bundled-skills/notifications/SKILL.md +3 -2
  441. package/src/config/bundled-skills/notifications/TOOLS.json +7 -13
  442. package/src/config/bundled-skills/notifications/tools/send-notification.ts +69 -34
  443. package/src/config/bundled-skills/notifications/tools/shared.ts +1 -1
  444. package/src/config/bundled-skills/phone-calls/SKILL.md +46 -48
  445. package/src/config/bundled-skills/phone-calls/TOOLS.json +13 -1
  446. package/src/config/bundled-skills/phone-calls/tools/call-end.ts +1 -1
  447. package/src/config/bundled-skills/phone-calls/tools/call-start.ts +1 -1
  448. package/src/config/bundled-skills/phone-calls/tools/call-status.ts +1 -1
  449. package/src/config/bundled-skills/playbooks/TOOLS.json +16 -0
  450. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +91 -51
  451. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +30 -16
  452. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +66 -27
  453. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +89 -42
  454. package/src/config/bundled-skills/public-ingress/SKILL.md +26 -19
  455. package/src/config/bundled-skills/reminder/TOOLS.json +15 -2
  456. package/src/config/bundled-skills/reminder/tools/reminder-cancel.ts +5 -2
  457. package/src/config/bundled-skills/reminder/tools/reminder-create.ts +5 -2
  458. package/src/config/bundled-skills/reminder/tools/reminder-list.ts +5 -2
  459. package/src/config/bundled-skills/schedule/SKILL.md +33 -15
  460. package/src/config/bundled-skills/schedule/TOOLS.json +17 -1
  461. package/src/config/bundled-skills/schedule/tools/schedule-create.ts +5 -2
  462. package/src/config/bundled-skills/schedule/tools/schedule-delete.ts +5 -2
  463. package/src/config/bundled-skills/schedule/tools/schedule-list.ts +5 -2
  464. package/src/config/bundled-skills/schedule/tools/schedule-update.ts +5 -2
  465. package/src/config/bundled-skills/screen-recording/SKILL.md +11 -3
  466. package/src/config/bundled-skills/self-upgrade/SKILL.md +9 -8
  467. package/src/config/bundled-skills/slack/SKILL.md +30 -1
  468. package/src/config/bundled-skills/slack/TOOLS.json +122 -17
  469. package/src/config/bundled-skills/slack/tools/shared.ts +7 -5
  470. package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +11 -5
  471. package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +11 -5
  472. package/src/config/bundled-skills/slack/tools/slack-channel-permissions.ts +146 -0
  473. package/src/config/bundled-skills/slack/tools/slack-configure-channels.ts +46 -16
  474. package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +11 -5
  475. package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +28 -0
  476. package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +12 -6
  477. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +120 -0
  478. package/src/config/bundled-skills/slack-app-setup/SKILL.md +200 -0
  479. package/src/config/bundled-skills/sms-setup/SKILL.md +5 -8
  480. package/src/config/bundled-skills/subagent/TOOLS.json +22 -2
  481. package/src/config/bundled-skills/subagent/tools/subagent-abort.ts +5 -2
  482. package/src/config/bundled-skills/subagent/tools/subagent-message.ts +5 -2
  483. package/src/config/bundled-skills/subagent/tools/subagent-read.ts +5 -2
  484. package/src/config/bundled-skills/subagent/tools/subagent-spawn.ts +5 -2
  485. package/src/config/bundled-skills/subagent/tools/subagent-status.ts +5 -2
  486. package/src/config/bundled-skills/tasks/TOOLS.json +86 -14
  487. package/src/config/bundled-skills/tasks/tools/task-delete.ts +5 -2
  488. package/src/config/bundled-skills/tasks/tools/task-list-add.ts +5 -2
  489. package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +5 -2
  490. package/src/config/bundled-skills/tasks/tools/task-list-show.ts +5 -2
  491. package/src/config/bundled-skills/tasks/tools/task-list-update.ts +5 -2
  492. package/src/config/bundled-skills/tasks/tools/task-list.ts +5 -2
  493. package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +5 -2
  494. package/src/config/bundled-skills/tasks/tools/task-run.ts +5 -2
  495. package/src/config/bundled-skills/tasks/tools/task-save.ts +5 -2
  496. package/src/config/bundled-skills/telegram-setup/SKILL.md +7 -8
  497. package/src/config/bundled-skills/transcribe/TOOLS.json +4 -0
  498. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +232 -127
  499. package/src/config/bundled-skills/twilio-setup/SKILL.md +7 -12
  500. package/src/config/bundled-skills/twitter/SKILL.md +19 -2
  501. package/src/config/bundled-skills/voice-setup/SKILL.md +5 -5
  502. package/src/config/bundled-skills/watcher/TOOLS.json +20 -0
  503. package/src/config/bundled-skills/watcher/tools/watcher-create.ts +5 -2
  504. package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +5 -2
  505. package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +5 -2
  506. package/src/config/bundled-skills/watcher/tools/watcher-list.ts +5 -2
  507. package/src/config/bundled-skills/watcher/tools/watcher-update.ts +5 -2
  508. package/src/config/bundled-skills/weather/TOOLS.json +4 -0
  509. package/src/config/bundled-skills/weather/tools/get-weather.ts +5 -2
  510. package/src/config/bundled-tool-registry.ts +2 -0
  511. package/src/config/calls-schema.ts +108 -63
  512. package/src/config/channel-permission-profiles.ts +155 -0
  513. package/src/config/computer-use-prompt.ts +7 -7
  514. package/src/config/core-schema.ts +239 -155
  515. package/src/config/defaults.ts +2 -2
  516. package/src/config/elevenlabs-schema.ts +15 -15
  517. package/src/config/env-registry.ts +33 -33
  518. package/src/config/env.ts +4 -1
  519. package/src/config/feature-flag-registry.json +31 -7
  520. package/src/config/loader.ts +118 -58
  521. package/src/config/mcp-schema.ts +29 -15
  522. package/src/config/memory-schema.ts +434 -229
  523. package/src/config/notifications-schema.ts +4 -4
  524. package/src/config/sandbox-schema.ts +2 -2
  525. package/src/config/schema.ts +12 -2
  526. package/src/config/skill-state.ts +27 -15
  527. package/src/config/skills-schema.ts +72 -23
  528. package/src/config/skills.ts +303 -143
  529. package/src/config/system-prompt.ts +25 -6
  530. package/src/config/types.ts +1 -1
  531. package/src/config/update-bulletin-format.ts +3 -3
  532. package/src/config/update-bulletin-state.ts +15 -6
  533. package/src/config/update-bulletin-template-path.ts +8 -4
  534. package/src/config/update-bulletin.ts +33 -14
  535. package/src/config/user-reference.ts +8 -8
  536. package/src/contacts/contact-events.ts +21 -0
  537. package/src/contacts/contact-store.ts +813 -100
  538. package/src/contacts/contacts-write.ts +287 -0
  539. package/src/contacts/index.ts +13 -4
  540. package/src/contacts/startup-migration.ts +21 -0
  541. package/src/contacts/types.ts +73 -2
  542. package/src/context/token-estimator.ts +54 -31
  543. package/src/context/tool-result-truncation.ts +41 -7
  544. package/src/context/window-manager.ts +225 -120
  545. package/src/daemon/approval-generators.ts +83 -55
  546. package/src/daemon/approved-devices-store.ts +33 -20
  547. package/src/daemon/assistant-attachments.ts +157 -101
  548. package/src/daemon/auth-manager.ts +17 -15
  549. package/src/daemon/classifier.ts +117 -46
  550. package/src/daemon/computer-use-session.ts +316 -187
  551. package/src/daemon/config-watcher.ts +91 -44
  552. package/src/daemon/connection-policy.ts +18 -10
  553. package/src/daemon/context-overflow-approval.ts +48 -0
  554. package/src/daemon/context-overflow-policy.ts +50 -0
  555. package/src/daemon/context-overflow-reducer.ts +300 -0
  556. package/src/daemon/daemon-control.ts +79 -51
  557. package/src/daemon/date-context.ts +119 -69
  558. package/src/daemon/dictation-profile-store.ts +94 -48
  559. package/src/daemon/dictation-text-processing.ts +33 -12
  560. package/src/daemon/doordash-steps.ts +92 -49
  561. package/src/daemon/guardian-action-generators.ts +62 -46
  562. package/src/daemon/guardian-verification-intent.ts +35 -19
  563. package/src/daemon/handlers/apps.ts +258 -113
  564. package/src/daemon/handlers/avatar.ts +20 -15
  565. package/src/daemon/handlers/computer-use.ts +82 -39
  566. package/src/daemon/handlers/config-channels.ts +146 -69
  567. package/src/daemon/handlers/config-heartbeat.ts +114 -59
  568. package/src/daemon/handlers/config-inbox.ts +213 -160
  569. package/src/daemon/handlers/config-ingress.ts +127 -55
  570. package/src/daemon/handlers/config-integrations.ts +145 -88
  571. package/src/daemon/handlers/config-model.ts +58 -22
  572. package/src/daemon/handlers/config-platform.ts +40 -16
  573. package/src/daemon/handlers/config-scheduling.ts +109 -48
  574. package/src/daemon/handlers/config-slack-channel.ts +67 -35
  575. package/src/daemon/handlers/config-slack.ts +21 -20
  576. package/src/daemon/handlers/config-telegram.ts +100 -70
  577. package/src/daemon/handlers/config-tools.ts +103 -55
  578. package/src/daemon/handlers/config-trust.ts +50 -20
  579. package/src/daemon/handlers/config.ts +72 -24
  580. package/src/daemon/handlers/contacts.ts +163 -0
  581. package/src/daemon/handlers/diagnostics.ts +90 -48
  582. package/src/daemon/handlers/documents.ts +74 -46
  583. package/src/daemon/handlers/guardian-actions.ts +57 -77
  584. package/src/daemon/handlers/home-base.ts +19 -16
  585. package/src/daemon/handlers/identity.ts +65 -45
  586. package/src/daemon/handlers/index.ts +78 -54
  587. package/src/daemon/handlers/misc.ts +664 -234
  588. package/src/daemon/handlers/navigate-settings.ts +14 -11
  589. package/src/daemon/handlers/oauth-connect.ts +48 -35
  590. package/src/daemon/handlers/open-bundle-handler.ts +31 -24
  591. package/src/daemon/handlers/pairing.ts +51 -25
  592. package/src/daemon/handlers/publish.ts +55 -33
  593. package/src/daemon/handlers/recording.ts +378 -162
  594. package/src/daemon/handlers/sessions.ts +922 -423
  595. package/src/daemon/handlers/shared.ts +202 -117
  596. package/src/daemon/handlers/signing.ts +25 -6
  597. package/src/daemon/handlers/subagents.ts +117 -56
  598. package/src/daemon/handlers/twitter-auth.ts +70 -49
  599. package/src/daemon/handlers/work-items.ts +264 -112
  600. package/src/daemon/handlers/workspace-files.ts +27 -20
  601. package/src/daemon/handlers.ts +2 -2
  602. package/src/daemon/history-repair.ts +16 -15
  603. package/src/daemon/identity-helpers.ts +4 -4
  604. package/src/daemon/install-cli-launchers.ts +33 -22
  605. package/src/daemon/ipc-blob-store.ts +38 -24
  606. package/src/daemon/ipc-contract/apps.ts +61 -50
  607. package/src/daemon/ipc-contract/computer-use.ts +47 -37
  608. package/src/daemon/ipc-contract/contacts.ts +69 -0
  609. package/src/daemon/ipc-contract/diagnostics.ts +14 -14
  610. package/src/daemon/ipc-contract/documents.ts +8 -8
  611. package/src/daemon/ipc-contract/guardian-actions.ts +4 -4
  612. package/src/daemon/ipc-contract/inbox.ts +12 -71
  613. package/src/daemon/ipc-contract/integrations.ts +57 -44
  614. package/src/daemon/ipc-contract/memory.ts +3 -5
  615. package/src/daemon/ipc-contract/messages.ts +95 -69
  616. package/src/daemon/ipc-contract/notifications.ts +10 -6
  617. package/src/daemon/ipc-contract/pairing.ts +8 -8
  618. package/src/daemon/ipc-contract/schedules.ts +20 -20
  619. package/src/daemon/ipc-contract/sessions.ts +89 -57
  620. package/src/daemon/ipc-contract/settings.ts +12 -7
  621. package/src/daemon/ipc-contract/shared.ts +9 -7
  622. package/src/daemon/ipc-contract/skills.ts +46 -26
  623. package/src/daemon/ipc-contract/subagents.ts +9 -9
  624. package/src/daemon/ipc-contract/surfaces.ts +0 -1
  625. package/src/daemon/ipc-contract/trust.ts +11 -11
  626. package/src/daemon/ipc-contract/work-items.ts +33 -28
  627. package/src/daemon/ipc-contract/workspace.ts +28 -21
  628. package/src/daemon/ipc-contract-inventory.json +10 -4
  629. package/src/daemon/ipc-contract-inventory.ts +29 -26
  630. package/src/daemon/ipc-contract.ts +111 -44
  631. package/src/daemon/ipc-handler.ts +27 -19
  632. package/src/daemon/ipc-protocol.ts +22 -12
  633. package/src/daemon/ipc-validate.ts +91 -46
  634. package/src/daemon/lifecycle.ts +39 -3
  635. package/src/daemon/main.ts +10 -8
  636. package/src/daemon/media-visibility-policy.ts +3 -1
  637. package/src/daemon/pairing-store.ts +72 -40
  638. package/src/daemon/providers-setup.ts +35 -25
  639. package/src/daemon/recording-executor.ts +37 -30
  640. package/src/daemon/recording-intent-fallback.ts +58 -28
  641. package/src/daemon/recording-intent.ts +71 -61
  642. package/src/daemon/ride-shotgun-handler.ts +201 -121
  643. package/src/daemon/seed-files.ts +28 -17
  644. package/src/daemon/server.ts +23 -14
  645. package/src/daemon/session-agent-loop-handlers.ts +270 -135
  646. package/src/daemon/session-agent-loop.ts +796 -253
  647. package/src/daemon/session-attachments.ts +109 -40
  648. package/src/daemon/session-conflict-gate.ts +72 -28
  649. package/src/daemon/session-dynamic-profile.ts +36 -22
  650. package/src/daemon/session-error.ts +68 -45
  651. package/src/daemon/session-evictor.ts +17 -10
  652. package/src/daemon/session-history.ts +201 -89
  653. package/src/daemon/session-lifecycle.ts +80 -44
  654. package/src/daemon/session-media-retry.ts +104 -42
  655. package/src/daemon/session-memory.ts +77 -55
  656. package/src/daemon/session-messaging.ts +261 -111
  657. package/src/daemon/session-notifiers.ts +57 -45
  658. package/src/daemon/session-process.ts +370 -154
  659. package/src/daemon/session-queue-manager.ts +30 -13
  660. package/src/daemon/session-runtime-assembly.ts +61 -15
  661. package/src/daemon/session-skill-tools.ts +84 -36
  662. package/src/daemon/session-slash.ts +178 -113
  663. package/src/daemon/session-surfaces.ts +498 -212
  664. package/src/daemon/session-tool-setup.ts +24 -16
  665. package/src/daemon/session-usage.ts +26 -13
  666. package/src/daemon/session-workspace.ts +7 -4
  667. package/src/daemon/session.ts +18 -19
  668. package/src/daemon/shutdown-handlers.ts +36 -33
  669. package/src/daemon/tls-certs.ts +90 -57
  670. package/src/daemon/tool-side-effects.ts +97 -65
  671. package/src/daemon/trace-emitter.ts +8 -7
  672. package/src/daemon/video-thumbnail.ts +55 -25
  673. package/src/daemon/watch-handler.ts +164 -86
  674. package/src/email/provider.ts +1 -1
  675. package/src/email/providers/agentmail.ts +87 -45
  676. package/src/email/providers/index.ts +19 -14
  677. package/src/email/service.ts +52 -24
  678. package/src/email/types.ts +2 -2
  679. package/src/errors.ts +1 -1
  680. package/src/events/bus.ts +30 -10
  681. package/src/events/domain-events.ts +20 -13
  682. package/src/events/index.ts +6 -6
  683. package/src/events/tool-audit-listener.ts +34 -20
  684. package/src/events/tool-domain-event-publisher.ts +22 -20
  685. package/src/events/tool-metrics-listener.ts +26 -21
  686. package/src/events/tool-notification-listener.ts +5 -5
  687. package/src/events/tool-profiling-listener.ts +33 -23
  688. package/src/events/tool-trace-listener.ts +70 -46
  689. package/src/export/formatter.ts +38 -32
  690. package/src/followups/followup-store.ts +43 -36
  691. package/src/followups/index.ts +2 -2
  692. package/src/followups/types.ts +1 -1
  693. package/src/gallery/default-gallery.ts +37 -34
  694. package/src/gallery/gallery-manifest.ts +9 -9
  695. package/src/heartbeat/heartbeat-service.ts +59 -37
  696. package/src/home-base/app-link-store.ts +14 -12
  697. package/src/home-base/bootstrap.ts +14 -8
  698. package/src/home-base/prebuilt/seed.ts +34 -26
  699. package/src/home-base/prebuilt-home-base-updater.ts +14 -8
  700. package/src/hooks/cli.ts +56 -43
  701. package/src/hooks/config.ts +27 -14
  702. package/src/hooks/discovery.ts +53 -33
  703. package/src/hooks/manager.ts +50 -26
  704. package/src/hooks/runner.ts +35 -29
  705. package/src/hooks/templates.ts +38 -15
  706. package/src/hooks/types.ts +13 -13
  707. package/src/inbound/platform-callback-registration.ts +21 -15
  708. package/src/inbound/public-ingress-urls.ts +9 -6
  709. package/src/index.ts +20 -19
  710. package/src/influencer/client.ts +261 -117
  711. package/src/instrument.ts +3 -1
  712. package/src/logfire.ts +64 -39
  713. package/src/mcp/client.ts +107 -55
  714. package/src/mcp/manager.ts +45 -18
  715. package/src/mcp/mcp-oauth-provider.ts +114 -62
  716. package/src/media/gemini-image-service.ts +75 -23
  717. package/src/memory/account-store.ts +16 -9
  718. package/src/memory/admin.ts +87 -57
  719. package/src/memory/app-git-service.ts +77 -47
  720. package/src/memory/app-store.ts +148 -78
  721. package/src/memory/attachments-store.ts +123 -53
  722. package/src/memory/canonical-guardian-store.ts +190 -48
  723. package/src/memory/channel-delivery-store.ts +5 -5
  724. package/src/memory/channel-guardian-store.ts +31 -16
  725. package/src/memory/checkpoints.ts +14 -7
  726. package/src/memory/clarification-resolver.ts +219 -104
  727. package/src/memory/conflict-intent.ts +74 -23
  728. package/src/memory/conflict-policy.ts +20 -7
  729. package/src/memory/conflict-store.ts +144 -94
  730. package/src/memory/contradiction-checker.ts +257 -132
  731. package/src/memory/conversation-attention-store.ts +74 -32
  732. package/src/memory/conversation-bootstrap.ts +28 -0
  733. package/src/memory/conversation-crud.ts +12 -5
  734. package/src/memory/conversation-display-order-migration.ts +7 -7
  735. package/src/memory/conversation-key-store.ts +18 -13
  736. package/src/memory/conversation-queries.ts +130 -52
  737. package/src/memory/conversation-store.ts +43 -26
  738. package/src/memory/conversation-title-service.ts +89 -66
  739. package/src/memory/db-init.ts +94 -2
  740. package/src/memory/db.ts +10 -3
  741. package/src/memory/delivery-channels.ts +12 -6
  742. package/src/memory/delivery-crud.ts +26 -12
  743. package/src/memory/delivery-status.ts +19 -16
  744. package/src/memory/embedding-backend.ts +205 -77
  745. package/src/memory/embedding-gemini.ts +23 -10
  746. package/src/memory/embedding-local.ts +89 -44
  747. package/src/memory/embedding-ollama.ts +25 -13
  748. package/src/memory/embedding-openai.ts +20 -11
  749. package/src/memory/embedding-runtime-manager.ts +163 -90
  750. package/src/memory/entity-extractor.ts +185 -123
  751. package/src/memory/external-conversation-store.ts +30 -12
  752. package/src/memory/fingerprint.ts +2 -2
  753. package/src/memory/fts-reconciler.ts +57 -28
  754. package/src/memory/guardian-action-store.ts +162 -100
  755. package/src/memory/guardian-approvals.ts +63 -129
  756. package/src/memory/guardian-rate-limits.ts +20 -9
  757. package/src/memory/guardian-verification.ts +82 -35
  758. package/src/memory/indexer.ts +96 -55
  759. package/src/memory/{ingress-invite-store.ts → invite-store.ts} +28 -169
  760. package/src/memory/items-extractor.ts +313 -157
  761. package/src/memory/job-handlers/backfill.ts +116 -63
  762. package/src/memory/job-handlers/cleanup.ts +64 -41
  763. package/src/memory/job-handlers/conflict.ts +90 -49
  764. package/src/memory/job-handlers/embedding.ts +32 -17
  765. package/src/memory/job-handlers/extraction.ts +58 -33
  766. package/src/memory/job-handlers/index-maintenance.ts +31 -17
  767. package/src/memory/job-handlers/media-processing.ts +65 -24
  768. package/src/memory/job-handlers/summarization.ts +186 -128
  769. package/src/memory/job-utils.ts +100 -57
  770. package/src/memory/jobs-store.ts +235 -142
  771. package/src/memory/jobs-worker.ts +167 -83
  772. package/src/memory/llm-request-log-store.ts +13 -11
  773. package/src/memory/llm-usage-store.ts +35 -26
  774. package/src/memory/media-store.ts +151 -44
  775. package/src/memory/message-content.ts +28 -18
  776. package/src/memory/migrations/001-job-deferrals.ts +11 -5
  777. package/src/memory/migrations/002-tool-invocations-fk.ts +14 -6
  778. package/src/memory/migrations/003-memory-fts-backfill.ts +11 -5
  779. package/src/memory/migrations/004-entity-relation-dedup.ts +17 -11
  780. package/src/memory/migrations/005-fingerprint-scope-unique.ts +36 -21
  781. package/src/memory/migrations/006-scope-salted-fingerprints.ts +35 -20
  782. package/src/memory/migrations/007-assistant-id-to-self.ts +40 -27
  783. package/src/memory/migrations/008-remove-assistant-id-columns.ts +58 -36
  784. package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +36 -22
  785. package/src/memory/migrations/010-ext-conv-bindings-channel-chat-unique.ts +21 -11
  786. package/src/memory/migrations/011-call-sessions-provider-sid-dedup.ts +30 -15
  787. package/src/memory/migrations/012-call-sessions-add-initiated-from.ts +4 -2
  788. package/src/memory/migrations/013-guardian-action-tables.ts +29 -11
  789. package/src/memory/migrations/014-backfill-inbox-thread-state.ts +35 -21
  790. package/src/memory/migrations/015-drop-active-search-index.ts +17 -11
  791. package/src/memory/migrations/016-memory-segments-indexes.ts +7 -3
  792. package/src/memory/migrations/017-memory-items-indexes.ts +4 -2
  793. package/src/memory/migrations/018-remaining-table-indexes.ts +13 -5
  794. package/src/memory/migrations/019-notification-tables-schema-migration.ts +34 -20
  795. package/src/memory/migrations/020-rename-macos-ios-channel-to-vellum.ts +87 -53
  796. package/src/memory/migrations/021-conversation-status-indexes.ts +7 -3
  797. package/src/memory/migrations/022-add-origin-interface.ts +4 -2
  798. package/src/memory/migrations/023-memory-item-sources-indexes.ts +4 -2
  799. package/src/memory/migrations/024-embedding-vector-blob.ts +34 -18
  800. package/src/memory/migrations/025-messages-fts-backfill.ts +11 -5
  801. package/src/memory/migrations/026-guardian-verification-sessions.ts +80 -14
  802. package/src/memory/migrations/026a-embeddings-nullable-vector-json.ts +42 -26
  803. package/src/memory/migrations/027-notification-delivery-pairing-columns.ts +22 -8
  804. package/src/memory/migrations/027a-guardian-bootstrap-token.ts +11 -3
  805. package/src/memory/migrations/028-call-session-mode.ts +13 -3
  806. package/src/memory/migrations/028-notification-delivery-client-ack.ts +22 -8
  807. package/src/memory/migrations/029-channel-inbound-delivered-segments.ts +7 -3
  808. package/src/memory/migrations/030-guardian-action-followup.ts +46 -8
  809. package/src/memory/migrations/030-guardian-verification-purpose.ts +4 -2
  810. package/src/memory/migrations/031-conversations-thread-type-index.ts +4 -2
  811. package/src/memory/migrations/032-guardian-delivery-conversation-index.ts +4 -2
  812. package/src/memory/migrations/032-notification-delivery-thread-decision.ts +22 -8
  813. package/src/memory/migrations/033-scoped-approval-grants.ts +1 -1
  814. package/src/memory/migrations/034-guardian-action-tool-metadata.ts +15 -3
  815. package/src/memory/migrations/035-guardian-action-supersession.ts +15 -3
  816. package/src/memory/migrations/036-normalize-phone-identities.ts +101 -87
  817. package/src/memory/migrations/037-voice-invite-columns.ts +22 -4
  818. package/src/memory/migrations/038-actor-token-records.ts +5 -9
  819. package/src/memory/migrations/039-actor-refresh-token-records.ts +7 -13
  820. package/src/memory/migrations/100-core-tables.ts +1 -1
  821. package/src/memory/migrations/101-watchers-and-logs.ts +1 -1
  822. package/src/memory/migrations/103-complex-migrations.ts +9 -9
  823. package/src/memory/migrations/104-core-indexes.ts +188 -64
  824. package/src/memory/migrations/105-contacts-and-triage.ts +28 -10
  825. package/src/memory/migrations/106-call-sessions.ts +58 -16
  826. package/src/memory/migrations/107-followups.ts +16 -6
  827. package/src/memory/migrations/108-tasks-and-work-items.ts +43 -11
  828. package/src/memory/migrations/109-external-conversation-bindings.ts +11 -5
  829. package/src/memory/migrations/110-channel-guardian.ts +48 -10
  830. package/src/memory/migrations/111-media-assets.ts +52 -18
  831. package/src/memory/migrations/112-assistant-inbox.ts +32 -12
  832. package/src/memory/migrations/113-late-migrations.ts +12 -12
  833. package/src/memory/migrations/114-notifications.ts +28 -12
  834. package/src/memory/migrations/115-sequences.ts +10 -4
  835. package/src/memory/migrations/116-messages-fts.ts +1 -1
  836. package/src/memory/migrations/117-conversation-attention.ts +16 -6
  837. package/src/memory/migrations/118-reminder-routing-intent.ts +7 -3
  838. package/src/memory/migrations/119-schema-indexes-and-columns.ts +35 -15
  839. package/src/memory/migrations/120-fk-cascade-rebuilds.ts +36 -17
  840. package/src/memory/migrations/121-canonical-guardian-requests.ts +25 -9
  841. package/src/memory/migrations/122-canonical-guardian-requester-chat-id.ts +11 -3
  842. package/src/memory/migrations/123-canonical-guardian-deliveries-destination-index.ts +4 -2
  843. package/src/memory/migrations/124-voice-invite-display-metadata.ts +15 -3
  844. package/src/memory/migrations/125-guardian-principal-id-columns.ts +22 -4
  845. package/src/memory/migrations/126-backfill-guardian-principal-id.ts +174 -126
  846. package/src/memory/migrations/127-guardian-principal-id-not-null.ts +58 -42
  847. package/src/memory/migrations/128-contacts-role-principal.ts +26 -0
  848. package/src/memory/migrations/129-contact-channels-access-fields.ts +105 -0
  849. package/src/memory/migrations/130-contact-channels-type-ext-chat-id-index.ts +15 -0
  850. package/src/memory/migrations/131-drop-legacy-member-guardian-tables.ts +134 -0
  851. package/src/memory/migrations/132-contacts-assistant-id.ts +21 -0
  852. package/src/memory/migrations/133-assistant-contact-metadata.ts +21 -0
  853. package/src/memory/migrations/index.ts +83 -73
  854. package/src/memory/migrations/registry.ts +53 -37
  855. package/src/memory/migrations/validate-migration-state.ts +73 -46
  856. package/src/memory/profile-compiler.ts +58 -24
  857. package/src/memory/published-pages-store.ts +12 -16
  858. package/src/memory/qdrant-circuit-breaker.ts +28 -20
  859. package/src/memory/qdrant-client.ts +99 -63
  860. package/src/memory/qdrant-manager.ts +89 -57
  861. package/src/memory/query-builder.ts +9 -7
  862. package/src/memory/raw-query.ts +63 -14
  863. package/src/memory/recall-cache.ts +15 -8
  864. package/src/memory/retrieval-budget.ts +0 -1
  865. package/src/memory/retriever.ts +385 -192
  866. package/src/memory/schema-migration.ts +1 -1
  867. package/src/memory/schema.ts +56 -56
  868. package/src/memory/scoped-approval-grants.ts +99 -45
  869. package/src/memory/search/entity.ts +102 -40
  870. package/src/memory/search/formatting.ts +70 -52
  871. package/src/memory/search/lexical.ts +82 -43
  872. package/src/memory/search/ranking.ts +103 -39
  873. package/src/memory/search/semantic.ts +59 -35
  874. package/src/memory/search/types.ts +8 -8
  875. package/src/memory/segmenter.ts +20 -12
  876. package/src/memory/shared-app-links-store.ts +21 -16
  877. package/src/memory/slack-thread-store.ts +187 -0
  878. package/src/memory/task-memory-cleanup.ts +18 -8
  879. package/src/memory/tool-usage-store.ts +27 -19
  880. package/src/memory/validation.ts +4 -2
  881. package/src/messaging/activity-analyzer.ts +7 -7
  882. package/src/messaging/draft-store.ts +13 -10
  883. package/src/messaging/email-classifier.ts +73 -37
  884. package/src/messaging/index.ts +3 -3
  885. package/src/messaging/outreach-classifier.ts +76 -38
  886. package/src/messaging/provider-types.ts +2 -4
  887. package/src/messaging/provider.ts +37 -8
  888. package/src/messaging/providers/gmail/adapter.ts +183 -66
  889. package/src/messaging/providers/gmail/client.ts +3 -1
  890. package/src/messaging/providers/gmail/mime-builder.ts +21 -19
  891. package/src/messaging/providers/gmail/people-client.ts +22 -9
  892. package/src/messaging/providers/gmail/types.ts +6 -6
  893. package/src/messaging/providers/slack/adapter.ts +93 -43
  894. package/src/messaging/providers/slack/client.ts +165 -48
  895. package/src/messaging/providers/slack/types.ts +10 -0
  896. package/src/messaging/providers/sms/adapter.ts +76 -40
  897. package/src/messaging/providers/sms/client.ts +4 -4
  898. package/src/messaging/providers/telegram-bot/adapter.ts +52 -30
  899. package/src/messaging/providers/telegram-bot/client.ts +7 -7
  900. package/src/messaging/providers/whatsapp/adapter.ts +58 -31
  901. package/src/messaging/providers/whatsapp/client.ts +4 -4
  902. package/src/messaging/registry.ts +9 -5
  903. package/src/messaging/style-analyzer.ts +69 -39
  904. package/src/messaging/thread-summarizer.ts +101 -53
  905. package/src/messaging/triage-engine.ts +111 -82
  906. package/src/messaging/types.ts +10 -10
  907. package/src/migrations/config-merge.ts +18 -10
  908. package/src/migrations/data-layout.ts +35 -22
  909. package/src/migrations/data-merge.ts +17 -7
  910. package/src/migrations/hooks-merge.ts +43 -16
  911. package/src/migrations/index.ts +6 -6
  912. package/src/migrations/log.ts +9 -5
  913. package/src/migrations/skills-merge.ts +17 -7
  914. package/src/migrations/workspace-layout.ts +39 -25
  915. package/src/notifications/AGENTS.md +5 -0
  916. package/src/notifications/adapters/macos.ts +21 -14
  917. package/src/notifications/adapters/slack.ts +90 -0
  918. package/src/notifications/adapters/sms.ts +28 -15
  919. package/src/notifications/adapters/telegram.ts +24 -15
  920. package/src/notifications/broadcaster.ts +108 -52
  921. package/src/notifications/conversation-pairing.ts +64 -29
  922. package/src/notifications/copy-composer.ts +165 -95
  923. package/src/notifications/decision-engine.ts +353 -147
  924. package/src/notifications/decisions-store.ts +26 -10
  925. package/src/notifications/deliveries-store.ts +23 -13
  926. package/src/notifications/destination-resolver.ts +83 -24
  927. package/src/notifications/deterministic-checks.ts +78 -27
  928. package/src/notifications/emit-signal.ts +95 -41
  929. package/src/notifications/events-store.ts +13 -7
  930. package/src/notifications/guardian-question-mode.ts +125 -75
  931. package/src/notifications/preference-extractor.ts +85 -53
  932. package/src/notifications/preference-summary.ts +31 -18
  933. package/src/notifications/preferences-store.ts +29 -18
  934. package/src/notifications/runtime-dispatch.ts +22 -12
  935. package/src/notifications/signal.ts +4 -4
  936. package/src/notifications/thread-candidates.ts +59 -23
  937. package/src/notifications/thread-seed-composer.ts +45 -27
  938. package/src/notifications/types.ts +19 -10
  939. package/src/oauth/connect-orchestrator.ts +105 -54
  940. package/src/oauth/connect-types.ts +3 -3
  941. package/src/oauth/provider-profiles.ts +102 -59
  942. package/src/oauth/scope-policy.ts +5 -2
  943. package/src/oauth/token-persistence.ts +58 -24
  944. package/src/outbound-proxy/certs.ts +284 -0
  945. package/src/outbound-proxy/config.ts +94 -0
  946. package/src/outbound-proxy/connect-tunnel.ts +84 -0
  947. package/src/outbound-proxy/health.ts +62 -0
  948. package/src/outbound-proxy/host-pattern-match.ts +67 -0
  949. package/src/outbound-proxy/http-forwarder.ts +162 -0
  950. package/src/outbound-proxy/index.ts +80 -0
  951. package/src/outbound-proxy/logging.ts +193 -0
  952. package/src/outbound-proxy/mitm-handler.ts +292 -0
  953. package/src/outbound-proxy/policy.ts +172 -0
  954. package/src/outbound-proxy/router.ts +64 -0
  955. package/src/outbound-proxy/server.ts +145 -0
  956. package/src/outbound-proxy/types.ts +150 -0
  957. package/src/permissions/checker.ts +481 -189
  958. package/src/permissions/defaults.ts +135 -108
  959. package/src/permissions/prompter.ts +53 -27
  960. package/src/permissions/secret-prompter.ts +21 -15
  961. package/src/permissions/shell-identity.ts +47 -16
  962. package/src/permissions/trust-store.ts +185 -73
  963. package/src/permissions/types.ts +22 -12
  964. package/src/permissions/workspace-policy.ts +47 -38
  965. package/src/playbooks/index.ts +10 -2
  966. package/src/playbooks/playbook-compiler.ts +30 -24
  967. package/src/playbooks/types.ts +11 -8
  968. package/src/providers/anthropic/client.ts +328 -168
  969. package/src/providers/failover.ts +57 -22
  970. package/src/providers/fireworks/client.ts +9 -5
  971. package/src/providers/gemini/client.ts +61 -39
  972. package/src/providers/model-intents.ts +40 -33
  973. package/src/providers/ollama/client.ts +7 -7
  974. package/src/providers/openai/client.ts +109 -68
  975. package/src/providers/openrouter/client.ts +9 -5
  976. package/src/providers/provider-send-message.ts +59 -27
  977. package/src/providers/ratelimit.ts +25 -8
  978. package/src/providers/registry.ts +86 -38
  979. package/src/providers/retry.ts +93 -37
  980. package/src/providers/stream-timeout.ts +5 -3
  981. package/src/providers/types.ts +7 -6
  982. package/src/runtime/AGENTS.md +42 -0
  983. package/src/runtime/access-request-helper.ts +118 -68
  984. package/src/runtime/actor-refresh-token-store.ts +21 -16
  985. package/src/runtime/actor-token-store.ts +25 -18
  986. package/src/runtime/actor-trust-resolver.ts +191 -80
  987. package/src/runtime/approval-conversation-turn.ts +39 -26
  988. package/src/runtime/approval-message-composer.ts +116 -84
  989. package/src/runtime/assistant-event-hub.ts +25 -6
  990. package/src/runtime/assistant-event.ts +4 -4
  991. package/src/runtime/assistant-scope.ts +1 -1
  992. package/src/runtime/auth/__tests__/guard-tests.test.ts +36 -14
  993. package/src/runtime/auth/context.ts +8 -7
  994. package/src/runtime/auth/credential-service.ts +60 -38
  995. package/src/runtime/auth/external-assistant-id.ts +16 -8
  996. package/src/runtime/auth/index.ts +23 -16
  997. package/src/runtime/auth/require-bound-guardian.ts +44 -0
  998. package/src/runtime/auth/route-policy.ts +166 -104
  999. package/src/runtime/auth/scopes.ts +22 -29
  1000. package/src/runtime/auth/subject.ts +19 -13
  1001. package/src/runtime/auth/token-service.ts +3 -3
  1002. package/src/runtime/auth/types.ts +23 -23
  1003. package/src/runtime/channel-approval-parser.ts +37 -14
  1004. package/src/runtime/channel-approval-types.ts +30 -4
  1005. package/src/runtime/channel-approvals.ts +49 -23
  1006. package/src/runtime/channel-guardian-service.ts +144 -103
  1007. package/src/runtime/channel-invite-transport.ts +5 -3
  1008. package/src/runtime/channel-invite-transports/telegram.ts +16 -10
  1009. package/src/runtime/channel-invite-transports/voice.ts +7 -7
  1010. package/src/runtime/channel-readiness-service.ts +139 -90
  1011. package/src/runtime/channel-readiness-types.ts +4 -2
  1012. package/src/runtime/channel-reply-delivery.ts +83 -14
  1013. package/src/runtime/channel-retry-sweep.ts +111 -62
  1014. package/src/runtime/confirmation-request-guardian-bridge.ts +73 -54
  1015. package/src/runtime/gateway-client.ts +122 -55
  1016. package/src/runtime/gateway-internal-client.ts +86 -0
  1017. package/src/runtime/guardian-action-conversation-turn.ts +34 -18
  1018. package/src/runtime/guardian-action-followup-executor.ts +115 -45
  1019. package/src/runtime/guardian-action-grant-minter.ts +40 -24
  1020. package/src/runtime/guardian-action-message-composer.ts +105 -84
  1021. package/src/runtime/guardian-action-service.ts +127 -0
  1022. package/src/runtime/guardian-decision-types.ts +28 -13
  1023. package/src/runtime/guardian-outbound-actions.ts +9 -0
  1024. package/src/runtime/guardian-reply-router.ts +274 -145
  1025. package/src/runtime/guardian-vellum-migration.ts +38 -24
  1026. package/src/runtime/guardian-verification-templates.ts +24 -12
  1027. package/src/runtime/http-router.ts +175 -0
  1028. package/src/runtime/http-server.ts +913 -680
  1029. package/src/runtime/http-types.ts +2 -2
  1030. package/src/runtime/invite-redemption-service.ts +211 -134
  1031. package/src/runtime/invite-redemption-templates.ts +18 -11
  1032. package/src/runtime/{ingress-service.ts → invite-service.ts} +92 -151
  1033. package/src/runtime/local-actor-identity.ts +73 -55
  1034. package/src/runtime/middleware/auth.ts +25 -14
  1035. package/src/runtime/middleware/error-handler.ts +15 -11
  1036. package/src/runtime/middleware/rate-limiter.ts +23 -17
  1037. package/src/runtime/middleware/request-logger.ts +4 -4
  1038. package/src/runtime/middleware/twilio-validation.ts +29 -20
  1039. package/src/runtime/migrations/migration-transport.ts +575 -0
  1040. package/src/runtime/migrations/migration-wizard.ts +715 -0
  1041. package/src/runtime/migrations/rebind-secrets-screen.ts +351 -0
  1042. package/src/runtime/migrations/transfer-progress-screen.ts +321 -0
  1043. package/src/runtime/migrations/validation-results-screen.ts +467 -0
  1044. package/src/runtime/migrations/vbundle-builder.ts +295 -0
  1045. package/src/runtime/migrations/vbundle-import-analyzer.ts +212 -0
  1046. package/src/runtime/migrations/vbundle-importer.ts +339 -0
  1047. package/src/runtime/migrations/vbundle-validator.ts +356 -0
  1048. package/src/runtime/nl-approval-parser.ts +138 -0
  1049. package/src/runtime/pending-interactions.ts +16 -7
  1050. package/src/runtime/routes/access-request-decision.ts +73 -52
  1051. package/src/runtime/routes/app-routes.ts +56 -38
  1052. package/src/runtime/routes/approval-routes.ts +144 -92
  1053. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +930 -0
  1054. package/src/runtime/routes/approval-strategies/guardian-legacy-fallback-strategy.ts +82 -0
  1055. package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +151 -0
  1056. package/src/runtime/routes/attachment-routes.ts +59 -48
  1057. package/src/runtime/routes/brain-graph-routes.ts +85 -69
  1058. package/src/runtime/routes/call-routes.ts +79 -38
  1059. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +10 -10
  1060. package/src/runtime/routes/channel-delivery-routes.ts +19 -14
  1061. package/src/runtime/routes/channel-guardian-routes.ts +3 -3
  1062. package/src/runtime/routes/channel-inbound-routes.ts +2 -2
  1063. package/src/runtime/routes/channel-readiness-routes.ts +12 -6
  1064. package/src/runtime/routes/channel-route-shared.ts +67 -25
  1065. package/src/runtime/routes/channel-routes.ts +4 -6
  1066. package/src/runtime/routes/contact-routes.ts +374 -17
  1067. package/src/runtime/routes/conversation-attention-routes.ts +57 -28
  1068. package/src/runtime/routes/conversation-routes.ts +321 -174
  1069. package/src/runtime/routes/debug-routes.ts +14 -10
  1070. package/src/runtime/routes/events-routes.ts +90 -57
  1071. package/src/runtime/routes/global-search-routes.ts +266 -0
  1072. package/src/runtime/routes/guardian-action-routes.ts +112 -113
  1073. package/src/runtime/routes/guardian-approval-interception.ts +325 -874
  1074. package/src/runtime/routes/guardian-approval-prompt.ts +40 -24
  1075. package/src/runtime/routes/guardian-approval-reply-helpers.ts +135 -0
  1076. package/src/runtime/routes/guardian-bootstrap-routes.ts +55 -36
  1077. package/src/runtime/routes/guardian-expiry-sweep.ts +63 -37
  1078. package/src/runtime/routes/guardian-refresh-routes.ts +40 -19
  1079. package/src/runtime/routes/identity-routes.ts +71 -42
  1080. package/src/runtime/routes/inbound-conversation.ts +17 -11
  1081. package/src/runtime/routes/inbound-message-handler.ts +305 -1459
  1082. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +880 -0
  1083. package/src/runtime/routes/inbound-stages/background-dispatch.ts +600 -0
  1084. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +214 -0
  1085. package/src/runtime/routes/inbound-stages/edit-intercept.ts +116 -0
  1086. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +167 -0
  1087. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +185 -0
  1088. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +132 -0
  1089. package/src/runtime/routes/inbound-stages/verification-intercept.ts +340 -0
  1090. package/src/runtime/routes/integration-routes.ts +60 -21
  1091. package/src/runtime/routes/invite-routes.ts +140 -0
  1092. package/src/runtime/routes/migration-routes.ts +434 -0
  1093. package/src/runtime/routes/pairing-routes.ts +157 -79
  1094. package/src/runtime/routes/secret-routes.ts +6 -2
  1095. package/src/runtime/routes/twilio-routes.ts +443 -249
  1096. package/src/runtime/slack-block-formatting.ts +176 -0
  1097. package/src/runtime/tool-grant-request-helper.ts +36 -27
  1098. package/src/runtime/{guardian-context-resolver.ts → trust-context-resolver.ts} +29 -41
  1099. package/src/schedule/integration-status.ts +44 -9
  1100. package/src/schedule/recurrence-engine.ts +47 -24
  1101. package/src/schedule/recurrence-types.ts +12 -7
  1102. package/src/schedule/schedule-store.ts +166 -83
  1103. package/src/schedule/scheduler.ts +37 -24
  1104. package/src/security/encrypted-store.ts +68 -38
  1105. package/src/security/keychain.ts +183 -120
  1106. package/src/security/oauth-callback-registry.ts +3 -3
  1107. package/src/security/oauth2.ts +226 -138
  1108. package/src/security/redaction.ts +24 -24
  1109. package/src/security/secret-allowlist.ts +46 -21
  1110. package/src/security/secret-ingress.ts +15 -7
  1111. package/src/security/secret-scanner.ts +193 -104
  1112. package/src/security/secure-keys.ts +9 -3
  1113. package/src/security/token-manager.ts +99 -40
  1114. package/src/security/tool-approval-digest.ts +3 -3
  1115. package/src/sequence/analytics.ts +52 -27
  1116. package/src/sequence/engine.ts +135 -72
  1117. package/src/sequence/guardrails.ts +32 -20
  1118. package/src/sequence/importer.ts +75 -37
  1119. package/src/sequence/reply-matcher.ts +36 -18
  1120. package/src/sequence/store.ts +137 -75
  1121. package/src/sequence/types.ts +30 -16
  1122. package/src/services/published-app-updater.ts +26 -16
  1123. package/src/services/vercel-deploy.ts +19 -15
  1124. package/src/skills/active-skill-tools.ts +3 -3
  1125. package/src/skills/clawhub.ts +178 -90
  1126. package/src/skills/include-graph.ts +24 -17
  1127. package/src/skills/managed-store.ts +89 -42
  1128. package/src/skills/path-classifier.ts +10 -10
  1129. package/src/skills/remote-skill-policy.ts +31 -22
  1130. package/src/skills/slash-commands.ts +36 -30
  1131. package/src/skills/tool-manifest.ts +60 -31
  1132. package/src/skills/version-hash.ts +25 -15
  1133. package/src/slack/slack-webhook.ts +19 -15
  1134. package/src/subagent/index.ts +4 -8
  1135. package/src/subagent/manager.ts +119 -69
  1136. package/src/subagent/types.ts +9 -12
  1137. package/src/swarm/backend-claude-code.ts +124 -45
  1138. package/src/swarm/checkpoint.ts +36 -16
  1139. package/src/swarm/graph-utils.ts +1 -3
  1140. package/src/swarm/index.ts +38 -19
  1141. package/src/swarm/limits.ts +13 -4
  1142. package/src/swarm/orchestrator.ts +108 -57
  1143. package/src/swarm/plan-validator.ts +23 -17
  1144. package/src/swarm/router-planner.ts +51 -22
  1145. package/src/swarm/router-prompts.ts +4 -1
  1146. package/src/swarm/synthesizer.ts +26 -18
  1147. package/src/swarm/types.ts +14 -4
  1148. package/src/swarm/worker-backend.ts +36 -26
  1149. package/src/swarm/worker-prompts.ts +13 -9
  1150. package/src/swarm/worker-runner.ts +40 -34
  1151. package/src/tasks/candidate-store.ts +14 -6
  1152. package/src/tasks/ephemeral-permissions.ts +9 -5
  1153. package/src/tasks/task-compiler.ts +41 -38
  1154. package/src/tasks/task-runner.ts +54 -26
  1155. package/src/tasks/task-scheduler.ts +1 -1
  1156. package/src/tasks/task-store.ts +20 -7
  1157. package/src/tasks/tool-sanitizer.ts +3 -3
  1158. package/src/tools/apps/definitions.ts +23 -15
  1159. package/src/tools/apps/executors.ts +122 -40
  1160. package/src/tools/apps/open-proxy.ts +5 -5
  1161. package/src/tools/apps/registry.ts +2 -2
  1162. package/src/tools/assets/materialize.ts +59 -41
  1163. package/src/tools/assets/search.ts +86 -48
  1164. package/src/tools/browser/api-map.ts +52 -36
  1165. package/src/tools/browser/auth-cache.ts +21 -18
  1166. package/src/tools/browser/auth-detector.ts +43 -28
  1167. package/src/tools/browser/auto-navigate.ts +149 -68
  1168. package/src/tools/browser/browser-execution.ts +9 -3
  1169. package/src/tools/browser/headless-browser.ts +287 -150
  1170. package/src/tools/browser/jit-auth.ts +37 -21
  1171. package/src/tools/browser/network-recorder.ts +138 -56
  1172. package/src/tools/browser/recording-store.ts +22 -15
  1173. package/src/tools/browser/runtime-check.ts +8 -5
  1174. package/src/tools/browser/x-auto-navigate.ts +88 -47
  1175. package/src/tools/calls/call-end.ts +10 -7
  1176. package/src/tools/calls/call-start.ts +30 -20
  1177. package/src/tools/calls/call-status.ts +8 -5
  1178. package/src/tools/claude-code/claude-code.ts +301 -165
  1179. package/src/tools/computer-use/definitions.ts +175 -130
  1180. package/src/tools/computer-use/registry.ts +2 -2
  1181. package/src/tools/computer-use/request-computer-control.ts +21 -13
  1182. package/src/tools/computer-use/skill-proxy-bridge.ts +1 -1
  1183. package/src/tools/credentials/account-registry.ts +52 -35
  1184. package/src/tools/credentials/broker-types.ts +1 -1
  1185. package/src/tools/credentials/broker.ts +97 -55
  1186. package/src/tools/credentials/domain-policy.ts +5 -2
  1187. package/src/tools/credentials/host-pattern-match.ts +15 -8
  1188. package/src/tools/credentials/metadata-store.ts +93 -43
  1189. package/src/tools/credentials/policy-types.ts +5 -2
  1190. package/src/tools/credentials/policy-validate.ts +21 -14
  1191. package/src/tools/credentials/post-connect-hooks.ts +18 -7
  1192. package/src/tools/credentials/resolve.ts +11 -10
  1193. package/src/tools/credentials/selection.ts +30 -25
  1194. package/src/tools/credentials/tool-policy.ts +5 -2
  1195. package/src/tools/credentials/vault.ts +538 -185
  1196. package/src/tools/document/document-tool.ts +23 -17
  1197. package/src/tools/document/editor-template.ts +12 -7
  1198. package/src/tools/execution-target.ts +13 -10
  1199. package/src/tools/execution-timeout.ts +6 -5
  1200. package/src/tools/executor.ts +141 -74
  1201. package/src/tools/filesystem/edit.ts +82 -45
  1202. package/src/tools/filesystem/fuzzy-match.ts +70 -32
  1203. package/src/tools/filesystem/read.ts +46 -28
  1204. package/src/tools/filesystem/view-image.ts +86 -42
  1205. package/src/tools/filesystem/write.ts +53 -32
  1206. package/src/tools/followups/followup_create.ts +43 -17
  1207. package/src/tools/followups/followup_list.ts +28 -13
  1208. package/src/tools/followups/followup_resolve.ts +9 -6
  1209. package/src/tools/guardian-control-plane-policy.ts +15 -14
  1210. package/src/tools/host-filesystem/edit.ts +77 -42
  1211. package/src/tools/host-filesystem/read.ts +52 -33
  1212. package/src/tools/host-filesystem/write.ts +50 -29
  1213. package/src/tools/host-terminal/host-shell.ts +97 -61
  1214. package/src/tools/mcp/mcp-tool-factory.ts +21 -14
  1215. package/src/tools/memory/definitions.ts +60 -28
  1216. package/src/tools/memory/handlers.ts +149 -77
  1217. package/src/tools/memory/register.ts +39 -16
  1218. package/src/tools/network/__tests__/web-search.test.ts +236 -177
  1219. package/src/tools/network/domain-normalize.ts +13 -9
  1220. package/src/tools/network/script-proxy/__tests__/logging.test.ts +193 -123
  1221. package/src/tools/network/script-proxy/__tests__/policy.test.ts +225 -127
  1222. package/src/tools/network/script-proxy/index.ts +1 -17
  1223. package/src/tools/network/script-proxy/session-manager.ts +178 -86
  1224. package/src/tools/network/url-safety.ts +56 -34
  1225. package/src/tools/network/web-fetch.ts +273 -155
  1226. package/src/tools/network/web-search.ts +166 -81
  1227. package/src/tools/permission-checker.ts +24 -25
  1228. package/src/tools/policy-context.ts +8 -5
  1229. package/src/tools/registry.ts +73 -46
  1230. package/src/tools/reminder/reminder-store.ts +65 -44
  1231. package/src/tools/reminder/reminder.ts +76 -35
  1232. package/src/tools/schedule/create.ts +44 -21
  1233. package/src/tools/schedule/delete.ts +8 -5
  1234. package/src/tools/schedule/list.ts +39 -19
  1235. package/src/tools/schedule/update.ts +49 -26
  1236. package/src/tools/secret-detection-handler.ts +130 -49
  1237. package/src/tools/sensitive-output-placeholders.ts +15 -8
  1238. package/src/tools/shared/filesystem/edit-engine.ts +45 -14
  1239. package/src/tools/shared/filesystem/errors.ts +18 -18
  1240. package/src/tools/shared/filesystem/file-ops-service.ts +59 -32
  1241. package/src/tools/shared/filesystem/format-diff.ts +21 -11
  1242. package/src/tools/shared/filesystem/path-policy.ts +17 -13
  1243. package/src/tools/shared/filesystem/size-guard.ts +8 -4
  1244. package/src/tools/shared/filesystem/types.ts +2 -2
  1245. package/src/tools/shared/shell-output.ts +4 -3
  1246. package/src/tools/side-effects.ts +36 -28
  1247. package/src/tools/skills/delete-managed.ts +30 -17
  1248. package/src/tools/skills/load.ts +88 -46
  1249. package/src/tools/skills/sandbox-runner.ts +62 -46
  1250. package/src/tools/skills/scaffold-managed.ts +98 -48
  1251. package/src/tools/skills/script-contract.ts +5 -2
  1252. package/src/tools/skills/skill-script-runner.ts +29 -13
  1253. package/src/tools/skills/skill-tool-factory.ts +20 -10
  1254. package/src/tools/subagent/abort.ts +10 -4
  1255. package/src/tools/subagent/message.ts +14 -8
  1256. package/src/tools/subagent/read.ts +20 -11
  1257. package/src/tools/subagent/spawn.ts +14 -6
  1258. package/src/tools/subagent/status.ts +7 -4
  1259. package/src/tools/swarm/delegate.ts +75 -49
  1260. package/src/tools/system/avatar-generator.ts +46 -33
  1261. package/src/tools/system/navigate-settings.ts +29 -19
  1262. package/src/tools/system/open-system-settings.ts +30 -20
  1263. package/src/tools/system/request-permission.ts +59 -44
  1264. package/src/tools/system/version.ts +27 -16
  1265. package/src/tools/system/voice-config.ts +116 -53
  1266. package/src/tools/tasks/index.ts +8 -8
  1267. package/src/tools/tasks/task-delete.ts +61 -22
  1268. package/src/tools/tasks/task-list.ts +23 -11
  1269. package/src/tools/tasks/task-run.ts +41 -16
  1270. package/src/tools/tasks/task-save.ts +27 -10
  1271. package/src/tools/tasks/work-item-enqueue.ts +114 -48
  1272. package/src/tools/tasks/work-item-list.ts +20 -10
  1273. package/src/tools/tasks/work-item-remove.ts +49 -15
  1274. package/src/tools/tasks/work-item-run.ts +34 -13
  1275. package/src/tools/tasks/work-item-update.ts +84 -31
  1276. package/src/tools/terminal/backends/native.ts +64 -35
  1277. package/src/tools/terminal/backends/types.ts +6 -2
  1278. package/src/tools/terminal/parser.ts +200 -125
  1279. package/src/tools/terminal/safe-env.ts +27 -21
  1280. package/src/tools/terminal/sandbox-diagnostics.ts +31 -13
  1281. package/src/tools/terminal/sandbox.ts +10 -6
  1282. package/src/tools/terminal/shell.ts +134 -68
  1283. package/src/tools/tool-approval-handler.ts +239 -140
  1284. package/src/tools/types.ts +79 -22
  1285. package/src/tools/ui-surface/definitions.ts +124 -89
  1286. package/src/tools/ui-surface/registry.ts +2 -2
  1287. package/src/tools/watch/screen-watch.ts +50 -32
  1288. package/src/tools/watch/watch-state.ts +41 -15
  1289. package/src/tools/watcher/create.ts +37 -15
  1290. package/src/tools/watcher/delete.ts +9 -6
  1291. package/src/tools/watcher/digest.ts +10 -6
  1292. package/src/tools/watcher/list.ts +37 -14
  1293. package/src/tools/watcher/update.ts +33 -18
  1294. package/src/tools/weather/service.ts +331 -174
  1295. package/src/twitter/client.ts +261 -138
  1296. package/src/twitter/oauth-client.ts +17 -13
  1297. package/src/twitter/router.ts +51 -23
  1298. package/src/twitter/session.ts +27 -18
  1299. package/src/types/qrcode.d.ts +6 -3
  1300. package/src/usage/actors.ts +16 -16
  1301. package/src/usage/types.ts +3 -3
  1302. package/src/util/bundled-asset.ts +10 -6
  1303. package/src/util/canonicalize-identity.ts +11 -4
  1304. package/src/util/clipboard.ts +7 -7
  1305. package/src/util/content-id.ts +3 -3
  1306. package/src/util/debounce.ts +3 -2
  1307. package/src/util/diff.ts +55 -33
  1308. package/src/util/errors.ts +31 -27
  1309. package/src/util/fs.ts +8 -2
  1310. package/src/util/log-redact.ts +12 -12
  1311. package/src/util/logger.ts +112 -51
  1312. package/src/util/network-info.ts +13 -5
  1313. package/src/util/object.ts +4 -2
  1314. package/src/util/phone.ts +4 -4
  1315. package/src/util/platform.ts +80 -58
  1316. package/src/util/pricing.ts +49 -31
  1317. package/src/util/retry.ts +39 -7
  1318. package/src/util/row-mapper.ts +7 -4
  1319. package/src/util/silently.ts +7 -4
  1320. package/src/util/spawn.ts +48 -0
  1321. package/src/util/spinner.ts +9 -7
  1322. package/src/util/time.ts +16 -3
  1323. package/src/util/truncate.ts +1 -1
  1324. package/src/util/voice-code.ts +6 -4
  1325. package/src/util/xml.ts +5 -1
  1326. package/src/version.ts +12 -8
  1327. package/src/watcher/engine.ts +71 -44
  1328. package/src/watcher/provider-registry.ts +1 -1
  1329. package/src/watcher/providers/github.ts +40 -23
  1330. package/src/watcher/providers/gmail.ts +59 -38
  1331. package/src/watcher/providers/google-calendar.ts +62 -48
  1332. package/src/watcher/providers/linear.ts +219 -150
  1333. package/src/watcher/providers/slack.ts +125 -29
  1334. package/src/watcher/watcher-store.ts +75 -55
  1335. package/src/work-items/work-item-runner.ts +62 -29
  1336. package/src/work-items/work-item-store.ts +137 -47
  1337. package/src/workspace/commit-message-enrichment-service.ts +65 -25
  1338. package/src/workspace/commit-message-provider.ts +14 -12
  1339. package/src/workspace/git-service.ts +355 -239
  1340. package/src/workspace/heartbeat-service.ts +74 -37
  1341. package/src/workspace/provider-commit-message-generator.ts +95 -70
  1342. package/src/workspace/top-level-renderer.ts +10 -8
  1343. package/src/workspace/top-level-scanner.ts +9 -3
  1344. package/src/workspace/turn-commit.ts +63 -36
  1345. package/src/__tests__/ingress-member-store.test.ts +0 -294
  1346. package/src/__tests__/script-proxy-router.test.ts +0 -215
  1347. package/src/config/bundled-skills/trusted-contacts/SKILL.md +0 -372
  1348. package/src/memory/guardian-bindings.ts +0 -158
  1349. package/src/memory/ingress-member-store.ts +0 -352
  1350. package/src/runtime/routes/ingress-routes.ts +0 -229
  1351. package/src/tools/network/script-proxy/__tests__/router.test.ts +0 -77
  1352. package/src/tools/network/script-proxy/certs.ts +0 -7
  1353. package/src/tools/network/script-proxy/connect-tunnel.ts +0 -1
  1354. package/src/tools/network/script-proxy/http-forwarder.ts +0 -2
  1355. package/src/tools/network/script-proxy/logging.ts +0 -12
  1356. package/src/tools/network/script-proxy/mitm-handler.ts +0 -2
  1357. package/src/tools/network/script-proxy/policy.ts +0 -4
  1358. package/src/tools/network/script-proxy/router.ts +0 -2
  1359. package/src/tools/network/script-proxy/server.ts +0 -5
  1360. package/src/tools/network/script-proxy/types.ts +0 -19
@@ -8,465 +8,9 @@ You are an expert app builder and visual designer. When the user asks you to cre
8
8
 
9
9
  **Every app gets its own visual identity.** A plant tracker should feel earthy and green. A finance dashboard should feel precise and navy. A fitness app should feel energetic and purple. Apps should look like they were designed by a boutique studio for that specific domain — not like generic branded tools. Think standalone premium product, not template.
10
10
 
11
- **Your default behavior:** Build immediately. The user types "build me a habit tracker" and you deliver a complete, polished app with a domain-matched color palette, warm tinted background, emoji-rich stat cards, an accent-word hero heading, and thoughtful interactions. Don't ask what colors they want. Don't show wireframes. Just build something stunning and let them refine from there.
12
-
13
- ## Design Philosophy
14
-
15
- Every app you create must clear this bar: **Would someone screenshot this and share it?** If the answer is no, you haven't tried hard enough.
16
-
17
- ### The Quality Bar
18
-
19
- Your apps compete with products built by professional design teams. That means:
20
-
21
- - Every screen has visual depth — layers, shadows, gradients, texture
22
- - Typography creates clear hierarchy — not everything is 14px regular weight
23
- - Color is intentional and atmospheric — not just "blue buttons on white"
24
- - Interactions feel physical — elements respond to hover, press, and focus
25
- - Empty states are designed moments, not error messages
26
- - The page loads with grace — elements stagger in, content shimmers while loading
27
-
28
- ### Anti-AI-Slop Rules
29
-
30
- These are hard prohibitions. Violating any of these produces that unmistakable "AI-generated" look:
31
-
32
- - **NEVER** use flat cards with no depth — every card needs a subtle 1px border and gentle shadow, not heavy multi-layer shadows
33
- - **NEVER** ship an app with zero animations — at minimum: page load stagger, hover states, state transitions
34
- - **NEVER** make all text the same size and weight — establish clear hierarchy with at least 3 distinct levels
35
- - **NEVER** use a pure white (`#fff`) or pure dark (`#000`/`#0a0a0a`) background — ALWAYS tint it to match the domain (cream `#FEFCF9` for lifestyle, sage `#F0F5F0` for nature, cool gray `#F5F7FA` for finance, warm blush `#FDF6F3` for wellness)
36
- - **NEVER** leave clickable elements without hover AND active states
37
- - **NEVER** hand-code SVG/CSS charts (lines, bars, sparklines, gauges) — ALWAYS use `vellum.widgets.lineChart()`, `.barChart()`, `.sparkline()`, or `.progressRing()`. They handle bounds, clipping, scaling, and dark mode correctly. Hand-coded charts invariably overflow and bleed into adjacent elements.
38
- - **ALWAYS** use emoji as visual identifiers in stat cards, list items, and navigation — they replace icon libraries and add instant personality (🍎 for food, 🔥 for streaks, 💰 for money, 🌿 for plants)
39
- - **ALWAYS** apply the accent-word pattern in hero headings — color ONE key word or phrase in the accent color: "Your <span style='color: var(--accent)'>Week</span> in Motion"
40
- - **ALWAYS** include a contextual/personalized header — a greeting ("Good morning"), date ("Saturday, Feb 15"), or welcome ("Welcome back, Alex") — not just the app title
41
- - **ALWAYS** include at least one pill-shaped trust/status badge somewhere visible — "🌟 Trusted by 12,000+ users", "+8.2% this week", "✨ Pro plan"
42
- - **ALWAYS** use tight letter-spacing on headings (`-0.02em` to `-0.04em`)
43
- - **ALWAYS** use `clamp()` for display/heading text so it scales fluidly
44
- - **ALWAYS** add at least one accent gradient somewhere — a hero, a button, a decorative element
45
- - **ALWAYS** give the app a distinct visual personality — if you removed the content, could you still tell which app this is?
46
-
47
- ### Color Strategy
48
-
49
- - **Theme-match your palette to the domain.** Don't default to violet. Pick the color that feels right: emerald/sage for plants & nature, purple for fitness & wellness, amber/gold for finance & productivity, rose for social & lifestyle, indigo for tech & developer tools.
50
- - **Define custom CSS variables at the top of `<style>`** for every app:
51
- ```css
52
- :root {
53
- --accent: #18B07A; /* domain-matched accent */
54
- --accent-light: #ECFDF5; /* tinted surface */
55
- --bg-tint: #F0F5F0; /* warm/cool background tint */
56
- }
57
- @media (prefers-color-scheme: dark) {
58
- :root {
59
- --accent: #38CF93;
60
- --accent-light: #073D2E;
61
- --bg-tint: #0A1A14;
62
- }
63
- }
64
- ```
65
- - **Background tint examples:** `#FEFCF9` cream (lifestyle), `#F0F5F0` sage (nature), `#F5F7FA` cool gray (finance), `#FDF6F3` warm blush (wellness), `#F5F3FF` lavender (creative). Apply to `body { background: var(--bg-tint); }`.
66
- - **60-30-10 rule:** 60% tinted background/surface, 30% secondary/text, 10% accent. Never use accent for large areas.
67
- - **Status colors are semantic:** emerald = success/positive, rose = danger/destructive, amber = warning/attention. Don't use these for decoration.
68
- - **`--v-*` tokens remain available** for spacing, radius, shadows, and animations. Use them for layout consistency. But stop defaulting to `--v-violet-*` for accent — use your domain-matched `--accent` variable instead.
69
- - For branded/themed apps, write custom CSS with `@media (prefers-color-scheme: dark)` overrides instead of mixing `--v-*` auto-switching variables with hardcoded colors.
70
-
71
- ### Typography Rules
72
-
73
- - **Display/hero text:** `font-weight: 800`, `letter-spacing: -0.03em`, `clamp(1.75rem, 4vw, 2.5rem)` for fluid sizing
74
- - **Accent-word technique:** In hero headings, wrap ONE key word in a `<span>` with the accent color or a gradient. This is the single most impactful typography move: `<h1>Track your <span class="accent-word">Growth</span> daily</h1>`. Use `.accent-word { color: var(--accent); }` or apply a gradient fill.
75
- - **Section headings:** `font-weight: 700`, `letter-spacing: -0.02em`, `--v-font-size-xl` or `--v-font-size-2xl`
76
- - **Body text:** `--v-font-size-base` (14px), `line-height: 1.55`
77
- - **Labels/captions:** `text-transform: uppercase`, `letter-spacing: 0.04em`, `--v-font-size-xs`, `font-weight: 600`, `color: var(--v-text-muted)`
78
- - **Monospace data:** Use `--v-font-mono` for numbers in metrics, code, timestamps
79
-
80
- ### Spacing & Layout
81
-
82
- - Use the `--v-spacing-*` scale consistently — don't mix arbitrary pixel values with token values
83
- - **Card padding:** `--v-spacing-lg` (16px) minimum, `--v-spacing-xl` (24px) for hero/featured cards
84
- - **Section gaps:** `--v-spacing-xxl` (32px) to `--v-spacing-xxxl` (48px) between major sections — Lovable-quality apps use generous whitespace
85
- - **Hero to first content:** minimum `--v-spacing-xxxl` (48px)
86
- - **Element gaps:** `--v-spacing-sm` to `--v-spacing-md` between related elements
87
- - **When in doubt, add more whitespace.** The #1 difference between AI-generated and designer-quality is spacing. Double what feels right, then evaluate.
88
- - Use CSS Grid for dashboards and complex layouts. Use Flexbox for single-axis arrangements.
89
- - Every layout should look good from 400px to 600px wide
90
-
91
- ## Visual Techniques Cookbook
92
-
93
- Copy-paste-ready CSS techniques. All work in the sandboxed WebView with no external dependencies.
94
-
95
- ### Animated Gradient Background
96
-
97
- Choose **one** of the following color variants (do not combine both):
98
-
99
- **Variant A — Warm pastels (light, airy feel):**
100
- ```css
101
- body {
102
- background: linear-gradient(-45deg, #fef3c7, #fce7f3, #e0e7ff, #d1fae5);
103
- background-size: 400% 400%;
104
- animation: gradientShift 15s ease infinite;
105
- }
106
- @keyframes gradientShift {
107
- 0%, 100% { background-position: 0% 50%; }
108
- 50% { background-position: 100% 50%; }
109
- }
110
- ```
111
-
112
- **Variant B — Dark jewel tones (deep, rich feel):**
113
- ```css
114
- body {
115
- background: linear-gradient(-45deg, #0f172a, #1e1b4b, #172554, #0c4a6e);
116
- background-size: 400% 400%;
117
- animation: gradientShift 15s ease infinite;
118
- }
119
- @keyframes gradientShift {
120
- 0%, 100% { background-position: 0% 50%; }
121
- 50% { background-position: 100% 50%; }
122
- }
123
- ```
124
-
125
- ### Mesh Gradient (Layered Radials)
126
- ```css
127
- body {
128
- background:
129
- radial-gradient(ellipse at 20% 50%, color-mix(in srgb, var(--v-rose-400) 15%, transparent) 0%, transparent 50%),
130
- radial-gradient(ellipse at 80% 20%, color-mix(in srgb, var(--v-amber-400) 12%, transparent) 0%, transparent 50%),
131
- radial-gradient(ellipse at 50% 80%, color-mix(in srgb, var(--v-teal-400) 10%, transparent) 0%, transparent 50%),
132
- var(--v-bg);
133
- }
134
- ```
135
-
136
- ### Glassmorphism Card
137
- ```css
138
- .glass-card {
139
- background: color-mix(in srgb, var(--v-surface) 70%, transparent);
140
- backdrop-filter: blur(12px);
141
- -webkit-backdrop-filter: blur(12px);
142
- border: 1px solid color-mix(in srgb, var(--v-surface-border) 50%, transparent);
143
- border-radius: var(--v-radius-lg);
144
- box-shadow: var(--v-shadow-lg);
145
- }
146
- ```
147
-
148
- ### Layered Shadows (Realistic Depth)
149
- ```css
150
- .elevated-card {
151
- box-shadow:
152
- 0 1px 2px rgba(0,0,0,0.04),
153
- 0 4px 8px rgba(0,0,0,0.06),
154
- 0 12px 24px rgba(0,0,0,0.08);
155
- transition: box-shadow var(--v-duration-standard), transform var(--v-duration-standard);
156
- }
157
- .elevated-card:hover {
158
- transform: translateY(-2px);
159
- box-shadow:
160
- 0 2px 4px rgba(0,0,0,0.04),
161
- 0 8px 16px rgba(0,0,0,0.08),
162
- 0 24px 48px rgba(0,0,0,0.12);
163
- }
164
- ```
165
-
166
- ### Noise/Grain Texture Overlay
167
- ```css
168
- body::before {
169
- content: '';
170
- position: fixed;
171
- inset: 0;
172
- opacity: 0.03;
173
- pointer-events: none;
174
- z-index: 9999;
175
- background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
176
- }
177
- ```
178
-
179
- ### Gradient Text
180
- ```css
181
- .gradient-text {
182
- background: linear-gradient(135deg, var(--v-rose-500), var(--v-amber-400));
183
- -webkit-background-clip: text;
184
- -webkit-text-fill-color: transparent;
185
- background-clip: text;
186
- }
187
- ```
188
-
189
- ### Glow Effect
190
- ```css
191
- .glow-accent {
192
- box-shadow:
193
- 0 0 20px color-mix(in srgb, var(--v-accent) 30%, transparent),
194
- 0 0 40px color-mix(in srgb, var(--v-accent) 15%, transparent);
195
- }
196
- ```
197
-
198
- ### Dot Grid Pattern Background
199
- ```css
200
- .dot-pattern {
201
- background-image: radial-gradient(circle, var(--v-surface-border) 1px, transparent 1px);
202
- background-size: 20px 20px;
203
- }
204
- ```
205
-
206
- ### Staggered Reveal Animation
207
- ```css
208
- .reveal { opacity: 0; transform: translateY(20px); transition: opacity 0.6s ease, transform 0.6s ease; }
209
- .reveal.visible { opacity: 1; transform: translateY(0); }
210
- ```
211
- ```javascript
212
- const observer = new IntersectionObserver((entries) => {
213
- entries.forEach((entry, i) => {
214
- if (entry.isIntersecting) {
215
- setTimeout(() => entry.target.classList.add('visible'), i * 100);
216
- observer.unobserve(entry.target);
217
- }
218
- });
219
- }, { threshold: 0.1 });
220
- document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
221
- ```
222
-
223
- ### Card Hover (Lift + Border Glow)
224
- ```css
225
- .interactive-card {
226
- transition: transform var(--v-duration-standard), box-shadow var(--v-duration-standard),
227
- border-color var(--v-duration-standard);
228
- border: 1px solid var(--v-surface-border);
229
- cursor: pointer;
230
- }
231
- .interactive-card:hover {
232
- transform: translateY(-4px);
233
- box-shadow: var(--v-shadow-lg), 0 0 0 1px color-mix(in srgb, var(--v-accent) 20%, transparent);
234
- border-color: color-mix(in srgb, var(--v-accent) 40%, var(--v-surface-border));
235
- }
236
- ```
237
-
238
- ### Loading Skeleton Shimmer
239
- ```css
240
- .skeleton {
241
- background: linear-gradient(90deg,
242
- var(--v-surface) 25%,
243
- color-mix(in srgb, var(--v-surface-border) 50%, var(--v-surface)) 50%,
244
- var(--v-surface) 75%);
245
- background-size: 200% 100%;
246
- animation: shimmer 1.5s infinite;
247
- border-radius: var(--v-radius-sm);
248
- }
249
- .skeleton-text { height: 14px; margin-bottom: 8px; width: 80%; }
250
- .skeleton-heading { height: 24px; margin-bottom: 12px; width: 60%; }
251
- .skeleton-avatar { width: 40px; height: 40px; border-radius: 50%; }
252
- @keyframes shimmer { to { background-position: -200% 0; } }
253
- ```
254
-
255
- ### Animated Checkmark (Success Feedback)
256
- ```css
257
- .checkmark-circle {
258
- width: 48px; height: 48px; border-radius: 50%;
259
- background: var(--v-success); display: flex;
260
- align-items: center; justify-content: center;
261
- animation: scaleIn 0.3s ease;
262
- }
263
- .checkmark-circle::after {
264
- content: ''; width: 12px; height: 20px;
265
- border: solid white; border-width: 0 3px 3px 0;
266
- transform: rotate(45deg); margin-top: -4px;
267
- animation: checkDraw 0.2s 0.2s ease both;
268
- }
269
- @keyframes scaleIn { from { transform: scale(0); } to { transform: scale(1); } }
270
- @keyframes checkDraw { from { opacity: 0; } to { opacity: 1; } }
271
- ```
272
-
273
- ### Navigation Bar (Sticky Header)
274
- ```html
275
- <nav class="app-navbar">
276
- <div class="navbar-brand">🌿 PlantCare</div>
277
- <div class="navbar-links">
278
- <a href="#" class="nav-link active">Dashboard</a>
279
- <a href="#" class="nav-link">My Plants</a>
280
- <a href="#" class="nav-link">Schedule</a>
281
- </div>
282
- <button class="v-button navbar-cta">Add Plant</button>
283
- </nav>
284
- ```
285
- ```css
286
- .app-navbar {
287
- position: sticky; top: 0; z-index: 100;
288
- display: flex; align-items: center; gap: var(--v-spacing-lg);
289
- padding: var(--v-spacing-md) var(--v-spacing-xl);
290
- background: color-mix(in srgb, var(--bg-tint, var(--v-bg)) 85%, transparent);
291
- backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
292
- border-bottom: 1px solid var(--v-surface-border);
293
- }
294
- .navbar-brand { font-weight: 700; font-size: var(--v-font-size-lg); }
295
- .navbar-links { display: flex; gap: var(--v-spacing-sm); margin-left: auto; }
296
- .navbar-links .nav-link {
297
- padding: var(--v-spacing-xs) var(--v-spacing-md); border-radius: var(--v-radius-md);
298
- color: var(--v-text-secondary); font-weight: 500; font-size: var(--v-font-size-sm);
299
- text-decoration: none; transition: all var(--v-duration-fast);
300
- }
301
- .navbar-links .nav-link:hover { color: var(--v-text); background: var(--v-surface); }
302
- .navbar-links .nav-link.active { color: var(--accent, var(--v-accent)); font-weight: 600; }
303
- .navbar-cta { margin-left: var(--v-spacing-sm); padding: var(--v-spacing-xs) var(--v-spacing-lg); font-size: var(--v-font-size-sm); }
304
- ```
305
-
306
- ### Pill Badge / Trust Badge
307
- ```html
308
- <span class="trust-pill">🌟 Trusted by 12,000+ homes</span>
309
- <span class="trust-pill accent">+8.2% this week</span>
310
- ```
311
- ```css
312
- .trust-pill {
313
- display: inline-flex; align-items: center; gap: var(--v-spacing-xs);
314
- padding: var(--v-spacing-xs) var(--v-spacing-md);
315
- background: var(--v-surface); border: 1px solid var(--v-surface-border);
316
- border-radius: var(--v-radius-md); font-size: var(--v-font-size-xs);
317
- font-weight: 600; color: var(--v-text-secondary);
318
- }
319
- .trust-pill.accent {
320
- background: color-mix(in srgb, var(--accent, var(--v-accent)) 10%, transparent);
321
- border-color: color-mix(in srgb, var(--accent, var(--v-accent)) 25%, transparent);
322
- color: var(--accent, var(--v-accent));
323
- }
324
- ```
325
-
326
- ### Emoji Stat Card
327
- ```html
328
- <div class="emoji-stat-row">
329
- <div class="emoji-stat-card">
330
- <span class="emoji-stat-icon">🔥</span>
331
- <span class="emoji-stat-value">1,284</span>
332
- <span class="emoji-stat-label">Calories</span>
333
- </div>
334
- <div class="emoji-stat-card">
335
- <span class="emoji-stat-icon">🏃</span>
336
- <span class="emoji-stat-value">8,421</span>
337
- <span class="emoji-stat-label">Steps</span>
338
- </div>
339
- <div class="emoji-stat-card">
340
- <span class="emoji-stat-icon">💧</span>
341
- <span class="emoji-stat-value">2.4L</span>
342
- <span class="emoji-stat-label">Hydration</span>
343
- </div>
344
- </div>
345
- ```
346
- ```css
347
- .emoji-stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: var(--v-spacing-md); }
348
- .emoji-stat-card {
349
- background: var(--v-surface); border: 1px solid var(--v-surface-border);
350
- border-radius: var(--v-radius-lg); padding: var(--v-spacing-lg);
351
- display: flex; flex-direction: column; align-items: center; gap: var(--v-spacing-xs);
352
- text-align: center;
353
- }
354
- .emoji-stat-icon { font-size: 28px; line-height: 1; }
355
- .emoji-stat-value { font-size: var(--v-font-size-xl); font-weight: 700; color: var(--v-text); }
356
- .emoji-stat-label { font-size: var(--v-font-size-xs); color: var(--v-text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
357
- ```
11
+ **Your default behavior:** Build immediately. The user types "build me a habit tracker" and you deliver a complete, polished app with a domain-matched color palette, atmospheric background, and thoughtful interactions. Don't ask what colors they want. Don't show wireframes. Just build something stunning and let them refine from there.
358
12
 
359
- ### Accent Word Heading
360
- ```html
361
- <h1>Track your <span class="accent-word">Growth</span> daily</h1>
362
- <!-- Or with gradient variant: -->
363
- <h1>Imagine it. <span class="v-gradient-text">See it.</span></h1>
364
- ```
365
- ```css
366
- .accent-word { color: var(--accent, var(--v-accent)); }
367
- /* Gradient variant — use .v-gradient-text from the design system, or customize: */
368
- .accent-gradient {
369
- background: linear-gradient(135deg, var(--accent, var(--v-rose-500)), var(--v-amber-400));
370
- -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
371
- }
372
- ```
373
-
374
- ### Interactive Pill Toggles
375
- ```html
376
- <div class="pill-toggles">
377
- <button class="pill-toggle active">1W</button>
378
- <button class="pill-toggle">1M</button>
379
- <button class="pill-toggle">3M</button>
380
- <button class="pill-toggle">1Y</button>
381
- </div>
382
- ```
383
- ```css
384
- .pill-toggles {
385
- display: inline-flex; gap: var(--v-spacing-xxs);
386
- background: var(--v-surface); border: 1px solid var(--v-surface-border);
387
- border-radius: var(--v-radius-md); padding: var(--v-spacing-xxs);
388
- }
389
- .pill-toggle {
390
- padding: var(--v-spacing-xs) var(--v-spacing-md);
391
- border-radius: var(--v-radius-md); border: none; background: none;
392
- font-size: var(--v-font-size-sm); font-weight: 500; color: var(--v-text-secondary);
393
- cursor: pointer; transition: all var(--v-duration-fast);
394
- }
395
- .pill-toggle:hover { color: var(--v-text); }
396
- .pill-toggle.active {
397
- background: var(--accent, var(--v-accent)); color: white; font-weight: 600;
398
- box-shadow: var(--v-shadow-sm);
399
- }
400
- ```
401
- ```javascript
402
- document.querySelectorAll('.pill-toggles').forEach(group => {
403
- group.addEventListener('click', (e) => {
404
- if (!e.target.classList.contains('pill-toggle')) return;
405
- group.querySelectorAll('.pill-toggle').forEach(b => b.classList.remove('active'));
406
- e.target.classList.add('active');
407
- });
408
- });
409
- ```
410
-
411
- ### Suggestion Chips
412
- ```html
413
- <div class="chip-group">
414
- <button class="chip">🏠 All Rooms</button>
415
- <button class="chip">🛋️ Living Room</button>
416
- <button class="chip">🍳 Kitchen</button>
417
- <button class="chip">🛏️ Bedroom</button>
418
- <button class="chip active">🚿 Bathroom</button>
419
- </div>
420
- ```
421
- ```css
422
- .chip-group { display: flex; flex-wrap: wrap; gap: var(--v-spacing-xs); }
423
- .chip {
424
- padding: var(--v-spacing-xs) var(--v-spacing-md);
425
- border-radius: var(--v-radius-md); border: 1px solid var(--v-surface-border);
426
- background: var(--v-surface); font-size: var(--v-font-size-sm);
427
- color: var(--v-text-secondary); cursor: pointer; transition: all var(--v-duration-fast);
428
- }
429
- .chip:hover { border-color: var(--accent, var(--v-accent)); color: var(--v-text); }
430
- .chip.active {
431
- background: color-mix(in srgb, var(--accent, var(--v-accent)) 12%, transparent);
432
- border-color: var(--accent, var(--v-accent)); color: var(--accent, var(--v-accent)); font-weight: 600;
433
- }
434
- ```
435
-
436
- ### Category Card Row
437
- ```html
438
- <div class="category-cards">
439
- <div class="category-card">
440
- <span class="category-icon">🧹</span>
441
- <span class="category-name">Standard Clean</span>
442
- <span class="category-meta">2-3 hrs · From $60</span>
443
- </div>
444
- <div class="category-card">
445
- <span class="category-icon">✨</span>
446
- <span class="category-name">Deep Clean</span>
447
- <span class="category-meta">4-5 hrs · From $120</span>
448
- </div>
449
- <div class="category-card">
450
- <span class="category-icon">📦</span>
451
- <span class="category-name">Move-Out</span>
452
- <span class="category-meta">5-7 hrs · From $180</span>
453
- </div>
454
- </div>
455
- ```
456
- ```css
457
- .category-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: var(--v-spacing-md); }
458
- .category-card {
459
- background: var(--v-surface); border: 1px solid var(--v-surface-border);
460
- border-radius: var(--v-radius-lg); padding: var(--v-spacing-lg);
461
- display: flex; flex-direction: column; align-items: center; gap: var(--v-spacing-sm);
462
- text-align: center; cursor: pointer;
463
- transition: transform var(--v-duration-fast), border-color var(--v-duration-fast);
464
- }
465
- .category-card:hover { transform: translateY(-2px); border-color: var(--accent, var(--v-accent)); }
466
- .category-icon { font-size: 32px; line-height: 1; }
467
- .category-name { font-weight: 600; font-size: var(--v-font-size-base); color: var(--v-text); }
468
- .category-meta { font-size: var(--v-font-size-xs); color: var(--v-text-muted); }
469
- ```
13
+ **Design quality is delegated to the `frontend-design` skill.** That skill defines your aesthetic principles: typography, color strategy, motion, spatial composition, and visual detail. Follow it completely for every build. This skill (app-builder) handles the technical infrastructure: sandbox constraints, data bridge, widget API, app lifecycle, and interaction patterns.
470
14
 
471
15
  ## Workflow
472
16
 
@@ -475,7 +19,7 @@ document.querySelectorAll('.pill-toggles').forEach(group => {
475
19
  **Default: just build.** When a user says "build me a habit tracker," don't ask what colors they want or how many fields to include. Immediately:
476
20
 
477
21
  1. Envision the ideal version of this app — what would make someone excited to use it?
478
- 2. Pick a distinctive visual direction a color palette, atmospheric background, visual personality
22
+ 2. Pick a distinctive visual direction following the `frontend-design` skill
479
23
  3. Design a clean data schema
480
24
  4. Build the complete, polished app with animations, interactions, and empty states
481
25
 
@@ -485,11 +29,14 @@ document.querySelectorAll('.pill-toggles').forEach(group => {
485
29
 
486
30
  **When in doubt, build something impressive** and let the user refine with `app_update`. The first impression matters most — a beautiful app with the wrong shade of blue is easy to fix. A correct but ugly app is hard to come back from.
487
31
 
32
+ **There are no "quick" builds.** Every app, regardless of complexity, gets the full design treatment. A 3-field form and a 20-section dashboard get the same design care. The only difference is scope, not quality.
33
+
488
34
  ### 2. Design the Data Schema
489
35
 
490
36
  Create a JSON Schema that defines the structure of a single record. Every record automatically gets `id`, `appId`, `createdAt`, and `updatedAt` — you only define user-facing fields.
491
37
 
492
38
  Schema guidelines:
39
+
493
40
  - Use `type: "object"` at the top level
494
41
  - Define `properties` for each field
495
42
  - Supported types: `string`, `number`, `boolean`
@@ -497,13 +44,20 @@ Schema guidelines:
497
44
  - Keep schemas reasonably flat — encode complex nested data as JSON strings when needed
498
45
 
499
46
  Example schema for a project tracker:
47
+
500
48
  ```json
501
49
  {
502
50
  "type": "object",
503
51
  "properties": {
504
52
  "title": { "type": "string" },
505
- "status": { "type": "string", "enum": ["backlog", "in-progress", "review", "done"] },
506
- "priority": { "type": "string", "enum": ["low", "medium", "high", "critical"] },
53
+ "status": {
54
+ "type": "string",
55
+ "enum": ["backlog", "in-progress", "review", "done"]
56
+ },
57
+ "priority": {
58
+ "type": "string",
59
+ "enum": ["low", "medium", "high", "critical"]
60
+ },
507
61
  "description": { "type": "string" },
508
62
  "tags": { "type": "string" }
509
63
  },
@@ -531,29 +85,29 @@ A design system CSS is auto-injected inside a `@layer`, so your styles always ta
531
85
 
532
86
  Available design tokens:
533
87
 
534
- | Category | Tokens |
535
- |---|---|
536
- | **Backgrounds** | `--v-bg`, `--v-surface`, `--v-surface-border` |
537
- | **Text** | `--v-text`, `--v-text-secondary`, `--v-text-muted` |
538
- | **Accent** | `--v-accent`, `--v-accent-hover` |
539
- | **Status** | `--v-success`, `--v-danger`, `--v-warning` |
540
- | **Spacing** | `--v-spacing-xxs` (2px) / `-xs` (4px) / `-sm` (8px) / `-md` (12px) / `-lg` (16px) / `-xl` (24px) / `-xxl` (32px) / `-xxxl` (48px) |
541
- | **Radius** | `--v-radius-xs` (2px) / `-sm` (4px) / `-md` (8px) / `-lg` (12px) / `-xl` (16px) / `-pill` (999px) |
542
- | **Shadows** | `--v-shadow-sm`, `--v-shadow-md`, `--v-shadow-lg` |
543
- | **Typography** | `--v-font-family`, `--v-font-mono`, `--v-font-size-xs` (10px) / `-sm` (11px) / `-base` (14px) / `-lg` (17px) / `-xl` (22px) / `-2xl` (26px), `--v-line-height` |
544
- | **Animation** | `--v-duration-fast` (0.15s) / `-standard` (0.25s) / `-slow` (0.4s) |
545
- | **Palettes** | `--v-slate-{950..50}`, `--v-emerald-*`, `--v-violet-*`, `--v-indigo-*`, `--v-rose-*`, `--v-amber-*` |
88
+ | Category | Tokens |
89
+ | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
90
+ | **Backgrounds** | `--v-bg`, `--v-surface`, `--v-surface-border` |
91
+ | **Text** | `--v-text`, `--v-text-secondary`, `--v-text-muted` |
92
+ | **Accent** | `--v-accent`, `--v-accent-hover` |
93
+ | **Status** | `--v-success`, `--v-danger`, `--v-warning` |
94
+ | **Spacing** | `--v-spacing-xxs` (2px) / `-xs` (4px) / `-sm` (8px) / `-md` (12px) / `-lg` (16px) / `-xl` (24px) / `-xxl` (32px) / `-xxxl` (48px) |
95
+ | **Radius** | `--v-radius-xs` (2px) / `-sm` (4px) / `-md` (8px) / `-lg` (12px) / `-xl` (16px) / `-pill` (999px) |
96
+ | **Shadows** | `--v-shadow-sm`, `--v-shadow-md`, `--v-shadow-lg` |
97
+ | **Typography** | `--v-font-family`, `--v-font-mono`, `--v-font-size-xs` (10px) / `-sm` (11px) / `-base` (14px) / `-lg` (17px) / `-xl` (22px) / `-2xl` (26px), `--v-line-height` |
98
+ | **Animation** | `--v-duration-fast` (0.15s) / `-standard` (0.25s) / `-slow` (0.4s) |
99
+ | **Palettes** | `--v-slate-{950..50}`, `--v-emerald-*`, `--v-violet-*`, `--v-indigo-*`, `--v-rose-*`, `--v-amber-*` |
546
100
 
547
101
  Utility classes: `.v-button` (`.secondary`/`.danger`/`.ghost`), `.v-card`, `.v-list`/`.v-list-item`, `.v-badge` (`.success`/`.warning`/`.danger`), `.v-input-row`, `.v-empty-state`, `.v-toggle`.
548
102
 
549
103
  **Custom themes:** When the user wants a specific branded look, write complete CSS with hardcoded colors and `@media (prefers-color-scheme: dark)` for dark variants. Don't mix `--v-*` auto-switching variables with hardcoded colors in the same element.
550
104
 
551
105
  **Theme detection in JavaScript:**
106
+
552
107
  ```javascript
553
108
  console.log(window.vellum.theme.mode); // 'light' or 'dark'
554
- window.addEventListener('vellum-theme-change', (e) => {
555
- // Update canvas colors, chart themes, etc.
556
- console.log('Theme:', e.detail.mode);
109
+ window.addEventListener("vellum-theme-change", (e) => {
110
+ console.log("Theme:", e.detail.mode);
557
111
  });
558
112
  ```
559
113
 
@@ -561,617 +115,127 @@ window.addEventListener('vellum-theme-change', (e) => {
561
115
 
562
116
  A CSS/JS widget library is auto-injected alongside the design system. Use these for standard UI patterns — skip them when custom HTML serves the user better.
563
117
 
564
- **Layout & Data Primitives:**
565
-
566
- `.v-metric-card` Big number with emoji icon, label, and trend:
567
- ```html
568
- <div class="v-metric-card">
569
- <span class="v-metric-icon">💰</span>
570
- <span class="v-metric-label">Revenue</span>
571
- <span class="v-metric-value">$12,450</span>
572
- <span class="v-metric-trend up">↑ 12.3%</span>
573
- </div>
574
- ```
575
- Wrap in `.v-metric-grid` for responsive 2-4 column layout. Always use a semantically meaningful emoji: 🔥 for streaks, 🏃 for activity, 💧 for hydration, 📈 for growth, etc.
576
-
577
- `.v-data-table` Sortable table with sticky header and hover states:
578
- ```html
579
- <table class="v-data-table" id="my-table">
580
- <thead><tr>
581
- <th><input type="checkbox"></th>
582
- <th data-sortable>Name</th>
583
- <th data-sortable>Amount</th>
584
- </tr></thead>
585
- <tbody><tr data-id="1">
586
- <td><input type="checkbox"></td>
587
- <td>Item</td>
588
- <td data-sort-value="100">$100.00</td>
589
- </tr></tbody>
590
- </table>
591
- ```
592
-
593
- `.v-tabs` Tab navigation with keyboard support:
594
- ```html
595
- <div class="v-tabs" id="my-tabs">
596
- <div class="v-tab-bar" role="tablist">
597
- <button class="v-tab" aria-controls="panel-1">Tab 1</button>
598
- <button class="v-tab" aria-controls="panel-2">Tab 2</button>
599
- </div>
600
- <div class="v-tab-panel" id="panel-1">Content 1</div>
601
- <div class="v-tab-panel" id="panel-2" hidden>Content 2</div>
602
- </div>
603
- ```
604
-
605
- `.v-accordion` Collapsible sections:
606
- ```html
607
- <div class="v-accordion" id="my-accordion">
608
- <div class="v-accordion-item">
609
- <button class="v-accordion-header" aria-expanded="true">Section 1</button>
610
- <div class="v-accordion-body">Content here</div>
611
- </div>
612
- </div>
613
- ```
614
-
615
- `.v-search-bar` — Search input with clear button:
616
- ```html
617
- <div class="v-search-bar">
618
- <input type="text" placeholder="Search..." id="search">
619
- <button class="v-search-clear">✕</button>
620
- </div>
621
- ```
622
-
623
- `.v-empty-state` — No-data placeholder with CTA:
624
- ```html
625
- <div class="v-empty-state">
626
- <div class="v-empty-icon">📋</div>
627
- <div class="v-empty-title">No items yet</div>
628
- <div class="v-empty-desc">Create your first item to get started.</div>
629
- <button class="v-button">Create Item</button>
630
- </div>
631
- ```
632
-
633
- **Additional layout widgets** (use with semantic HTML, all support `--v-*` tokens):
634
-
635
- | Widget | Usage | Key Classes/Modifiers |
636
- |---|---|---|
637
- | `.v-timeline` | Vertical timeline | `.v-timeline-entry` (`.active`/`.success`/`.error`), `.v-timeline-time`, `.v-timeline-title`, `.v-timeline-desc` |
638
- | `.v-action-list` | Rows with per-item actions | `.v-action-list-item`, `.v-action-content`, `.v-action-title`, `.v-action-subtitle`, `.v-action-buttons` |
639
- | `.v-card-grid` | Responsive card grid | Wrap `.v-card` elements |
640
- | `.v-progress-bar` | Horizontal progress | `.v-progress-header`, `.v-progress-track`, `.v-progress-fill` (`.success`/`.warning`/`.danger`) |
641
- | `.v-status-badge` | Colored pill with dot | `.success`, `.error`, `.warning`, `.info` |
642
- | `.v-stat-row` | Horizontal label-value pairs | `.v-stat`, `.v-stat-label`, `.v-stat-value` |
643
- | `.v-toast` | Notification banner | `.success`, `.error`, `.warning`, `.info` — prefer `vellum.widgets.toast()` |
644
- | `.v-divider` | Section separator | Optional text label inside |
645
- | `.v-avatar-row` | Contact/team display | `.v-avatar`, `.v-avatar-info`, `.v-avatar-name`, `.v-avatar-subtitle` |
646
- | `.v-tag-group` | Wrapping tag row | Wrap `.v-badge` elements |
647
-
648
- **Domain-specific widgets** (infer HTML structure from class names):
649
-
650
- | Widget | Purpose | Key Classes |
651
- |---|---|---|
652
- | `.v-weather-card` | Temperature + forecast | `.v-weather-main`, `.v-weather-temp`, `.v-weather-condition`, `.v-weather-icon`, `.v-weather-details`, `.v-weather-forecast`, `.v-weather-forecast-item` |
653
- | `.v-stock-ticker` | Price display + chart | `.v-stock-header`, `.v-stock-symbol`, `.v-stock-price`, `.v-stock-change` (`.up`/`.down`), `.v-stock-chart`, `.v-stock-meta` |
654
- | `.v-flight-card` | Flight info | `.v-flight-header`, `.v-flight-airline`, `.v-flight-price`, `.v-flight-route`, `.v-flight-endpoint`, `.v-flight-time`, `.v-flight-code`, `.v-flight-duration`, `.v-flight-line` |
655
- | `.v-billing-chart` | Usage/billing display | `.v-billing-header`, `.v-billing-total`, `.v-billing-period`, `.v-billing-canvas`, `.v-billing-legend`, `.v-billing-legend-item`, `.v-billing-legend-dot` |
656
- | `.v-boarding-pass` | Pass-styled layout | `.v-bp-header`, `.v-bp-route`, `.v-bp-city`, `.v-bp-details`, `.v-bp-field`, `.v-bp-field-label`, `.v-bp-field-value` |
657
- | `.v-itinerary` | Day-by-day travel plan | `.v-itinerary-day`, `.v-itinerary-date`, `.v-itinerary-item`, `.v-itinerary-time`, `.v-itinerary-content`, `.v-itinerary-title`, `.v-itinerary-location` |
658
- | `.v-receipt` | Receipt layout | `.v-receipt-header`, `.v-receipt-store`, `.v-receipt-items`, `.v-receipt-line`, `.v-receipt-divider`, `.v-receipt-total` |
659
- | `.v-invoice` | Formal invoice | `.v-invoice-header`, `.v-invoice-title`, `.v-invoice-number`, `.v-invoice-parties`, `.v-invoice-party-label`, `.v-invoice-party-name`, `.v-invoice-table`, `.v-invoice-totals`, `.v-invoice-line` (`.total`) |
660
-
661
- **Content & landing page components:**
662
-
663
- `.v-hero` — Hero banner with gradient background, trust badge, and accent word:
664
- ```html
665
- <div class="v-hero">
666
- <span class="v-hero-badge">✨ Now with 4x faster generation</span>
667
- <h1>Imagine it. <span class="v-gradient-text">See it.</span></h1>
668
- <p class="v-hero-subtitle">A compelling tagline that makes users feel something.</p>
669
- </div>
670
- ```
671
-
672
- `.v-section-header` — Section intro with label:
673
- ```html
674
- <div class="v-section-header">
675
- <span class="v-section-label">🎯 Section</span>
676
- <h2>Section Title</h2>
677
- <p class="v-section-desc">Description text.</p>
678
- </div>
679
- ```
680
-
681
- `.v-feature-grid` + `.v-feature-card` — Feature showcase with hover lift:
682
- ```html
683
- <div class="v-feature-grid">
684
- <div class="v-feature-card">
685
- <div class="v-feature-icon">🚀</div>
686
- <div class="v-feature-title">Feature Name</div>
687
- <div class="v-feature-desc">Short description.</div>
688
- </div>
689
- </div>
690
- ```
691
-
692
- `.v-pullquote` — Blockquote with gradient accent border. `.v-comparison` — Before/after cards (3-column grid with `.before`/`.after` modifiers). `.v-page` — Centered container (max-width 600px). Use `.v-animate-in` on children for staggered fade-in. Use `.v-gradient-text` for accent-colored gradient text.
693
-
694
- `.v-slideshow` — Presentation slide deck with transitions and navigation. Init with `vellum.widgets.slideshow()`:
695
- ```html
696
- <div class="v-slideshow" id="deck">
697
- <div class="v-slide">
698
- <div class="v-slide-header">
699
- <span class="v-slide-label">Overview</span>
700
- </div>
701
- <h1 class="v-slide-title">The city that never <span class="accent-word">sleeps</span></h1>
702
- <p class="v-slide-body">Body text here...</p>
703
- <div class="v-slide-stats">
704
- <div class="v-slide-stat">
705
- <span class="v-slide-stat-value">8.3M</span>
706
- <span class="v-slide-stat-label">Residents</span>
707
- </div>
708
- </div>
709
- </div>
710
- <div class="v-slide"><!-- Slide 2 --></div>
711
- <div class="v-slide"><!-- Slide 3 --></div>
712
- </div>
713
- ```
714
- Slide content helpers: `.v-slide-label` (section label with colored dot), `.v-slide-title` (responsive heading), `.v-slide-body` (body text, max-width 540px), `.v-slide-stats` (auto-fit grid), `.v-slide-stat` / `.v-slide-stat-value` / `.v-slide-stat-label` (big-number cards), `.v-slide-quote` / `.v-slide-quote-attribution` (blockquote), `.v-slide-list` (styled list), `.v-slide-columns` / `.v-slide-column` (2-column comparison grid).
118
+ **Layout widgets** (class names, infer HTML structure):
119
+
120
+ | Widget | Purpose |
121
+ | ------------------------------------------------------------ | -------------------------------------------------------------- |
122
+ | `.v-metric-card` (`.v-metric-grid`) | Big number with emoji icon, label, trend |
123
+ | `.v-data-table` | Sortable table with sticky header, `th[data-sortable]` |
124
+ | `.v-tabs` / `.v-tab-bar` / `.v-tab-panel` | Tab navigation with keyboard support |
125
+ | `.v-accordion` / `.v-accordion-item` | Collapsible sections |
126
+ | `.v-search-bar` | Search input with clear button |
127
+ | `.v-empty-state` | No-data placeholder with CTA |
128
+ | `.v-timeline` / `.v-timeline-entry` | Vertical timeline (`.active`/`.success`/`.error`) |
129
+ | `.v-action-list` / `.v-action-list-item` | Rows with per-item actions |
130
+ | `.v-card-grid` | Responsive card grid |
131
+ | `.v-progress-bar` / `.v-progress-track` / `.v-progress-fill` | Horizontal progress |
132
+ | `.v-status-badge` | Colored pill with dot (`.success`/`.error`/`.warning`/`.info`) |
133
+ | `.v-stat-row` / `.v-stat` | Horizontal label-value pairs |
134
+ | `.v-toast` | Notification banner — prefer `vellum.widgets.toast()` |
135
+ | `.v-avatar-row` | Contact/team display |
136
+ | `.v-tag-group` | Wrapping tag row |
137
+
138
+ **Domain-specific widgets** (class names, infer HTML structure):
139
+
140
+ | Widget | Purpose |
141
+ | ------------------ | ---------------------- |
142
+ | `.v-weather-card` | Temperature + forecast |
143
+ | `.v-stock-ticker` | Price display + chart |
144
+ | `.v-flight-card` | Flight info with route |
145
+ | `.v-billing-chart` | Usage/billing display |
146
+ | `.v-boarding-pass` | Pass-styled layout |
147
+ | `.v-itinerary` | Day-by-day travel plan |
148
+ | `.v-receipt` | Receipt layout |
149
+ | `.v-invoice` | Formal invoice |
150
+
151
+ **Content & landing page components** (class names, infer HTML structure):
152
+
153
+ | Widget | Purpose |
154
+ | ------------------------------------------------ | --------------------------------------------------- |
155
+ | `.v-hero` / `.v-hero-badge` / `.v-hero-subtitle` | Hero banner with gradient, trust badge, accent word |
156
+ | `.v-section-header` / `.v-section-label` | Section intro with label |
157
+ | `.v-feature-grid` / `.v-feature-card` | Feature showcase with hover lift |
158
+ | `.v-pullquote` | Blockquote with gradient accent border |
159
+ | `.v-comparison` | Before/after cards (`.before`/`.after`) |
160
+ | `.v-page` | Centered container (max-width 600px) |
161
+ | `.v-gradient-text` | Accent-colored gradient text |
162
+ | `.v-animate-in` | Staggered fade-in for children |
163
+
164
+ **Slideshow** (`.v-slideshow`): Presentation slide deck with transitions. Init with `vellum.widgets.slideshow()`. Slide helpers: `.v-slide`, `.v-slide-label`, `.v-slide-title`, `.v-slide-body`, `.v-slide-stats`, `.v-slide-stat`, `.v-slide-quote`, `.v-slide-list`, `.v-slide-columns`.
715
165
 
716
166
  #### Widget JavaScript utilities
717
167
 
718
168
  Interactive utilities at `window.vellum.widgets.*`:
719
169
 
720
- **SVG Charts:**
170
+ **Charts** (always use these instead of hand-coding SVG/CSS charts):
171
+
721
172
  ```javascript
722
- // Sparkline inline mini chart
723
- vellum.widgets.sparkline('container-id', [10, 25, 15, 30], {
724
- width: 200, height: 40, color: 'var(--v-success)', strokeWidth: 2, fill: true
173
+ vellum.widgets.sparkline("container-id", [10, 25, 15, 30], {
174
+ width: 200,
175
+ height: 40,
176
+ color: "var(--v-success)",
177
+ strokeWidth: 2,
178
+ fill: true,
725
179
  });
726
-
727
- // Bar chart — labels, tooltips, optional horizontal
728
- vellum.widgets.barChart('container-id', [
729
- { label: 'Jan', value: 120 },
730
- { label: 'Feb', value: 180, color: 'var(--v-success)' }
731
- ], { width: 400, height: 200, showLabels: true, showValues: true, horizontal: false });
732
-
733
- // Line chart — gradient fill, grid, hover crosshair
734
- vellum.widgets.lineChart('container-id', [
735
- { label: 'Mon', value: 42 },
736
- { label: 'Tue', value: 58 }
737
- ], { width: 400, height: 200, showDots: true, showGrid: true, gridLines: 4 });
738
-
739
- // Progress ring — circular gauge
740
- vellum.widgets.progressRing('container-id', 75, {
741
- size: 100, strokeWidth: 8, color: 'var(--v-success)', label: '75%'
180
+ vellum.widgets.barChart(
181
+ "container-id",
182
+ [
183
+ { label: "Jan", value: 120 },
184
+ { label: "Feb", value: 180, color: "var(--v-success)" },
185
+ ],
186
+ {
187
+ width: 400,
188
+ height: 200,
189
+ showLabels: true,
190
+ showValues: true,
191
+ horizontal: false,
192
+ },
193
+ );
194
+ vellum.widgets.lineChart(
195
+ "container-id",
196
+ [
197
+ { label: "Mon", value: 42 },
198
+ { label: "Tue", value: 58 },
199
+ ],
200
+ { width: 400, height: 200, showDots: true, showGrid: true, gridLines: 4 },
201
+ );
202
+ vellum.widgets.progressRing("container-id", 75, {
203
+ size: 100,
204
+ strokeWidth: 8,
205
+ color: "var(--v-success)",
206
+ label: "75%",
742
207
  });
743
208
  ```
744
209
 
745
210
  **Data Formatting:**
211
+
746
212
  ```javascript
747
- vellum.widgets.formatCurrency(1234.56, 'USD'); // "$1,234.56"
748
- vellum.widgets.formatDate('2025-01-15', 'relative'); // "3d ago"
749
- vellum.widgets.formatDate('2025-01-15', 'short'); // "1/15/25"
213
+ vellum.widgets.formatCurrency(1234.56, "USD"); // "$1,234.56"
214
+ vellum.widgets.formatDate("2025-01-15", "relative"); // "3d ago"
215
+ vellum.widgets.formatDate("2025-01-15", "short"); // "1/15/25"
750
216
  vellum.widgets.formatNumber(1234567, { compact: true }); // "1.2M"
751
- vellum.widgets.formatNumber(0.156, { decimals: 1 }); // "0.2"
752
217
  ```
753
218
 
754
219
  **Interactive Behaviors:**
755
- ```javascript
756
- vellum.widgets.sortTable('table-id'); // Wire th[data-sortable] click-to-sort
757
- vellum.widgets.sortTable('table-id', 0); // Sort by column 0 immediately
758
- vellum.widgets.filterTable('table-id', 'search-input-id'); // Live text search
759
- vellum.widgets.tabs('tabs-id'); // Tab switching + keyboard nav
760
- vellum.widgets.accordion('accordion-id', { allowMultiple: true });
761
- vellum.widgets.multiSelect('table-id'); // Checkboxes + select-all
762
- vellum.widgets.toast('Saved!', 'success', 4000); // Auto-dismiss notification
763
- vellum.widgets.toast('Connection lost', 'error', 0); // Manual dismiss
764
- vellum.widgets.countdown('timer-el', '2025-12-31T00:00:00Z', {
765
- onComplete: () => console.log('Done!')
766
- });
767
-
768
- // Slideshow — presentation deck with transitions and navigation
769
- vellum.widgets.slideshow('deck', {
770
- transition: 'fade', showDots: true, showArrows: true,
771
- showCounter: true, keyboard: true, loop: true
772
- });
773
- // Returns: { goTo(index), next(), prev() }
774
- ```
775
-
776
- #### Composition recipes
777
-
778
- Combine widgets with wiring code to build complex UIs:
779
-
780
- **Search-driven list with suggestion chips** — filter items with quick-tap categories:
781
- ```html
782
- <div class="v-search-bar"><input id="search" placeholder="Search..."></div>
783
- <div class="chip-group" style="margin-top: var(--v-spacing-sm);">
784
- <button class="chip active" data-filter="all">🏠 All</button>
785
- <button class="chip" data-filter="kitchen">🍳 Kitchen</button>
786
- <button class="chip" data-filter="bedroom">🛏️ Bedroom</button>
787
- <button class="chip" data-filter="bathroom">🚿 Bathroom</button>
788
- </div>
789
- <ul class="v-action-list" id="list"></ul>
790
- <div class="v-empty-state" id="empty" hidden>
791
- <div class="v-empty-icon">🔍</div>
792
- <div class="v-empty-title">No results</div>
793
- </div>
794
- ```
795
- ```javascript
796
- let activeFilter = 'all';
797
- document.getElementById('search').addEventListener('input', filterList);
798
- document.querySelectorAll('.chip[data-filter]').forEach(chip => {
799
- chip.addEventListener('click', () => {
800
- document.querySelectorAll('.chip[data-filter]').forEach(c => c.classList.remove('active'));
801
- chip.classList.add('active');
802
- activeFilter = chip.dataset.filter;
803
- filterList();
804
- });
805
- });
806
-
807
- function filterList() {
808
- const q = document.getElementById('search').value.toLowerCase();
809
- let visible = 0;
810
- document.querySelectorAll('#list .v-action-list-item').forEach(item => {
811
- const textMatch = item.textContent.toLowerCase().includes(q);
812
- const catMatch = activeFilter === 'all' || item.dataset.category === activeFilter;
813
- item.hidden = !(textMatch && catMatch);
814
- if (!item.hidden) visible++;
815
- });
816
- document.getElementById('empty').hidden = visible > 0;
817
- }
818
- ```
819
220
 
820
- **Form with inline validation:**
821
- ```html
822
- <form id="create-form" novalidate>
823
- <div class="v-input-row">
824
- <label>Title *</label>
825
- <input id="title" required placeholder="Enter title">
826
- <span class="field-error" id="title-error"></span>
827
- </div>
828
- <div class="v-input-row">
829
- <label>Priority</label>
830
- <select id="priority">
831
- <option value="low">Low</option>
832
- <option value="medium" selected>Medium</option>
833
- <option value="high">High</option>
834
- </select>
835
- </div>
836
- <button type="submit" class="v-button" id="submit-btn">Create</button>
837
- </form>
838
- ```
839
- ```css
840
- .field-error { color: var(--v-danger); font-size: var(--v-font-size-xs); min-height: 1em; }
841
- input:invalid:not(:placeholder-shown) { border-color: var(--v-danger); }
842
- ```
843
221
  ```javascript
844
- document.getElementById('create-form').addEventListener('submit', async (e) => {
845
- e.preventDefault();
846
- const title = document.getElementById('title').value.trim();
847
- if (!title) {
848
- document.getElementById('title-error').textContent = 'Title is required';
849
- return;
850
- }
851
- document.getElementById('submit-btn').disabled = true;
852
- try {
853
- await window.vellum.data.create({
854
- title,
855
- priority: document.getElementById('priority').value
856
- });
857
- vellum.widgets.toast('Created!', 'success');
858
- e.target.reset();
859
- document.getElementById('title-error').textContent = '';
860
- await loadRecords();
861
- } catch (err) {
862
- vellum.widgets.toast('Failed to create', 'error');
863
- } finally {
864
- document.getElementById('submit-btn').disabled = false;
865
- }
222
+ vellum.widgets.sortTable("table-id"); // Wire th[data-sortable] click-to-sort
223
+ vellum.widgets.filterTable("table-id", "input-id"); // Live text search
224
+ vellum.widgets.tabs("tabs-id"); // Tab switching + keyboard nav
225
+ vellum.widgets.accordion("accordion-id", { allowMultiple: true });
226
+ vellum.widgets.multiSelect("table-id"); // Checkboxes + select-all
227
+ vellum.widgets.toast("Saved!", "success", 4000); // Auto-dismiss notification
228
+ vellum.widgets.countdown("timer-el", "2025-12-31T00:00:00Z", {
229
+ onComplete: () => {},
866
230
  });
867
- ```
868
-
869
- **Dashboard** — contextual header + emoji stats + pill toggles + chart:
870
- ```html
871
- <!-- Contextual header -->
872
- <div style="margin-bottom: var(--v-spacing-xxxl);">
873
- <p style="color: var(--v-text-muted); font-size: var(--v-font-size-sm); margin: 0;">Saturday, Feb 15</p>
874
- <h1 style="margin: var(--v-spacing-xs) 0;">Good morning, <span class="accent-word">Alex</span></h1>
875
- <span class="trust-pill accent">🔥 7-day streak</span>
876
- </div>
877
-
878
- <!-- Pill toggles for time range -->
879
- <div class="pill-toggles" style="margin-bottom: var(--v-spacing-xl);">
880
- <button class="pill-toggle active">1W</button>
881
- <button class="pill-toggle">1M</button>
882
- <button class="pill-toggle">3M</button>
883
- <button class="pill-toggle">1Y</button>
884
- </div>
885
-
886
- <!-- Emoji stat cards -->
887
- <div class="emoji-stat-row" style="margin-bottom: var(--v-spacing-xxl);">
888
- <div class="emoji-stat-card">
889
- <span class="emoji-stat-icon">🔥</span>
890
- <span class="emoji-stat-value" id="cal-value">1,284</span>
891
- <span class="emoji-stat-label">Calories</span>
892
- </div>
893
- <div class="emoji-stat-card">
894
- <span class="emoji-stat-icon">🏃</span>
895
- <span class="emoji-stat-value" id="steps-value">8,421</span>
896
- <span class="emoji-stat-label">Steps</span>
897
- </div>
898
- <div class="emoji-stat-card">
899
- <span class="emoji-stat-icon">💧</span>
900
- <span class="emoji-stat-value" id="hydration-value">2.4L</span>
901
- <span class="emoji-stat-label">Hydration</span>
902
- </div>
903
- </div>
904
-
905
- <!-- Chart + trend badge -->
906
- <div class="v-card" style="margin-bottom: var(--v-spacing-xxl);">
907
- <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom: var(--v-spacing-md);">
908
- <h3 style="margin:0;">Weekly Activity</h3>
909
- <span class="trust-pill accent">📈 +12% vs last week</span>
910
- </div>
911
- <div id="chart" style="height:200px;"></div>
912
- </div>
913
-
914
- <!-- Atmospheric tagline -->
915
- <p style="text-align:center; color: var(--v-text-muted); font-size: var(--v-font-size-sm); font-style:italic;">Powered by your consistency.</p>
916
- ```
917
- ```javascript
918
- function esc(s) { const d = document.createElement('div'); d.textContent = String(s); return d.innerHTML; }
919
-
920
- async function loadDashboard() {
921
- const records = await window.vellum.data.query();
922
- // Update stat values from real data
923
- // Render chart
924
- vellum.widgets.barChart('chart', records.map(r => ({
925
- label: esc(r.data.name), value: r.data.amount
926
- })));
927
- }
928
- // Wire pill toggles
929
- document.querySelectorAll('.pill-toggles').forEach(group => {
930
- group.addEventListener('click', (e) => {
931
- if (!e.target.classList.contains('pill-toggle')) return;
932
- group.querySelectorAll('.pill-toggle').forEach(b => b.classList.remove('active'));
933
- e.target.classList.add('active');
934
- // Re-fetch data for selected range
935
- });
936
- });
937
- ```
938
-
939
- **Landing page** — nav bar + trust badge hero + accent word + category cards:
940
- ```html
941
- <div class="v-page">
942
- <!-- Navigation bar -->
943
- <nav class="app-navbar reveal">
944
- <div class="navbar-brand">✨ SparkClean</div>
945
- <div class="navbar-links">
946
- <a href="#" class="nav-link active">Home</a>
947
- <a href="#" class="nav-link">Services</a>
948
- <a href="#" class="nav-link">Pricing</a>
949
- </div>
950
- <button class="v-button navbar-cta">Book Now</button>
951
- </nav>
952
-
953
- <!-- Hero with trust badge + accent word -->
954
- <div class="v-hero reveal">
955
- <span class="v-hero-badge">🌟 Trusted by 12,000+ homes</span>
956
- <h1>Your home, <span class="v-gradient-text">spotless.</span></h1>
957
- <p class="v-hero-subtitle">Professional cleaning matched to your schedule. Book in 60 seconds.</p>
958
- </div>
959
-
960
- <!-- Category cards -->
961
- <div class="reveal">
962
- <h2 style="text-align:center; margin-bottom: var(--v-spacing-xl);">Our <span class="accent-word">Services</span></h2>
963
- <div class="category-cards">
964
- <div class="category-card">
965
- <span class="category-icon">🧹</span>
966
- <span class="category-name">Standard Clean</span>
967
- <span class="category-meta">2-3 hrs · From $60</span>
968
- </div>
969
- <div class="category-card">
970
- <span class="category-icon">✨</span>
971
- <span class="category-name">Deep Clean</span>
972
- <span class="category-meta">4-5 hrs · From $120</span>
973
- </div>
974
- <div class="category-card">
975
- <span class="category-icon">📦</span>
976
- <span class="category-name">Move-Out</span>
977
- <span class="category-meta">5-7 hrs · From $180</span>
978
- </div>
979
- </div>
980
- </div>
981
-
982
- <!-- Feature grid -->
983
- <div class="v-feature-grid">
984
- <div class="v-feature-card reveal"><div class="v-feature-icon">⚡</div><div class="v-feature-title">Fast Booking</div><div class="v-feature-desc">Book in under 60 seconds.</div></div>
985
- <div class="v-feature-card reveal"><div class="v-feature-icon">🛡️</div><div class="v-feature-title">Insured</div><div class="v-feature-desc">Fully bonded & insured teams.</div></div>
986
- <div class="v-feature-card reveal"><div class="v-feature-icon">💚</div><div class="v-feature-title">Eco Products</div><div class="v-feature-desc">Safe for kids & pets.</div></div>
987
- </div>
988
-
989
- <!-- Atmospheric tagline -->
990
- <p class="reveal" style="text-align:center; color: var(--v-text-muted); font-style:italic;">A cleaner home starts here.</p>
991
- </div>
992
- ```
993
- ```javascript
994
- const observer = new IntersectionObserver((entries) => {
995
- entries.forEach((entry, i) => {
996
- if (entry.isIntersecting) {
997
- setTimeout(() => entry.target.classList.add('visible'), i * 120);
998
- observer.unobserve(entry.target);
999
- }
1000
- });
1001
- }, { threshold: 0.1 });
1002
- document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
1003
- ```
1004
-
1005
- **Multi-select table** — checkboxes + bulk toolbar:
1006
- ```html
1007
- <table class="v-data-table" id="my-table">
1008
- <thead><tr>
1009
- <th><input type="checkbox"></th>
1010
- <th data-sortable>Name</th>
1011
- <th data-sortable>Status</th>
1012
- </tr></thead>
1013
- <tbody>
1014
- <tr data-id="1"><td><input type="checkbox"></td><td>Item 1</td><td>Active</td></tr>
1015
- </tbody>
1016
- </table>
1017
- <div id="bulk-toolbar" hidden style="position:sticky;bottom:0;padding:12px;background:var(--v-surface);border-top:1px solid var(--v-surface-border);display:flex;gap:8px;">
1018
- <button class="v-button danger" onclick="handleBulk('delete')">Delete Selected</button>
1019
- <button class="v-button secondary" onclick="handleBulk('archive')">Archive</button>
1020
- </div>
1021
- ```
1022
- ```javascript
1023
- vellum.widgets.multiSelect('my-table');
1024
- document.getElementById('my-table').addEventListener('change', () => {
1025
- const any = document.querySelectorAll('#my-table tbody input:checked').length > 0;
1026
- document.getElementById('bulk-toolbar').hidden = !any;
1027
- });
1028
-
1029
- async function handleBulk(action) {
1030
- const ids = Array.from(document.querySelectorAll('#my-table tbody input:checked'))
1031
- .map(cb => cb.closest('tr').dataset.id);
1032
- if (action === 'delete') {
1033
- const ok = await window.vellum.confirm('Delete items?', `Delete ${ids.length} selected items?`);
1034
- if (!ok) return;
1035
- for (const id of ids) await window.vellum.data.delete(id);
1036
- vellum.widgets.toast(`Deleted ${ids.length} items`, 'success');
1037
- }
1038
- await loadRecords();
1039
- }
1040
- ```
1041
-
1042
- **Presentation slideshow** — multi-slide deck with 8 layout variants (title, stats, bullets, quote, comparison, visual, timeline, closing). Use the slideshow widget for presentations, pitch decks, and multi-slide educational content. The model provides slide content; the widget handles navigation, transitions, and keyboard support. Never tell the user how to navigate slides — the UI is self-explanatory.
1043
-
1044
- > **For comprehensive slide design guidelines, see the "Presentation Slide Design" section below.** The following HTML shows the structural template for all 8 layout types.
1045
-
1046
- ```html
1047
- <!DOCTYPE html>
1048
- <html lang="en">
1049
- <head>
1050
- <meta charset="UTF-8">
1051
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
1052
- <style>
1053
- :root { --v-accent: #8B5CF6; }
1054
- body { margin: 0; padding: 0; background: linear-gradient(-45deg, #0f172a, #1e1b4b, #172554); min-height: 100vh; }
1055
- .v-slideshow { border-radius: 0; min-height: 100vh; }
1056
- .accent-word { color: var(--v-accent); }
1057
- .trust-pill { display: inline-flex; align-items: center; gap: 6px; padding: 6px 14px; border-radius: 8px; font-size: 13px; font-weight: 500; background: color-mix(in srgb, var(--v-surface) 60%, transparent); border: 1px solid var(--v-surface-border); color: var(--v-text-secondary); margin-top: var(--v-spacing-lg); }
1058
- .trust-pill.accent { border-color: color-mix(in srgb, var(--v-accent) 30%, transparent); color: var(--v-accent); }
1059
- .v-slide-list li { font-size: 15px; line-height: 1.7; }
1060
- .v-slide-columns h3 { margin: 0 0 var(--v-spacing-sm); color: var(--v-text); font-size: var(--v-font-size-lg); }
1061
- .slide-visual { position: relative; overflow: hidden; }
1062
- .slide-visual-bg { position: absolute; inset: 0; background: radial-gradient(ellipse at 30% 40%, color-mix(in srgb, var(--v-accent) 15%, transparent), transparent 70%), radial-gradient(ellipse at 70% 60%, color-mix(in srgb, var(--v-forest-500, #22c55e) 10%, transparent), transparent 60%); }
1063
- .slide-visual-overlay { position: relative; z-index: 1; background: color-mix(in srgb, var(--v-bg) 40%, transparent); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border-radius: var(--v-radius-lg); padding: var(--v-spacing-xl); max-width: 500px; }
1064
- </style>
1065
- </head>
1066
- <body>
1067
- <div class="v-slideshow" id="deck">
1068
-
1069
- <!-- 1. Title slide -->
1070
- <div class="v-slide">
1071
- <span class="v-slide-label">Introduction</span>
1072
- <h1 class="v-slide-title">The city that never <span class="accent-word">sleeps</span></h1>
1073
- <p class="v-slide-body">A brief subtitle or tagline here.</p>
1074
- <span class="trust-pill accent">&#x1f5fd; 8.3 million residents</span>
1075
- </div>
1076
-
1077
- <!-- 2. Content + Stats slide -->
1078
- <div class="v-slide">
1079
- <span class="v-slide-label">By the Numbers</span>
1080
- <h2 class="v-slide-title">Economy at a glance</h2>
1081
- <p class="v-slide-body">New York generates more GDP than most countries...</p>
1082
- <div class="v-slide-stats">
1083
- <div class="v-slide-stat"><span class="v-slide-stat-value">$2.1T</span><span class="v-slide-stat-label">Metro GDP</span></div>
1084
- <div class="v-slide-stat"><span class="v-slide-stat-value">4.7M</span><span class="v-slide-stat-label">Jobs</span></div>
1085
- <div class="v-slide-stat"><span class="v-slide-stat-value">#1</span><span class="v-slide-stat-label">Financial Hub</span></div>
1086
- </div>
1087
- </div>
1088
-
1089
- <!-- 3. Bullet points slide -->
1090
- <div class="v-slide">
1091
- <span class="v-slide-label">Culture</span>
1092
- <h2 class="v-slide-title">What makes it <span class="accent-word">unique</span></h2>
1093
- <ul class="v-slide-list">
1094
- <li>&#x1f3ad; Broadway — 41 professional theaters in the Theater District</li>
1095
- <li>&#x1f3db;&#xfe0f; 80+ world-class museums including the Met and MoMA</li>
1096
- <li>&#x1f355; Over 27,000 restaurants spanning every cuisine on earth</li>
1097
- <li>&#x1f333; 843 acres of Central Park in the heart of Manhattan</li>
1098
- </ul>
1099
- </div>
1100
-
1101
- <!-- 4. Quote slide -->
1102
- <div class="v-slide" style="justify-content: center; align-items: center; text-align: center;">
1103
- <div class="v-slide-quote" style="border-left: none; padding-left: 0;">
1104
- "There is no place like New York. It is the most exciting city in the world."
1105
- </div>
1106
- <div class="v-slide-quote-attribution">— John Updike</div>
1107
- </div>
1108
-
1109
- <!-- 5. Comparison / Two-column slide -->
1110
- <div class="v-slide">
1111
- <span class="v-slide-label">Comparison</span>
1112
- <h2 class="v-slide-title">Manhattan vs Brooklyn</h2>
1113
- <div class="v-slide-columns">
1114
- <div class="v-slide-column">
1115
- <h3>&#x1f3d9;&#xfe0f; Manhattan</h3>
1116
- <p class="v-slide-body" style="margin-bottom: var(--v-spacing-sm);">Financial center, dense skyscrapers, high-energy nightlife, world-famous landmarks.</p>
1117
- <span class="v-slide-stat-value">1.6M</span>
1118
- <span class="v-slide-stat-label">Population</span>
1119
- </div>
1120
- <div class="v-slide-column">
1121
- <h3>&#x1f309; Brooklyn</h3>
1122
- <p class="v-slide-body" style="margin-bottom: var(--v-spacing-sm);">Creative hub, brownstone neighborhoods, artisan food scene, waterfront parks.</p>
1123
- <span class="v-slide-stat-value">2.7M</span>
1124
- <span class="v-slide-stat-label">Population</span>
1125
- </div>
1126
- </div>
1127
- </div>
1128
-
1129
- <!-- 6. Image/visual slide -->
1130
- <div class="v-slide slide-visual">
1131
- <div class="slide-visual-bg"></div>
1132
- <div class="slide-visual-overlay">
1133
- <span class="v-slide-label">Skyline</span>
1134
- <h2 class="v-slide-title">An iconic <span class="accent-word">horizon</span></h2>
1135
- <p class="v-slide-body">The Manhattan skyline is recognized worldwide...</p>
1136
- </div>
1137
- </div>
1138
-
1139
- <!-- 7. Timeline slide -->
1140
- <div class="v-slide">
1141
- <span class="v-slide-label">History</span>
1142
- <h2 class="v-slide-title">Key <span class="accent-word">milestones</span></h2>
1143
- <div class="v-timeline" style="margin-top: var(--v-spacing-lg);">
1144
- <div class="v-timeline-entry"><span class="v-timeline-time">1626</span><span class="v-timeline-title">Manhattan purchased</span></div>
1145
- <div class="v-timeline-entry"><span class="v-timeline-time">1886</span><span class="v-timeline-title">Statue of Liberty dedicated</span></div>
1146
- <div class="v-timeline-entry active"><span class="v-timeline-time">1931</span><span class="v-timeline-title">Empire State Building opens</span></div>
1147
- </div>
1148
- </div>
1149
-
1150
- <!-- 8. Closing / CTA slide -->
1151
- <div class="v-slide" style="text-align: center; align-items: center;">
1152
- <h1 class="v-slide-title">The world's <span class="accent-word">capital</span></h1>
1153
- <p class="v-slide-body" style="max-width: 400px;">New York isn't just a city — it's an idea that never stops evolving.</p>
1154
- <div class="v-slide-stats" style="margin-top: var(--v-spacing-xxl);">
1155
- <div class="v-slide-stat"><span class="v-slide-stat-value">800+</span><span class="v-slide-stat-label">Languages spoken</span></div>
1156
- <div class="v-slide-stat"><span class="v-slide-stat-value">62M</span><span class="v-slide-stat-label">Annual visitors</span></div>
1157
- </div>
1158
- </div>
1159
-
1160
- </div>
1161
- <script>
1162
- document.addEventListener('DOMContentLoaded', function() {
1163
- vellum.widgets.slideshow('deck', {
1164
- transition: 'fade',
1165
- showDots: true,
1166
- showArrows: true,
1167
- showCounter: true,
1168
- keyboard: true,
1169
- loop: true
1170
- });
231
+ vellum.widgets.slideshow("deck", {
232
+ transition: "fade",
233
+ showDots: true,
234
+ showArrows: true,
235
+ showCounter: true,
236
+ keyboard: true,
237
+ loop: true,
1171
238
  });
1172
- </script>
1173
- </body>
1174
- </html>
1175
239
  ```
1176
240
 
1177
241
  #### When to use widgets vs custom HTML
@@ -1179,25 +243,7 @@ document.addEventListener('DOMContentLoaded', function() {
1179
243
  - **Use widgets** for standard patterns — tables, metrics, timelines, notifications, presentations
1180
244
  - **Use custom HTML** for novel or creative UIs — games, art tools, unique dashboards
1181
245
  - **Mix freely** — widgets compose well together and with custom elements
1182
- - Always prioritize the ideal user experience over using the widget library — EXCEPT for charts: always use `vellum.widgets.*` chart functions (lineChart, barChart, sparkline, progressRing) instead of hand-coding SVG/CSS charts. They handle overflow clipping, bounds, scaling, and dark mode. Hand-coded charts break layouts.
1183
-
1184
- #### Advanced techniques
1185
-
1186
- Use modern web APIs to build genuinely impressive apps:
1187
-
1188
- - **Canvas 2D / WebGL** — charts, visualization, drawing, games, generative art
1189
- - **SVG** — icons, diagrams, interactive graphics
1190
- - **CSS animations & keyframes** — loading states, micro-interactions, page transitions
1191
- - **CSS transforms** — drag-and-drop, card flips, 3D effects
1192
- - **CSS gradients & filters** — blur effects, color overlays, rich backgrounds
1193
- - **CSS Grid subgrid** — complex dashboard layouts
1194
- - **Web Audio API** — sound effects, metronomes, music tools
1195
- - **requestAnimationFrame** — smooth animations, interactive canvases
1196
- - **Drag and drop** (HTML5) — reorderable lists, kanban boards
1197
- - **IntersectionObserver** — scroll-triggered animations, lazy rendering
1198
- - **ResizeObserver** — responsive canvas/chart sizing
1199
-
1200
- Don't reach for these when a simple list will do, but don't avoid them when they'd make the app genuinely better.
246
+ - **ALWAYS use `vellum.widgets.*` chart functions** instead of hand-coding SVG/CSS charts. They handle overflow clipping, bounds, scaling, and dark mode. Hand-coded charts break layouts.
1201
247
 
1202
248
  #### Data bridge API
1203
249
 
@@ -1209,6 +255,7 @@ The HTML interface can read and write records via `window.vellum.data`. All meth
1209
255
  - `window.vellum.data.delete(recordId)` — Deletes a record by ID. Returns void.
1210
256
 
1211
257
  Important:
258
+
1212
259
  - Call `query()` on page load to populate initial state
1213
260
  - User fields live in `record.data` (e.g., `record.data.title`)
1214
261
  - Record IDs are UUID strings
@@ -1222,8 +269,9 @@ Important:
1222
269
  #### JavaScript patterns
1223
270
 
1224
271
  Initialize apps with clean state management:
272
+
1225
273
  ```javascript
1226
- document.addEventListener('DOMContentLoaded', async () => {
274
+ document.addEventListener("DOMContentLoaded", async () => {
1227
275
  await loadRecords();
1228
276
  });
1229
277
 
@@ -1234,473 +282,118 @@ async function loadRecords() {
1234
282
  allRecords = await window.vellum.data.query();
1235
283
  render();
1236
284
  } catch (err) {
1237
- console.error('Failed to load:', err);
285
+ console.error("Failed to load:", err);
1238
286
  }
1239
287
  }
1240
288
 
1241
289
  function render() {
1242
290
  // Re-render UI from allRecords
1243
- // Apply client-side filtering/sorting
1244
291
  }
1245
292
  ```
1246
293
 
1247
- For complex apps, use a single state object:
1248
- ```javascript
1249
- const state = {
1250
- records: [],
1251
- filter: localStorage.getItem('filter') || 'all',
1252
- sortBy: localStorage.getItem('sortBy') || 'createdAt',
1253
- searchQuery: '',
1254
- editingId: null,
1255
- };
1256
-
1257
- function setState(updates) {
1258
- Object.assign(state, updates);
1259
- render();
1260
- }
1261
- ```
294
+ **HTML escaping:** Always escape user-controlled data before inserting into the DOM via `innerHTML`:
1262
295
 
1263
- **Loading state pattern:**
1264
296
  ```javascript
1265
- async function loadWithSkeleton() {
1266
- document.getElementById('content').innerHTML = `
1267
- <div class="skeleton skeleton-heading"></div>
1268
- <div class="skeleton skeleton-text"></div>
1269
- <div class="skeleton skeleton-text" style="width:60%"></div>`;
1270
- const records = await window.vellum.data.query();
1271
- setState({ records });
297
+ function esc(s) {
298
+ const d = document.createElement("div");
299
+ d.textContent = String(s);
300
+ return d.innerHTML;
1272
301
  }
1273
302
  ```
1274
303
 
1275
- **HTML escaping:** Always escape user-controlled data before inserting it into the DOM via `innerHTML`. Use this utility:
1276
- ```javascript
1277
- function esc(s) { const d = document.createElement('div'); d.textContent = String(s); return d.innerHTML; }
1278
- ```
1279
- Then wrap every user data interpolation: `` `<td>${esc(record.data.name)}</td>` ``. Alternatively, use `textContent` or DOM APIs to set text without innerHTML. Failing to escape leads to XSS vulnerabilities.
1280
-
1281
304
  ### 4. Single-Page App Views
1282
305
 
1283
- Apps run inside a sandboxed WebView that blocks all navigation — standard `<a>` links will not work for in-app navigation. All apps are effectively single-page. When an app needs multiple views (e.g., list + detail, dashboard + settings), use JavaScript to swap content within the page.
1284
-
1285
- #### View switching pattern
1286
-
1287
- Use a simple `showView()` function to toggle between sections:
1288
- ```html
1289
- <nav class="app-nav">
1290
- <button class="nav-link active" onclick="showView('home')">Home</button>
1291
- <button class="nav-link" onclick="showView('settings')">Settings</button>
1292
- </nav>
1293
-
1294
- <div id="view-home" class="view">
1295
- <!-- Home content -->
1296
- </div>
1297
- <div id="view-settings" class="view" hidden>
1298
- <!-- Settings content -->
1299
- </div>
1300
-
1301
- <style>
1302
- .app-nav { display: flex; gap: 4px; padding: 8px 12px; background: var(--v-surface); border-bottom: 1px solid var(--v-surface-border); }
1303
- .nav-link { padding: 6px 14px; border-radius: 6px; border: none; background: none; color: var(--v-text-secondary); font-size: 13px; font-weight: 500; cursor: pointer; transition: all 150ms; }
1304
- .nav-link:hover { background: var(--v-surface-border); color: var(--v-text); }
1305
- .nav-link.active { background: var(--v-accent); color: white; }
1306
- </style>
1307
- ```
306
+ Apps run inside a sandboxed WebView that blocks all navigation. All apps are effectively single-page. When an app needs multiple views, use JavaScript to swap content:
307
+
1308
308
  ```javascript
1309
309
  function showView(name) {
1310
- document.querySelectorAll('.view').forEach(v => v.hidden = true);
1311
- document.getElementById('view-' + name).hidden = false;
1312
- document.querySelectorAll('.nav-link').forEach(btn => btn.classList.remove('active'));
1313
- document.querySelector(`[onclick="showView('${name}')"]`)?.classList.add('active');
310
+ document.querySelectorAll(".view").forEach((v) => (v.hidden = true));
311
+ document.getElementById("view-" + name).hidden = false;
312
+ document
313
+ .querySelectorAll(".nav-link")
314
+ .forEach((btn) => btn.classList.remove("active"));
315
+ document
316
+ .querySelector(`[onclick="showView('${name}')"]`)
317
+ ?.classList.add("active");
1314
318
  }
1315
319
  ```
1316
320
 
1317
- For detail pages, call `showView('detail')` and populate the detail section's content dynamically before showing it. Use a "Back" button that calls `showView('home')` to return to the list.
1318
-
1319
321
  ### 5. Create and Open the App
1320
322
 
1321
323
  Call `app_create` with:
324
+
1322
325
  - `name`: Short descriptive name
1323
326
  - `description`: One-sentence summary
1324
327
  - `schema_json`: JSON schema as string
1325
- - `html`: Complete HTML document as string
1326
- - `auto_open`: (optional, defaults to `true`) Shows an inline preview card in chat after creation
1327
- - `preview`: Always include this see below
1328
-
1329
- Since `auto_open` defaults to `true`, an inline preview card is shown in chat after creation. The app is NOT opened in a workspace panel automatically — users open it explicitly if desired by clicking 'Open App' on the inline card. The app appears in Things (sidebar) immediately after creation via the `app_files_changed` broadcast.
1330
-
1331
- #### Preview metadata
1332
-
1333
- Always include preview metadata in `app_create` calls. The app shows as an inline card in chat first — no workspace opens automatically. Users can click 'Open App' on the inline card to open the workspace.
1334
-
1335
- Both `ui_show` and `app_create` support a `preview` object for an inline chat preview card. Always include it so the user sees a compact summary of what was built.
1336
-
1337
- **With `ui_show`:**
1338
- ```json
1339
- {
1340
- "surface_type": "dynamic_page",
1341
- "data": {
1342
- "html": "...",
1343
- "preview": {
1344
- "title": "Expense Tracker",
1345
- "subtitle": "Personal Finance",
1346
- "description": "Track daily expenses with category breakdowns.",
1347
- "icon": "💰",
1348
- "metrics": [
1349
- { "label": "Records", "value": "24" },
1350
- { "label": "Categories", "value": "8" }
1351
- ]
1352
- }
1353
- }
1354
- }
1355
- ```
1356
-
1357
- **With `app_create` (image URL icon):**
1358
- ```json
1359
- {
1360
- "name": "Microsoft Overview",
1361
- "schema_json": "{}",
1362
- "html": "...",
1363
- "preview": {
1364
- "title": "Microsoft",
1365
- "subtitle": "3 Slides",
1366
- "icon": "https://www.microsoft.com/favicon.ico",
1367
- "metrics": [
1368
- { "label": "Founded", "value": "1975" },
1369
- { "label": "Market Cap", "value": "$2.98T" }
1370
- ]
1371
- }
1372
- }
1373
- ```
328
+ - `html`: (optional) Complete HTML document as string for `index.html`. If omitted, a minimal scaffold is created — you can then write `index.html` and other files via `app_file_write`.
329
+ - `auto_open`: (optional, defaults to `true`) Shows an inline preview card in chat
330
+ - `preview`: Always include — `title` (required), `subtitle`, `description`, `icon` (image URL preferred, emoji fallback), `metrics` (up to 3 key-value pills)
1374
331
 
1375
- **With `app_create` (emoji icon):**
1376
- ```json
1377
- {
1378
- "name": "Expense Tracker",
1379
- "schema_json": "{}",
1380
- "html": "...",
1381
- "preview": {
1382
- "title": "Expense Tracker",
1383
- "icon": "💰",
1384
- "metrics": [
1385
- { "label": "Records", "value": "24" },
1386
- { "label": "Categories", "value": "8" }
1387
- ]
1388
- }
1389
- }
1390
- ```
1391
-
1392
- Preview fields: `title` (required), `subtitle`, `description`, `icon`, `metrics` (up to 3 key-value pills). The `icon` field accepts an emoji or an image URL. **Prefer an image URL whenever you have a relevant one** — logos, favicons, product images, headshots, flags, album art, or any image you encountered during research. The preview card renders image URLs as a thumbnail automatically. Fall back to emoji only when there is no natural image. When `app_create` is called with `auto_open: true` (the default), the inline preview card is shown in chat — the app is NOT automatically opened in a workspace panel.
332
+ The app is NOT opened in a workspace panel automatically — users open it via the 'Open App' button on the inline card.
1393
333
 
1394
334
  ### 6. Handle Iteration
1395
335
 
1396
- When the user requests changes to an existing app, prefer **`app_file_edit`** over rewriting the entire file. It performs surgical find-and-replace edits (like sed), which is faster and less error-prone than re-emitting a full page.
1397
-
1398
- #### Editing code
1399
-
1400
- - **`app_file_edit`** — preferred for modifying existing code. Provide `app_id`, `path` (e.g. `index.html`, `styles.css`), `old_string` (exact text to find), and `new_string` (replacement). Use this for targeted changes like updating styles, fixing bugs, or adding features.
1401
- - **`app_file_write`** — use when creating a new file or when changes are so extensive that a full rewrite is cleaner. Provide `app_id`, `path`, and `content`.
1402
- - Always include a **`status`** parameter when calling `app_file_edit` or `app_file_write` — a brief human-readable message describing what you are doing (e.g. "adding dark mode styles", "updating navigation layout", "fixing chart rendering bug"). This gives the user visible progress feedback.
1403
-
1404
- #### Metadata vs code changes
1405
-
1406
- - **`app_update`** — use for metadata changes only: `name`, `description`, and `schema_json`. Do not use it for code changes.
1407
- - **`app_file_edit`** / **`app_file_write`** — use for all code changes (HTML, CSS, JS). The surface refreshes automatically after file edits.
1408
- - If schema changes affect existing records, mention this.
1409
-
1410
- #### Multi-file apps
1411
-
1412
- Apps can have multiple files beyond `index.html`. Use separate files for CSS and JavaScript to keep code organized:
1413
-
1414
- - Create additional files with `app_file_write` (e.g. `styles.css`, `app.js`, `components/chart.js`).
1415
- - Link them from `index.html` using `<link rel="stylesheet" href="styles.css">` and `<script src="app.js"></script>`.
1416
- - Use `app_file_list` to see all files in an app.
1417
- - Use `app_file_read` to read any file with line numbers (helpful before making edits).
1418
-
1419
- Use `app_delete` to start over. Use `app_list` to check existing apps. Use `app_query` to inspect app data.
1420
-
1421
- ## Interactive Quality Standard
1422
-
1423
- Every app must meet these interaction baselines — they're the difference between "works" and "feels professional."
1424
-
1425
- ### Feedback for Every Action
1426
-
1427
- Every user action must produce visible feedback:
1428
- ```javascript
1429
- // After creating a record
1430
- vellum.widgets.toast('Task created', 'success');
1431
-
1432
- // After deleting
1433
- vellum.widgets.toast('Deleted', 'success');
1434
-
1435
- // After updating
1436
- vellum.widgets.toast('Changes saved', 'success');
1437
-
1438
- // On error
1439
- vellum.widgets.toast('Something went wrong', 'error');
1440
- ```
1441
-
1442
- ### Confirmation for Destructive Actions
336
+ When the user requests changes, prefer **`app_file_edit`** over rewriting the entire file.
1443
337
 
1444
- Use `window.vellum.confirm()` before deleting, resetting, or any irreversible action:
1445
- ```javascript
1446
- async function deleteRecord(id) {
1447
- const confirmed = await window.vellum.confirm(
1448
- 'Delete this item?',
1449
- 'This action cannot be undone.'
1450
- );
1451
- if (!confirmed) return;
1452
- await window.vellum.data.delete(id);
1453
- vellum.widgets.toast('Deleted', 'success');
1454
- await loadRecords();
1455
- }
1456
- ```
1457
- `window.vellum.confirm(title, message)` returns a `Promise<boolean>` — `true` if the user clicks OK, `false` for Cancel. It shows a native macOS dialog.
1458
-
1459
- ### Form Validation
1460
-
1461
- Validate before submit, show errors inline:
1462
- ```css
1463
- .field-error {
1464
- color: var(--v-danger);
1465
- font-size: var(--v-font-size-xs);
1466
- margin-top: 2px;
1467
- min-height: 1em;
1468
- }
1469
- input.invalid, select.invalid {
1470
- border-color: var(--v-danger);
1471
- box-shadow: 0 0 0 2px color-mix(in srgb, var(--v-danger) 15%, transparent);
1472
- }
1473
- ```
1474
- - Disable submit button while a required field is empty
1475
- - Clear error messages on input focus
1476
- - Show loading state on submit button during async operations
1477
-
1478
- ### Loading States
1479
-
1480
- Never show a blank screen while data loads:
1481
- ```javascript
1482
- function showLoading() {
1483
- container.innerHTML = `
1484
- <div class="skeleton skeleton-heading"></div>
1485
- <div class="skeleton skeleton-text"></div>
1486
- <div class="skeleton skeleton-text" style="width:70%"></div>`;
1487
- }
1488
- ```
1489
- - Disable buttons during async operations to prevent double-submit
1490
- - Use the skeleton shimmer CSS from the Visual Techniques section
1491
-
1492
- ### Keyboard Navigation
338
+ - **`app_file_edit`** preferred for targeted changes (styles, bugs, features). Provide `app_id`, `path`, `old_string`, `new_string`.
339
+ - **`app_file_write`** — use when creating new files or when changes are so extensive a full rewrite is cleaner.
340
+ - **`app_update`** metadata only: `name`, `description`, `schema_json`. Not for code changes.
341
+ - Always include a **`status`** parameter describing what you're doing.
1493
342
 
1494
- - `Tab` moves between interactive elements in logical order
1495
- - `Enter` submits forms, activates buttons
1496
- - `Escape` closes modals, cancels edits, clears search
1497
- - Use `tabindex` only when natural DOM order is insufficient
343
+ Apps can have multiple files (`styles.css`, `app.js`, etc.). Link from `index.html` with standard tags.
1498
344
 
1499
- ## What Great Apps Look Like
345
+ ## Interaction Standards
1500
346
 
1501
- These are the apps you should aspire to — each one demonstrates the Lovable-quality patterns in action:
347
+ Every app must meet these baselines:
1502
348
 
1503
- - **Fitness dashboard** Purple accent (`--accent: #8A5BE0`), lavender tinted background. Contextual header: "Good morning, Alex" with date. Pill toggles (Day/Week/Month) switching chart ranges. Emoji stat cards row (🔥 Calories, 🏃 Steps, 💧 Hydration, 😴 Sleep). Progress rings with distinct colors per metric. Trust pill: "🔥 7-day streak". Atmospheric tagline: "Powered by your consistency."
1504
- - **Plant tracker** Sage green accent (`--accent: #18B07A`), soft sage background (`#F0F5F0`). Contextual header: "🌿 Your Garden" with plant count badge. Category cards for plant types with emoji (🌵 Succulents, 🌿 Tropicals, 🌸 Flowering). Emoji stat row (💧 Watered today, ☀️ Light exposure, 🌱 New growth). Suggestion chips for filtering: "Needs water", "Low light", "Outdoors".
1505
- - **Finance vault** Navy/blue-gray accent (`--accent: #3B82F6`), cool gray background (`#F5F7FA`). Contextual header: "Welcome back, Alex" with net worth badge. Transaction list with emoji identifiers (🏠 Rent, 🛒 Groceries, ☕ Coffee). Trend badge: "+8.2% this month". Pill toggles for time ranges (1W/1M/3M/1Y).
1506
- - **Cleaning service landing page** Warm amber accent (`--accent: #E8A020`), cream background (`#FEFCF9`). Nav bar with logo ("✨ SparkClean") + CTA. Trust pill in hero: "🌟 Trusted by 12,000+ homes". Accent word hero: "Your home, **spotless.**" Category cards (🧹 Standard, ✨ Deep Clean, 📦 Move-Out with pricing). Feature grid with eco/speed/insurance.
1507
- - **AI tool landing page** — Purple gradient text, dark hero section. Suggestion chips below a demo input: "Summarize this", "Generate code", "Explain like I'm 5". Feature grid with emoji icons. Trust badge: "⚡ 4x faster than v1". Atmospheric tagline: "Intelligence, simplified."
349
+ - **Feedback for every action:** Use `vellum.widgets.toast()` after creates, deletes, updates, and errors.
350
+ - **Confirmation for destructive actions:** Use `window.vellum.confirm(title, message)` before deleting or resetting. Returns `Promise<boolean>`.
351
+ - **Form validation:** Validate before submit, show errors inline, disable submit during async operations.
352
+ - **Loading states:** Never show a blank screen while data loads. Use skeleton shimmer or spinners.
353
+ - **Keyboard navigation:** `Tab` between elements, `Enter` to submit, `Escape` to close/cancel.
1508
354
 
1509
- ### Pre-Ship Design Checklist
1510
-
1511
- Before delivering any app, mentally verify these 10 items — they cover the gap between "functional" and "designer-quality":
1512
-
1513
- 1. **Domain-matched palette** — Is the accent color appropriate for this domain? (Not default violet)
1514
- 2. **Tinted background** — Does the body have a warm/cool tint instead of pure white/dark?
1515
- 3. **Emoji stat cards** — Are there emoji icons in metric cards, list items, or navigation?
1516
- 4. **Accent word in heading** — Is ONE key word in the hero heading colored or gradient-filled?
1517
- 5. **Contextual header** — Is there a greeting, date, or personalized welcome (not just an app title)?
1518
- 6. **Trust/status pill badge** — Is there at least one pill badge with a stat, streak, or social proof?
1519
- 7. **Generous spacing** — Are section gaps 32-48px? Does the layout feel spacious, not cramped?
1520
- 8. **Clean card borders** — Do cards use subtle 1px borders instead of heavy multi-layer shadows?
1521
- 9. **Interactive elements** — Are there pill toggles, suggestion chips, or filter controls?
1522
- 10. **Atmospheric tagline** — Is there a warm, human-sounding line at the bottom or between sections?
355
+ ## Presentation Slide Design
1523
356
 
1524
- ### Additional widget classes
357
+ Slides are a different domain from apps. Skip app-specific patterns (contextual headers, search/filter, toast notifications, form validation, data bridge). Slides are static content.
1525
358
 
1526
- | Widget | Purpose | Key Classes |
1527
- |---|---|---|
1528
- | `.v-pill-toggles` | Time range / filter toggle group | `.v-pill-toggle` (`.active`) — container with pill buttons |
1529
- | `.v-chip-group` | Suggestion / filter chip row | `.v-chip` (`.active`) — wrapping row of clickable pills |
1530
- | `.v-metric-card .v-metric-icon` | Emoji icon in metric cards | Place emoji `<span>` with `.v-metric-icon` inside `.v-metric-card` |
1531
- | `.v-slideshow` | Presentation slide deck with transitions | `.v-slide` (`.active`), `.v-slide-label`, `.v-slide-title`, `.v-slide-body`, `.v-slide-stats`, `.v-slide-stat`, `.v-slide-quote` — init with `vellum.widgets.slideshow()` |
359
+ **Key principles:**
1532
360
 
1533
- Every app should include: search/filter, toast notifications for all CRUD operations, `window.vellum.confirm()` for destructive actions, staggered page-load animation, card hover effects, and skeleton loading states. (These requirements do not apply to presentation slide decks see "Presentation Slide Design" below.)
361
+ - One idea per slide — understood in 3 seconds
362
+ - Layout variety — 3+ different types per deck, never consecutive same-type
363
+ - 8 layout types: Title, Stats, Bullets, Quote, Comparison, Timeline, Visual/Immersive, Closing/CTA
364
+ - Bold backgrounds — dark, gradient, or strongly tinted
365
+ - Max 6 bullets per slide, max 3 sentences body text
366
+ - Never go below 15px for any visible text
1534
367
 
1535
- ## Presentation Slide Design
1536
-
1537
- ### Slide Design Philosophy
1538
-
1539
- - **One idea per slide** — each slide communicates a single concept, not a cluster of related points
1540
- - **Glanceable, not readable** — a slide should be understood in 3 seconds; dense text belongs in documents, not presentations
1541
- - **Visual storytelling arc** — open strong, build context, create emotional resonance, close with impact
1542
- - **Cinematic quality bar** — every deck should feel at home in a startup pitch, TED talk, or Apple keynote
1543
- - **The slide is the visual** — don't describe what the audience should imagine; show it through layout, color, and typography
1544
-
1545
- ### What App Rules to Skip for Slides
1546
-
1547
- The general app design checklist does NOT apply to slide decks. Specifically skip:
1548
-
1549
- - Contextual header/greeting ("Good morning, Alex") — slides are not dashboards
1550
- - Search/filter, pill toggles, suggestion chips — slides are not interactive apps
1551
- - Toast notifications, confirm dialogs, form validation — no CRUD in slides
1552
- - Data bridge API / `window.vellum.data` — slides are static content
1553
- - Skeleton loading states — slides render instantly
1554
- - Mandatory trust/status pill badge — use only when slide content calls for it (e.g., a "verified" badge on a stats slide)
1555
- - Mandatory emoji stat cards — use when they strengthen the message, skip when they clutter
1556
- - The app Pre-Ship Design Checklist — use the Slide Pre-Ship Checklist instead
1557
-
1558
- ### Slide Typography
1559
-
1560
- - **Title slides:** `clamp(2rem, 5vw, 3rem)`, weight 800 — much larger than app text
1561
- - **Body text:** `clamp(1rem, 2.5vw, 1.25rem)` — larger than app body (14px); keep to 2–3 sentences max
1562
- - **Stat values:** `clamp(1.75rem, 4vw, 2.5rem)` — big numbers are the most impactful element on any slide
1563
- - **Accent-word technique is ESSENTIAL** — even more than apps, every heading should color one key word with the accent color
1564
- - **Contrast is everything** — near-white on dark, near-black on light; no washed-out middle ground
1565
- - **Never go below 15px** for any visible text — if it doesn't fit, cut words, don't shrink font
1566
-
1567
- ### Slide Color & Visual Treatment
1568
-
1569
- - **Bold, full-bleed backgrounds** — warm cream, blush pink, soft lavender, deep navy, rich purple, dark emerald; vary light and dark across the deck
1570
- - **Animated gradient backgrounds** are ideal for title and closing slides — use `background-size: 400% 400%` with CSS animation
1571
- - **Domain-matched palettes still apply**, just executed more dramatically — a finance deck is navy/gold, a health deck is teal/white
1572
- - **One accent color used sparingly** — titles, stat borders, label dots, CTA buttons; never more than one accent
1573
- - **Glassmorphism works well** for slide overlays on visual/immersive slides — `backdrop-filter: blur()` with semi-transparent bg
1574
- - **Full-screen immersion:** `.v-slideshow` should use `border-radius: 0; min-height: 100vh` for edge-to-edge feel
1575
- - **Vary background darkness across slides** — alternate between dark, medium, and light backgrounds to create visual rhythm
1576
-
1577
- ### Slide Layout Rhythm
1578
-
1579
- When to use each of the 8 layout variants:
1580
-
1581
- | Type | When to Use |
1582
- |---|---|
1583
- | **Title** | Bold title with accent word, subtitle, optional badge — always first |
1584
- | **Stats** | Early for credibility; 2–4 stat cards with big numbers |
1585
- | **Bullets / Content** | Core message; 3–5 bullets max, or 2–3 sentence body |
1586
- | **Quote** | Emotional punctuation; center-aligned, breaks visual pattern |
1587
- | **Comparison** | Two-column before/after, entity comparison, or pros/cons |
1588
- | **Timeline** | Chronological progression; milestones, history, roadmap, or process steps using `.v-timeline-entry` entries |
1589
- | **Visual / Immersive** | Gradient background with glass overlay, minimal text |
1590
- | **Closing / CTA** | Bold title, short takeaway, optional stat reinforcement |
1591
-
1592
- **Layout rhythm rules:**
1593
-
1594
- - **NEVER** two slides of the same type back-to-back
1595
- - **5–8 slides:** title → stats → bullets → quote → comparison or timeline or visual → closing
1596
- - **3–4 slides:** title → stats or bullets → closing
1597
- - **10+ slides:** repeat content/stats but always separate with a quote, timeline, or visual slide
1598
- - **Every deck needs at least 3 different layout types** — variety creates visual interest
1599
-
1600
- ### Slide Anti-Slop Rules
1601
-
1602
- - **NEVER** more than 6 bullet points per slide — if you have more, split into two slides
1603
- - **NEVER** body text smaller than 15px — cut words instead of shrinking
1604
- - **NEVER** the same background color on consecutive slides — vary dark/light/gradient
1605
- - **NEVER** skip accent-word on title/heading slides — it's the #1 visual technique
1606
- - **NEVER** use `.v-slide-label` on every single slide — aim for 40–60% of slides
1607
- - **NEVER** center-align bullet slides — only center quotes and closing slides
1608
- - **NEVER** use the same stat value format everywhere — mix `$2.4M`, `147%`, `3x`, `12k+` for variety
1609
- - **NEVER** hand-code charts on slides — use `vellum.widgets.lineChart()` / `.barChart()` / `.sparkline()` / `.progressRing()` rendered into a `<div>` with a fixed height. Hand-coded chart SVGs bleed into adjacent slide elements.
1610
-
1611
- ### Slide Pre-Ship Checklist
1612
-
1613
- Before delivering any slide deck, verify:
1614
-
1615
- 1. **Domain-matched palette** — colors match the topic (not default violet for everything)
1616
- 2. **Bold background** — dark, gradient, or strongly tinted; not plain white
1617
- 3. **Accent word in every title** — one key word colored with the accent
1618
- 4. **One idea per slide** — each slide understood in 3 seconds
1619
- 5. **Layout variety** — 3+ different layout types, no consecutive same-type
1620
- 6. **Typography scale** — clear hierarchy; titles much larger than body text
1621
- 7. **Sparse content** — max 6 bullets, max 3 sentences body text per slide
1622
- 8. **Visual punctuation** — at least one quote, visual, or center-aligned slide
1623
- 9. **Strong open and close** — impactful title slide, clear takeaway closing
1624
- 10. **Immersive feel** — full-viewport slides, `min-height: 100vh; border-radius: 0`
1625
-
1626
- ### What Great Slide Decks Look Like
1627
-
1628
- - **Startup pitch deck** — dark navy animated gradient, accent-word title, trust pill on stats, big stat numbers (`$12M ARR`, `3x growth`), customer quote mid-deck, CTA closing with one bold ask
1629
- - **Company overview** — corporate blue on charcoal, stats-heavy early slides, comparison slide (us vs. competitors), timeline slide, professional/minimal emoji usage
1630
- - **Educational deck** — bright accent on light background, emoji in bullet points for visual anchoring, expert quote, glass overlay visual slide, "key takeaways" closing
1631
- - **Creative agency deck** — bold saturated palette, animated gradient backgrounds, minimal text per slide, maximum visual drama, notable client quote, portfolio-style comparison
368
+ Init with `vellum.widgets.slideshow()`. Use `.v-slide` with helpers: `.v-slide-label`, `.v-slide-title`, `.v-slide-body`, `.v-slide-stats`, `.v-slide-stat`, `.v-slide-quote`, `.v-slide-list`, `.v-slide-columns`.
1632
369
 
1633
370
  ## Error Handling
1634
371
 
1635
- - If `app_create` fails, verify `schema_json` is valid JSON and `html` is a complete HTML document. Retry with fixes.
1636
- - If `app_open` fails, verify `app_id` with `app_list`.
1637
- - If the user reports visual issues, use `app_file_edit` to fix the code. The surface refreshes automatically.
1638
- - All `window.vellum.data` calls must be wrapped in `try/catch` with user-friendly error feedback:
1639
- ```javascript
1640
- try {
1641
- await window.vellum.data.create(data);
1642
- vellum.widgets.toast('Created!', 'success');
1643
- } catch (err) {
1644
- console.error('Create failed:', err);
1645
- vellum.widgets.toast('Failed to save. Please try again.', 'error');
1646
- }
1647
- ```
1648
- - Never let a failed data operation silently pass — always show a toast or inline error message.
1649
- - If the page loads with no data, show a designed empty state (`.v-empty-state`) — never a blank screen.
1650
- - For forms, show validation errors inline next to the relevant field, not as an alert.
372
+ - All `window.vellum.data` calls must be wrapped in `try/catch` with user-friendly feedback.
373
+ - Never let a failed operation silently pass — always show a toast or inline error.
374
+ - If the page loads with no data, show a designed empty state (`.v-empty-state`).
375
+ - For forms, show validation errors inline next to the relevant field.
1651
376
 
1652
377
  ## Actionable UI
1653
378
 
1654
- When the user wants to triage, manage, or bulk-act on a collection of items (emails, files, notifications, tasks, subscriptions, contacts), generate an interactive UI that lets them review, select, and act on items directly.
1655
-
1656
- ### Pattern
1657
- 1. **Fetch data** — use the relevant tools to gather the items
1658
- 2. **Generate interactive UI** — render a `dynamic_page` with selectable items and action buttons
1659
- 3. **User selects + clicks action** — the UI sends a `surfaceAction` with an action ID and selected item IDs
1660
- 4. **Execute tools** — parse the action, call the appropriate tools
1661
- 5. **Update UI** — use `ui_update` to remove processed items and show feedback via `widgets.toast()`
1662
-
1663
- ### HTML structure
1664
- Choose the best layout for the data: grouped cards with checkboxes, data tables with selectable rows, kanban columns, stacked list items with inline actions, or any creative layout. The key constraint: items must be selectable and action buttons must call `sendAction` with the selected item IDs.
1665
-
1666
- ### CSS building blocks
1667
- - `.v-action-bar` — sticky bar at top, auto-hidden when nothing selected. Contains `.v-action-bar-count` and `.v-action-bar-buttons`
1668
- - `.v-action-progress` — inline progress bar for bulk operations
1669
- - `.v-group-header` / `.v-group-body` — collapsible grouped sections
1670
- - `.v-row-removing` — fade-out + slide animation for processed items
1671
-
1672
- ### Action data conventions
1673
- - Use semantic action IDs: `archive`, `unsubscribe`, `delete`, `move`, `mark_read`
1674
- - Always include selected item IDs: `sendAction("archive", { ids: ["msg_1", "msg_2"] })`
1675
-
1676
- ### Processing flow
1677
- 1. Parse the `surfaceAction` to get the action ID and data
1678
- 2. Use `vellum.confirm(title, message)` for destructive actions before executing
1679
- 3. Call the relevant tools with the item IDs
1680
- 4. Use `ui_update` to remove processed items and update counts
1681
- 5. Show `widgets.toast()` for feedback
1682
-
1683
- ### Error handling
1684
- - Handle partial failures: remove successful items, toast count, keep failed items selectable for retry
379
+ When the user wants to triage or bulk-act on items, generate an interactive UI with selectable items and action buttons.
1685
380
 
1686
- ### Surface lifecycle
1687
- - Use `ui_show` with `display: "panel"` to keep the surface open alongside chat
1688
- - Use `widgets.groupedSelect()` for grouped multi-select with action bar
1689
- - Use `widgets.removeItems()` to animate processed items out
381
+ 1. Fetch data with relevant tools
382
+ 2. Render a `dynamic_page` with selectable items and action buttons
383
+ 3. User selects + clicks action — UI sends `surfaceAction` with action ID and selected IDs
384
+ 4. Execute tools, update UI with `ui_update`, show feedback via `widgets.toast()`
385
+ 5. Use `window.vellum.confirm()` for destructive actions
1690
386
 
1691
387
  ## Home Base
1692
388
 
1693
- Home Base starts from a prebuilt scaffold. When updating Home Base, preserve required task-lane anchors and apply changes through `app_file_edit` or `app_file_write`.
389
+ Home Base starts from a prebuilt scaffold. When updating, preserve required task-lane anchors and apply changes through `app_file_edit` or `app_file_write`.
1694
390
 
1695
- Home Base buttons send prefilled natural-language prompts through `vellum.sendAction`. Treat these as normal user messages, not as direct execution commands.
1696
- - For appearance changes: keep customization color-first, ask for explicit confirmation before applying a full-dashboard update.
1697
- - For optional capability setup tasks (voice/computer control/ambient): keep them user-initiated and request permissions only when required for the chosen path.
1698
- - If a prompt is underspecified, ask one brief follow-up and continue.
391
+ Home Base buttons send prefilled natural-language prompts through `vellum.sendAction`. Treat these as normal user messages.
1699
392
 
1700
393
  ## External Links
1701
394
 
1702
- When building apps with linkable items (search results, product cards, bookings), use `vellum.openLink(url, metadata)` to make them clickable. Construct deep-link URLs when possible (airline booking pages, product pages, hotel reservations). Include `metadata.provider` and `metadata.type` for context: `vellum.openLink("https://delta.com/book?flight=DL123", {provider: "delta", type: "booking"})`.
395
+ Use `vellum.openLink(url, metadata)` to make items clickable. Construct deep-link URLs when possible. Include `metadata.provider` and `metadata.type` for context.
1703
396
 
1704
397
  ## Branding
1705
398
 
1706
- A "Built on Vellum" badge is auto-injected into every dynamic page and app at the bottom-right corner. Do NOT add your own "Built on Vellum" or "Powered by Vellum" text — the badge is handled automatically by the rendering layer.
399
+ A "Built on Vellum" badge is auto-injected into every page. Do NOT add your own.