@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,7 +1,7 @@
1
- import { describe, expect,test } from 'bun:test';
1
+ import { describe, expect, test } from "bun:test";
2
2
 
3
- import type { AppDefinition } from '../memory/app-store.js';
4
- import type { AppStore, ProxyResolver } from '../tools/apps/executors.js';
3
+ import type { AppDefinition } from "../memory/app-store.js";
4
+ import type { AppStore, ProxyResolver } from "../tools/apps/executors.js";
5
5
  import {
6
6
  executeAppCreate,
7
7
  executeAppDelete,
@@ -12,8 +12,8 @@ import {
12
12
  executeAppList,
13
13
  executeAppQuery,
14
14
  executeAppUpdate,
15
- } from '../tools/apps/executors.js';
16
- import type { EditEngineResult } from '../tools/shared/filesystem/edit-engine.js';
15
+ } from "../tools/apps/executors.js";
16
+ import type { EditEngineResult } from "../tools/shared/filesystem/edit-engine.js";
17
17
 
18
18
  // ---------------------------------------------------------------------------
19
19
  // Mock factory
@@ -21,11 +21,11 @@ import type { EditEngineResult } from '../tools/shared/filesystem/edit-engine.js
21
21
 
22
22
  function makeApp(overrides: Partial<AppDefinition> = {}): AppDefinition {
23
23
  return {
24
- id: 'app-1',
25
- name: 'Test App',
26
- description: 'A test app',
27
- schemaJson: '{}',
28
- htmlDefinition: '<h1>Hi</h1>',
24
+ id: "app-1",
25
+ name: "Test App",
26
+ description: "A test app",
27
+ schemaJson: "{}",
28
+ htmlDefinition: "<h1>Hi</h1>",
29
29
  createdAt: 1000,
30
30
  updatedAt: 2000,
31
31
  ...overrides,
@@ -37,15 +37,23 @@ function makeMockStore(overrides: Partial<AppStore> = {}): AppStore {
37
37
  getApp: () => makeApp(),
38
38
  listApps: () => [makeApp()],
39
39
  queryAppRecords: () => [],
40
- listAppFiles: () => ['index.html'],
41
- readAppFile: () => '<h1>Hi</h1>',
40
+ listAppFiles: () => ["index.html"],
41
+ readAppFile: () => "<h1>Hi</h1>",
42
42
  createApp: (params) =>
43
43
  makeApp({ name: params.name, description: params.description }),
44
44
  updateApp: (id, updates) => makeApp({ id, ...updates }),
45
45
  deleteApp: () => {},
46
46
  writeAppFile: () => {},
47
47
  editAppFile: () =>
48
- ({ ok: true, updatedContent: 'new', matchCount: 1, matchMethod: 'exact', similarity: 1, actualOld: 'old', actualNew: 'new' }) as EditEngineResult,
48
+ ({
49
+ ok: true,
50
+ updatedContent: "new",
51
+ matchCount: 1,
52
+ matchMethod: "exact",
53
+ similarity: 1,
54
+ actualOld: "old",
55
+ actualNew: "new",
56
+ }) as EditEngineResult,
49
57
  ...overrides,
50
58
  };
51
59
  }
@@ -54,16 +62,16 @@ function makeMockStore(overrides: Partial<AppStore> = {}): AppStore {
54
62
  // app_create
55
63
  // ---------------------------------------------------------------------------
56
64
 
57
- describe('executeAppCreate', () => {
58
- test('creates an app and returns its definition', async () => {
65
+ describe("executeAppCreate", () => {
66
+ test("creates an app and returns its definition", async () => {
59
67
  const store = makeMockStore();
60
68
  const result = await executeAppCreate(
61
- { name: 'My App', html: '<p>Hello</p>' },
69
+ { name: "My App", html: "<p>Hello</p>" },
62
70
  store,
63
71
  );
64
72
  expect(result.isError).toBe(false);
65
73
  const parsed = JSON.parse(result.content);
66
- expect(parsed.name).toBe('My App');
74
+ expect(parsed.name).toBe("My App");
67
75
  });
68
76
 
69
77
  test('defaults schema_json to "{}" when not provided', async () => {
@@ -74,11 +82,11 @@ describe('executeAppCreate', () => {
74
82
  return makeApp({ name: params.name });
75
83
  },
76
84
  });
77
- await executeAppCreate({ name: 'App', html: '<p/>' }, store);
78
- expect(capturedSchema).toBe('{}');
85
+ await executeAppCreate({ name: "App", html: "<p/>" }, store);
86
+ expect(capturedSchema).toBe("{}");
79
87
  });
80
88
 
81
- test('passes schema_json through when provided', async () => {
89
+ test("passes schema_json through when provided", async () => {
82
90
  let capturedSchema: string | undefined;
83
91
  const store = makeMockStore({
84
92
  createApp: (params) => {
@@ -87,36 +95,36 @@ describe('executeAppCreate', () => {
87
95
  },
88
96
  });
89
97
  await executeAppCreate(
90
- { name: 'App', html: '<p/>', schema_json: '{"type":"object"}' },
98
+ { name: "App", html: "<p/>", schema_json: '{"type":"object"}' },
91
99
  store,
92
100
  );
93
101
  expect(capturedSchema).toBe('{"type":"object"}');
94
102
  });
95
103
 
96
- test('auto-opens the app when proxyToolResolver is provided', async () => {
104
+ test("auto-opens the app when proxyToolResolver is provided", async () => {
97
105
  const store = makeMockStore();
98
106
  const proxy: ProxyResolver = async () => ({
99
- content: 'opened',
107
+ content: "opened",
100
108
  isError: false,
101
109
  });
102
110
  const result = await executeAppCreate(
103
- { name: 'Auto', html: '<p/>' },
111
+ { name: "Auto", html: "<p/>" },
104
112
  store,
105
113
  proxy,
106
114
  );
107
115
  expect(result.isError).toBe(false);
108
116
  const parsed = JSON.parse(result.content);
109
117
  expect(parsed.auto_opened).toBe(true);
110
- expect(parsed.open_result).toBe('opened');
118
+ expect(parsed.open_result).toBe("opened");
111
119
  });
112
120
 
113
- test('returns auto_opened=false when proxy resolver throws', async () => {
121
+ test("returns auto_opened=false when proxy resolver throws", async () => {
114
122
  const store = makeMockStore();
115
123
  const proxy: ProxyResolver = async () => {
116
- throw new Error('no client');
124
+ throw new Error("no client");
117
125
  };
118
126
  const result = await executeAppCreate(
119
- { name: 'Fail Open', html: '<p/>' },
127
+ { name: "Fail Open", html: "<p/>" },
120
128
  store,
121
129
  proxy,
122
130
  );
@@ -124,19 +132,19 @@ describe('executeAppCreate', () => {
124
132
  const parsed = JSON.parse(result.content);
125
133
  expect(parsed.auto_opened).toBe(false);
126
134
  expect(parsed.auto_open_error).toBe(
127
- 'Failed to auto-open app. Use app_open to open it manually.',
135
+ "Failed to auto-open app. Use app_open to open it manually.",
128
136
  );
129
137
  });
130
138
 
131
- test('skips auto-open when auto_open is false', async () => {
139
+ test("skips auto-open when auto_open is false", async () => {
132
140
  let proxyCalled = false;
133
141
  const store = makeMockStore();
134
142
  const proxy: ProxyResolver = async () => {
135
143
  proxyCalled = true;
136
- return { content: 'opened', isError: false };
144
+ return { content: "opened", isError: false };
137
145
  };
138
146
  const result = await executeAppCreate(
139
- { name: 'No Open', html: '<p/>', auto_open: false },
147
+ { name: "No Open", html: "<p/>", auto_open: false },
140
148
  store,
141
149
  proxy,
142
150
  );
@@ -146,10 +154,10 @@ describe('executeAppCreate', () => {
146
154
  expect(parsed.auto_opened).toBeUndefined();
147
155
  });
148
156
 
149
- test('skips auto-open when no proxyToolResolver', async () => {
157
+ test("skips auto-open when no proxyToolResolver", async () => {
150
158
  const store = makeMockStore();
151
159
  const result = await executeAppCreate(
152
- { name: 'No Proxy', html: '<p/>' },
160
+ { name: "No Proxy", html: "<p/>" },
153
161
  store,
154
162
  );
155
163
  expect(result.isError).toBe(false);
@@ -157,7 +165,7 @@ describe('executeAppCreate', () => {
157
165
  expect(parsed.auto_opened).toBeUndefined();
158
166
  });
159
167
 
160
- test('passes pages through to store.createApp', async () => {
168
+ test("passes pages through to store.createApp", async () => {
161
169
  let capturedPages: Record<string, string> | undefined;
162
170
  const store = makeMockStore({
163
171
  createApp: (params) => {
@@ -166,37 +174,34 @@ describe('executeAppCreate', () => {
166
174
  },
167
175
  });
168
176
  await executeAppCreate(
169
- { name: 'Multi', html: '<p/>', pages: { 'settings.html': '<div/>' } },
177
+ { name: "Multi", html: "<p/>", pages: { "settings.html": "<div/>" } },
170
178
  store,
171
179
  );
172
- expect(capturedPages).toEqual({ 'settings.html': '<div/>' });
180
+ expect(capturedPages).toEqual({ "settings.html": "<div/>" });
173
181
  });
174
182
 
175
183
  test('maps type "site" to appType "site"', async () => {
176
- let capturedType: 'app' | 'site' | undefined;
184
+ let capturedType: "app" | "site" | undefined;
177
185
  const store = makeMockStore({
178
186
  createApp: (params) => {
179
187
  capturedType = params.appType;
180
188
  return makeApp({ name: params.name });
181
189
  },
182
190
  });
183
- await executeAppCreate(
184
- { name: 'Site', html: '<p/>', type: 'site' },
185
- store,
186
- );
187
- expect(capturedType).toBe('site');
191
+ await executeAppCreate({ name: "Site", html: "<p/>", type: "site" }, store);
192
+ expect(capturedType).toBe("site");
188
193
  });
189
194
 
190
195
  test('defaults appType to "app" when type is not "site"', async () => {
191
- let capturedType: 'app' | 'site' | undefined;
196
+ let capturedType: "app" | "site" | undefined;
192
197
  const store = makeMockStore({
193
198
  createApp: (params) => {
194
199
  capturedType = params.appType;
195
200
  return makeApp({ name: params.name });
196
201
  },
197
202
  });
198
- await executeAppCreate({ name: 'App', html: '<p/>' }, store);
199
- expect(capturedType).toBe('app');
203
+ await executeAppCreate({ name: "App", html: "<p/>" }, store);
204
+ expect(capturedType).toBe("app");
200
205
  });
201
206
  });
202
207
 
@@ -204,26 +209,36 @@ describe('executeAppCreate', () => {
204
209
  // app_list
205
210
  // ---------------------------------------------------------------------------
206
211
 
207
- describe('executeAppList', () => {
208
- test('returns mapped list of apps', () => {
212
+ describe("executeAppList", () => {
213
+ test("returns mapped list of apps", () => {
209
214
  const store = makeMockStore({
210
215
  listApps: () => [
211
- makeApp({ id: 'a1', name: 'First', description: 'desc1', updatedAt: 100 }),
212
- makeApp({ id: 'a2', name: 'Second', updatedAt: 200 }),
216
+ makeApp({
217
+ id: "a1",
218
+ name: "First",
219
+ description: "desc1",
220
+ updatedAt: 100,
221
+ }),
222
+ makeApp({ id: "a2", name: "Second", updatedAt: 200 }),
213
223
  ],
214
224
  });
215
225
  const result = executeAppList(store);
216
226
  expect(result.isError).toBe(false);
217
227
  const parsed = JSON.parse(result.content);
218
228
  expect(parsed).toHaveLength(2);
219
- expect(parsed[0]).toEqual({ id: 'a1', name: 'First', description: 'desc1', updatedAt: 100 });
220
- expect(parsed[1].id).toBe('a2');
229
+ expect(parsed[0]).toEqual({
230
+ id: "a1",
231
+ name: "First",
232
+ description: "desc1",
233
+ updatedAt: 100,
234
+ });
235
+ expect(parsed[1].id).toBe("a2");
221
236
  // Should not include htmlDefinition or schemaJson
222
237
  expect(parsed[0].htmlDefinition).toBeUndefined();
223
238
  expect(parsed[0].schemaJson).toBeUndefined();
224
239
  });
225
240
 
226
- test('returns empty array when no apps exist', () => {
241
+ test("returns empty array when no apps exist", () => {
227
242
  const store = makeMockStore({ listApps: () => [] });
228
243
  const result = executeAppList(store);
229
244
  expect(result.isError).toBe(false);
@@ -235,18 +250,18 @@ describe('executeAppList', () => {
235
250
  // app_query
236
251
  // ---------------------------------------------------------------------------
237
252
 
238
- describe('executeAppQuery', () => {
239
- test('returns records for a given app', () => {
240
- const records = [{ id: 'r1', appId: 'app-1', data: { x: 1 } }];
253
+ describe("executeAppQuery", () => {
254
+ test("returns records for a given app", () => {
255
+ const records = [{ id: "r1", appId: "app-1", data: { x: 1 } }];
241
256
  const store = makeMockStore({ queryAppRecords: () => records });
242
- const result = executeAppQuery({ app_id: 'app-1' }, store);
257
+ const result = executeAppQuery({ app_id: "app-1" }, store);
243
258
  expect(result.isError).toBe(false);
244
259
  expect(JSON.parse(result.content)).toEqual(records);
245
260
  });
246
261
 
247
- test('returns empty array when no records', () => {
262
+ test("returns empty array when no records", () => {
248
263
  const store = makeMockStore({ queryAppRecords: () => [] });
249
- const result = executeAppQuery({ app_id: 'app-1' }, store);
264
+ const result = executeAppQuery({ app_id: "app-1" }, store);
250
265
  expect(result.isError).toBe(false);
251
266
  expect(JSON.parse(result.content)).toEqual([]);
252
267
  });
@@ -256,8 +271,8 @@ describe('executeAppQuery', () => {
256
271
  // app_update
257
272
  // ---------------------------------------------------------------------------
258
273
 
259
- describe('executeAppUpdate', () => {
260
- test('passes update fields through to store', () => {
274
+ describe("executeAppUpdate", () => {
275
+ test("passes update fields through to store", () => {
261
276
  let capturedUpdates: Record<string, unknown> = {};
262
277
  const store = makeMockStore({
263
278
  updateApp: (_id, updates) => {
@@ -267,26 +282,26 @@ describe('executeAppUpdate', () => {
267
282
  });
268
283
  const result = executeAppUpdate(
269
284
  {
270
- app_id: 'app-1',
271
- name: 'New Name',
272
- description: 'New desc',
285
+ app_id: "app-1",
286
+ name: "New Name",
287
+ description: "New desc",
273
288
  schema_json: '{"a":1}',
274
- html: '<div/>',
275
- pages: { 'about.html': '<p/>' },
289
+ html: "<div/>",
290
+ pages: { "about.html": "<p/>" },
276
291
  },
277
292
  store,
278
293
  );
279
294
  expect(result.isError).toBe(false);
280
295
  expect(capturedUpdates).toEqual({
281
- name: 'New Name',
282
- description: 'New desc',
296
+ name: "New Name",
297
+ description: "New desc",
283
298
  schemaJson: '{"a":1}',
284
- htmlDefinition: '<div/>',
285
- pages: { 'about.html': '<p/>' },
299
+ htmlDefinition: "<div/>",
300
+ pages: { "about.html": "<p/>" },
286
301
  });
287
302
  });
288
303
 
289
- test('only includes provided fields in updates', () => {
304
+ test("only includes provided fields in updates", () => {
290
305
  let capturedUpdates: Record<string, unknown> = {};
291
306
  const store = makeMockStore({
292
307
  updateApp: (_id, updates) => {
@@ -294,23 +309,23 @@ describe('executeAppUpdate', () => {
294
309
  return makeApp({ id: _id, ...updates });
295
310
  },
296
311
  });
297
- executeAppUpdate({ app_id: 'app-1', name: 'Only Name' }, store);
298
- expect(capturedUpdates).toEqual({ name: 'Only Name' });
312
+ executeAppUpdate({ app_id: "app-1", name: "Only Name" }, store);
313
+ expect(capturedUpdates).toEqual({ name: "Only Name" });
299
314
  // html, description, schema_json, pages should NOT be in the updates
300
- expect('htmlDefinition' in capturedUpdates).toBe(false);
301
- expect('description' in capturedUpdates).toBe(false);
302
- expect('schemaJson' in capturedUpdates).toBe(false);
303
- expect('pages' in capturedUpdates).toBe(false);
315
+ expect("htmlDefinition" in capturedUpdates).toBe(false);
316
+ expect("description" in capturedUpdates).toBe(false);
317
+ expect("schemaJson" in capturedUpdates).toBe(false);
318
+ expect("pages" in capturedUpdates).toBe(false);
304
319
  });
305
320
 
306
- test('propagates store errors', () => {
321
+ test("propagates store errors", () => {
307
322
  const store = makeMockStore({
308
323
  updateApp: () => {
309
- throw new Error('App not found: bad-id');
324
+ throw new Error("App not found: bad-id");
310
325
  },
311
326
  });
312
- expect(() => executeAppUpdate({ app_id: 'bad-id' }, store)).toThrow(
313
- 'App not found: bad-id',
327
+ expect(() => executeAppUpdate({ app_id: "bad-id" }, store)).toThrow(
328
+ "App not found: bad-id",
314
329
  );
315
330
  });
316
331
  });
@@ -319,18 +334,21 @@ describe('executeAppUpdate', () => {
319
334
  // app_delete
320
335
  // ---------------------------------------------------------------------------
321
336
 
322
- describe('executeAppDelete', () => {
323
- test('deletes the app and returns confirmation', () => {
337
+ describe("executeAppDelete", () => {
338
+ test("deletes the app and returns confirmation", () => {
324
339
  let deletedId: string | undefined;
325
340
  const store = makeMockStore({
326
341
  deleteApp: (id) => {
327
342
  deletedId = id;
328
343
  },
329
344
  });
330
- const result = executeAppDelete({ app_id: 'app-1' }, store);
345
+ const result = executeAppDelete({ app_id: "app-1" }, store);
331
346
  expect(result.isError).toBe(false);
332
- expect(JSON.parse(result.content)).toEqual({ deleted: true, appId: 'app-1' });
333
- expect(deletedId).toBe('app-1');
347
+ expect(JSON.parse(result.content)).toEqual({
348
+ deleted: true,
349
+ appId: "app-1",
350
+ });
351
+ expect(deletedId).toBe("app-1");
334
352
  });
335
353
  });
336
354
 
@@ -338,23 +356,23 @@ describe('executeAppDelete', () => {
338
356
  // app_file_list
339
357
  // ---------------------------------------------------------------------------
340
358
 
341
- describe('executeAppFileList', () => {
342
- test('returns list of files', () => {
359
+ describe("executeAppFileList", () => {
360
+ test("returns list of files", () => {
343
361
  const store = makeMockStore({
344
- listAppFiles: () => ['index.html', 'styles.css', 'js/app.js'],
362
+ listAppFiles: () => ["index.html", "styles.css", "js/app.js"],
345
363
  });
346
- const result = executeAppFileList({ app_id: 'app-1' }, store);
364
+ const result = executeAppFileList({ app_id: "app-1" }, store);
347
365
  expect(result.isError).toBe(false);
348
366
  expect(JSON.parse(result.content)).toEqual([
349
- 'index.html',
350
- 'styles.css',
351
- 'js/app.js',
367
+ "index.html",
368
+ "styles.css",
369
+ "js/app.js",
352
370
  ]);
353
371
  });
354
372
 
355
- test('returns empty array when app has no files', () => {
373
+ test("returns empty array when app has no files", () => {
356
374
  const store = makeMockStore({ listAppFiles: () => [] });
357
- const result = executeAppFileList({ app_id: 'app-1' }, store);
375
+ const result = executeAppFileList({ app_id: "app-1" }, store);
358
376
  expect(result.isError).toBe(false);
359
377
  expect(JSON.parse(result.content)).toEqual([]);
360
378
  });
@@ -364,80 +382,76 @@ describe('executeAppFileList', () => {
364
382
  // app_file_read
365
383
  // ---------------------------------------------------------------------------
366
384
 
367
- describe('executeAppFileRead', () => {
368
- test('returns formatted content with line numbers', () => {
385
+ describe("executeAppFileRead", () => {
386
+ test("returns formatted content with line numbers", () => {
369
387
  const store = makeMockStore({
370
- readAppFile: () => 'line1\nline2\nline3',
388
+ readAppFile: () => "line1\nline2\nline3",
371
389
  });
372
390
  const result = executeAppFileRead(
373
- { app_id: 'app-1', path: 'index.html' },
391
+ { app_id: "app-1", path: "index.html" },
374
392
  store,
375
393
  );
376
394
  expect(result.isError).toBe(false);
377
- expect(result.content).toBe(
378
- ' 1\tline1\n 2\tline2\n 3\tline3',
379
- );
395
+ expect(result.content).toBe(" 1\tline1\n 2\tline2\n 3\tline3");
380
396
  });
381
397
 
382
- test('applies offset parameter (1-based)', () => {
398
+ test("applies offset parameter (1-based)", () => {
383
399
  const store = makeMockStore({
384
- readAppFile: () => 'a\nb\nc\nd\ne',
400
+ readAppFile: () => "a\nb\nc\nd\ne",
385
401
  });
386
402
  const result = executeAppFileRead(
387
- { app_id: 'app-1', path: 'f.txt', offset: 3 },
403
+ { app_id: "app-1", path: "f.txt", offset: 3 },
388
404
  store,
389
405
  );
390
406
  expect(result.isError).toBe(false);
391
407
  // Lines 3, 4, 5
392
- expect(result.content).toBe(
393
- ' 3\tc\n 4\td\n 5\te',
394
- );
408
+ expect(result.content).toBe(" 3\tc\n 4\td\n 5\te");
395
409
  });
396
410
 
397
- test('applies limit parameter', () => {
411
+ test("applies limit parameter", () => {
398
412
  const store = makeMockStore({
399
- readAppFile: () => 'a\nb\nc\nd\ne',
413
+ readAppFile: () => "a\nb\nc\nd\ne",
400
414
  });
401
415
  const result = executeAppFileRead(
402
- { app_id: 'app-1', path: 'f.txt', limit: 2 },
416
+ { app_id: "app-1", path: "f.txt", limit: 2 },
403
417
  store,
404
418
  );
405
419
  expect(result.isError).toBe(false);
406
- expect(result.content).toBe(' 1\ta\n 2\tb');
420
+ expect(result.content).toBe(" 1\ta\n 2\tb");
407
421
  });
408
422
 
409
- test('applies both offset and limit', () => {
423
+ test("applies both offset and limit", () => {
410
424
  const store = makeMockStore({
411
- readAppFile: () => 'a\nb\nc\nd\ne',
425
+ readAppFile: () => "a\nb\nc\nd\ne",
412
426
  });
413
427
  const result = executeAppFileRead(
414
- { app_id: 'app-1', path: 'f.txt', offset: 2, limit: 2 },
428
+ { app_id: "app-1", path: "f.txt", offset: 2, limit: 2 },
415
429
  store,
416
430
  );
417
431
  expect(result.isError).toBe(false);
418
- expect(result.content).toBe(' 2\tb\n 3\tc');
432
+ expect(result.content).toBe(" 2\tb\n 3\tc");
419
433
  });
420
434
 
421
- test('defaults offset to 1 when not provided', () => {
435
+ test("defaults offset to 1 when not provided", () => {
422
436
  const store = makeMockStore({
423
- readAppFile: () => 'only',
437
+ readAppFile: () => "only",
424
438
  });
425
439
  const result = executeAppFileRead(
426
- { app_id: 'app-1', path: 'f.txt' },
440
+ { app_id: "app-1", path: "f.txt" },
427
441
  store,
428
442
  );
429
- expect(result.content).toBe(' 1\tonly');
443
+ expect(result.content).toBe(" 1\tonly");
430
444
  });
431
445
 
432
- test('propagates store errors (e.g. file not found)', () => {
446
+ test("propagates store errors (e.g. file not found)", () => {
433
447
  const store = makeMockStore({
434
448
  readAppFile: () => {
435
- throw new Error('File not found: missing.txt');
449
+ throw new Error("File not found: missing.txt");
436
450
  },
437
451
  });
438
452
  expect(() =>
439
- executeAppFileRead({ app_id: 'app-1', path: 'missing.txt' }, store),
440
- ).toThrow('File not found: missing.txt');
453
+ executeAppFileRead({ app_id: "app-1", path: "missing.txt" }, store),
454
+ ).toThrow("File not found: missing.txt");
441
455
  });
442
456
  });
443
457
 
@@ -445,24 +459,24 @@ describe('executeAppFileRead', () => {
445
459
  // app_file_edit
446
460
  // ---------------------------------------------------------------------------
447
461
 
448
- describe('executeAppFileEdit', () => {
449
- test('returns edit result from store', () => {
462
+ describe("executeAppFileEdit", () => {
463
+ test("returns edit result from store", () => {
450
464
  const editResult: EditEngineResult = {
451
465
  ok: true,
452
- updatedContent: 'updated',
466
+ updatedContent: "updated",
453
467
  matchCount: 1,
454
- matchMethod: 'exact' as const,
468
+ matchMethod: "exact" as const,
455
469
  similarity: 1,
456
- actualOld: 'old',
457
- actualNew: 'new',
470
+ actualOld: "old",
471
+ actualNew: "new",
458
472
  };
459
473
  const store = makeMockStore({ editAppFile: () => editResult });
460
474
  const result = executeAppFileEdit(
461
475
  {
462
- app_id: 'app-1',
463
- path: 'index.html',
464
- old_string: 'old',
465
- new_string: 'new',
476
+ app_id: "app-1",
477
+ path: "index.html",
478
+ old_string: "old",
479
+ new_string: "new",
466
480
  },
467
481
  store,
468
482
  );
@@ -470,37 +484,45 @@ describe('executeAppFileEdit', () => {
470
484
  expect(JSON.parse(result.content)).toEqual(editResult);
471
485
  });
472
486
 
473
- test('returns error when old_string is empty', () => {
487
+ test("returns error when old_string is empty", () => {
474
488
  const store = makeMockStore();
475
489
  const result = executeAppFileEdit(
476
490
  {
477
- app_id: 'app-1',
478
- path: 'index.html',
479
- old_string: '',
480
- new_string: 'new',
491
+ app_id: "app-1",
492
+ path: "index.html",
493
+ old_string: "",
494
+ new_string: "new",
481
495
  },
482
496
  store,
483
497
  );
484
498
  expect(result.isError).toBe(true);
485
499
  expect(JSON.parse(result.content)).toEqual({
486
- error: 'old_string must not be empty',
500
+ error: "old_string must not be empty",
487
501
  });
488
502
  });
489
503
 
490
- test('passes replace_all through to store', () => {
504
+ test("passes replace_all through to store", () => {
491
505
  let capturedReplaceAll: boolean | undefined;
492
506
  const store = makeMockStore({
493
507
  editAppFile: (_appId, _path, _old, _new, replaceAll) => {
494
508
  capturedReplaceAll = replaceAll;
495
- return { ok: true, updatedContent: '', matchCount: 1, matchMethod: 'exact' as const, similarity: 1, actualOld: '', actualNew: '' };
509
+ return {
510
+ ok: true,
511
+ updatedContent: "",
512
+ matchCount: 1,
513
+ matchMethod: "exact" as const,
514
+ similarity: 1,
515
+ actualOld: "",
516
+ actualNew: "",
517
+ };
496
518
  },
497
519
  });
498
520
  executeAppFileEdit(
499
521
  {
500
- app_id: 'app-1',
501
- path: 'f.txt',
502
- old_string: 'x',
503
- new_string: 'y',
522
+ app_id: "app-1",
523
+ path: "f.txt",
524
+ old_string: "x",
525
+ new_string: "y",
504
526
  replace_all: true,
505
527
  },
506
528
  store,
@@ -508,39 +530,47 @@ describe('executeAppFileEdit', () => {
508
530
  expect(capturedReplaceAll).toBe(true);
509
531
  });
510
532
 
511
- test('defaults replace_all to false', () => {
533
+ test("defaults replace_all to false", () => {
512
534
  let capturedReplaceAll: boolean | undefined;
513
535
  const store = makeMockStore({
514
536
  editAppFile: (_appId, _path, _old, _new, replaceAll) => {
515
537
  capturedReplaceAll = replaceAll;
516
- return { ok: true, updatedContent: '', matchCount: 1, matchMethod: 'exact' as const, similarity: 1, actualOld: '', actualNew: '' };
538
+ return {
539
+ ok: true,
540
+ updatedContent: "",
541
+ matchCount: 1,
542
+ matchMethod: "exact" as const,
543
+ similarity: 1,
544
+ actualOld: "",
545
+ actualNew: "",
546
+ };
517
547
  },
518
548
  });
519
549
  executeAppFileEdit(
520
550
  {
521
- app_id: 'app-1',
522
- path: 'f.txt',
523
- old_string: 'x',
524
- new_string: 'y',
551
+ app_id: "app-1",
552
+ path: "f.txt",
553
+ old_string: "x",
554
+ new_string: "y",
525
555
  },
526
556
  store,
527
557
  );
528
558
  expect(capturedReplaceAll).toBe(false);
529
559
  });
530
560
 
531
- test('passes status through to result', () => {
561
+ test("passes status through to result", () => {
532
562
  const store = makeMockStore();
533
563
  const result = executeAppFileEdit(
534
564
  {
535
- app_id: 'app-1',
536
- path: 'f.txt',
537
- old_string: 'x',
538
- new_string: 'y',
539
- status: 'updating styles',
565
+ app_id: "app-1",
566
+ path: "f.txt",
567
+ old_string: "x",
568
+ new_string: "y",
569
+ status: "updating styles",
540
570
  },
541
571
  store,
542
572
  );
543
- expect(result.status).toBe('updating styles');
573
+ expect(result.status).toBe("updating styles");
544
574
  });
545
575
  });
546
576
 
@@ -548,8 +578,8 @@ describe('executeAppFileEdit', () => {
548
578
  // app_file_write
549
579
  // ---------------------------------------------------------------------------
550
580
 
551
- describe('executeAppFileWrite', () => {
552
- test('writes file and returns confirmation', () => {
581
+ describe("executeAppFileWrite", () => {
582
+ test("writes file and returns confirmation", () => {
553
583
  let writtenPath: string | undefined;
554
584
  let writtenContent: string | undefined;
555
585
  const store = makeMockStore({
@@ -559,22 +589,22 @@ describe('executeAppFileWrite', () => {
559
589
  },
560
590
  });
561
591
  const result = executeAppFileWrite(
562
- { app_id: 'app-1', path: 'new.html', content: '<div/>' },
592
+ { app_id: "app-1", path: "new.html", content: "<div/>" },
563
593
  store,
564
594
  );
565
595
  expect(result.isError).toBe(false);
566
596
  expect(JSON.parse(result.content)).toEqual({
567
597
  written: true,
568
- path: 'new.html',
598
+ path: "new.html",
569
599
  });
570
- expect(writtenPath).toBe('new.html');
571
- expect(writtenContent).toBe('<div/>');
600
+ expect(writtenPath).toBe("new.html");
601
+ expect(writtenContent).toBe("<div/>");
572
602
  });
573
603
 
574
- test('returns error when app is not found', () => {
604
+ test("returns error when app is not found", () => {
575
605
  const store = makeMockStore({ getApp: () => null });
576
606
  const result = executeAppFileWrite(
577
- { app_id: 'missing', path: 'f.txt', content: 'hi' },
607
+ { app_id: "missing", path: "f.txt", content: "hi" },
578
608
  store,
579
609
  );
580
610
  expect(result.isError).toBe(true);
@@ -583,21 +613,21 @@ describe('executeAppFileWrite', () => {
583
613
  });
584
614
  });
585
615
 
586
- test('passes status through to result', () => {
616
+ test("passes status through to result", () => {
587
617
  const store = makeMockStore();
588
618
  const result = executeAppFileWrite(
589
619
  {
590
- app_id: 'app-1',
591
- path: 'f.txt',
592
- content: 'hi',
593
- status: 'adding dark mode styles',
620
+ app_id: "app-1",
621
+ path: "f.txt",
622
+ content: "hi",
623
+ status: "adding dark mode styles",
594
624
  },
595
625
  store,
596
626
  );
597
- expect(result.status).toBe('adding dark mode styles');
627
+ expect(result.status).toBe("adding dark mode styles");
598
628
  });
599
629
 
600
- test('does not call writeAppFile when app not found', () => {
630
+ test("does not call writeAppFile when app not found", () => {
601
631
  let writeCalled = false;
602
632
  const store = makeMockStore({
603
633
  getApp: () => null,
@@ -605,10 +635,7 @@ describe('executeAppFileWrite', () => {
605
635
  writeCalled = true;
606
636
  },
607
637
  });
608
- executeAppFileWrite(
609
- { app_id: 'bad', path: 'f.txt', content: 'x' },
610
- store,
611
- );
638
+ executeAppFileWrite({ app_id: "bad", path: "f.txt", content: "x" }, store);
612
639
  expect(writeCalled).toBe(false);
613
640
  });
614
641
  });