@mycadet/assistant 0.12.6-dev.202610091338.ee7f3e3 → 0.12.7

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 (300) hide show
  1. package/README.md +3 -3
  2. package/docs/runbook-trusted-contacts.md +3 -3
  3. package/docs/skills.md +3 -3
  4. package/docs/trusted-contact-access.md +2 -2
  5. package/eslint.config.mjs +15 -0
  6. package/knip.json +2 -8
  7. package/openapi.yaml +11 -7
  8. package/package.json +2 -2
  9. package/scripts/run-tests.ts +4 -1
  10. package/src/__tests__/app-builder-tool-scripts.test.ts +34 -60
  11. package/src/__tests__/app-bundler.test.ts +9 -18
  12. package/src/__tests__/app-routes-csp.test.ts +28 -69
  13. package/src/__tests__/approval-cascade.test.ts +0 -22
  14. package/src/__tests__/approval-routes-http.test.ts +0 -21
  15. package/src/__tests__/assistant-attachment-directive.test.ts +1 -2
  16. package/src/__tests__/assistant-attachments.test.ts +2 -4
  17. package/src/__tests__/assistant-event-hub-connection-history.test.ts +7 -3
  18. package/src/__tests__/browser-fill-credential.test.ts +15 -18
  19. package/src/__tests__/byok-default-profile-ensure.test.ts +41 -24
  20. package/src/__tests__/compaction-events.test.ts +0 -10
  21. package/src/__tests__/compactor-tail-resolution.test.ts +2 -7
  22. package/src/__tests__/config-get-vision-flag.test.ts +0 -4
  23. package/src/__tests__/config-loader-backfill.test.ts +45 -48
  24. package/src/__tests__/config-schema.test.ts +15 -9
  25. package/src/__tests__/config-set-route.test.ts +13 -10
  26. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +0 -4
  27. package/src/__tests__/config-watcher.test.ts +0 -4
  28. package/src/__tests__/conversation-abort-tool-results.test.ts +0 -8
  29. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +0 -6
  30. package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -6
  31. package/src/__tests__/conversation-agent-loop.test.ts +0 -6
  32. package/src/__tests__/conversation-app-control-lifecycle.test.ts +0 -8
  33. package/src/__tests__/conversation-attachments.test.ts +0 -4
  34. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -10
  35. package/src/__tests__/conversation-fork-referential.test.ts +8 -3
  36. package/src/__tests__/conversation-lifecycle.test.ts +0 -8
  37. package/src/__tests__/conversation-load-history-repair.test.ts +0 -8
  38. package/src/__tests__/conversation-load-history-stripped.test.ts +0 -8
  39. package/src/__tests__/conversation-messaging-secret-redirect.test.ts +13 -16
  40. package/src/__tests__/conversation-process-callsite.test.ts +0 -8
  41. package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -8
  42. package/src/__tests__/conversation-queue.test.ts +0 -11
  43. package/src/__tests__/conversation-rendered-delegation-state.test.ts +0 -10
  44. package/src/__tests__/conversation-slash-queue.test.ts +0 -8
  45. package/src/__tests__/conversation-slash-unknown.test.ts +0 -8
  46. package/src/__tests__/conversation-slash.test.ts +2 -2
  47. package/src/__tests__/conversation-speed-override.test.ts +0 -10
  48. package/src/__tests__/conversation-store-ephemeral.test.ts +0 -8
  49. package/src/__tests__/conversation-summarize-up-to.test.ts +0 -10
  50. package/src/__tests__/conversation-title-service.test.ts +4 -1
  51. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +0 -7
  52. package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -8
  53. package/src/__tests__/conversation-wait-for-idle.test.ts +0 -10
  54. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -15
  55. package/src/__tests__/conversation-workspace-injection.test.ts +0 -12
  56. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -12
  57. package/src/__tests__/copy-composer-tc-templates.test.ts +1 -3
  58. package/src/__tests__/credential-prompt-route.test.ts +17 -20
  59. package/src/__tests__/credential-routes.test.ts +112 -82
  60. package/src/__tests__/daemon-credential-client.test.ts +1 -7
  61. package/src/__tests__/db-migration-rollback.test.ts +1 -3
  62. package/src/__tests__/default-profile-catalog-fallback.test.ts +32 -23
  63. package/src/__tests__/ensure-conversation-exists.test.ts +1 -4
  64. package/src/__tests__/file-read-tool.test.ts +1 -7
  65. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -4
  66. package/src/__tests__/headless-browser-navigate.test.ts +1 -3
  67. package/src/__tests__/helpers/secure-keys.ts +6 -1
  68. package/src/__tests__/helpers/seed-app.ts +64 -0
  69. package/src/__tests__/inference-profile-session-handler.test.ts +2 -2
  70. package/src/__tests__/llm-resolver-override-or-default.test.ts +14 -4
  71. package/src/__tests__/llm-resolver.test.ts +30 -10
  72. package/src/__tests__/llm-schema-fallback-profile.test.ts +46 -52
  73. package/src/__tests__/llm-schema.test.ts +8 -8
  74. package/src/__tests__/managed-profile-guard.test.ts +4 -4
  75. package/src/__tests__/manual-token-reconciliation.test.ts +22 -16
  76. package/src/__tests__/mcp-config-secret-boundary.test.ts +0 -7
  77. package/src/__tests__/media-generate-image.test.ts +29 -45
  78. package/src/__tests__/media-resolve-image-validation.test.ts +3 -1
  79. package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -7
  80. package/src/__tests__/migration-export-http.test.ts +1 -7
  81. package/src/__tests__/migration-export-streaming.test.ts +1 -7
  82. package/src/__tests__/migration-export-to-gcs.test.ts +7 -15
  83. package/src/__tests__/migration-import-commit-http.test.ts +0 -7
  84. package/src/__tests__/migration-import-from-gcs.test.ts +0 -11
  85. package/src/__tests__/migration-import-from-path.test.ts +0 -7
  86. package/src/__tests__/migration-import-from-url.test.ts +0 -11
  87. package/src/__tests__/migration-import-preflight-http.test.ts +1 -7
  88. package/src/__tests__/notification-decision-strategy.test.ts +1 -3
  89. package/src/__tests__/notification-routing-intent.test.ts +1 -5
  90. package/src/__tests__/oauth-provider-visibility.test.ts +5 -6
  91. package/src/__tests__/oauth-store.test.ts +44 -47
  92. package/src/__tests__/outbound-slack-persistence.test.ts +2 -6
  93. package/src/__tests__/platform-callback-registration.test.ts +74 -50
  94. package/src/__tests__/processing-flag-persist-failure.test.ts +0 -15
  95. package/src/__tests__/prompt-cache-cross-turn-stability.test.ts +0 -12
  96. package/src/__tests__/provider-commit-message-generator.test.ts +1 -1
  97. package/src/__tests__/provider-platform-proxy-integration.test.ts +45 -43
  98. package/src/__tests__/proxy-approval-callback.test.ts +0 -10
  99. package/src/__tests__/published-app-updater.test.ts +18 -41
  100. package/src/__tests__/resolve-app-id.test.ts +50 -36
  101. package/src/__tests__/run-conversation-turn-persistence.test.ts +3 -3
  102. package/src/__tests__/scheduler-result-notification.test.ts +9 -1
  103. package/src/__tests__/secure-keys.test.ts +1 -7
  104. package/src/__tests__/slack-share-routes.test.ts +2 -18
  105. package/src/__tests__/starter-task-flow.test.ts +23 -29
  106. package/src/__tests__/subagent-tool-gate-mode.test.ts +0 -8
  107. package/src/__tests__/tool-side-effects-documents.test.ts +0 -29
  108. package/src/__tests__/tool-side-effects-hook-failures.test.ts +0 -29
  109. package/src/__tests__/usage-attribution.test.ts +5 -5
  110. package/src/__tests__/workspace-greetings.test.ts +20 -27
  111. package/src/__tests__/workspace-migration-add-send-diagnostics.test.ts +23 -40
  112. package/src/__tests__/workspace-migration-avatar-rename.test.ts +48 -90
  113. package/src/__tests__/workspace-migration-drop-collect-usage-data.test.ts +31 -58
  114. package/src/__tests__/workspace-migration-drop-send-diagnostics.test.ts +36 -58
  115. package/src/__tests__/workspace-migration-extract-collect-usage-data.test.ts +49 -81
  116. package/src/acp/__tests__/acp-claude-oauth.test.ts +32 -65
  117. package/src/acp/session-snapshot.ts +1 -3
  118. package/src/approvals/guardian-decision-primitive.ts +2 -4
  119. package/src/apps/resolve-app.ts +0 -1
  120. package/src/apps/source-fingerprint.ts +1 -6
  121. package/src/bundler/app-bundler.ts +1 -2
  122. package/src/bundler/manifest.ts +0 -4
  123. package/src/calls/__tests__/call-controller.test.ts +25 -19
  124. package/src/cli/commands/__tests__/avatar.test.ts +2 -3
  125. package/src/cli/commands/__tests__/changelog.test.ts +1 -2
  126. package/src/cli/commands/__tests__/email-core.test.ts +10 -2
  127. package/src/cli/commands/__tests__/inference-providers.test.ts +21 -41
  128. package/src/cli/commands/__tests__/tts.test.ts +10 -16
  129. package/src/cli/commands/__tests__/ui-confirm.test.ts +2 -0
  130. package/src/cli/commands/apps.ts +4 -10
  131. package/src/cli/commands/bash.ts +2 -3
  132. package/src/cli/commands/clients.ts +3 -1
  133. package/src/cli/commands/cloud/__tests__/callback-routes-list.test.ts +1 -5
  134. package/src/cli/commands/cloud/__tests__/invoices.test.ts +1 -5
  135. package/src/cli/commands/cloud/index.help.ts +1 -2
  136. package/src/cli/commands/cloud/index.ts +1 -4
  137. package/src/cli/commands/config.help.ts +6 -6
  138. package/src/cli/commands/db/status.ts +4 -3
  139. package/src/cli/commands/inference-providers-default.ts +1 -1
  140. package/src/cli/commands/inference-providers.ts +0 -7
  141. package/src/cli/commands/inference.help.ts +2 -81
  142. package/src/cli/commands/notifications.ts +4 -1
  143. package/src/cli/lib/__tests__/plugin-artifact.test.ts +1 -4
  144. package/src/config/__tests__/assistant-initiated-threads-gate.test.ts +2 -3
  145. package/src/config/__tests__/default-profile-catalog.test.ts +47 -33
  146. package/src/config/__tests__/default-provider.test.ts +82 -67
  147. package/src/config/__tests__/jev-managed-profile.test.ts +2 -2
  148. package/src/config/__tests__/platform-rehydration.test.ts +2 -4
  149. package/src/config/__tests__/seed-default-provider.test.ts +87 -43
  150. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +1 -1
  151. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +5 -5
  152. package/src/config/call-site-defaults.ts +1 -1
  153. package/src/config/default-profile-catalog.ts +31 -35
  154. package/src/config/default-profile-names.ts +1 -1
  155. package/src/config/default-provider-resolution.ts +20 -25
  156. package/src/config/default-provider.ts +54 -19
  157. package/src/config/feature-flag-registry.json +5 -23
  158. package/src/config/inference-profile-validation.ts +2 -5
  159. package/src/config/input-modalities.test.ts +3 -3
  160. package/src/config/input-modalities.ts +6 -4
  161. package/src/config/llm-resolver.ts +10 -12
  162. package/src/config/memory-v3-gate.test.ts +3 -3
  163. package/src/config/profile-tool-support.ts +1 -1
  164. package/src/config/schemas/llm.ts +78 -56
  165. package/src/config/schemas/services.ts +3 -1
  166. package/src/config/schemas/tts.ts +0 -1
  167. package/src/config/seed-inference-profiles.ts +65 -121
  168. package/src/credential-execution/ces-runtime.ts +2 -8
  169. package/src/credential-execution/process-manager.test.ts +1 -7
  170. package/src/daemon/__tests__/install-assistant-command.test.ts +1 -7
  171. package/src/daemon/auto-profile-router.ts +1 -4
  172. package/src/daemon/conversation-agent-loop.ts +1 -4
  173. package/src/daemon/conversation-error.ts +1 -2
  174. package/src/daemon/conversation-runtime-assembly.ts +1 -1
  175. package/src/daemon/conversation-slash.ts +1 -4
  176. package/src/daemon/lifecycle.ts +2 -17
  177. package/src/daemon/main.ts +0 -1
  178. package/src/daemon/port-oversized-content.test.ts +3 -3
  179. package/src/daemon/trust-context-types.test.ts +2 -7
  180. package/src/daemon/wake-conversation-ops.ts +2 -4
  181. package/src/documents/document-comments-store.ts +0 -12
  182. package/src/documents/document-store.ts +0 -28
  183. package/src/followups/followup-store.ts +1 -2
  184. package/src/inbound/__tests__/tunnel-probe.test.ts +9 -4
  185. package/src/mcp/__tests__/plugin-mcp-oauth-cleanup.test.ts +24 -48
  186. package/src/mcp/__tests__/plugin-mcp-oauth-provider-isolation.test.ts +5 -17
  187. package/src/mcp/__tests__/plugin-server-credential-isolation.test.ts +35 -24
  188. package/src/mcp/__tests__/tool-caps.test.ts +12 -13
  189. package/src/mcp/__tests__/workspace-mcp-config.test.ts +6 -2
  190. package/src/mcp/workspace-mcp-config.ts +6 -2
  191. package/src/media/__tests__/image-models.test.ts +8 -2
  192. package/src/messaging/providers/slack/api.test.ts +11 -28
  193. package/src/monitoring/__tests__/mount-watch.test.ts +26 -8
  194. package/src/monitoring/mount-watch.ts +2 -1
  195. package/src/notifications/README.md +5 -5
  196. package/src/notifications/__tests__/channel-allowlist.test.ts +3 -1
  197. package/src/notifications/__tests__/copy-composer.test.ts +2 -6
  198. package/src/notifications/broadcaster.ts +1 -2
  199. package/src/notifications/channel-allowlist.ts +5 -3
  200. package/src/permissions/checker.test.ts +0 -6
  201. package/src/persistence/client-connection-events-store.ts +1 -4
  202. package/src/persistence/embeddings/embedding-backend.test.ts +19 -24
  203. package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +3 -1
  204. package/src/persistence/slow-query-log.ts +1 -3
  205. package/src/platform/managed-speech.ts +1 -2
  206. package/src/plugin-api/app-globals.d.ts +1 -4
  207. package/src/plugin-api/model-profiles.test.ts +1 -1
  208. package/src/plugin-api/model-profiles.ts +1 -4
  209. package/src/plugin-api/vision-support.test.ts +6 -8
  210. package/src/plugin-api/vision-support.ts +3 -4
  211. package/src/plugins/__tests__/active-plugin-env.test.ts +5 -8
  212. package/src/plugins/defaults/memory/graph/tool-handlers.test.ts +0 -5
  213. package/src/plugins/defaults/memory/src/memory-v2-routes.ts +1 -4
  214. package/src/plugins/defaults/task-progress/__tests__/task-progress-context.test.ts +15 -13
  215. package/src/plugins/defaults/task-progress/src/format-task-progress-context.ts +1 -2
  216. package/src/providers/__tests__/cadet-connection-routing.test.ts +7 -15
  217. package/src/providers/__tests__/retry-callsite.test.ts +1 -1
  218. package/src/providers/__tests__/xml-tool-call-salvage.test.ts +7 -5
  219. package/src/providers/cadet-model-routing.ts +1 -3
  220. package/src/providers/connection-resolution.ts +1 -1
  221. package/src/providers/inference/__tests__/adapter-factory-opencode.test.ts +2 -3
  222. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +12 -4
  223. package/src/providers/inference/__tests__/codex-token-refresh.test.ts +15 -18
  224. package/src/providers/inference/adapter-factory.ts +1 -1
  225. package/src/providers/inference/connection-availability.ts +1 -1
  226. package/src/providers/inline-audio-support.test.ts +4 -4
  227. package/src/providers/inline-audio-support.ts +1 -3
  228. package/src/providers/jev/client.ts +4 -2
  229. package/src/providers/model-intents.ts +1 -1
  230. package/src/providers/openai/__tests__/api-error-normalization.test.ts +1 -3
  231. package/src/providers/openai/__tests__/chat-completions-provider-xml-salvage.test.ts +30 -26
  232. package/src/providers/openai/__tests__/google-thought-signature.test.ts +3 -1
  233. package/src/providers/speech-to-text/__tests__/cadet-managed.test.ts +3 -3
  234. package/src/providers/speech-to-text/__tests__/resolve.test.ts +93 -100
  235. package/src/providers/speech-to-text/resolve.ts +3 -3
  236. package/src/runtime/__tests__/pages-route-policy.test.ts +13 -29
  237. package/src/runtime/anchored-guardian.ts +1 -4
  238. package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +1 -3
  239. package/src/runtime/channel-readiness-service.ts +3 -6
  240. package/src/runtime/http-server.ts +1 -3
  241. package/src/runtime/migrations/__tests__/staged-import-path.test.ts +8 -2
  242. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +1 -4
  243. package/src/runtime/migrations/migration-transport.ts +57 -88
  244. package/src/runtime/migrations/migration-wizard.ts +51 -46
  245. package/src/runtime/migrations/vbundle-metadata-merge.ts +24 -40
  246. package/src/runtime/migrations/vbundle-streaming-importer.ts +20 -17
  247. package/src/runtime/pending-interactions.ts +1 -4
  248. package/src/runtime/routes/__tests__/content-source-routes.test.ts +21 -38
  249. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +10 -10
  250. package/src/runtime/routes/__tests__/default-provider-routes.test.ts +44 -79
  251. package/src/runtime/routes/__tests__/image-generation-routes.test.ts +1 -4
  252. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +24 -14
  253. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +26 -23
  254. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +1 -1
  255. package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +3 -2
  256. package/src/runtime/routes/__tests__/migration-cadet-metadata-reconcile.test.ts +6 -17
  257. package/src/runtime/routes/__tests__/plugins-routes.test.ts +5 -1
  258. package/src/runtime/routes/__tests__/sanity-routes.test.ts +11 -19
  259. package/src/runtime/routes/app-management-routes.ts +1 -5
  260. package/src/runtime/routes/channel-metadata.ts +2 -6
  261. package/src/runtime/routes/client-routes.ts +2 -1
  262. package/src/runtime/routes/conversation-query-routes.ts +81 -53
  263. package/src/runtime/routes/conversation-routes.ts +2 -7
  264. package/src/runtime/routes/default-provider-routes.ts +24 -25
  265. package/src/runtime/routes/domain-routes.ts +3 -4
  266. package/src/runtime/routes/inference-profile-session-handler.ts +1 -4
  267. package/src/runtime/routes/inference-profiles-routes.ts +5 -11
  268. package/src/runtime/routes/inference-provider-connection-routes.ts +14 -15
  269. package/src/runtime/routes/inference-send-routes.ts +2 -5
  270. package/src/runtime/routes/integrations/slack/__tests__/token-routing.test.ts +17 -9
  271. package/src/runtime/routes/integrations/twilio.ts +6 -4
  272. package/src/runtime/routes/llm-call-sites-routes.ts +1 -4
  273. package/src/runtime/routes/oauth-proxy-passthrough.test.ts +1 -3
  274. package/src/runtime/routes/secret-routes.ts +2 -1
  275. package/src/runtime/routes/settings-routes.ts +6 -5
  276. package/src/runtime/routes/watch-routes.ts +1 -3
  277. package/src/runtime/services/__tests__/conversation-serializer.test.ts +3 -1
  278. package/src/security/secure-keys.ts +2 -1
  279. package/src/skills/__tests__/workspace-skill-md-signature.test.ts +15 -3
  280. package/src/tools/acp/status.ts +1 -4
  281. package/src/tools/browser/__tests__/auth-detector.test.ts +1 -3
  282. package/src/tools/network/__tests__/firecrawl-compat.test.ts +3 -3
  283. package/src/tools/network/__tests__/web-search.test.ts +74 -113
  284. package/src/tools/workflows/manage-workflows.ts +1 -4
  285. package/src/util/host-process.test.ts +4 -1
  286. package/src/util/oauth-request-body.test.ts +4 -1
  287. package/src/watcher/__tests__/engine.test.ts +3 -1
  288. package/src/watcher/engine.ts +1 -1
  289. package/src/workflows/leaf-runner.ts +1 -5
  290. package/src/workspace/byok-default-profile-ensure.ts +16 -14
  291. package/src/workspace/custom-profile-ensure.ts +2 -2
  292. package/src/workspace/migrations/130-speech-mode-to-provider.ts +1 -2
  293. package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +8 -4
  294. package/src/workspace/migrations/utils.ts +2 -1
  295. package/docs/backup-troubleshooting.md +0 -52
  296. package/docs/browser-use-architecture-phase2.md +0 -289
  297. package/docs/flux-turn-detection-spike.md +0 -249
  298. package/docs/workspace-tools.md +0 -207
  299. package/src/__tests__/default-provider-ensure.test.ts +0 -353
  300. package/src/workspace/default-provider-ensure.ts +0 -163
package/README.md CHANGED
@@ -70,9 +70,9 @@ bun run src/index.ts # interactive CLI session
70
70
 
71
71
  | Command | Description |
72
72
  | ---------------------------------------------------------- | ------------------------------------------------ |
73
- | `cadet wake` | Start assistant + gateway from current checkout |
74
- | `cadet sleep` | Stop assistant + gateway processes |
75
- | `cadet ps` | List assistants and per-assistant process status |
73
+ | `cadet wake` | Start assistant + gateway from current checkout |
74
+ | `cadet sleep` | Stop assistant + gateway processes |
75
+ | `cadet ps` | List assistants and per-assistant process status |
76
76
  | `assistant` | Launch interactive CLI session |
77
77
  | `assistant conversations list\|search\|new\|export\|clear` | Manage conversations |
78
78
  | `assistant config set\|get\|list` | Manage configuration |
@@ -4,10 +4,10 @@ Operational procedures for inspecting, managing, and debugging the trusted conta
4
4
 
5
5
  Two databases hold this state — pick the right one before reaching for SQL:
6
6
 
7
- | Data | Database | Location |
8
- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
7
+ | Data | Database | Location |
8
+ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
9
9
  | Contact ACL (`contacts` role, `contact_channels` status/policy/reasons), guardian requests (`guardian_requests` + `guardian_request_deliveries`), verification sessions, rate limits, invites | Gateway DB (`gateway.sqlite`) | `$GATEWAY_SECURITY_DIR/gateway.sqlite` (Docker: the `/gateway-security` volume; local fallback: `~/.cadet/protected/`) |
10
- | Notification pipeline, contact info/identity mirror | Assistant DB (`assistant.db`) | `$CADET_WORKSPACE_DIR/data/db/assistant.db` (local fallback: `~/.cadet/workspace/`) |
10
+ | Notification pipeline, contact info/identity mirror | Assistant DB (`assistant.db`) | `$CADET_WORKSPACE_DIR/data/db/assistant.db` (local fallback: `~/.cadet/workspace/`) |
11
11
 
12
12
  Prefer the CLI and HTTP surfaces below over raw SQL — they go through the gateway's validation (status vocabulary, revoke-of-blocked guard) and emit the change events clients rely on. Raw SQL is break-glass only.
13
13
 
package/docs/skills.md CHANGED
@@ -116,10 +116,10 @@ Acceptance is idempotent and recorded in `trust.json`. The bundle does not inclu
116
116
 
117
117
  Tools can execute in two contexts:
118
118
 
119
- | Target | Description |
120
- | --------- | ---------------------------------------------------------------------------------------- |
119
+ | Target | Description |
120
+ | --------- | --------------------------------------------------------------------------------------- |
121
121
  | `sandbox` | Isolated execution within `$CADET_WORKSPACE_DIR` (Docker container or OS-level sandbox) |
122
- | `host` | Direct execution on the host machine |
122
+ | `host` | Direct execution on the host machine |
123
123
 
124
124
  Trust rules can include an `executionTarget` field to bind the rule to a specific context. A rule without `executionTarget` matches both sandbox and host invocations.
125
125
 
@@ -9,7 +9,7 @@ Design doc defining how unknown users gain access to a Cadet assistant via chann
9
9
  | `guardian` | The verified owner/administrator of the assistant on a given channel. Has a record in the gateway DB `contacts` table with `role: 'guardian'` and an active `contact_channels` entry. Approves or denies access requests. |
10
10
  | `trusted_contact` | An external user who has completed the verification flow and holds a gateway `contact_channels` record with `status: 'active'` and `policy: 'allow'`. |
11
11
  | `gateway` | The ACL and verification engine. Owns the contact ACL, guardian requests + their delivery records, verification sessions, rate limits, secret minting, code interception, and the validate+consume decision. Commits every guardian decision (status CAS + ACL outcome) in one transaction. Stamps a trust verdict on every inbound message. |
12
- | `assistant` | The Cadet assistant daemon. Orchestrates the approval workflow around the gateway-owned requests: guardian notification, message composition, channel delivery, and post-decision side effects (cards, notices, grant minting). It never mints or validates verification secrets. |
12
+ | `assistant` | The Cadet assistant daemon. Orchestrates the approval workflow around the gateway-owned requests: guardian notification, message composition, channel delivery, and post-decision side effects (cards, notices, grant minting). It never mints or validates verification secrets. |
13
13
 
14
14
  ## Data Ownership
15
15
 
@@ -84,7 +84,7 @@ Identity binding ensures the verification code can only be consumed by the inten
84
84
  | Store | Table | Record |
85
85
  | ----------------------------------------------------------------------------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
86
86
  | gateway `guardian-request-store.ts` (via the daemon's `channels/gateway-guardian-requests.ts` client) | `guardian_requests` (gateway DB) | `status: 'pending'`, `kind: 'access_request'`, `toolName: 'ingress_access_request'`, `requesterExternalUserId`, `requesterChatId`, `guardianExternalUserId`/`guardianPrincipalId` (anchored resolution), `requestCode`, `expiresAt` (GUARDIAN_APPROVAL_TTL_MS from now). |
87
- | `guardian-delivery-recorder.ts` (single write sink, relays to the gateway) | `guardian_request_deliveries` (gateway DB) | Per-surface approval-card delivery records (cadet, Telegram, Slack). |
87
+ | `guardian-delivery-recorder.ts` (single write sink, relays to the gateway) | `guardian_request_deliveries` (gateway DB) | Per-surface approval-card delivery records (cadet, Telegram, Slack). |
88
88
  | notification pipeline (assistant DB) | `notification_events` | Event with `sourceEventName: 'ingress.access_request'`, deduped via `dedupeKey`. |
89
89
  | notification pipeline (assistant DB) | `notification_decisions` | Decision engine output: `shouldNotify`, `selectedChannels`, `confidence`, reasoning. |
90
90
  | notification pipeline (assistant DB) | `notification_deliveries` | Per-channel delivery records, linked via `notificationDecisionId`. |
package/eslint.config.mjs CHANGED
@@ -35,6 +35,21 @@ const eslintConfig = defineConfig([
35
35
  { argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
36
36
  ],
37
37
  "@typescript-eslint/no-explicit-any": "error",
38
+ // Flag `mock.module` at warning level: the lint script pins
39
+ // --max-warnings to the current count and each PR chips away at it
40
+ // (same countdown the cli uses for `as` casts). Prefer running the
41
+ // test on the real backend behind a seam — e.g. the memory-backed
42
+ // helpers in src/__tests__/helpers/secure-keys.ts — instead of
43
+ // masking module state.
44
+ "no-restricted-syntax": [
45
+ "warn",
46
+ {
47
+ selector:
48
+ "CallExpression[callee.object.name='mock'][callee.property.name='module']",
49
+ message:
50
+ "mock.module masks module state across tests; run on the real backend behind a seam instead. Remaining uses are being counted down — do not add new ones.",
51
+ },
52
+ ],
38
53
  },
39
54
  },
40
55
  {
package/knip.json CHANGED
@@ -11,14 +11,8 @@
11
11
  "src/api/index.ts!",
12
12
  "src/config/bundled-skills/**/tools/**/*.ts!"
13
13
  ],
14
- "project": [
15
- "src/**/*.ts!",
16
- "src/**/*.tsx!",
17
- "scripts/**/*.ts"
18
- ],
19
- "ignore": [
20
- "src/config/preloaded-apps/**"
21
- ],
14
+ "project": ["src/**/*.ts!", "src/**/*.tsx!", "scripts/**/*.ts"],
15
+ "ignore": ["src/config/preloaded-apps/**"],
22
16
  "ignoreDependencies": [
23
17
  "@microsoft/api-extractor",
24
18
  "@mycadet/app-icons",
package/openapi.yaml CHANGED
@@ -3,7 +3,7 @@
3
3
  openapi: 3.1.0
4
4
  info:
5
5
  title: Cadet Assistant API
6
- version: 0.12.6
6
+ version: 0.12.7
7
7
  description: Auto-generated OpenAPI specification for the Cadet Assistant runtime HTTP server.
8
8
  servers:
9
9
  - url: http://127.0.0.1:7821
@@ -5659,9 +5659,9 @@ paths:
5659
5659
  operationId: config_llm_defaultprovider_get
5660
5660
  summary: Get the default provider and its availability
5661
5661
  description:
5662
- Returns `llm.defaultProvider`, the connection name it resolves to, and whether that connection is currently
5663
- usable (connection exists, credential stored, Cadet authenticated). Availability is informational — a broken
5664
- default is a valid persisted state that surfaces explainable errors at resolution time.
5662
+ Returns the default provider stored in `llm.default`, the connection name it resolves to, and whether that
5663
+ connection is currently usable (connection exists, credential stored, Cadet authenticated). Availability is
5664
+ informational — a broken default is a valid persisted state that surfaces explainable errors at resolution time.
5665
5665
  tags:
5666
5666
  - config
5667
5667
  responses:
@@ -5675,9 +5675,9 @@ paths:
5675
5675
  operationId: config_llm_defaultprovider_put
5676
5676
  summary: Set the default provider
5677
5677
  description:
5678
- Replaces `llm.defaultProvider`. Strict-validates the body (unlike the generic config write paths, which
5679
- silently drop invalid values). Does not require the referenced connection to exist — a dangling name is allowed
5680
- by design and reported via the availability status.
5678
+ Replaces the default provider stored in the `llm.default` blob. Strict-validates the body (unlike the
5679
+ generic config write paths, which silently drop or clamp invalid values). Does not require the referenced
5680
+ connection to exist — a dangling name is allowed by design and reported via the availability status.
5681
5681
  tags:
5682
5682
  - config
5683
5683
  requestBody:
@@ -39199,6 +39199,9 @@ components:
39199
39199
  type: object
39200
39200
  properties:
39201
39201
  autoArchive:
39202
+ default:
39203
+ enabled: false
39204
+ afterDays: 7
39202
39205
  type: object
39203
39206
  properties:
39204
39207
  enabled:
@@ -39358,6 +39361,7 @@ components:
39358
39361
  type: boolean
39359
39362
  provider_connection:
39360
39363
  type: string
39364
+ minLength: 1
39361
39365
  additionalProperties: false
39362
39366
  defaultProvider:
39363
39367
  type: object
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mycadet/assistant",
3
- "version": "0.12.6-dev.202610091338.ee7f3e3",
3
+ "version": "0.12.7",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -20,7 +20,7 @@
20
20
  "probe:skill-retrieval": "bun run scripts/probe-skill-retrieval.ts",
21
21
  "format": "prettier --write .",
22
22
  "format:check": "prettier --check .",
23
- "lint": "bun run lint:skills && bun run lint:openapi && eslint",
23
+ "lint": "bun run lint:skills && bun run lint:openapi && eslint --max-warnings 3033",
24
24
  "lint:unused": "knip --include files,dependencies,unlisted",
25
25
  "lint:circular": "bun run scripts/check-circular-deps.ts",
26
26
  "lint:unused:production": "knip --production --include exports",
@@ -84,5 +84,8 @@ await runIsolatedTests({
84
84
  bunTestArgs: EXCLUDE_EXPERIMENTAL
85
85
  ? ["--test-name-pattern", "^(?!.*\\[experimental\\])"]
86
86
  : [],
87
- fixture: { script: "scripts/build-test-fixtures.ts", envVar: "CADET_TEST_FIXTURES_DIR" },
87
+ fixture: {
88
+ script: "scripts/build-test-fixtures.ts",
89
+ envVar: "CADET_TEST_FIXTURES_DIR",
90
+ },
88
91
  });
@@ -2,43 +2,9 @@ import { readFileSync } from "node:fs";
2
2
  import { resolve } from "node:path";
3
3
  import { describe, expect, mock, test } from "bun:test";
4
4
 
5
- import type { AppDefinition } from "../apps/app-store.js";
6
- import type { AppStore } from "../tools/apps/executors.js";
5
+ import { initializeDb } from "../persistence/db-init.js";
7
6
  import type { ToolContext } from "../tools/types.js";
8
-
9
- // ---------------------------------------------------------------------------
10
- // Mock factory helpers
11
- // ---------------------------------------------------------------------------
12
-
13
- function makeApp(overrides: Partial<AppDefinition> = {}): AppDefinition {
14
- return {
15
- id: "app-1",
16
- name: "Test App",
17
- description: "A test app",
18
- schemaJson: "{}",
19
- htmlDefinition: "<h1>Hi</h1>",
20
- createdAt: 1000,
21
- updatedAt: 2000,
22
- ...overrides,
23
- };
24
- }
25
-
26
- function makeMockStore(overrides: Partial<AppStore> = {}): AppStore {
27
- const files = new Set<string>();
28
- return {
29
- getApp: () => makeApp(),
30
- listApps: () => [makeApp()],
31
- appFileExists: (_appId: string, path: string) => files.has(path),
32
- createApp: (params) =>
33
- makeApp({ name: params.name, description: params.description }),
34
- updateApp: (id, updates) => makeApp({ id, ...updates }),
35
- deleteApp: () => {},
36
- writeAppFile: (_appId: string, path: string) => {
37
- files.add(path);
38
- },
39
- ...overrides,
40
- };
41
- }
7
+ import { seedApp } from "./helpers/seed-app.js";
42
8
 
43
9
  function makeContext(overrides: Partial<ToolContext> = {}): ToolContext {
44
10
  return {
@@ -50,25 +16,15 @@ function makeContext(overrides: Partial<ToolContext> = {}): ToolContext {
50
16
  }
51
17
 
52
18
  // ---------------------------------------------------------------------------
53
- // Mock the app-store module so that skill scripts import our controllable store
19
+ // The skill scripts pass the REAL app-store module to the executors, so the
20
+ // store runs on the per-process test workspace. `app-1` is re-seeded before
21
+ // each test (the app-delete test really deletes it); per-conversation lookups
22
+ // go through real rows seeded with conversationIds.
54
23
  // ---------------------------------------------------------------------------
55
24
 
56
- const mockStore = makeMockStore();
57
-
58
- // Mutable per-conversation app list backing `listAppsByConversation`, which
59
- // `resolveAppId` consults when a tool's app_id is omitted. Tests set it directly.
60
- let appsByConversation: AppDefinition[] = [];
61
-
62
- mock.module("../apps/app-store.js", () => ({
63
- ...mockStore,
64
- listAppsByConversation: (_conversationId: string) => appsByConversation,
65
- getAppsDir: () => "/tmp/test-apps",
66
- getAppDirPath: (appId: string) => `/tmp/test-apps/${appId}`,
67
- resolveAppDir: (id: string) => ({
68
- dirName: id,
69
- appDir: `/tmp/test-apps/${id}`,
70
- }),
71
- }));
25
+ beforeAll(async () => {
26
+ await initializeDb();
27
+ });
72
28
 
73
29
  // Mock compileApp for multifile scaffold path
74
30
  mock.module("../bundler/app-compiler.js", () => ({
@@ -84,6 +40,8 @@ mock.module("../bundler/app-compiler.js", () => ({
84
40
  // Import skill scripts (after mocking)
85
41
  // ---------------------------------------------------------------------------
86
42
 
43
+ import { beforeAll, beforeEach } from "bun:test";
44
+
87
45
  import * as appCreateScript from "../config/bundled-skills/app-builder/tools/app-create.js";
88
46
  import * as appDeleteScript from "../config/bundled-skills/app-builder/tools/app-delete.js";
89
47
  import * as appOpenScript from "../config/bundled-skills/app-builder/tools/app-open.js";
@@ -95,6 +53,10 @@ import * as appUpdateScript from "../config/bundled-skills/app-builder/tools/app
95
53
  // ---------------------------------------------------------------------------
96
54
 
97
55
  describe("app-builder skill tool scripts", () => {
56
+ beforeEach(() => {
57
+ seedApp({ id: "app-1", name: "Test App", description: "A test app" });
58
+ });
59
+
98
60
  // ---- app-create --------------------------------------------------------
99
61
 
100
62
  describe("app-create", () => {
@@ -208,7 +170,11 @@ describe("app-builder skill tool scripts", () => {
208
170
  });
209
171
 
210
172
  test("resolves the active app when app_id is omitted", async () => {
211
- appsByConversation = [makeApp({ id: "active-app" })];
173
+ seedApp({
174
+ id: "active-app",
175
+ name: "active-app",
176
+ conversationIds: ["conv-open-1"],
177
+ });
212
178
  const calls: Array<{ name: string; input: Record<string, unknown> }> = [];
213
179
  const proxy: ToolContext["proxyToolResolver"] = async (name, input) => {
214
180
  calls.push({ name, input });
@@ -217,7 +183,10 @@ describe("app-builder skill tool scripts", () => {
217
183
 
218
184
  const result = await appOpenScript.run(
219
185
  {},
220
- makeContext({ proxyToolResolver: proxy }),
186
+ makeContext({
187
+ conversationId: "conv-open-1",
188
+ proxyToolResolver: proxy,
189
+ }),
221
190
  );
222
191
 
223
192
  expect(result.isError).toBe(false);
@@ -227,7 +196,6 @@ describe("app-builder skill tool scripts", () => {
227
196
  });
228
197
 
229
198
  test("forwards an explicit app_id unchanged", async () => {
230
- appsByConversation = [makeApp({ id: "active-app" })];
231
199
  const calls: Array<{ input: Record<string, unknown> }> = [];
232
200
  const proxy: ToolContext["proxyToolResolver"] = async (_name, input) => {
233
201
  calls.push({ input });
@@ -243,7 +211,6 @@ describe("app-builder skill tool scripts", () => {
243
211
  });
244
212
 
245
213
  test("errors when app_id is omitted and no active app exists", async () => {
246
- appsByConversation = [];
247
214
  const proxy: ToolContext["proxyToolResolver"] = async () => ({
248
215
  content: "opened",
249
216
  isError: false,
@@ -251,7 +218,10 @@ describe("app-builder skill tool scripts", () => {
251
218
 
252
219
  const result = await appOpenScript.run(
253
220
  {},
254
- makeContext({ proxyToolResolver: proxy }),
221
+ makeContext({
222
+ conversationId: "conv-open-none",
223
+ proxyToolResolver: proxy,
224
+ }),
255
225
  );
256
226
 
257
227
  expect(result.isError).toBe(true);
@@ -259,10 +229,14 @@ describe("app-builder skill tool scripts", () => {
259
229
  });
260
230
 
261
231
  test("errors when no client proxy resolver is available", async () => {
262
- appsByConversation = [makeApp({ id: "active-app" })];
232
+ seedApp({
233
+ id: "active-app",
234
+ name: "active-app",
235
+ conversationIds: ["conv-open-noproxy"],
236
+ });
263
237
  const result = await appOpenScript.run(
264
238
  { app_id: "app-1" },
265
- makeContext(),
239
+ makeContext({ conversationId: "conv-open-noproxy" }),
266
240
  );
267
241
 
268
242
  expect(result.isError).toBe(true);
@@ -6,22 +6,14 @@ import {
6
6
  writeFileSync,
7
7
  } from "node:fs";
8
8
  import { readFile } from "node:fs/promises";
9
- import { tmpdir } from "node:os";
10
9
  import { join } from "node:path";
11
- import { afterEach, describe, expect, mock, test } from "bun:test";
10
+ import { afterEach, beforeAll, describe, expect, mock, test } from "bun:test";
12
11
 
13
12
  import JSZip from "jszip";
14
13
 
15
- // Temp directory for fake app data used in packageApp tests
16
- const testAppsDir = join(tmpdir(), `app-bundler-test-${Date.now()}`);
17
-
18
- // Mock app-store so packageApp can find our test apps
19
- const mockApps = new Map<string, Record<string, unknown>>();
20
- mock.module("../apps/app-store.js", () => ({
21
- getApp: (id: string) => mockApps.get(id) ?? null,
22
- getAppsDir: () => testAppsDir,
23
- getAppDirPath: (id: string) => join(testAppsDir, id),
24
- }));
14
+ // Real apps dir inside the per-process test workspace; packageApp tests
15
+ // write the store's on-disk format (<id>.json + <id>/src) directly.
16
+ let testAppsDir: string;
25
17
 
26
18
  // Mock content-id to avoid pulling in crypto internals
27
19
  mock.module("../util/content-id.js", () => ({
@@ -79,6 +71,7 @@ mock.module("./bundle-signer.js", () => ({
79
71
  signBundle: async () => ({}),
80
72
  }));
81
73
 
74
+ import { getAppsDir } from "../apps/app-store.js";
82
75
  import { packageApp } from "../bundler/app-bundler.js";
83
76
  import type { AppManifest } from "../bundler/manifest.js";
84
77
 
@@ -87,9 +80,12 @@ import type { AppManifest } from "../bundler/manifest.js";
87
80
  // ---------------------------------------------------------------------------
88
81
 
89
82
  describe("packageApp", () => {
83
+ beforeAll(() => {
84
+ testAppsDir = getAppsDir();
85
+ });
86
+
90
87
  afterEach(() => {
91
88
  compileAppOverride = undefined;
92
- mockApps.clear();
93
89
  try {
94
90
  rmSync(testAppsDir, { recursive: true, force: true });
95
91
  } catch {
@@ -133,7 +129,6 @@ describe("packageApp", () => {
133
129
  formatVersion: 2,
134
130
  };
135
131
  writeFileSync(join(testAppsDir, `${appId}.json`), JSON.stringify(appDef));
136
- mockApps.set(appId, appDef);
137
132
 
138
133
  return appDef;
139
134
  }
@@ -156,7 +151,6 @@ describe("packageApp", () => {
156
151
  updatedAt: Date.now(),
157
152
  };
158
153
  writeFileSync(join(testAppsDir, `${appId}.json`), JSON.stringify(appDef));
159
- mockApps.set(appId, appDef);
160
154
 
161
155
  return appDef;
162
156
  }
@@ -238,7 +232,6 @@ describe("packageApp", () => {
238
232
  formatVersion: 2,
239
233
  };
240
234
  writeFileSync(join(testAppsDir, `${appId}.json`), JSON.stringify(appDef));
241
- mockApps.set(appId, appDef);
242
235
 
243
236
  await expect(packageApp(appId)).rejects.toThrow(
244
237
  /Compilation failed for app "Broken App"/,
@@ -264,7 +257,6 @@ describe("packageApp", () => {
264
257
  formatVersion: 2,
265
258
  };
266
259
  writeFileSync(join(testAppsDir, `${appId}.json`), JSON.stringify(appDef));
267
- mockApps.set(appId, appDef);
268
260
 
269
261
  await expect(packageApp(appId)).rejects.toThrow(
270
262
  /missing src\/index\.html and src\/main\.tsx/,
@@ -302,7 +294,6 @@ render(<App />, document.getElementById('app')!);
302
294
  formatVersion: 2,
303
295
  };
304
296
  writeFileSync(join(testAppsDir, `${appId}.json`), JSON.stringify(appDef));
305
- mockApps.set(appId, appDef);
306
297
 
307
298
  await expect(packageApp(appId)).rejects.toThrow(
308
299
  /still has the default src\/main\.tsx scaffold/,
@@ -1,71 +1,30 @@
1
- import { describe, expect, mock, test } from "bun:test";
2
-
3
- // Fake app records keyed by ID
4
- const compiledApp = {
5
- id: "app-1",
6
- name: "Compiled App",
7
- htmlDefinition: "",
8
- schemaJson: "{}",
9
- createdAt: 0,
10
- updatedAt: 0,
11
- formatVersion: 2,
12
- };
13
-
14
- const legacyApp = {
15
- id: "legacy-1",
16
- name: "Legacy App",
17
- htmlDefinition: "<div>Hello</div>",
18
- schemaJson: "{}",
19
- createdAt: 0,
20
- updatedAt: 0,
21
- };
22
-
23
- const apps = new Map<string, typeof compiledApp | typeof legacyApp>([
24
- ["app-1", compiledApp],
25
- ["legacy-1", legacyApp],
26
- ]);
27
-
28
- const UNSUPPORTED_HTML = `<p>This app uses the retired single-file format and can no longer be opened.</p>`;
29
-
30
- mock.module("../apps/app-store.js", () => ({
31
- resolveAppSource: (id: string) => {
32
- const app = apps.get(id);
33
- if (!app) {
34
- return null;
35
- }
36
- return {
37
- id,
38
- name: app.name,
39
- dirName: id,
40
- sourceDir: `/fake/apps/${id}`,
41
- origin: { kind: "workspace" as const },
42
- };
43
- },
44
- readAppFileBytesFromDir: () => Buffer.from(""),
45
- // Only the legacy app's directory has a root index.html and no src/.
46
- isLegacySingleFileDir: (sourceDir: string) =>
47
- sourceDir === "/fake/apps/legacy-1",
48
- UNSUPPORTED_LEGACY_APP_HTML: UNSUPPORTED_HTML,
49
- }));
50
-
51
- // Mock shared-app-links-store (imported by app-routes but unused here)
52
- mock.module("../apps/shared-app-links-store.js", () => ({
53
- createSharedAppLink: () => ({ shareToken: "tok" }),
54
- getSharedAppLink: () => null,
55
- incrementDownloadCount: () => {},
56
- deleteSharedAppLinkByToken: () => false,
57
- }));
58
-
59
- // Stub fs so the serve path finds a fake dist/index.html for the compiled app
60
- mock.module("node:fs", () => ({
61
- existsSync: (p: string) => p === "/fake/apps/app-1/dist/index.html",
62
- readFileSync: (p: string, _enc?: string) => {
63
- if (p === "/fake/apps/app-1/dist/index.html") {
64
- return '<!DOCTYPE html><html><head></head><body><script src="main.js"></script></body></html>';
65
- }
66
- return "";
67
- },
68
- }));
1
+ import { mkdirSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { beforeAll, describe, expect, test } from "bun:test";
4
+
5
+ import {
6
+ getAppDirPath,
7
+ UNSUPPORTED_LEGACY_APP_HTML,
8
+ } from "../apps/app-store.js";
9
+ import { seedApp } from "./helpers/seed-app.js";
10
+
11
+ beforeAll(() => {
12
+ // Real store rows written in the on-disk format. The compiled app carries
13
+ // a dist/index.html; the legacy app has only a root index.html and no src/.
14
+ seedApp({ id: "app-1", name: "Compiled App", schemaJson: "{}" });
15
+ const appDir = getAppDirPath("app-1");
16
+ mkdirSync(join(appDir, "dist"), { recursive: true });
17
+ writeFileSync(
18
+ join(appDir, "dist", "index.html"),
19
+ '<!DOCTYPE html><html><head></head><body><script src="main.js"></script></body></html>',
20
+ );
21
+ seedApp({
22
+ id: "legacy-1",
23
+ name: "Legacy App",
24
+ htmlDefinition: "<div>Hello</div>",
25
+ schemaJson: "{}",
26
+ });
27
+ });
69
28
 
70
29
  import { ROUTES } from "../runtime/routes/app-routes.js";
71
30
  import { BadRequestError, NotFoundError } from "../runtime/routes/errors.js";
@@ -155,7 +114,7 @@ describe("handleServePage", () => {
155
114
 
156
115
  test("serves the unsupported-format message for legacy single-file apps", () => {
157
116
  const html = pageHandler({ pathParams: { appId: "legacy-1" } }) as string;
158
- expect(html).toContain(UNSUPPORTED_HTML);
117
+ expect(html).toContain(UNSUPPORTED_LEGACY_APP_HTML);
159
118
  expect(html).not.toContain("<div>Hello</div>");
160
119
  });
161
120
 
@@ -6,8 +6,6 @@
6
6
  */
7
7
  import { beforeEach, describe, expect, mock, test } from "bun:test";
8
8
 
9
- import { Minimatch } from "minimatch";
10
-
11
9
  import { CompactionCircuit } from "../agent/compaction-circuit.js";
12
10
  import type { AgentEvent } from "../agent/loop.js";
13
11
  import type { ConfirmationStateChangedEvent } from "../api/events/confirmation-state-changed.js";
@@ -38,26 +36,6 @@ mock.module("../config/skill-state.js", () => ({
38
36
  resolveSkillStates: () => [],
39
37
  }));
40
38
 
41
- // Trust store mock — uses real minimatch for patternMatchesCandidate so the
42
- // mock doesn't break trust-store-pattern-matches.test.ts when both files run
43
- // in the same Bun process (mock.module leaks across test files).
44
- mock.module("../permissions/trust-store.js", () => ({
45
- addRule: () => {},
46
- findHighestPriorityRule: () => null,
47
- clearCache: () => {},
48
- patternMatchesCandidate: (pattern: string, candidate: string): boolean => {
49
- try {
50
- return new Minimatch(pattern).match(candidate);
51
- } catch {
52
- return false;
53
- }
54
- },
55
- }));
56
-
57
- mock.module("../security/secret-allowlist.js", () => ({
58
- resetAllowlist: () => {},
59
- }));
60
-
61
39
  mock.module("../persistence/conversation-crud.js", () => ({
62
40
  setConversationProcessingStartedAt: () => {},
63
41
  isConversationProcessing: () => false,
@@ -23,27 +23,6 @@ const addRuleCalls: Array<{
23
23
  priority?: number;
24
24
  options?: { executionTarget?: string };
25
25
  }> = [];
26
- mock.module("../permissions/trust-store.js", () => ({
27
- addRule: (
28
- tool: string,
29
- pattern: string,
30
- scope: string,
31
- decision: string,
32
- priority?: number,
33
- options?: { executionTarget?: string },
34
- ) => {
35
- addRuleCalls.push({ tool, pattern, scope, decision, priority, options });
36
- return {
37
- id: "test-rule",
38
- tool,
39
- pattern,
40
- scope,
41
- decision,
42
- priority: priority ?? 100,
43
- };
44
- },
45
- getRules: () => [],
46
- }));
47
26
 
48
27
  // ---------------------------------------------------------------------------
49
28
  // Module mocks for direct-import deps used by conversation-routes ROUTES
@@ -132,8 +132,7 @@ describe("parseDirectives", () => {
132
132
  });
133
133
 
134
134
  test("preserves non-self-closing tags as plain text", () => {
135
- const text =
136
- '<cadet-attachment path="file.txt">content</cadet-attachment>';
135
+ const text = '<cadet-attachment path="file.txt">content</cadet-attachment>';
137
136
  const result = parseDirectives(text);
138
137
 
139
138
  // The regex only matches self-closing tags, so non-self-closing is not matched
@@ -816,16 +816,14 @@ describe("drainDirectiveDisplayBuffer", () => {
816
816
  });
817
817
 
818
818
  test("does not insert space when stripped directive already has trailing whitespace", () => {
819
- const input =
820
- 'sentence. <cadet-attachment path="out.png" />Next sentence.';
819
+ const input = 'sentence. <cadet-attachment path="out.png" />Next sentence.';
821
820
  const result = drainDirectiveDisplayBuffer(input);
822
821
  expect(result.emitText).toBe("sentence. Next sentence.");
823
822
  expect(result.bufferedRemainder).toBe("");
824
823
  });
825
824
 
826
825
  test("does not insert space when stripped directive already has leading whitespace on next char", () => {
827
- const input =
828
- 'sentence.<cadet-attachment path="out.png" /> Next sentence.';
826
+ const input = 'sentence.<cadet-attachment path="out.png" /> Next sentence.';
829
827
  const result = drainDirectiveDisplayBuffer(input);
830
828
  expect(result.emitText).toBe("sentence. Next sentence.");
831
829
  expect(result.bufferedRemainder).toBe("");