@vellumai/assistant 0.4.17 → 0.4.19

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 (528) hide show
  1. package/docs/runbook-trusted-contacts.md +5 -3
  2. package/eslint.config.mjs +2 -2
  3. package/package.json +1 -1
  4. package/src/__tests__/access-request-decision.test.ts +128 -120
  5. package/src/__tests__/account-registry.test.ts +121 -110
  6. package/src/__tests__/active-skill-tools.test.ts +200 -172
  7. package/src/__tests__/actor-token-service.test.ts +341 -274
  8. package/src/__tests__/agent-loop-thinking.test.ts +28 -19
  9. package/src/__tests__/agent-loop.test.ts +798 -378
  10. package/src/__tests__/anthropic-provider.test.ts +405 -247
  11. package/src/__tests__/app-builder-tool-scripts.test.ts +97 -97
  12. package/src/__tests__/app-bundler.test.ts +112 -79
  13. package/src/__tests__/app-executors.test.ts +205 -178
  14. package/src/__tests__/app-git-history.test.ts +90 -73
  15. package/src/__tests__/app-git-service.test.ts +67 -53
  16. package/src/__tests__/app-open-proxy.test.ts +29 -25
  17. package/src/__tests__/approval-conversation-turn.test.ts +100 -81
  18. package/src/__tests__/approval-hardcoded-copy-guard.test.ts +45 -17
  19. package/src/__tests__/approval-message-composer.test.ts +119 -119
  20. package/src/__tests__/approval-primitive.test.ts +264 -233
  21. package/src/__tests__/approval-routes-http.test.ts +4 -3
  22. package/src/__tests__/asset-materialize-tool.test.ts +250 -178
  23. package/src/__tests__/asset-search-tool.test.ts +251 -191
  24. package/src/__tests__/assistant-attachment-directive.test.ts +187 -142
  25. package/src/__tests__/assistant-attachments.test.ts +254 -186
  26. package/src/__tests__/assistant-event-hub.test.ts +105 -63
  27. package/src/__tests__/assistant-event.test.ts +66 -58
  28. package/src/__tests__/assistant-events-sse-hardening.test.ts +113 -73
  29. package/src/__tests__/assistant-feature-flag-guard.test.ts +78 -52
  30. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +48 -45
  31. package/src/__tests__/assistant-feature-flags-integration.test.ts +118 -77
  32. package/src/__tests__/assistant-id-boundary-guard.test.ts +158 -104
  33. package/src/__tests__/attachments-store.test.ts +240 -183
  34. package/src/__tests__/attachments.test.ts +70 -62
  35. package/src/__tests__/audit-log-rotation.test.ts +50 -35
  36. package/src/__tests__/browser-fill-credential.test.ts +169 -101
  37. package/src/__tests__/browser-manager.test.ts +97 -75
  38. package/src/__tests__/browser-runtime-check.test.ts +16 -15
  39. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +12 -10
  40. package/src/__tests__/browser-skill-endstate.test.ts +97 -72
  41. package/src/__tests__/bundle-scanner.test.ts +47 -22
  42. package/src/__tests__/bundled-asset.test.ts +74 -47
  43. package/src/__tests__/call-constants.test.ts +19 -19
  44. package/src/__tests__/call-controller.test.ts +0 -1
  45. package/src/__tests__/call-conversation-messages.test.ts +90 -65
  46. package/src/__tests__/call-domain.test.ts +149 -121
  47. package/src/__tests__/call-pointer-message-composer.test.ts +113 -83
  48. package/src/__tests__/call-pointer-messages.test.ts +213 -154
  49. package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +9 -10
  50. package/src/__tests__/call-recovery.test.ts +232 -212
  51. package/src/__tests__/call-routes-http.test.ts +0 -1
  52. package/src/__tests__/call-start-guardian-guard.test.ts +32 -30
  53. package/src/__tests__/call-state-machine.test.ts +62 -51
  54. package/src/__tests__/call-state.test.ts +89 -75
  55. package/src/__tests__/call-store.test.ts +387 -316
  56. package/src/__tests__/callback-handoff-copy.test.ts +84 -82
  57. package/src/__tests__/canonical-guardian-store.test.ts +331 -280
  58. package/src/__tests__/channel-approval-routes.test.ts +1643 -1115
  59. package/src/__tests__/channel-approval.test.ts +139 -137
  60. package/src/__tests__/channel-approvals.test.ts +7 -2
  61. package/src/__tests__/channel-delivery-store.test.ts +232 -194
  62. package/src/__tests__/channel-guardian.test.ts +5 -3
  63. package/src/__tests__/channel-invite-transport.test.ts +107 -92
  64. package/src/__tests__/channel-policy.test.ts +42 -38
  65. package/src/__tests__/channel-readiness-service.test.ts +119 -102
  66. package/src/__tests__/channel-reply-delivery.test.ts +147 -118
  67. package/src/__tests__/channel-retry-sweep.test.ts +153 -110
  68. package/src/__tests__/checker.test.ts +3309 -1850
  69. package/src/__tests__/clarification-resolver.test.ts +91 -79
  70. package/src/__tests__/classifier.test.ts +64 -54
  71. package/src/__tests__/claude-code-skill-regression.test.ts +42 -37
  72. package/src/__tests__/claude-code-tool-profiles.test.ts +31 -29
  73. package/src/__tests__/clawhub.test.ts +92 -82
  74. package/src/__tests__/cli.test.ts +30 -30
  75. package/src/__tests__/clipboard.test.ts +53 -46
  76. package/src/__tests__/commit-guarantee.test.ts +59 -52
  77. package/src/__tests__/commit-message-enrichment-service.test.ts +203 -75
  78. package/src/__tests__/compaction.benchmark.test.ts +33 -31
  79. package/src/__tests__/computer-use-session-compaction.test.ts +60 -50
  80. package/src/__tests__/computer-use-session-lifecycle.test.ts +145 -117
  81. package/src/__tests__/computer-use-session-working-dir.test.ts +62 -48
  82. package/src/__tests__/computer-use-skill-baseline.test.ts +22 -19
  83. package/src/__tests__/computer-use-skill-endstate.test.ts +45 -31
  84. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +121 -88
  85. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +65 -42
  86. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +33 -18
  87. package/src/__tests__/computer-use-tools.test.ts +121 -98
  88. package/src/__tests__/config-schema.test.ts +443 -347
  89. package/src/__tests__/config-watcher.test.ts +96 -81
  90. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +148 -133
  91. package/src/__tests__/conflict-intent-tokenization.test.ts +96 -78
  92. package/src/__tests__/conflict-policy.test.ts +151 -80
  93. package/src/__tests__/conflict-store.test.ts +203 -157
  94. package/src/__tests__/connection-policy.test.ts +89 -59
  95. package/src/__tests__/contacts-tools.test.ts +247 -178
  96. package/src/__tests__/context-memory-e2e.test.ts +306 -214
  97. package/src/__tests__/context-token-estimator.test.ts +114 -74
  98. package/src/__tests__/context-window-manager.test.ts +269 -167
  99. package/src/__tests__/contradiction-checker.test.ts +161 -135
  100. package/src/__tests__/conversation-attention-store.test.ts +350 -290
  101. package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
  102. package/src/__tests__/conversation-pairing.test.ts +220 -113
  103. package/src/__tests__/conversation-routes-guardian-reply.test.ts +8 -0
  104. package/src/__tests__/conversation-store.test.ts +390 -235
  105. package/src/__tests__/credential-broker-browser-fill.test.ts +325 -250
  106. package/src/__tests__/credential-broker-server-use.test.ts +283 -243
  107. package/src/__tests__/credential-broker.test.ts +128 -74
  108. package/src/__tests__/credential-host-pattern-match.test.ts +64 -44
  109. package/src/__tests__/credential-metadata-store.test.ts +360 -311
  110. package/src/__tests__/credential-policy-validate.test.ts +81 -65
  111. package/src/__tests__/credential-resolve.test.ts +212 -145
  112. package/src/__tests__/credential-security-e2e.test.ts +144 -103
  113. package/src/__tests__/credential-security-invariants.test.ts +253 -208
  114. package/src/__tests__/credential-selection.test.ts +254 -146
  115. package/src/__tests__/credential-vault-unit.test.ts +531 -341
  116. package/src/__tests__/credential-vault.test.ts +761 -484
  117. package/src/__tests__/daemon-assistant-events.test.ts +91 -66
  118. package/src/__tests__/daemon-lifecycle.test.ts +258 -190
  119. package/src/__tests__/daemon-server-session-init.test.ts +2 -1
  120. package/src/__tests__/date-context.test.ts +314 -249
  121. package/src/__tests__/db-migration-rollback.test.ts +259 -130
  122. package/src/__tests__/db-schedule-syntax-migration.test.ts +78 -41
  123. package/src/__tests__/delete-managed-skill-tool.test.ts +77 -53
  124. package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -1
  125. package/src/__tests__/dictation-mode-detection.test.ts +77 -55
  126. package/src/__tests__/dictation-profile-store.test.ts +70 -56
  127. package/src/__tests__/dictation-text-processing.test.ts +53 -35
  128. package/src/__tests__/diff.test.ts +102 -98
  129. package/src/__tests__/domain-normalize.test.ts +54 -54
  130. package/src/__tests__/domain-policy.test.ts +71 -55
  131. package/src/__tests__/dynamic-page-surface.test.ts +31 -33
  132. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +69 -69
  133. package/src/__tests__/edit-engine.test.ts +56 -56
  134. package/src/__tests__/elevenlabs-client.test.ts +117 -91
  135. package/src/__tests__/elevenlabs-config.test.ts +32 -31
  136. package/src/__tests__/email-classifier.test.ts +15 -12
  137. package/src/__tests__/email-cli.test.ts +121 -108
  138. package/src/__tests__/emit-signal-routing-intent.test.ts +76 -69
  139. package/src/__tests__/encrypted-store.test.ts +180 -154
  140. package/src/__tests__/entity-extractor.test.ts +108 -87
  141. package/src/__tests__/entity-search.test.ts +664 -258
  142. package/src/__tests__/ephemeral-permissions.test.ts +224 -188
  143. package/src/__tests__/event-bus.test.ts +81 -77
  144. package/src/__tests__/extract-email.test.ts +29 -20
  145. package/src/__tests__/file-edit-tool.test.ts +62 -44
  146. package/src/__tests__/file-ops-service.test.ts +131 -114
  147. package/src/__tests__/file-read-tool.test.ts +48 -31
  148. package/src/__tests__/file-write-tool.test.ts +43 -37
  149. package/src/__tests__/filesystem-tools.test.ts +238 -209
  150. package/src/__tests__/followup-tools.test.ts +237 -162
  151. package/src/__tests__/forbidden-legacy-symbols.test.ts +19 -20
  152. package/src/__tests__/frontmatter.test.ts +96 -81
  153. package/src/__tests__/fuzzy-match-property.test.ts +75 -81
  154. package/src/__tests__/fuzzy-match.test.ts +71 -65
  155. package/src/__tests__/gateway-client-managed-outbound.test.ts +76 -57
  156. package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
  157. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  158. package/src/__tests__/gemini-image-service.test.ts +113 -100
  159. package/src/__tests__/gemini-provider.test.ts +297 -220
  160. package/src/__tests__/get-weather.test.ts +188 -114
  161. package/src/__tests__/gmail-integration.test.ts +13 -5
  162. package/src/__tests__/guardian-action-conversation-turn.test.ts +226 -171
  163. package/src/__tests__/guardian-action-copy-generator.test.ts +111 -93
  164. package/src/__tests__/guardian-action-followup-executor.test.ts +0 -1
  165. package/src/__tests__/guardian-action-followup-store.test.ts +199 -167
  166. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +297 -250
  167. package/src/__tests__/guardian-action-late-reply.test.ts +462 -316
  168. package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +23 -18
  169. package/src/__tests__/guardian-action-store.test.ts +158 -109
  170. package/src/__tests__/guardian-action-sweep.test.ts +114 -100
  171. package/src/__tests__/guardian-actions-endpoint.test.ts +440 -256
  172. package/src/__tests__/guardian-control-plane-policy.test.ts +497 -331
  173. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +217 -215
  174. package/src/__tests__/guardian-dispatch.test.ts +316 -256
  175. package/src/__tests__/guardian-grant-minting.test.ts +247 -178
  176. package/src/__tests__/guardian-outbound-http.test.ts +5 -3
  177. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +99 -96
  178. package/src/__tests__/guardian-question-copy.test.ts +17 -17
  179. package/src/__tests__/guardian-question-mode.test.ts +134 -100
  180. package/src/__tests__/guardian-routing-invariants.test.ts +0 -1
  181. package/src/__tests__/guardian-routing-state.test.ts +0 -1
  182. package/src/__tests__/guardian-verification-intent-routing.test.ts +94 -88
  183. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
  184. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +0 -1
  185. package/src/__tests__/handle-user-message-secret-resume.test.ts +7 -2
  186. package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +92 -76
  187. package/src/__tests__/handlers-cu-observation-blob.test.ts +103 -70
  188. package/src/__tests__/handlers-ipc-blob-probe.test.ts +77 -51
  189. package/src/__tests__/handlers-slack-config.test.ts +63 -54
  190. package/src/__tests__/handlers-task-submit-slash.test.ts +18 -18
  191. package/src/__tests__/handlers-telegram-config.test.ts +662 -329
  192. package/src/__tests__/handlers-twitter-config.test.ts +525 -298
  193. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +5 -2
  194. package/src/__tests__/headless-browser-interactions.test.ts +444 -280
  195. package/src/__tests__/headless-browser-navigate.test.ts +116 -79
  196. package/src/__tests__/headless-browser-read-tools.test.ts +123 -86
  197. package/src/__tests__/headless-browser-snapshot.test.ts +71 -56
  198. package/src/__tests__/heartbeat-service.test.ts +76 -58
  199. package/src/__tests__/history-repair-observability.test.ts +14 -14
  200. package/src/__tests__/history-repair.test.ts +171 -167
  201. package/src/__tests__/home-base-bootstrap.test.ts +30 -27
  202. package/src/__tests__/hooks-blocking.test.ts +86 -37
  203. package/src/__tests__/hooks-cli.test.ts +104 -68
  204. package/src/__tests__/hooks-config.test.ts +81 -43
  205. package/src/__tests__/hooks-discovery.test.ts +106 -96
  206. package/src/__tests__/hooks-integration.test.ts +78 -72
  207. package/src/__tests__/hooks-manager.test.ts +99 -61
  208. package/src/__tests__/hooks-runner.test.ts +94 -71
  209. package/src/__tests__/hooks-settings.test.ts +69 -64
  210. package/src/__tests__/hooks-templates.test.ts +85 -54
  211. package/src/__tests__/hooks-ts-runner.test.ts +82 -45
  212. package/src/__tests__/hooks-watch.test.ts +32 -22
  213. package/src/__tests__/host-file-edit-tool.test.ts +190 -148
  214. package/src/__tests__/host-file-read-tool.test.ts +86 -63
  215. package/src/__tests__/host-file-write-tool.test.ts +98 -64
  216. package/src/__tests__/host-shell-tool.test.ts +342 -233
  217. package/src/__tests__/inbound-invite-redemption.test.ts +0 -1
  218. package/src/__tests__/ingress-member-store.test.ts +163 -159
  219. package/src/__tests__/ingress-reconcile.test.ts +13 -6
  220. package/src/__tests__/ingress-routes-http.test.ts +441 -356
  221. package/src/__tests__/ingress-url-consistency.test.ts +125 -64
  222. package/src/__tests__/integration-status.test.ts +93 -73
  223. package/src/__tests__/intent-routing.test.ts +148 -118
  224. package/src/__tests__/invite-redemption-service.test.ts +163 -121
  225. package/src/__tests__/ipc-blob-store.test.ts +104 -91
  226. package/src/__tests__/ipc-contract-inventory.test.ts +27 -15
  227. package/src/__tests__/ipc-contract.test.ts +24 -23
  228. package/src/__tests__/ipc-protocol.test.ts +52 -46
  229. package/src/__tests__/ipc-roundtrip.benchmark.test.ts +61 -50
  230. package/src/__tests__/ipc-snapshot.test.ts +1135 -1056
  231. package/src/__tests__/ipc-validate.test.ts +240 -179
  232. package/src/__tests__/key-migration.test.ts +123 -90
  233. package/src/__tests__/keychain.test.ts +150 -123
  234. package/src/__tests__/lifecycle-docs-guard.test.ts +65 -64
  235. package/src/__tests__/llm-usage-store.test.ts +112 -87
  236. package/src/__tests__/managed-skill-lifecycle.test.ts +147 -108
  237. package/src/__tests__/managed-store.test.ts +411 -360
  238. package/src/__tests__/mcp-cli.test.ts +190 -124
  239. package/src/__tests__/mcp-health-check.test.ts +26 -21
  240. package/src/__tests__/media-generate-image.test.ts +122 -99
  241. package/src/__tests__/media-reuse-story.e2e.test.ts +282 -214
  242. package/src/__tests__/media-visibility-policy.test.ts +86 -38
  243. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +146 -100
  244. package/src/__tests__/memory-lifecycle-e2e.test.ts +385 -297
  245. package/src/__tests__/memory-query-builder.test.ts +32 -33
  246. package/src/__tests__/memory-recall-quality.test.ts +761 -407
  247. package/src/__tests__/memory-regressions.experimental.test.ts +443 -380
  248. package/src/__tests__/memory-regressions.test.ts +3725 -2642
  249. package/src/__tests__/memory-retrieval-budget.test.ts +7 -8
  250. package/src/__tests__/memory-retrieval.benchmark.test.ts +144 -109
  251. package/src/__tests__/memory-upsert-concurrency.test.ts +292 -201
  252. package/src/__tests__/messaging-send-tool.test.ts +36 -29
  253. package/src/__tests__/migration-cli-flows.test.ts +69 -53
  254. package/src/__tests__/migration-ordering.test.ts +103 -86
  255. package/src/__tests__/mime-builder.test.ts +55 -32
  256. package/src/__tests__/mock-signup-server.test.ts +384 -246
  257. package/src/__tests__/model-intents.test.ts +61 -37
  258. package/src/__tests__/no-direct-anthropic-sdk-imports.test.ts +9 -12
  259. package/src/__tests__/no-is-trusted-guard.test.ts +24 -21
  260. package/src/__tests__/non-member-access-request.test.ts +3 -2
  261. package/src/__tests__/notification-broadcaster.test.ts +99 -81
  262. package/src/__tests__/notification-decision-fallback.test.ts +223 -178
  263. package/src/__tests__/notification-decision-strategy.test.ts +375 -337
  264. package/src/__tests__/notification-deep-link.test.ts +67 -61
  265. package/src/__tests__/notification-guardian-path.test.ts +248 -206
  266. package/src/__tests__/notification-routing-intent.test.ts +166 -93
  267. package/src/__tests__/notification-thread-candidate-validation.test.ts +78 -75
  268. package/src/__tests__/notification-thread-candidates.test.ts +64 -61
  269. package/src/__tests__/oauth-callback-registry.test.ts +40 -30
  270. package/src/__tests__/oauth-connect-handler.test.ts +109 -89
  271. package/src/__tests__/oauth-scope-policy.test.ts +63 -55
  272. package/src/__tests__/oauth2-gateway-transport.test.ts +252 -174
  273. package/src/__tests__/onboarding-starter-tasks.test.ts +93 -89
  274. package/src/__tests__/onboarding-template-contract.test.ts +93 -94
  275. package/src/__tests__/openai-provider.test.ts +366 -274
  276. package/src/__tests__/pairing-concurrent.test.ts +18 -12
  277. package/src/__tests__/pairing-routes.test.ts +45 -41
  278. package/src/__tests__/parallel-tool.benchmark.test.ts +108 -58
  279. package/src/__tests__/parser.test.ts +316 -226
  280. package/src/__tests__/path-classifier.test.ts +24 -25
  281. package/src/__tests__/path-policy.test.ts +187 -147
  282. package/src/__tests__/phone.test.ts +36 -36
  283. package/src/__tests__/platform-move-helper.test.ts +48 -40
  284. package/src/__tests__/platform-socket-path.test.ts +23 -24
  285. package/src/__tests__/platform-workspace-migration.test.ts +464 -414
  286. package/src/__tests__/platform.test.ts +61 -53
  287. package/src/__tests__/playbook-execution.test.ts +397 -265
  288. package/src/__tests__/playbook-tools.test.ts +267 -196
  289. package/src/__tests__/prebuilt-home-base-seed.test.ts +30 -27
  290. package/src/__tests__/pricing.test.ts +316 -136
  291. package/src/__tests__/profile-compiler.test.ts +206 -188
  292. package/src/__tests__/provider-commit-message-generator.test.ts +114 -106
  293. package/src/__tests__/provider-error-scenarios.test.ts +212 -158
  294. package/src/__tests__/provider-fail-open-selection.test.ts +51 -44
  295. package/src/__tests__/provider-registry-ollama.test.ts +13 -9
  296. package/src/__tests__/provider-streaming.benchmark.test.ts +232 -183
  297. package/src/__tests__/proxy-approval-callback.test.ts +180 -119
  298. package/src/__tests__/public-ingress-urls.test.ts +112 -94
  299. package/src/__tests__/qdrant-manager.test.ts +147 -98
  300. package/src/__tests__/ratelimit.test.ts +152 -82
  301. package/src/__tests__/recording-handler.test.ts +273 -151
  302. package/src/__tests__/recording-intent-fallback.test.ts +94 -75
  303. package/src/__tests__/recording-intent-handler.test.ts +9 -2
  304. package/src/__tests__/recording-intent.test.ts +578 -379
  305. package/src/__tests__/recording-state-machine.test.ts +530 -316
  306. package/src/__tests__/recurrence-engine-rruleset.test.ts +150 -92
  307. package/src/__tests__/recurrence-engine.test.ts +81 -41
  308. package/src/__tests__/recurrence-types.test.ts +63 -44
  309. package/src/__tests__/relay-server.test.ts +2131 -1602
  310. package/src/__tests__/reminder-store.test.ts +158 -80
  311. package/src/__tests__/reminder.test.ts +113 -109
  312. package/src/__tests__/remote-skill-policy.test.ts +96 -72
  313. package/src/__tests__/request-file-tool.test.ts +74 -67
  314. package/src/__tests__/response-tier.test.ts +131 -74
  315. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
  316. package/src/__tests__/runtime-events-sse-parity.test.ts +167 -145
  317. package/src/__tests__/runtime-events-sse.test.ts +0 -1
  318. package/src/__tests__/sandbox-diagnostics.test.ts +66 -56
  319. package/src/__tests__/sandbox-host-parity.test.ts +377 -301
  320. package/src/__tests__/scaffold-managed-skill-tool.test.ts +213 -161
  321. package/src/__tests__/schedule-store.test.ts +268 -205
  322. package/src/__tests__/schedule-tools.test.ts +702 -524
  323. package/src/__tests__/scheduler-recurrence.test.ts +240 -130
  324. package/src/__tests__/scoped-approval-grants.test.ts +258 -168
  325. package/src/__tests__/scoped-grant-security-matrix.test.ts +160 -146
  326. package/src/__tests__/script-proxy-certs.test.ts +38 -35
  327. package/src/__tests__/script-proxy-connect-tunnel.test.ts +71 -46
  328. package/src/__tests__/script-proxy-decision-trace.test.ts +161 -84
  329. package/src/__tests__/script-proxy-http-forwarder.test.ts +146 -129
  330. package/src/__tests__/script-proxy-injection-runtime.test.ts +139 -113
  331. package/src/__tests__/script-proxy-mitm-handler.test.ts +226 -142
  332. package/src/__tests__/script-proxy-policy-runtime.test.ts +126 -86
  333. package/src/__tests__/script-proxy-policy.test.ts +308 -153
  334. package/src/__tests__/script-proxy-rewrite-specificity.test.ts +74 -62
  335. package/src/__tests__/script-proxy-router.test.ts +111 -77
  336. package/src/__tests__/script-proxy-session-manager.test.ts +156 -113
  337. package/src/__tests__/script-proxy-session-runtime.test.ts +28 -24
  338. package/src/__tests__/secret-allowlist.test.ts +105 -90
  339. package/src/__tests__/secret-ingress-handler.test.ts +41 -30
  340. package/src/__tests__/secret-onetime-send.test.ts +67 -50
  341. package/src/__tests__/secret-prompt-log-hygiene.test.ts +35 -31
  342. package/src/__tests__/secret-response-routing.test.ts +50 -41
  343. package/src/__tests__/secret-scanner-executor.test.ts +152 -111
  344. package/src/__tests__/secret-scanner.test.ts +495 -413
  345. package/src/__tests__/secure-keys.test.ts +132 -121
  346. package/src/__tests__/send-endpoint-busy.test.ts +8 -3
  347. package/src/__tests__/send-notification-tool.test.ts +43 -42
  348. package/src/__tests__/sensitive-output-placeholders.test.ts +72 -64
  349. package/src/__tests__/sequence-store.test.ts +335 -167
  350. package/src/__tests__/server-history-render.test.ts +341 -202
  351. package/src/__tests__/session-abort-tool-results.test.ts +133 -70
  352. package/src/__tests__/session-confirmation-signals.test.ts +252 -160
  353. package/src/__tests__/session-conflict-gate.test.ts +775 -585
  354. package/src/__tests__/session-error.test.ts +222 -191
  355. package/src/__tests__/session-evictor.test.ts +79 -62
  356. package/src/__tests__/session-init.benchmark.test.ts +170 -108
  357. package/src/__tests__/session-load-history-repair.test.ts +273 -139
  358. package/src/__tests__/session-messaging-secret-redirect.test.ts +130 -90
  359. package/src/__tests__/session-pre-run-repair.test.ts +106 -59
  360. package/src/__tests__/session-profile-injection.test.ts +198 -130
  361. package/src/__tests__/session-provider-retry-repair.test.ts +223 -141
  362. package/src/__tests__/session-queue.test.ts +624 -321
  363. package/src/__tests__/session-runtime-assembly.test.ts +425 -329
  364. package/src/__tests__/session-runtime-workspace.test.ts +69 -61
  365. package/src/__tests__/session-skill-tools.test.ts +973 -678
  366. package/src/__tests__/session-slash-known.test.ts +185 -133
  367. package/src/__tests__/session-slash-queue.test.ts +147 -81
  368. package/src/__tests__/session-slash-unknown.test.ts +135 -90
  369. package/src/__tests__/session-surfaces-task-progress.test.ts +122 -87
  370. package/src/__tests__/session-tool-setup-app-refresh.test.ts +338 -177
  371. package/src/__tests__/session-tool-setup-memory-scope.test.ts +63 -40
  372. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +60 -37
  373. package/src/__tests__/session-tool-setup-tools-disabled.test.ts +28 -26
  374. package/src/__tests__/session-undo.test.ts +43 -30
  375. package/src/__tests__/session-workspace-cache-state.test.ts +108 -67
  376. package/src/__tests__/session-workspace-injection.test.ts +245 -117
  377. package/src/__tests__/session-workspace-tool-tracking.test.ts +260 -93
  378. package/src/__tests__/shared-filesystem-errors.test.ts +47 -47
  379. package/src/__tests__/shell-credential-ref.test.ts +126 -90
  380. package/src/__tests__/shell-identity.test.ts +134 -111
  381. package/src/__tests__/shell-parser-fuzz.test.ts +263 -179
  382. package/src/__tests__/shell-parser-property.test.ts +435 -288
  383. package/src/__tests__/shell-tool-proxy-mode.test.ts +142 -70
  384. package/src/__tests__/size-guard.test.ts +42 -44
  385. package/src/__tests__/skill-feature-flags-integration.test.ts +79 -52
  386. package/src/__tests__/skill-feature-flags.test.ts +75 -47
  387. package/src/__tests__/skill-include-graph.test.ts +143 -148
  388. package/src/__tests__/skill-load-feature-flag.test.ts +94 -59
  389. package/src/__tests__/skill-load-tool.test.ts +371 -199
  390. package/src/__tests__/skill-projection-feature-flag.test.ts +131 -88
  391. package/src/__tests__/skill-projection.benchmark.test.ts +93 -65
  392. package/src/__tests__/skill-script-runner-host.test.ts +460 -250
  393. package/src/__tests__/skill-script-runner-sandbox.test.ts +168 -108
  394. package/src/__tests__/skill-script-runner.test.ts +115 -74
  395. package/src/__tests__/skill-tool-factory.test.ts +140 -96
  396. package/src/__tests__/skill-tool-manifest.test.ts +306 -210
  397. package/src/__tests__/skill-version-hash.test.ts +70 -56
  398. package/src/__tests__/skills.test.ts +0 -1
  399. package/src/__tests__/slack-channel-config.test.ts +127 -84
  400. package/src/__tests__/slack-skill.test.ts +60 -47
  401. package/src/__tests__/slash-commands-catalog.test.ts +37 -31
  402. package/src/__tests__/slash-commands-parser.test.ts +71 -64
  403. package/src/__tests__/slash-commands-resolver.test.ts +143 -107
  404. package/src/__tests__/slash-commands-rewrite.test.ts +22 -22
  405. package/src/__tests__/sms-messaging-provider.test.ts +4 -0
  406. package/src/__tests__/speaker-identification.test.ts +28 -25
  407. package/src/__tests__/starter-bundle.test.ts +27 -23
  408. package/src/__tests__/starter-task-flow.test.ts +67 -52
  409. package/src/__tests__/subagent-manager-notify.test.ts +154 -108
  410. package/src/__tests__/subagent-tools.test.ts +311 -270
  411. package/src/__tests__/subagent-types.test.ts +40 -40
  412. package/src/__tests__/surface-mutex-cleanup.test.ts +42 -30
  413. package/src/__tests__/swarm-dag-pathological.test.ts +122 -111
  414. package/src/__tests__/swarm-orchestrator.test.ts +135 -101
  415. package/src/__tests__/swarm-plan-validator.test.ts +125 -73
  416. package/src/__tests__/swarm-recursion.test.ts +58 -46
  417. package/src/__tests__/swarm-router-planner.test.ts +99 -74
  418. package/src/__tests__/swarm-session-integration.test.ts +148 -91
  419. package/src/__tests__/swarm-tool.test.ts +65 -45
  420. package/src/__tests__/swarm-worker-backend.test.ts +59 -45
  421. package/src/__tests__/swarm-worker-runner.test.ts +133 -118
  422. package/src/__tests__/system-prompt.test.ts +311 -256
  423. package/src/__tests__/task-compiler.test.ts +176 -120
  424. package/src/__tests__/task-management-tools.test.ts +561 -456
  425. package/src/__tests__/task-memory-cleanup.test.ts +627 -362
  426. package/src/__tests__/task-runner.test.ts +117 -94
  427. package/src/__tests__/task-scheduler.test.ts +113 -84
  428. package/src/__tests__/task-tools.test.ts +349 -264
  429. package/src/__tests__/terminal-sandbox.test.ts +138 -108
  430. package/src/__tests__/terminal-tools.test.ts +350 -305
  431. package/src/__tests__/thread-seed-composer.test.ts +307 -180
  432. package/src/__tests__/tool-approval-handler.test.ts +238 -137
  433. package/src/__tests__/tool-audit-listener.test.ts +69 -69
  434. package/src/__tests__/tool-domain-event-publisher.test.ts +142 -132
  435. package/src/__tests__/tool-execution-abort-cleanup.test.ts +155 -146
  436. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +136 -105
  437. package/src/__tests__/tool-executor-lifecycle-events.test.ts +355 -239
  438. package/src/__tests__/tool-executor-redaction.test.ts +112 -109
  439. package/src/__tests__/tool-executor-shell-integration.test.ts +130 -79
  440. package/src/__tests__/tool-executor.test.ts +1274 -674
  441. package/src/__tests__/tool-grant-request-escalation.test.ts +401 -283
  442. package/src/__tests__/tool-metrics-listener.test.ts +97 -85
  443. package/src/__tests__/tool-notification-listener.test.ts +42 -25
  444. package/src/__tests__/tool-permission-simulate-handler.test.ts +137 -113
  445. package/src/__tests__/tool-policy.test.ts +44 -25
  446. package/src/__tests__/tool-profiling-listener.test.ts +99 -93
  447. package/src/__tests__/tool-result-truncation.test.ts +5 -4
  448. package/src/__tests__/tool-trace-listener.test.ts +131 -111
  449. package/src/__tests__/top-level-renderer.test.ts +62 -58
  450. package/src/__tests__/top-level-scanner.test.ts +68 -64
  451. package/src/__tests__/trace-emitter.test.ts +56 -56
  452. package/src/__tests__/trust-context-guards.test.ts +65 -65
  453. package/src/__tests__/trust-store.test.ts +1239 -806
  454. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  455. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
  456. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +3 -2
  457. package/src/__tests__/trusted-contact-multichannel.test.ts +3 -2
  458. package/src/__tests__/trusted-contact-verification.test.ts +251 -231
  459. package/src/__tests__/turn-commit.test.ts +259 -200
  460. package/src/__tests__/twilio-provider.test.ts +140 -126
  461. package/src/__tests__/twilio-rest.test.ts +22 -18
  462. package/src/__tests__/twilio-routes-elevenlabs.test.ts +0 -1
  463. package/src/__tests__/twilio-routes-twiml.test.ts +55 -55
  464. package/src/__tests__/twilio-routes.test.ts +0 -1
  465. package/src/__tests__/twitter-auth-handler.test.ts +184 -139
  466. package/src/__tests__/twitter-cli-error-shaping.test.ts +88 -73
  467. package/src/__tests__/twitter-cli-routing.test.ts +146 -99
  468. package/src/__tests__/twitter-oauth-client.test.ts +82 -65
  469. package/src/__tests__/update-bulletin-format.test.ts +69 -66
  470. package/src/__tests__/update-bulletin-state.test.ts +66 -60
  471. package/src/__tests__/update-bulletin.test.ts +150 -114
  472. package/src/__tests__/update-template-contract.test.ts +15 -10
  473. package/src/__tests__/url-safety.test.ts +288 -265
  474. package/src/__tests__/user-reference.test.ts +32 -32
  475. package/src/__tests__/view-image-tool.test.ts +118 -96
  476. package/src/__tests__/voice-invite-redemption.test.ts +111 -106
  477. package/src/__tests__/voice-quality.test.ts +117 -102
  478. package/src/__tests__/voice-scoped-grant-consumer.test.ts +204 -146
  479. package/src/__tests__/voice-session-bridge.test.ts +351 -216
  480. package/src/__tests__/weather-skill-regression.test.ts +170 -120
  481. package/src/__tests__/web-fetch.test.ts +664 -526
  482. package/src/__tests__/web-search.test.ts +379 -213
  483. package/src/__tests__/work-item-output.test.ts +90 -53
  484. package/src/__tests__/workspace-git-service.test.ts +437 -356
  485. package/src/__tests__/workspace-heartbeat-service.test.ts +125 -91
  486. package/src/__tests__/workspace-lifecycle.test.ts +98 -64
  487. package/src/__tests__/workspace-policy.test.ts +139 -71
  488. package/src/cli/mcp.ts +81 -28
  489. package/src/commands/__tests__/cc-command-registry.test.ts +142 -134
  490. package/src/config/__tests__/feature-flag-registry-guard.test.ts +48 -39
  491. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +25 -10
  492. package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +0 -1
  493. package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +6 -11
  494. package/src/config/bundled-skills/messaging/SKILL.md +4 -3
  495. package/src/config/bundled-skills/messaging/tools/gmail-outreach-scan.ts +15 -5
  496. package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +16 -5
  497. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -2
  498. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +34 -32
  499. package/src/config/bundled-skills/sms-setup/SKILL.md +8 -16
  500. package/src/config/bundled-skills/telegram-setup/SKILL.md +3 -3
  501. package/src/config/bundled-skills/trusted-contacts/SKILL.md +13 -25
  502. package/src/config/bundled-skills/twilio-setup/SKILL.md +13 -23
  503. package/src/config/bundled-tool-registry.ts +2 -0
  504. package/src/config/env.ts +3 -4
  505. package/src/config/system-prompt.ts +32 -0
  506. package/src/mcp/client.ts +2 -7
  507. package/src/memory/db-connection.ts +16 -10
  508. package/src/messaging/providers/gmail/adapter.ts +10 -3
  509. package/src/messaging/providers/gmail/client.ts +280 -72
  510. package/src/runtime/auth/__tests__/context.test.ts +75 -65
  511. package/src/runtime/auth/__tests__/credential-service.test.ts +137 -114
  512. package/src/runtime/auth/__tests__/guard-tests.test.ts +84 -90
  513. package/src/runtime/auth/__tests__/ipc-auth-context.test.ts +40 -40
  514. package/src/runtime/auth/__tests__/middleware.test.ts +80 -74
  515. package/src/runtime/auth/__tests__/policy.test.ts +9 -9
  516. package/src/runtime/auth/__tests__/route-policy.test.ts +76 -65
  517. package/src/runtime/auth/__tests__/scopes.test.ts +68 -60
  518. package/src/runtime/auth/__tests__/subject.test.ts +54 -54
  519. package/src/runtime/auth/__tests__/token-service.test.ts +115 -108
  520. package/src/runtime/auth/scopes.ts +3 -0
  521. package/src/runtime/auth/token-service.ts +4 -1
  522. package/src/runtime/auth/types.ts +2 -1
  523. package/src/runtime/http-server.ts +2 -1
  524. package/src/security/secure-keys.ts +120 -54
  525. package/src/tools/browser/__tests__/auth-cache.test.ts +69 -63
  526. package/src/tools/browser/__tests__/auth-detector.test.ts +218 -157
  527. package/src/tools/browser/__tests__/jit-auth.test.ts +83 -99
  528. package/src/tools/terminal/safe-env.ts +7 -0
@@ -1,26 +1,25 @@
1
- import { mkdtempSync, rmSync } from 'node:fs';
2
- import { tmpdir } from 'node:os';
3
- import { join } from 'node:path';
1
+ import { mkdtempSync, rmSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
4
5
 
5
- import { afterAll, beforeEach, describe, expect, mock, test } from 'bun:test';
6
+ const testDir = mkdtempSync(join(tmpdir(), "approval-primitive-test-"));
6
7
 
7
- const testDir = mkdtempSync(join(tmpdir(), 'approval-primitive-test-'));
8
-
9
- mock.module('../util/platform.js', () => ({
8
+ mock.module("../util/platform.js", () => ({
10
9
  getDataDir: () => testDir,
11
- isMacOS: () => process.platform === 'darwin',
12
- isLinux: () => process.platform === 'linux',
13
- isWindows: () => process.platform === 'win32',
14
- getSocketPath: () => join(testDir, 'test.sock'),
15
- getPidPath: () => join(testDir, 'test.pid'),
16
- getDbPath: () => join(testDir, 'test.db'),
17
- getLogPath: () => join(testDir, 'test.log'),
10
+ isMacOS: () => process.platform === "darwin",
11
+ isLinux: () => process.platform === "linux",
12
+ isWindows: () => process.platform === "win32",
13
+ getSocketPath: () => join(testDir, "test.sock"),
14
+ getPidPath: () => join(testDir, "test.pid"),
15
+ getDbPath: () => join(testDir, "test.db"),
16
+ getLogPath: () => join(testDir, "test.log"),
18
17
  ensureDataDir: () => {},
19
18
  migrateToDataLayout: () => {},
20
19
  migrateToWorkspaceLayout: () => {},
21
20
  }));
22
21
 
23
- mock.module('../util/logger.js', () => ({
22
+ mock.module("../util/logger.js", () => ({
24
23
  getLogger: () =>
25
24
  new Proxy({} as Record<string, unknown>, {
26
25
  get: () => () => {},
@@ -33,10 +32,10 @@ import {
33
32
  consumeGrantForInvocation,
34
33
  mintGrantFromDecision,
35
34
  type MintGrantParams,
36
- } from '../approvals/approval-primitive.js';
37
- import { getDb, initializeDb, resetDb } from '../memory/db.js';
38
- import { scopedApprovalGrants } from '../memory/schema.js';
39
- import { computeToolApprovalDigest } from '../security/tool-approval-digest.js';
35
+ } from "../approvals/approval-primitive.js";
36
+ import { getDb, initializeDb, resetDb } from "../memory/db.js";
37
+ import { scopedApprovalGrants } from "../memory/schema.js";
38
+ import { computeToolApprovalDigest } from "../security/tool-approval-digest.js";
40
39
 
41
40
  initializeDb();
42
41
 
@@ -61,10 +60,10 @@ afterAll(() => {
61
60
  function mintParams(overrides: Partial<MintGrantParams> = {}): MintGrantParams {
62
61
  const futureExpiry = new Date(Date.now() + 60_000).toISOString();
63
62
  return {
64
- assistantId: 'self',
65
- scopeMode: 'request_id',
66
- requestChannel: 'telegram',
67
- decisionChannel: 'telegram',
63
+ assistantId: "self",
64
+ scopeMode: "request_id",
65
+ requestChannel: "telegram",
66
+ decisionChannel: "telegram",
68
67
  expiresAt: futureExpiry,
69
68
  ...overrides,
70
69
  };
@@ -74,90 +73,90 @@ function mintParams(overrides: Partial<MintGrantParams> = {}): MintGrantParams {
74
73
  // MINT TESTS
75
74
  // ===========================================================================
76
75
 
77
- describe('approval-primitive / mintGrantFromDecision', () => {
76
+ describe("approval-primitive / mintGrantFromDecision", () => {
78
77
  beforeEach(() => clearTables());
79
78
 
80
- test('mints a request_id scoped grant successfully', () => {
79
+ test("mints a request_id scoped grant successfully", () => {
81
80
  const result = mintGrantFromDecision(
82
- mintParams({ scopeMode: 'request_id', requestId: 'req-1' }),
81
+ mintParams({ scopeMode: "request_id", requestId: "req-1" }),
83
82
  );
84
83
  expect(result.ok).toBe(true);
85
84
  if (!result.ok) return;
86
- expect(result.grant.status).toBe('active');
87
- expect(result.grant.requestId).toBe('req-1');
88
- expect(result.grant.scopeMode).toBe('request_id');
85
+ expect(result.grant.status).toBe("active");
86
+ expect(result.grant.requestId).toBe("req-1");
87
+ expect(result.grant.scopeMode).toBe("request_id");
89
88
  });
90
89
 
91
- test('mints a tool_signature scoped grant successfully', () => {
92
- const digest = computeToolApprovalDigest('shell', { command: 'ls' });
90
+ test("mints a tool_signature scoped grant successfully", () => {
91
+ const digest = computeToolApprovalDigest("shell", { command: "ls" });
93
92
  const result = mintGrantFromDecision(
94
93
  mintParams({
95
- scopeMode: 'tool_signature',
96
- toolName: 'shell',
94
+ scopeMode: "tool_signature",
95
+ toolName: "shell",
97
96
  inputDigest: digest,
98
97
  }),
99
98
  );
100
99
  expect(result.ok).toBe(true);
101
100
  if (!result.ok) return;
102
- expect(result.grant.toolName).toBe('shell');
101
+ expect(result.grant.toolName).toBe("shell");
103
102
  expect(result.grant.inputDigest).toBe(digest);
104
- expect(result.grant.scopeMode).toBe('tool_signature');
103
+ expect(result.grant.scopeMode).toBe("tool_signature");
105
104
  });
106
105
 
107
- test('rejects request_id scope when requestId is missing', () => {
106
+ test("rejects request_id scope when requestId is missing", () => {
108
107
  const result = mintGrantFromDecision(
109
- mintParams({ scopeMode: 'request_id', requestId: null }),
108
+ mintParams({ scopeMode: "request_id", requestId: null }),
110
109
  );
111
110
  expect(result.ok).toBe(false);
112
111
  if (result.ok) return;
113
- expect(result.reason).toBe('missing_request_id');
112
+ expect(result.reason).toBe("missing_request_id");
114
113
  });
115
114
 
116
- test('rejects tool_signature scope when toolName is missing', () => {
115
+ test("rejects tool_signature scope when toolName is missing", () => {
117
116
  const result = mintGrantFromDecision(
118
117
  mintParams({
119
- scopeMode: 'tool_signature',
118
+ scopeMode: "tool_signature",
120
119
  toolName: null,
121
- inputDigest: 'abc123',
120
+ inputDigest: "abc123",
122
121
  }),
123
122
  );
124
123
  expect(result.ok).toBe(false);
125
124
  if (result.ok) return;
126
- expect(result.reason).toBe('missing_tool_fields');
125
+ expect(result.reason).toBe("missing_tool_fields");
127
126
  });
128
127
 
129
- test('rejects tool_signature scope when inputDigest is missing', () => {
128
+ test("rejects tool_signature scope when inputDigest is missing", () => {
130
129
  const result = mintGrantFromDecision(
131
130
  mintParams({
132
- scopeMode: 'tool_signature',
133
- toolName: 'shell',
131
+ scopeMode: "tool_signature",
132
+ toolName: "shell",
134
133
  inputDigest: null,
135
134
  }),
136
135
  );
137
136
  expect(result.ok).toBe(false);
138
137
  if (result.ok) return;
139
- expect(result.reason).toBe('missing_tool_fields');
138
+ expect(result.reason).toBe("missing_tool_fields");
140
139
  });
141
140
 
142
- test('mints grant with full scope context fields', () => {
141
+ test("mints grant with full scope context fields", () => {
143
142
  const result = mintGrantFromDecision(
144
143
  mintParams({
145
- scopeMode: 'request_id',
146
- requestId: 'req-full',
147
- conversationId: 'conv-1',
148
- callSessionId: 'call-1',
149
- requesterExternalUserId: 'user-1',
150
- guardianExternalUserId: 'guardian-1',
151
- executionChannel: 'voice',
144
+ scopeMode: "request_id",
145
+ requestId: "req-full",
146
+ conversationId: "conv-1",
147
+ callSessionId: "call-1",
148
+ requesterExternalUserId: "user-1",
149
+ guardianExternalUserId: "guardian-1",
150
+ executionChannel: "voice",
152
151
  }),
153
152
  );
154
153
  expect(result.ok).toBe(true);
155
154
  if (!result.ok) return;
156
- expect(result.grant.conversationId).toBe('conv-1');
157
- expect(result.grant.callSessionId).toBe('call-1');
158
- expect(result.grant.requesterExternalUserId).toBe('user-1');
159
- expect(result.grant.guardianExternalUserId).toBe('guardian-1');
160
- expect(result.grant.executionChannel).toBe('voice');
155
+ expect(result.grant.conversationId).toBe("conv-1");
156
+ expect(result.grant.callSessionId).toBe("call-1");
157
+ expect(result.grant.requesterExternalUserId).toBe("user-1");
158
+ expect(result.grant.guardianExternalUserId).toBe("guardian-1");
159
+ expect(result.grant.executionChannel).toBe("voice");
161
160
  });
162
161
  });
163
162
 
@@ -165,286 +164,314 @@ describe('approval-primitive / mintGrantFromDecision', () => {
165
164
  // CONSUME TESTS
166
165
  // ===========================================================================
167
166
 
168
- describe('approval-primitive / consumeGrantForInvocation', () => {
167
+ describe("approval-primitive / consumeGrantForInvocation", () => {
169
168
  beforeEach(() => clearTables());
170
169
 
171
- test('consumes a request_id grant when requestId matches', async () => {
172
- mintGrantFromDecision(mintParams({ scopeMode: 'request_id', requestId: 'req-100' }));
170
+ test("consumes a request_id grant when requestId matches", async () => {
171
+ mintGrantFromDecision(
172
+ mintParams({ scopeMode: "request_id", requestId: "req-100" }),
173
+ );
173
174
 
174
175
  const result = await consumeGrantForInvocation({
175
- requestId: 'req-100',
176
- toolName: 'shell',
177
- inputDigest: computeToolApprovalDigest('shell', { command: 'ls' }),
178
- consumingRequestId: 'consumer-1',
179
- assistantId: 'self',
176
+ requestId: "req-100",
177
+ toolName: "shell",
178
+ inputDigest: computeToolApprovalDigest("shell", { command: "ls" }),
179
+ consumingRequestId: "consumer-1",
180
+ assistantId: "self",
180
181
  });
181
182
 
182
183
  expect(result.ok).toBe(true);
183
184
  if (!result.ok) return;
184
- expect(result.grant.status).toBe('consumed');
185
- expect(result.grant.consumedByRequestId).toBe('consumer-1');
185
+ expect(result.grant.status).toBe("consumed");
186
+ expect(result.grant.consumedByRequestId).toBe("consumer-1");
186
187
  });
187
188
 
188
- test('consumes a tool_signature grant when tool+input matches', async () => {
189
- const digest = computeToolApprovalDigest('shell', { command: 'ls' });
189
+ test("consumes a tool_signature grant when tool+input matches", async () => {
190
+ const digest = computeToolApprovalDigest("shell", { command: "ls" });
190
191
  mintGrantFromDecision(
191
192
  mintParams({
192
- scopeMode: 'tool_signature',
193
- toolName: 'shell',
193
+ scopeMode: "tool_signature",
194
+ toolName: "shell",
194
195
  inputDigest: digest,
195
196
  }),
196
197
  );
197
198
 
198
199
  const result = await consumeGrantForInvocation({
199
- toolName: 'shell',
200
+ toolName: "shell",
200
201
  inputDigest: digest,
201
- consumingRequestId: 'consumer-2',
202
- assistantId: 'self',
202
+ consumingRequestId: "consumer-2",
203
+ assistantId: "self",
203
204
  });
204
205
 
205
206
  expect(result.ok).toBe(true);
206
207
  if (!result.ok) return;
207
- expect(result.grant.status).toBe('consumed');
208
+ expect(result.grant.status).toBe("consumed");
208
209
  });
209
210
 
210
- test('falls back to tool_signature when request_id does not match', async () => {
211
- const digest = computeToolApprovalDigest('shell', { command: 'ls' });
211
+ test("falls back to tool_signature when request_id does not match", async () => {
212
+ const digest = computeToolApprovalDigest("shell", { command: "ls" });
212
213
  // Mint a tool_signature grant (not request_id)
213
214
  mintGrantFromDecision(
214
215
  mintParams({
215
- scopeMode: 'tool_signature',
216
- toolName: 'shell',
216
+ scopeMode: "tool_signature",
217
+ toolName: "shell",
217
218
  inputDigest: digest,
218
219
  }),
219
220
  );
220
221
 
221
222
  const result = await consumeGrantForInvocation({
222
- requestId: 'nonexistent-req',
223
- toolName: 'shell',
223
+ requestId: "nonexistent-req",
224
+ toolName: "shell",
224
225
  inputDigest: digest,
225
- consumingRequestId: 'consumer-3',
226
- assistantId: 'self',
226
+ consumingRequestId: "consumer-3",
227
+ assistantId: "self",
227
228
  });
228
229
 
229
230
  expect(result.ok).toBe(true);
230
231
  if (!result.ok) return;
231
- expect(result.grant.scopeMode).toBe('tool_signature');
232
+ expect(result.grant.scopeMode).toBe("tool_signature");
232
233
  });
233
234
 
234
235
  // ---------------------------------------------------------------------------
235
236
  // Consume miss scenarios
236
237
  // ---------------------------------------------------------------------------
237
238
 
238
- test('miss: no grants exist at all', async () => {
239
- const result = await consumeGrantForInvocation({
240
- toolName: 'shell',
241
- inputDigest: computeToolApprovalDigest('shell', { command: 'ls' }),
242
- consumingRequestId: 'consumer-miss',
243
- assistantId: 'self',
244
- }, { maxWaitMs: 0 });
239
+ test("miss: no grants exist at all", async () => {
240
+ const result = await consumeGrantForInvocation(
241
+ {
242
+ toolName: "shell",
243
+ inputDigest: computeToolApprovalDigest("shell", { command: "ls" }),
244
+ consumingRequestId: "consumer-miss",
245
+ assistantId: "self",
246
+ },
247
+ { maxWaitMs: 0 },
248
+ );
245
249
 
246
250
  expect(result.ok).toBe(false);
247
251
  if (result.ok) return;
248
- expect(result.reason).toBe('no_match');
252
+ expect(result.reason).toBe("no_match");
249
253
  });
250
254
 
251
- test('miss: tool name mismatch', async () => {
252
- const digest = computeToolApprovalDigest('shell', { command: 'ls' });
255
+ test("miss: tool name mismatch", async () => {
256
+ const digest = computeToolApprovalDigest("shell", { command: "ls" });
253
257
  mintGrantFromDecision(
254
258
  mintParams({
255
- scopeMode: 'tool_signature',
256
- toolName: 'shell',
259
+ scopeMode: "tool_signature",
260
+ toolName: "shell",
257
261
  inputDigest: digest,
258
262
  }),
259
263
  );
260
264
 
261
- const result = await consumeGrantForInvocation({
262
- toolName: 'file_write',
263
- inputDigest: digest,
264
- consumingRequestId: 'consumer-mismatch-tool',
265
- assistantId: 'self',
266
- }, { maxWaitMs: 0 });
265
+ const result = await consumeGrantForInvocation(
266
+ {
267
+ toolName: "file_write",
268
+ inputDigest: digest,
269
+ consumingRequestId: "consumer-mismatch-tool",
270
+ assistantId: "self",
271
+ },
272
+ { maxWaitMs: 0 },
273
+ );
267
274
 
268
275
  expect(result.ok).toBe(false);
269
276
  if (result.ok) return;
270
- expect(result.reason).toBe('no_match');
277
+ expect(result.reason).toBe("no_match");
271
278
  });
272
279
 
273
- test('miss: input digest mismatch', async () => {
280
+ test("miss: input digest mismatch", async () => {
274
281
  mintGrantFromDecision(
275
282
  mintParams({
276
- scopeMode: 'tool_signature',
277
- toolName: 'shell',
278
- inputDigest: computeToolApprovalDigest('shell', { command: 'ls' }),
283
+ scopeMode: "tool_signature",
284
+ toolName: "shell",
285
+ inputDigest: computeToolApprovalDigest("shell", { command: "ls" }),
279
286
  }),
280
287
  );
281
288
 
282
- const result = await consumeGrantForInvocation({
283
- toolName: 'shell',
284
- inputDigest: computeToolApprovalDigest('shell', { command: 'rm -rf /' }),
285
- consumingRequestId: 'consumer-mismatch-input',
286
- assistantId: 'self',
287
- }, { maxWaitMs: 0 });
289
+ const result = await consumeGrantForInvocation(
290
+ {
291
+ toolName: "shell",
292
+ inputDigest: computeToolApprovalDigest("shell", {
293
+ command: "rm -rf /",
294
+ }),
295
+ consumingRequestId: "consumer-mismatch-input",
296
+ assistantId: "self",
297
+ },
298
+ { maxWaitMs: 0 },
299
+ );
288
300
 
289
301
  expect(result.ok).toBe(false);
290
302
  if (result.ok) return;
291
- expect(result.reason).toBe('no_match');
303
+ expect(result.reason).toBe("no_match");
292
304
  });
293
305
 
294
- test('miss: assistant ID mismatch', async () => {
306
+ test("miss: assistant ID mismatch", async () => {
295
307
  mintGrantFromDecision(
296
308
  mintParams({
297
- scopeMode: 'request_id',
298
- requestId: 'req-assist',
299
- assistantId: 'assistant-A',
309
+ scopeMode: "request_id",
310
+ requestId: "req-assist",
311
+ assistantId: "assistant-A",
300
312
  }),
301
313
  );
302
314
 
303
- const result = await consumeGrantForInvocation({
304
- requestId: 'req-assist',
305
- toolName: 'shell',
306
- inputDigest: computeToolApprovalDigest('shell', {}),
307
- consumingRequestId: 'consumer-assist-mismatch',
308
- assistantId: 'assistant-B',
309
- }, { maxWaitMs: 0 });
315
+ const result = await consumeGrantForInvocation(
316
+ {
317
+ requestId: "req-assist",
318
+ toolName: "shell",
319
+ inputDigest: computeToolApprovalDigest("shell", {}),
320
+ consumingRequestId: "consumer-assist-mismatch",
321
+ assistantId: "assistant-B",
322
+ },
323
+ { maxWaitMs: 0 },
324
+ );
310
325
 
311
326
  expect(result.ok).toBe(false);
312
327
  if (result.ok) return;
313
- expect(result.reason).toBe('no_match');
328
+ expect(result.reason).toBe("no_match");
314
329
  });
315
330
 
316
- test('miss: grant expired', async () => {
331
+ test("miss: grant expired", async () => {
317
332
  const pastExpiry = new Date(Date.now() - 60_000).toISOString();
318
333
  mintGrantFromDecision(
319
334
  mintParams({
320
- scopeMode: 'request_id',
321
- requestId: 'req-expired',
335
+ scopeMode: "request_id",
336
+ requestId: "req-expired",
322
337
  expiresAt: pastExpiry,
323
338
  }),
324
339
  );
325
340
 
326
- const result = await consumeGrantForInvocation({
327
- requestId: 'req-expired',
328
- toolName: 'shell',
329
- inputDigest: computeToolApprovalDigest('shell', {}),
330
- consumingRequestId: 'consumer-expired',
331
- assistantId: 'self',
332
- }, { maxWaitMs: 0 });
341
+ const result = await consumeGrantForInvocation(
342
+ {
343
+ requestId: "req-expired",
344
+ toolName: "shell",
345
+ inputDigest: computeToolApprovalDigest("shell", {}),
346
+ consumingRequestId: "consumer-expired",
347
+ assistantId: "self",
348
+ },
349
+ { maxWaitMs: 0 },
350
+ );
333
351
 
334
352
  expect(result.ok).toBe(false);
335
353
  if (result.ok) return;
336
- expect(result.reason).toBe('no_match');
354
+ expect(result.reason).toBe("no_match");
337
355
  });
338
356
 
339
357
  // ---------------------------------------------------------------------------
340
358
  // One-time consume semantics
341
359
  // ---------------------------------------------------------------------------
342
360
 
343
- test('one-time consume: second consume of the same grant fails', async () => {
361
+ test("one-time consume: second consume of the same grant fails", async () => {
344
362
  mintGrantFromDecision(
345
- mintParams({ scopeMode: 'request_id', requestId: 'req-once' }),
363
+ mintParams({ scopeMode: "request_id", requestId: "req-once" }),
346
364
  );
347
365
 
348
366
  const first = await consumeGrantForInvocation({
349
- requestId: 'req-once',
350
- toolName: 'shell',
351
- inputDigest: computeToolApprovalDigest('shell', {}),
352
- consumingRequestId: 'consumer-first',
353
- assistantId: 'self',
367
+ requestId: "req-once",
368
+ toolName: "shell",
369
+ inputDigest: computeToolApprovalDigest("shell", {}),
370
+ consumingRequestId: "consumer-first",
371
+ assistantId: "self",
354
372
  });
355
373
  expect(first.ok).toBe(true);
356
374
 
357
- const second = await consumeGrantForInvocation({
358
- requestId: 'req-once',
359
- toolName: 'shell',
360
- inputDigest: computeToolApprovalDigest('shell', {}),
361
- consumingRequestId: 'consumer-second',
362
- assistantId: 'self',
363
- }, { maxWaitMs: 0 });
375
+ const second = await consumeGrantForInvocation(
376
+ {
377
+ requestId: "req-once",
378
+ toolName: "shell",
379
+ inputDigest: computeToolApprovalDigest("shell", {}),
380
+ consumingRequestId: "consumer-second",
381
+ assistantId: "self",
382
+ },
383
+ { maxWaitMs: 0 },
384
+ );
364
385
  expect(second.ok).toBe(false);
365
386
  if (second.ok) return;
366
- expect(second.reason).toBe('no_match');
387
+ expect(second.reason).toBe("no_match");
367
388
  });
368
389
 
369
- test('one-time consume: tool_signature grant is consumed only once', async () => {
370
- const digest = computeToolApprovalDigest('shell', { command: 'deploy' });
390
+ test("one-time consume: tool_signature grant is consumed only once", async () => {
391
+ const digest = computeToolApprovalDigest("shell", { command: "deploy" });
371
392
  mintGrantFromDecision(
372
393
  mintParams({
373
- scopeMode: 'tool_signature',
374
- toolName: 'shell',
394
+ scopeMode: "tool_signature",
395
+ toolName: "shell",
375
396
  inputDigest: digest,
376
397
  }),
377
398
  );
378
399
 
379
400
  const first = await consumeGrantForInvocation({
380
- toolName: 'shell',
401
+ toolName: "shell",
381
402
  inputDigest: digest,
382
- consumingRequestId: 'consumer-sig-first',
383
- assistantId: 'self',
403
+ consumingRequestId: "consumer-sig-first",
404
+ assistantId: "self",
384
405
  });
385
406
  expect(first.ok).toBe(true);
386
407
 
387
- const second = await consumeGrantForInvocation({
388
- toolName: 'shell',
389
- inputDigest: digest,
390
- consumingRequestId: 'consumer-sig-second',
391
- assistantId: 'self',
392
- }, { maxWaitMs: 0 });
408
+ const second = await consumeGrantForInvocation(
409
+ {
410
+ toolName: "shell",
411
+ inputDigest: digest,
412
+ consumingRequestId: "consumer-sig-second",
413
+ assistantId: "self",
414
+ },
415
+ { maxWaitMs: 0 },
416
+ );
393
417
  expect(second.ok).toBe(false);
394
418
  if (second.ok) return;
395
- expect(second.reason).toBe('no_match');
419
+ expect(second.reason).toBe("no_match");
396
420
  });
397
421
 
398
422
  // ---------------------------------------------------------------------------
399
423
  // Context-scoped consume
400
424
  // ---------------------------------------------------------------------------
401
425
 
402
- test('consumes tool_signature grant with matching conversation context', async () => {
403
- const digest = computeToolApprovalDigest('shell', { command: 'test' });
426
+ test("consumes tool_signature grant with matching conversation context", async () => {
427
+ const digest = computeToolApprovalDigest("shell", { command: "test" });
404
428
  mintGrantFromDecision(
405
429
  mintParams({
406
- scopeMode: 'tool_signature',
407
- toolName: 'shell',
430
+ scopeMode: "tool_signature",
431
+ toolName: "shell",
408
432
  inputDigest: digest,
409
- conversationId: 'conv-ctx',
410
- callSessionId: 'call-ctx',
433
+ conversationId: "conv-ctx",
434
+ callSessionId: "call-ctx",
411
435
  }),
412
436
  );
413
437
 
414
438
  const result = await consumeGrantForInvocation({
415
- toolName: 'shell',
439
+ toolName: "shell",
416
440
  inputDigest: digest,
417
- consumingRequestId: 'consumer-ctx',
418
- assistantId: 'self',
419
- conversationId: 'conv-ctx',
420
- callSessionId: 'call-ctx',
441
+ consumingRequestId: "consumer-ctx",
442
+ assistantId: "self",
443
+ conversationId: "conv-ctx",
444
+ callSessionId: "call-ctx",
421
445
  });
422
446
 
423
447
  expect(result.ok).toBe(true);
424
448
  });
425
449
 
426
- test('miss: conversation context mismatch on tool_signature grant', async () => {
427
- const digest = computeToolApprovalDigest('shell', { command: 'test' });
450
+ test("miss: conversation context mismatch on tool_signature grant", async () => {
451
+ const digest = computeToolApprovalDigest("shell", { command: "test" });
428
452
  mintGrantFromDecision(
429
453
  mintParams({
430
- scopeMode: 'tool_signature',
431
- toolName: 'shell',
454
+ scopeMode: "tool_signature",
455
+ toolName: "shell",
432
456
  inputDigest: digest,
433
- conversationId: 'conv-A',
457
+ conversationId: "conv-A",
434
458
  }),
435
459
  );
436
460
 
437
- const result = await consumeGrantForInvocation({
438
- toolName: 'shell',
439
- inputDigest: digest,
440
- consumingRequestId: 'consumer-ctx-mismatch',
441
- assistantId: 'self',
442
- conversationId: 'conv-B',
443
- }, { maxWaitMs: 0 });
461
+ const result = await consumeGrantForInvocation(
462
+ {
463
+ toolName: "shell",
464
+ inputDigest: digest,
465
+ consumingRequestId: "consumer-ctx-mismatch",
466
+ assistantId: "self",
467
+ conversationId: "conv-B",
468
+ },
469
+ { maxWaitMs: 0 },
470
+ );
444
471
 
445
472
  expect(result.ok).toBe(false);
446
473
  if (result.ok) return;
447
- expect(result.reason).toBe('no_match');
474
+ expect(result.reason).toBe("no_match");
448
475
  });
449
476
  });
450
477
 
@@ -452,44 +479,44 @@ describe('approval-primitive / consumeGrantForInvocation', () => {
452
479
  // RETRY POLLING TESTS
453
480
  // ===========================================================================
454
481
 
455
- describe('approval-primitive / consumeGrantForInvocation retry', () => {
482
+ describe("approval-primitive / consumeGrantForInvocation retry", () => {
456
483
  beforeEach(() => clearTables());
457
484
 
458
- test('succeeds immediately when grant already exists (no retry needed)', async () => {
459
- const digest = computeToolApprovalDigest('shell', { command: 'ls' });
485
+ test("succeeds immediately when grant already exists (no retry needed)", async () => {
486
+ const digest = computeToolApprovalDigest("shell", { command: "ls" });
460
487
  mintGrantFromDecision(
461
488
  mintParams({
462
- scopeMode: 'tool_signature',
463
- toolName: 'shell',
489
+ scopeMode: "tool_signature",
490
+ toolName: "shell",
464
491
  inputDigest: digest,
465
492
  }),
466
493
  );
467
494
 
468
495
  const start = Date.now();
469
496
  const result = await consumeGrantForInvocation({
470
- toolName: 'shell',
497
+ toolName: "shell",
471
498
  inputDigest: digest,
472
- consumingRequestId: 'consumer-async-immediate',
473
- assistantId: 'self',
499
+ consumingRequestId: "consumer-async-immediate",
500
+ assistantId: "self",
474
501
  });
475
502
  const elapsed = Date.now() - start;
476
503
 
477
504
  expect(result.ok).toBe(true);
478
505
  if (!result.ok) return;
479
- expect(result.grant.status).toBe('consumed');
506
+ expect(result.grant.status).toBe("consumed");
480
507
  // Should return nearly instantly — well under the retry interval
481
508
  expect(elapsed).toBeLessThan(200);
482
509
  });
483
510
 
484
- test('retries and succeeds when grant appears after a delay', async () => {
485
- const digest = computeToolApprovalDigest('shell', { command: 'delayed' });
511
+ test("retries and succeeds when grant appears after a delay", async () => {
512
+ const digest = computeToolApprovalDigest("shell", { command: "delayed" });
486
513
 
487
514
  // Mint the grant after 300ms — the async consumer should retry and find it
488
515
  setTimeout(() => {
489
516
  mintGrantFromDecision(
490
517
  mintParams({
491
- scopeMode: 'tool_signature',
492
- toolName: 'shell',
518
+ scopeMode: "tool_signature",
519
+ toolName: "shell",
493
520
  inputDigest: digest,
494
521
  }),
495
522
  );
@@ -498,10 +525,10 @@ describe('approval-primitive / consumeGrantForInvocation retry', () => {
498
525
  const start = Date.now();
499
526
  const result = await consumeGrantForInvocation(
500
527
  {
501
- toolName: 'shell',
528
+ toolName: "shell",
502
529
  inputDigest: digest,
503
- consumingRequestId: 'consumer-async-delayed',
504
- assistantId: 'self',
530
+ consumingRequestId: "consumer-async-delayed",
531
+ assistantId: "self",
505
532
  },
506
533
  { maxWaitMs: 5_000, intervalMs: 100 },
507
534
  );
@@ -509,22 +536,24 @@ describe('approval-primitive / consumeGrantForInvocation retry', () => {
509
536
 
510
537
  expect(result.ok).toBe(true);
511
538
  if (!result.ok) return;
512
- expect(result.grant.status).toBe('consumed');
539
+ expect(result.grant.status).toBe("consumed");
513
540
  // Should have taken at least ~300ms (the delay) but less than the max wait
514
541
  expect(elapsed).toBeGreaterThanOrEqual(250);
515
542
  expect(elapsed).toBeLessThan(5_000);
516
543
  });
517
544
 
518
- test('returns failure after timeout when no grant appears', async () => {
519
- const digest = computeToolApprovalDigest('shell', { command: 'never-minted' });
545
+ test("returns failure after timeout when no grant appears", async () => {
546
+ const digest = computeToolApprovalDigest("shell", {
547
+ command: "never-minted",
548
+ });
520
549
 
521
550
  const start = Date.now();
522
551
  const result = await consumeGrantForInvocation(
523
552
  {
524
- toolName: 'shell',
553
+ toolName: "shell",
525
554
  inputDigest: digest,
526
- consumingRequestId: 'consumer-async-timeout',
527
- assistantId: 'self',
555
+ consumingRequestId: "consumer-async-timeout",
556
+ assistantId: "self",
528
557
  },
529
558
  { maxWaitMs: 500, intervalMs: 100 },
530
559
  );
@@ -532,14 +561,14 @@ describe('approval-primitive / consumeGrantForInvocation retry', () => {
532
561
 
533
562
  expect(result.ok).toBe(false);
534
563
  if (result.ok) return;
535
- expect(result.reason).toBe('no_match');
564
+ expect(result.reason).toBe("no_match");
536
565
  // Should have waited approximately the max wait time
537
566
  expect(elapsed).toBeGreaterThanOrEqual(450);
538
567
  expect(elapsed).toBeLessThan(1_500);
539
568
  });
540
569
 
541
- test('returns aborted when signal fires during retry polling', async () => {
542
- const digest = computeToolApprovalDigest('shell', { command: 'aborted' });
570
+ test("returns aborted when signal fires during retry polling", async () => {
571
+ const digest = computeToolApprovalDigest("shell", { command: "aborted" });
543
572
  const controller = new AbortController();
544
573
 
545
574
  // Abort after 200ms — well before the 2s max wait
@@ -548,10 +577,10 @@ describe('approval-primitive / consumeGrantForInvocation retry', () => {
548
577
  const start = Date.now();
549
578
  const result = await consumeGrantForInvocation(
550
579
  {
551
- toolName: 'shell',
580
+ toolName: "shell",
552
581
  inputDigest: digest,
553
- consumingRequestId: 'consumer-aborted',
554
- assistantId: 'self',
582
+ consumingRequestId: "consumer-aborted",
583
+ assistantId: "self",
555
584
  },
556
585
  { maxWaitMs: 2_000, intervalMs: 50, signal: controller.signal },
557
586
  );
@@ -559,23 +588,25 @@ describe('approval-primitive / consumeGrantForInvocation retry', () => {
559
588
 
560
589
  expect(result.ok).toBe(false);
561
590
  if (result.ok) return;
562
- expect(result.reason).toBe('aborted');
591
+ expect(result.reason).toBe("aborted");
563
592
  // Should have exited shortly after the abort (200ms), not waited the full 2s
564
593
  expect(elapsed).toBeLessThan(1_000);
565
594
  });
566
595
 
567
- test('returns aborted immediately when signal is already aborted', async () => {
568
- const digest = computeToolApprovalDigest('shell', { command: 'pre-aborted' });
596
+ test("returns aborted immediately when signal is already aborted", async () => {
597
+ const digest = computeToolApprovalDigest("shell", {
598
+ command: "pre-aborted",
599
+ });
569
600
  const controller = new AbortController();
570
601
  controller.abort();
571
602
 
572
603
  const start = Date.now();
573
604
  const result = await consumeGrantForInvocation(
574
605
  {
575
- toolName: 'shell',
606
+ toolName: "shell",
576
607
  inputDigest: digest,
577
- consumingRequestId: 'consumer-pre-aborted',
578
- assistantId: 'self',
608
+ consumingRequestId: "consumer-pre-aborted",
609
+ assistantId: "self",
579
610
  },
580
611
  { maxWaitMs: 2_000, intervalMs: 50, signal: controller.signal },
581
612
  );
@@ -583,21 +614,21 @@ describe('approval-primitive / consumeGrantForInvocation retry', () => {
583
614
 
584
615
  expect(result.ok).toBe(false);
585
616
  if (result.ok) return;
586
- expect(result.reason).toBe('aborted');
617
+ expect(result.reason).toBe("aborted");
587
618
  // Should return nearly instantly since signal was already aborted
588
619
  expect(elapsed).toBeLessThan(200);
589
620
  });
590
621
 
591
- test('skips retry entirely when maxWaitMs is 0', async () => {
592
- const digest = computeToolApprovalDigest('shell', { command: 'no-retry' });
622
+ test("skips retry entirely when maxWaitMs is 0", async () => {
623
+ const digest = computeToolApprovalDigest("shell", { command: "no-retry" });
593
624
 
594
625
  const start = Date.now();
595
626
  const result = await consumeGrantForInvocation(
596
627
  {
597
- toolName: 'shell',
628
+ toolName: "shell",
598
629
  inputDigest: digest,
599
- consumingRequestId: 'consumer-no-retry',
600
- assistantId: 'self',
630
+ consumingRequestId: "consumer-no-retry",
631
+ assistantId: "self",
601
632
  },
602
633
  { maxWaitMs: 0 },
603
634
  );
@@ -605,7 +636,7 @@ describe('approval-primitive / consumeGrantForInvocation retry', () => {
605
636
 
606
637
  expect(result.ok).toBe(false);
607
638
  if (result.ok) return;
608
- expect(result.reason).toBe('no_match');
639
+ expect(result.reason).toBe("no_match");
609
640
  // Should return nearly instantly — no retry loop
610
641
  expect(elapsed).toBeLessThan(100);
611
642
  });