@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,20 +1,19 @@
1
- import { mkdirSync, mkdtempSync, rmSync,writeFileSync } from 'node:fs';
2
- import { tmpdir } from 'node:os';
3
- import { join } from 'node:path';
4
-
5
- import { afterEach,beforeEach, describe, expect, test } from 'bun:test';
1
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
6
5
 
7
6
  import {
8
7
  discoverCCCommands,
9
8
  getCCCommand,
10
9
  invalidateCCCommandCache,
11
10
  loadCCCommandTemplate,
12
- } from '../cc-command-registry.js';
11
+ } from "../cc-command-registry.js";
13
12
 
14
13
  let tmpDir: string;
15
14
 
16
15
  beforeEach(() => {
17
- tmpDir = mkdtempSync(join(tmpdir(), 'cc-cmd-test-'));
16
+ tmpDir = mkdtempSync(join(tmpdir(), "cc-cmd-test-"));
18
17
  invalidateCCCommandCache();
19
18
  });
20
19
 
@@ -25,118 +24,118 @@ afterEach(() => {
25
24
 
26
25
  /** Helper to create a .claude/commands/ directory with markdown files. */
27
26
  function createCommandsDir(base: string, files: Record<string, string>): void {
28
- const commandsDir = join(base, '.claude', 'commands');
27
+ const commandsDir = join(base, ".claude", "commands");
29
28
  mkdirSync(commandsDir, { recursive: true });
30
29
  for (const [name, content] of Object.entries(files)) {
31
- writeFileSync(join(commandsDir, name), content, 'utf-8');
30
+ writeFileSync(join(commandsDir, name), content, "utf-8");
32
31
  }
33
32
  }
34
33
 
35
- describe('discoverCCCommands', () => {
36
- test('discovers commands in .claude/commands/', () => {
34
+ describe("discoverCCCommands", () => {
35
+ test("discovers commands in .claude/commands/", () => {
37
36
  createCommandsDir(tmpDir, {
38
- 'hello.md': '# Hello World\nThis is the hello command.',
39
- 'deploy.md': 'Deploy the application to production.',
37
+ "hello.md": "# Hello World\nThis is the hello command.",
38
+ "deploy.md": "Deploy the application to production.",
40
39
  });
41
40
 
42
41
  const registry = discoverCCCommands(tmpDir);
43
42
  expect(registry.entries.size).toBe(2);
44
43
 
45
- const hello = registry.entries.get('hello');
44
+ const hello = registry.entries.get("hello");
46
45
  expect(hello).toBeDefined();
47
- expect(hello!.name).toBe('hello');
48
- expect(hello!.summary).toBe('Hello World');
46
+ expect(hello!.name).toBe("hello");
47
+ expect(hello!.summary).toBe("Hello World");
49
48
  expect(hello!.source).toBe(tmpDir);
50
49
 
51
- const deploy = registry.entries.get('deploy');
50
+ const deploy = registry.entries.get("deploy");
52
51
  expect(deploy).toBeDefined();
53
- expect(deploy!.name).toBe('deploy');
54
- expect(deploy!.summary).toBe('Deploy the application to production.');
52
+ expect(deploy!.name).toBe("deploy");
53
+ expect(deploy!.summary).toBe("Deploy the application to production.");
55
54
  });
56
55
 
57
- test('child directory commands override parent on name collisions', () => {
56
+ test("child directory commands override parent on name collisions", () => {
58
57
  // Create parent commands
59
58
  createCommandsDir(tmpDir, {
60
- 'shared.md': 'Parent version of shared command.',
59
+ "shared.md": "Parent version of shared command.",
61
60
  });
62
61
 
63
62
  // Create child directory with overriding command
64
- const childDir = join(tmpDir, 'project');
63
+ const childDir = join(tmpDir, "project");
65
64
  mkdirSync(childDir, { recursive: true });
66
65
  createCommandsDir(childDir, {
67
- 'shared.md': 'Child version of shared command.',
66
+ "shared.md": "Child version of shared command.",
68
67
  });
69
68
 
70
69
  const registry = discoverCCCommands(childDir);
71
- const shared = registry.entries.get('shared');
70
+ const shared = registry.entries.get("shared");
72
71
  expect(shared).toBeDefined();
73
- expect(shared!.summary).toBe('Child version of shared command.');
72
+ expect(shared!.summary).toBe("Child version of shared command.");
74
73
  expect(shared!.source).toBe(childDir);
75
74
  });
76
75
 
77
- test('invalid filenames are skipped', () => {
76
+ test("invalid filenames are skipped", () => {
78
77
  createCommandsDir(tmpDir, {
79
- 'valid-name.md': 'A valid command.',
80
- '.hidden.md': 'Hidden file should be skipped.',
81
- '-starts-with-dash.md': 'Invalid start character.',
78
+ "valid-name.md": "A valid command.",
79
+ ".hidden.md": "Hidden file should be skipped.",
80
+ "-starts-with-dash.md": "Invalid start character.",
82
81
  });
83
82
 
84
83
  const registry = discoverCCCommands(tmpDir);
85
84
  expect(registry.entries.size).toBe(1);
86
- expect(registry.entries.has('valid-name')).toBe(true);
87
- expect(registry.entries.has('.hidden')).toBe(false);
88
- expect(registry.entries.has('-starts-with-dash')).toBe(false);
85
+ expect(registry.entries.has("valid-name")).toBe(true);
86
+ expect(registry.entries.has(".hidden")).toBe(false);
87
+ expect(registry.entries.has("-starts-with-dash")).toBe(false);
89
88
  });
90
89
 
91
- test('non-.md files are ignored', () => {
90
+ test("non-.md files are ignored", () => {
92
91
  createCommandsDir(tmpDir, {
93
- 'readme.txt': 'Not a markdown file.',
94
- 'command.md': 'A real command.',
95
- 'notes.json': '{}',
92
+ "readme.txt": "Not a markdown file.",
93
+ "command.md": "A real command.",
94
+ "notes.json": "{}",
96
95
  });
97
96
 
98
97
  const registry = discoverCCCommands(tmpDir);
99
98
  expect(registry.entries.size).toBe(1);
100
- expect(registry.entries.has('command')).toBe(true);
99
+ expect(registry.entries.has("command")).toBe(true);
101
100
  });
102
101
 
103
- test('empty directory returns empty registry', () => {
104
- const commandsDir = join(tmpDir, '.claude', 'commands');
102
+ test("empty directory returns empty registry", () => {
103
+ const commandsDir = join(tmpDir, ".claude", "commands");
105
104
  mkdirSync(commandsDir, { recursive: true });
106
105
 
107
106
  const registry = discoverCCCommands(tmpDir);
108
107
  expect(registry.entries.size).toBe(0);
109
108
  });
110
109
 
111
- test('no .claude/commands/ directory returns empty registry', () => {
110
+ test("no .claude/commands/ directory returns empty registry", () => {
112
111
  const registry = discoverCCCommands(tmpDir);
113
112
  expect(registry.entries.size).toBe(0);
114
113
  });
115
114
 
116
- test('commands from multiple ancestor levels are merged', () => {
115
+ test("commands from multiple ancestor levels are merged", () => {
117
116
  // Parent has a unique command
118
117
  createCommandsDir(tmpDir, {
119
- 'parent-only.md': 'Only in parent.',
118
+ "parent-only.md": "Only in parent.",
120
119
  });
121
120
 
122
121
  // Child has a different command
123
- const childDir = join(tmpDir, 'child');
122
+ const childDir = join(tmpDir, "child");
124
123
  mkdirSync(childDir, { recursive: true });
125
124
  createCommandsDir(childDir, {
126
- 'child-only.md': 'Only in child.',
125
+ "child-only.md": "Only in child.",
127
126
  });
128
127
 
129
128
  const registry = discoverCCCommands(childDir);
130
129
  expect(registry.entries.size).toBe(2);
131
- expect(registry.entries.has('parent-only')).toBe(true);
132
- expect(registry.entries.has('child-only')).toBe(true);
130
+ expect(registry.entries.has("parent-only")).toBe(true);
131
+ expect(registry.entries.has("child-only")).toBe(true);
133
132
  });
134
133
  });
135
134
 
136
- describe('caching', () => {
137
- test('cache returns same instance within TTL', () => {
135
+ describe("caching", () => {
136
+ test("cache returns same instance within TTL", () => {
138
137
  createCommandsDir(tmpDir, {
139
- 'test.md': 'Test command.',
138
+ "test.md": "Test command.",
140
139
  });
141
140
 
142
141
  const first = discoverCCCommands(tmpDir);
@@ -144,9 +143,9 @@ describe('caching', () => {
144
143
  expect(first).toBe(second); // same object reference
145
144
  });
146
145
 
147
- test('invalidateCCCommandCache forces re-discovery', () => {
146
+ test("invalidateCCCommandCache forces re-discovery", () => {
148
147
  createCommandsDir(tmpDir, {
149
- 'test.md': 'Test command.',
148
+ "test.md": "Test command.",
150
149
  });
151
150
 
152
151
  const first = discoverCCCommands(tmpDir);
@@ -158,9 +157,9 @@ describe('caching', () => {
158
157
  expect(second.entries.size).toBe(1);
159
158
  });
160
159
 
161
- test('expired TTL forces re-discovery', () => {
160
+ test("expired TTL forces re-discovery", () => {
162
161
  createCommandsDir(tmpDir, {
163
- 'test.md': 'Test command.',
162
+ "test.md": "Test command.",
164
163
  });
165
164
 
166
165
  // Use a very short TTL
@@ -170,40 +169,41 @@ describe('caching', () => {
170
169
  });
171
170
  });
172
171
 
173
- describe('getCCCommand', () => {
174
- test('looks up command by name (case-insensitive)', () => {
172
+ describe("getCCCommand", () => {
173
+ test("looks up command by name (case-insensitive)", () => {
175
174
  createCommandsDir(tmpDir, {
176
- 'MyCommand.md': 'My command description.',
175
+ "MyCommand.md": "My command description.",
177
176
  });
178
177
 
179
- const entry = getCCCommand(tmpDir, 'mycommand');
178
+ const entry = getCCCommand(tmpDir, "mycommand");
180
179
  expect(entry).toBeDefined();
181
- expect(entry!.name).toBe('MyCommand');
180
+ expect(entry!.name).toBe("MyCommand");
182
181
 
183
- const entryUpper = getCCCommand(tmpDir, 'MYCOMMAND');
182
+ const entryUpper = getCCCommand(tmpDir, "MYCOMMAND");
184
183
  expect(entryUpper).toBeDefined();
185
- expect(entryUpper!.name).toBe('MyCommand');
184
+ expect(entryUpper!.name).toBe("MyCommand");
186
185
  });
187
186
 
188
- test('returns undefined for non-existent command', () => {
187
+ test("returns undefined for non-existent command", () => {
189
188
  createCommandsDir(tmpDir, {
190
- 'exists.md': 'I exist.',
189
+ "exists.md": "I exist.",
191
190
  });
192
191
 
193
- const entry = getCCCommand(tmpDir, 'nonexistent');
192
+ const entry = getCCCommand(tmpDir, "nonexistent");
194
193
  expect(entry).toBeUndefined();
195
194
  });
196
195
  });
197
196
 
198
- describe('loadCCCommandTemplate', () => {
199
- test('reads full file content at execution time', () => {
200
- const fullContent = '---\ntitle: Test\n---\n\n# Test Command\n\nThis is the full template body.\n\n## Arguments\n- arg1: required\n- arg2: optional\n';
197
+ describe("loadCCCommandTemplate", () => {
198
+ test("reads full file content at execution time", () => {
199
+ const fullContent =
200
+ "---\ntitle: Test\n---\n\n# Test Command\n\nThis is the full template body.\n\n## Arguments\n- arg1: required\n- arg2: optional\n";
201
201
  createCommandsDir(tmpDir, {
202
- 'test.md': fullContent,
202
+ "test.md": fullContent,
203
203
  });
204
204
 
205
205
  const registry = discoverCCCommands(tmpDir);
206
- const entry = registry.entries.get('test')!;
206
+ const entry = registry.entries.get("test")!;
207
207
  expect(entry).toBeDefined();
208
208
 
209
209
  const template = loadCCCommandTemplate(entry);
@@ -211,101 +211,106 @@ describe('loadCCCommandTemplate', () => {
211
211
  });
212
212
  });
213
213
 
214
- describe('summary extraction', () => {
215
- test('skips YAML frontmatter', () => {
214
+ describe("summary extraction", () => {
215
+ test("skips YAML frontmatter", () => {
216
216
  createCommandsDir(tmpDir, {
217
- 'with-frontmatter.md': '---\ntitle: My Command\nauthor: test\n---\n\nActual summary line.',
217
+ "with-frontmatter.md":
218
+ "---\ntitle: My Command\nauthor: test\n---\n\nActual summary line.",
218
219
  });
219
220
 
220
221
  const registry = discoverCCCommands(tmpDir);
221
- const entry = registry.entries.get('with-frontmatter');
222
+ const entry = registry.entries.get("with-frontmatter");
222
223
  expect(entry).toBeDefined();
223
- expect(entry!.summary).toBe('Actual summary line.');
224
+ expect(entry!.summary).toBe("Actual summary line.");
224
225
  });
225
226
 
226
- test('strips heading markers', () => {
227
+ test("strips heading markers", () => {
227
228
  createCommandsDir(tmpDir, {
228
- 'heading.md': '## This is a heading',
229
+ "heading.md": "## This is a heading",
229
230
  });
230
231
 
231
232
  const registry = discoverCCCommands(tmpDir);
232
- const entry = registry.entries.get('heading');
233
+ const entry = registry.entries.get("heading");
233
234
  expect(entry).toBeDefined();
234
- expect(entry!.summary).toBe('This is a heading');
235
+ expect(entry!.summary).toBe("This is a heading");
235
236
  });
236
237
 
237
- test('strips multiple heading levels', () => {
238
+ test("strips multiple heading levels", () => {
238
239
  createCommandsDir(tmpDir, {
239
- 'h1.md': '# H1 Heading',
240
- 'h3.md': '### H3 Heading',
240
+ "h1.md": "# H1 Heading",
241
+ "h3.md": "### H3 Heading",
241
242
  });
242
243
 
243
244
  const registry = discoverCCCommands(tmpDir);
244
- expect(registry.entries.get('h1')!.summary).toBe('H1 Heading');
245
- expect(registry.entries.get('h3')!.summary).toBe('H3 Heading');
245
+ expect(registry.entries.get("h1")!.summary).toBe("H1 Heading");
246
+ expect(registry.entries.get("h3")!.summary).toBe("H3 Heading");
246
247
  });
247
248
 
248
- test('skips empty lines before summary', () => {
249
+ test("skips empty lines before summary", () => {
249
250
  createCommandsDir(tmpDir, {
250
- 'empty-lines.md': '\n\n\nFirst real line.',
251
+ "empty-lines.md": "\n\n\nFirst real line.",
251
252
  });
252
253
 
253
254
  const registry = discoverCCCommands(tmpDir);
254
- expect(registry.entries.get('empty-lines')!.summary).toBe('First real line.');
255
+ expect(registry.entries.get("empty-lines")!.summary).toBe(
256
+ "First real line.",
257
+ );
255
258
  });
256
259
 
257
- test('truncates summary to 100 characters', () => {
258
- const longLine = 'A'.repeat(150);
260
+ test("truncates summary to 100 characters", () => {
261
+ const longLine = "A".repeat(150);
259
262
  createCommandsDir(tmpDir, {
260
- 'long.md': longLine,
263
+ "long.md": longLine,
261
264
  });
262
265
 
263
266
  const registry = discoverCCCommands(tmpDir);
264
- const entry = registry.entries.get('long');
267
+ const entry = registry.entries.get("long");
265
268
  expect(entry).toBeDefined();
266
269
  expect(entry!.summary.length).toBe(100);
267
- expect(entry!.summary).toBe('A'.repeat(100));
270
+ expect(entry!.summary).toBe("A".repeat(100));
268
271
  });
269
272
 
270
- test('handles file with only frontmatter and no content', () => {
273
+ test("handles file with only frontmatter and no content", () => {
271
274
  createCommandsDir(tmpDir, {
272
- 'empty-body.md': '---\ntitle: Empty\n---\n',
275
+ "empty-body.md": "---\ntitle: Empty\n---\n",
273
276
  });
274
277
 
275
278
  const registry = discoverCCCommands(tmpDir);
276
- const entry = registry.entries.get('empty-body');
279
+ const entry = registry.entries.get("empty-body");
277
280
  expect(entry).toBeDefined();
278
- expect(entry!.summary).toBe('');
281
+ expect(entry!.summary).toBe("");
279
282
  });
280
283
 
281
- test('returns empty summary when frontmatter is truncated by partial read', () => {
284
+ test("returns empty summary when frontmatter is truncated by partial read", () => {
282
285
  // Simulate frontmatter that exceeds SUMMARY_READ_BYTES (1024).
283
286
  // The closing --- delimiter will be cut off, causing FRONTMATTER_REGEX to
284
287
  // fail. extractSummary should return '' instead of '---'.
285
- const largeFrontmatter = '---\n' + 'key: ' + 'x'.repeat(1100) + '\n---\n\nActual summary.';
288
+ const largeFrontmatter =
289
+ "---\n" + "key: " + "x".repeat(1100) + "\n---\n\nActual summary.";
286
290
  createCommandsDir(tmpDir, {
287
- 'big-frontmatter.md': largeFrontmatter,
291
+ "big-frontmatter.md": largeFrontmatter,
288
292
  });
289
293
 
290
294
  const registry = discoverCCCommands(tmpDir);
291
- const entry = registry.entries.get('big-frontmatter');
295
+ const entry = registry.entries.get("big-frontmatter");
292
296
  expect(entry).toBeDefined();
293
- expect(entry!.summary).toBe('');
297
+ expect(entry!.summary).toBe("");
294
298
  });
295
299
 
296
- test('returns empty summary when frontmatter is truncated (CRLF)', () => {
297
- const largeFrontmatter = '---\r\n' + 'key: ' + 'x'.repeat(1100) + '\r\n---\r\n\r\nActual summary.';
300
+ test("returns empty summary when frontmatter is truncated (CRLF)", () => {
301
+ const largeFrontmatter =
302
+ "---\r\n" + "key: " + "x".repeat(1100) + "\r\n---\r\n\r\nActual summary.";
298
303
  createCommandsDir(tmpDir, {
299
- 'big-frontmatter-crlf.md': largeFrontmatter,
304
+ "big-frontmatter-crlf.md": largeFrontmatter,
300
305
  });
301
306
 
302
307
  const registry = discoverCCCommands(tmpDir);
303
- const entry = registry.entries.get('big-frontmatter-crlf');
308
+ const entry = registry.entries.get("big-frontmatter-crlf");
304
309
  expect(entry).toBeDefined();
305
- expect(entry!.summary).toBe('');
310
+ expect(entry!.summary).toBe("");
306
311
  });
307
312
 
308
- test('returns empty summary when frontmatter is truncated with multibyte UTF-8 characters', () => {
313
+ test("returns empty summary when frontmatter is truncated with multibyte UTF-8 characters", () => {
309
314
  // When frontmatter contains multibyte UTF-8 characters (e.g., CJK text),
310
315
  // the JavaScript string length (UTF-16 code units) is smaller than the
311
316
  // byte length. The truncation guard must compare byte length, not
@@ -314,72 +319,75 @@ describe('summary extraction', () => {
314
319
  // Each CJK character is 3 bytes in UTF-8 but 1 code unit in UTF-16.
315
320
  // We need the total byte count to reach 1024 while string length stays
316
321
  // well below 1024 to exercise the bug.
317
- const cjkChars = '\u4e00'.repeat(340); // 340 chars * 3 bytes = 1020 bytes
322
+ const cjkChars = "\u4e00".repeat(340); // 340 chars * 3 bytes = 1020 bytes
318
323
  // '---\n' is 4 bytes, so total = 4 + 1020 = 1024 bytes, but string
319
324
  // length = 4 + 340 = 344 chars — well under 1024.
320
- const truncatedContent = '---\n' + cjkChars;
325
+ const truncatedContent = "---\n" + cjkChars;
321
326
  createCommandsDir(tmpDir, {
322
- 'multibyte-frontmatter.md': truncatedContent,
327
+ "multibyte-frontmatter.md": truncatedContent,
323
328
  });
324
329
 
325
330
  const registry = discoverCCCommands(tmpDir);
326
- const entry = registry.entries.get('multibyte-frontmatter');
331
+ const entry = registry.entries.get("multibyte-frontmatter");
327
332
  expect(entry).toBeDefined();
328
333
  // Should return '' because the frontmatter opening delimiter is present
329
334
  // but the closing delimiter is missing and the byte length reached the
330
335
  // read limit — indicating truncation.
331
- expect(entry!.summary).toBe('');
336
+ expect(entry!.summary).toBe("");
332
337
  });
333
338
 
334
- test('returns summary for small file starting with thematic break ---', () => {
339
+ test("returns summary for small file starting with thematic break ---", () => {
335
340
  // A small markdown file that starts with "---" as a thematic break (not
336
341
  // frontmatter) should still have its first content line extracted as a
337
342
  // summary, rather than being treated as truncated frontmatter.
338
343
  createCommandsDir(tmpDir, {
339
- 'thematic-break.md': '---\nThis is a valid summary after a thematic break.',
344
+ "thematic-break.md":
345
+ "---\nThis is a valid summary after a thematic break.",
340
346
  });
341
347
 
342
348
  const registry = discoverCCCommands(tmpDir);
343
- const entry = registry.entries.get('thematic-break');
349
+ const entry = registry.entries.get("thematic-break");
344
350
  expect(entry).toBeDefined();
345
- expect(entry!.summary).toBe('This is a valid summary after a thematic break.');
351
+ expect(entry!.summary).toBe(
352
+ "This is a valid summary after a thematic break.",
353
+ );
346
354
  });
347
355
 
348
- test('handles frontmatter with Windows-style line endings', () => {
356
+ test("handles frontmatter with Windows-style line endings", () => {
349
357
  createCommandsDir(tmpDir, {
350
- 'crlf.md': '---\r\ntitle: Test\r\n---\r\n\r\nSummary with CRLF.',
358
+ "crlf.md": "---\r\ntitle: Test\r\n---\r\n\r\nSummary with CRLF.",
351
359
  });
352
360
 
353
361
  const registry = discoverCCCommands(tmpDir);
354
- const entry = registry.entries.get('crlf');
362
+ const entry = registry.entries.get("crlf");
355
363
  expect(entry).toBeDefined();
356
- expect(entry!.summary).toBe('Summary with CRLF.');
364
+ expect(entry!.summary).toBe("Summary with CRLF.");
357
365
  });
358
366
  });
359
367
 
360
- describe('command name validation', () => {
361
- test('accepts valid names with dots, dashes, underscores', () => {
368
+ describe("command name validation", () => {
369
+ test("accepts valid names with dots, dashes, underscores", () => {
362
370
  createCommandsDir(tmpDir, {
363
- 'my-command.md': 'Dashed name.',
364
- 'my_command.md': 'Underscored name.',
365
- 'my.command.md': 'Dotted name.',
366
- 'Command123.md': 'Alphanumeric.',
367
- 'a.md': 'Single char.',
371
+ "my-command.md": "Dashed name.",
372
+ "my_command.md": "Underscored name.",
373
+ "my.command.md": "Dotted name.",
374
+ "Command123.md": "Alphanumeric.",
375
+ "a.md": "Single char.",
368
376
  });
369
377
 
370
378
  const registry = discoverCCCommands(tmpDir);
371
- expect(registry.entries.has('my-command')).toBe(true);
372
- expect(registry.entries.has('my_command')).toBe(true);
373
- expect(registry.entries.has('my.command')).toBe(true);
374
- expect(registry.entries.has('command123')).toBe(true);
375
- expect(registry.entries.has('a')).toBe(true);
379
+ expect(registry.entries.has("my-command")).toBe(true);
380
+ expect(registry.entries.has("my_command")).toBe(true);
381
+ expect(registry.entries.has("my.command")).toBe(true);
382
+ expect(registry.entries.has("command123")).toBe(true);
383
+ expect(registry.entries.has("a")).toBe(true);
376
384
  });
377
385
 
378
- test('rejects names starting with special characters', () => {
386
+ test("rejects names starting with special characters", () => {
379
387
  createCommandsDir(tmpDir, {
380
- '_start.md': 'Starts with underscore.',
381
- '.start.md': 'Starts with dot.',
382
- '-start.md': 'Starts with dash.',
388
+ "_start.md": "Starts with underscore.",
389
+ ".start.md": "Starts with dot.",
390
+ "-start.md": "Starts with dash.",
383
391
  });
384
392
 
385
393
  const registry = discoverCCCommands(tmpDir);