@vellumai/assistant 0.10.8 → 0.10.9-dev.202607152225.ec6fdbf
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.
- package/AGENTS.md +4 -0
- package/ARCHITECTURE.md +52 -88
- package/README.md +14 -35
- package/docs/activation-funnel-telemetry.md +20 -18
- package/docs/architecture/scheduling.md +0 -86
- package/docs/runbook-trusted-contacts.md +19 -19
- package/docs/trusted-contact-access.md +70 -69
- package/docs/workspace-tools.md +4 -2
- package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +62 -360
- package/eslint-rules/cli-no-daemon-internals.js +91 -275
- package/eslint.config.mjs +4 -4
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-request-contract.test.ts +575 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -0
- package/node_modules/@vellumai/gateway-client/src/guardian-request-contract.ts +687 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +82 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
- package/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
- package/openapi.yaml +353 -742
- package/package.json +2 -2
- package/scripts/build-test-fixtures.ts +3 -2
- package/scripts/test.ts +2 -7
- package/src/__tests__/activation-early-marking.test.ts +1 -8
- package/src/__tests__/actor-token-service.test.ts +0 -7
- package/src/__tests__/add-message-preassigned-id.test.ts +1 -1
- package/src/__tests__/add-message-skip-indexing.test.ts +164 -0
- package/src/__tests__/agent-image-optimize.test.ts +104 -1
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +5 -15
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +0 -6
- package/src/__tests__/agent-loop-override-profile.test.ts +48 -50
- package/src/__tests__/agent-loop-pushes-post-hook-prompt.test.ts +4 -17
- package/src/__tests__/agent-loop-set-system-prompt.test.ts +3 -14
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -4
- package/src/__tests__/agent-wake-override-profile.test.ts +40 -71
- package/src/__tests__/always-loaded-tools-guard.test.ts +4 -7
- package/src/__tests__/annotate-activity-metadata.test.ts +4 -31
- package/src/__tests__/annotate-risk-options.test.ts +4 -31
- package/src/__tests__/anthropic-provider.test.ts +11 -0
- package/src/__tests__/app-asset-bytes.test.ts +72 -0
- package/src/__tests__/app-builder-tool-scripts.test.ts +0 -1
- package/src/__tests__/app-bundler.test.ts +4 -20
- package/src/__tests__/app-conversation-ids-backfill.test.ts +1 -8
- package/src/__tests__/app-executors.test.ts +2 -49
- package/src/__tests__/app-routes-csp.test.ts +126 -157
- package/src/__tests__/approval-cascade.test.ts +0 -82
- package/src/__tests__/approval-interception-trust-gates.test.ts +0 -7
- package/src/__tests__/approval-primitive.test.ts +1 -9
- package/src/__tests__/approval-routes-http.test.ts +5 -63
- package/src/__tests__/assistant-event-hub-machine-name.test.ts +1 -19
- package/src/__tests__/assistant-events-sse-hardening.test.ts +4 -21
- package/src/__tests__/attachment-stored-path-annotation.test.ts +1 -19
- package/src/__tests__/attachment-upload-trusted-source.test.ts +0 -13
- package/src/__tests__/attachments-store-heic-normalize.test.ts +0 -13
- package/src/__tests__/attachments-store.test.ts +5 -19
- package/src/__tests__/audit-log-rotation.test.ts +1 -9
- package/src/__tests__/auth-fallback-events-store.test.ts +43 -59
- package/src/__tests__/available-skills.test.ts +7 -15
- package/src/__tests__/avatar-e2e.test.ts +0 -19
- package/src/__tests__/avatar-generator.test.ts +0 -9
- package/src/__tests__/background-shell-bash.test.ts +0 -20
- package/src/__tests__/background-shell-host-bash.test.ts +0 -34
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -43
- package/src/__tests__/browser-fill-credential.test.ts +0 -7
- package/src/__tests__/browser-manager.test.ts +1 -8
- package/src/__tests__/browser-skill-endstate.test.ts +1 -5
- package/src/__tests__/btw-routes.test.ts +7 -30
- package/src/__tests__/build-persisted-content.test.ts +96 -29
- package/src/__tests__/bundle-scanner.test.ts +27 -1
- package/src/__tests__/call-controller.test.ts +96 -149
- package/src/__tests__/call-conversation-messages.test.ts +2 -9
- package/src/__tests__/call-domain.test.ts +21 -56
- package/src/__tests__/call-pointer-message-composer.test.ts +0 -8
- package/src/__tests__/call-pointer-messages.test.ts +1 -8
- package/src/__tests__/call-recovery.test.ts +4 -11
- package/src/__tests__/call-routes-http.test.ts +12 -47
- package/src/__tests__/call-site-routing-provider.test.ts +5 -16
- package/src/__tests__/call-start-guardian-guard.test.ts +0 -10
- package/src/__tests__/call-state.test.ts +1 -8
- package/src/__tests__/call-store.test.ts +4 -11
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +0 -32
- package/src/__tests__/catalog-cache.test.ts +0 -8
- package/src/__tests__/catalog-files.test.ts +0 -8
- package/src/__tests__/catalog-install-normalize.test.ts +0 -7
- package/src/__tests__/ces-rpc-credential-backend.test.ts +0 -7
- package/src/__tests__/channel-approval-routes.test.ts +23 -34
- package/src/__tests__/channel-approvals.test.ts +0 -7
- package/src/__tests__/channel-delivery-store.test.ts +6 -17
- package/src/__tests__/channel-guardian.test.ts +0 -7
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +15 -20
- package/src/__tests__/channel-readiness-routes.test.ts +41 -67
- package/src/__tests__/channel-readiness-service.test.ts +13 -45
- package/src/__tests__/channel-readiness-slack-remote.test.ts +5 -22
- package/src/__tests__/channel-reply-delivery.test.ts +18 -5
- package/src/__tests__/channel-retry-sweep.test.ts +0 -7
- package/src/__tests__/chat-credential-redaction.test.ts +1395 -0
- package/src/__tests__/chat-reveal-guard-priming.test.ts +791 -0
- package/src/__tests__/checker.test.ts +0 -24
- package/src/__tests__/clawhub-files.test.ts +0 -8
- package/src/__tests__/clawhub.test.ts +0 -7
- package/src/__tests__/clear-all-lexical.test.ts +0 -6
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +3 -0
- package/src/__tests__/client-os-metadata-persistence.test.ts +0 -5
- package/src/__tests__/compaction-events.test.ts +26 -99
- package/src/__tests__/compaction-ledger-store.test.ts +1 -7
- package/src/__tests__/compaction-summary-head-persisted-count.test.ts +0 -27
- package/src/__tests__/compaction-trail-store.test.ts +1 -19
- package/src/__tests__/compaction.benchmark.test.ts +2 -6
- package/src/__tests__/compactor-call-site-logging.test.ts +0 -21
- package/src/__tests__/compactor-fixed-boundary.test.ts +0 -21
- package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -10
- package/src/__tests__/compactor-low-watermark-cut.test.ts +0 -21
- package/src/__tests__/compactor-media-strip.test.ts +0 -21
- package/src/__tests__/compactor-preserved-tail-count.test.ts +0 -21
- package/src/__tests__/compactor-summary-call-truncation.test.ts +0 -21
- package/src/__tests__/compactor-web-search-strip.test.ts +0 -21
- package/src/__tests__/config-get-vision-flag.test.ts +24 -53
- package/src/__tests__/config-loader-backfill.test.ts +9 -25
- package/src/__tests__/config-loader-platform-defaults.test.ts +0 -21
- package/src/__tests__/config-schema-cmd.test.ts +10 -11
- package/src/__tests__/config-schema.test.ts +221 -275
- package/src/__tests__/config-set-route.test.ts +32 -62
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +44 -83
- package/src/__tests__/config-watcher-skill-reseed.test.ts +0 -16
- package/src/__tests__/config-watcher.test.ts +2 -17
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +57 -63
- package/src/__tests__/contact-store-interaction-info.test.ts +1 -8
- package/src/__tests__/contact-store-user-file.test.ts +1 -8
- package/src/__tests__/contacts-tools.test.ts +21 -26
- package/src/__tests__/contacts-write.test.ts +1 -8
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -6
- package/src/__tests__/context-window-manager-compact-retry.test.ts +0 -27
- package/src/__tests__/context-window-manager-overflow-rung.test.ts +0 -21
- package/src/__tests__/conversation-abort-tool-results.test.ts +9 -90
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +5 -41
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +16 -54
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +14 -79
- package/src/__tests__/conversation-agent-loop.test.ts +213 -136
- package/src/__tests__/conversation-app-control-instantiation.test.ts +10 -16
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +0 -43
- package/src/__tests__/conversation-attachments.test.ts +0 -17
- package/src/__tests__/conversation-attention-store.test.ts +1 -9
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -8
- package/src/__tests__/conversation-clear-safety.test.ts +20 -20
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -82
- package/src/__tests__/conversation-crud-enabled-plugins.test.ts +1 -7
- package/src/__tests__/conversation-crud-inference-profile.test.ts +1 -7
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -7
- package/src/__tests__/conversation-disk-view-integration.test.ts +1 -26
- package/src/__tests__/conversation-disk-view.test.ts +1 -26
- package/src/__tests__/conversation-enabledplugins-route.test.ts +3 -21
- package/src/__tests__/conversation-error.test.ts +21 -7
- package/src/__tests__/conversation-fork-crud.test.ts +35 -44
- package/src/__tests__/conversation-fork-retrospective.test.ts +9 -24
- package/src/__tests__/conversation-fork-route.test.ts +0 -32
- package/src/__tests__/conversation-history-web-search.test.ts +20 -17
- package/src/__tests__/conversation-inference-profile-list.test.ts +0 -17
- package/src/__tests__/conversation-inference-profile-route.test.ts +2 -24
- package/src/__tests__/conversation-init.benchmark.test.ts +3 -56
- package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -33
- package/src/__tests__/conversation-lifecycle.test.ts +63 -103
- package/src/__tests__/conversation-list-source.test.ts +0 -18
- package/src/__tests__/conversation-load-history-repair.test.ts +39 -91
- package/src/__tests__/conversation-load-history-stripped.test.ts +12 -57
- package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +10 -20
- package/src/__tests__/conversation-message-id-uuidv7.test.ts +1 -18
- package/src/__tests__/conversation-pairing.test.ts +0 -7
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +0 -9
- package/src/__tests__/conversation-process-callsite.test.ts +15 -97
- package/src/__tests__/conversation-provider-retry-repair.test.ts +3 -84
- package/src/__tests__/conversation-queue.test.ts +12 -108
- package/src/__tests__/conversation-routes-disk-view.test.ts +8 -60
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +5 -63
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +13 -22
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +5 -64
- package/src/__tests__/conversation-routes-slash-commands.test.ts +19 -87
- package/src/__tests__/conversation-runtime-assembly.test.ts +34 -37
- package/src/__tests__/conversation-seed-composer.test.ts +3 -3
- package/src/__tests__/conversation-skill-tools.test.ts +19 -32
- package/src/__tests__/conversation-slash-queue.test.ts +3 -90
- package/src/__tests__/conversation-slash-unknown.test.ts +0 -87
- package/src/__tests__/conversation-speed-override.test.ts +19 -94
- package/src/__tests__/conversation-starter-routes.test.ts +0 -7
- package/src/__tests__/conversation-store.test.ts +72 -66
- package/src/__tests__/conversation-summarize-route.test.ts +0 -11
- package/src/__tests__/conversation-summarize-up-to.test.ts +4 -89
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +131 -0
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +36 -36
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +4 -2
- package/src/__tests__/conversation-title-service.test.ts +0 -7
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +0 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +37 -60
- package/src/__tests__/conversation-tool-setup-tools-disabled.test.ts +17 -17
- package/src/__tests__/conversation-unread-route.test.ts +0 -7
- package/src/__tests__/conversation-usage.test.ts +21 -71
- package/src/__tests__/conversation-wait-for-idle.test.ts +0 -82
- package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -45
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -88
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -88
- package/src/__tests__/conversations-defer-cli.test.ts +3 -0
- package/src/__tests__/conversations-import-system-filter.test.ts +0 -17
- package/src/__tests__/credential-broker-browser-fill.test.ts +0 -9
- package/src/__tests__/credential-broker-server-use.test.ts +0 -9
- package/src/__tests__/credential-health-service.test.ts +14 -31
- package/src/__tests__/credential-metadata-store.test.ts +0 -8
- package/src/__tests__/credential-prompt-route.test.ts +9 -15
- package/src/__tests__/credential-resolve.test.ts +0 -8
- package/src/__tests__/credential-routes.test.ts +250 -0
- package/src/__tests__/credential-security-invariants.test.ts +4 -8
- package/src/__tests__/credential-token-resolver.test.ts +0 -9
- package/src/__tests__/cross-provider-web-search.test.ts +12 -18
- package/src/__tests__/daemon-assistant-events.test.ts +1 -9
- package/src/__tests__/daemon-credential-client.test.ts +0 -7
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +1 -8
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +1 -7
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +0 -8
- package/src/__tests__/db-readiness-http-gate.test.ts +0 -18
- package/src/__tests__/db-rename-inference-profile-snake-case-migration.test.ts +1 -7
- package/src/__tests__/db-test-helpers.ts +10 -3
- package/src/__tests__/delete-managed-skill-tool.test.ts +0 -7
- package/src/__tests__/delete-propagation.test.ts +0 -7
- package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -7
- package/src/__tests__/device-id.test.ts +1 -9
- package/src/__tests__/disk-pressure-guard.test.ts +0 -4
- package/src/__tests__/disk-pressure-routes.test.ts +0 -4
- package/src/__tests__/disk-pressure-tools.test.ts +4 -42
- package/src/__tests__/dm-backfill.test.ts +0 -7
- package/src/__tests__/dm-persistence.test.ts +0 -5
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +1 -8
- package/src/__tests__/drain-requeue-on-contention.test.ts +1 -8
- package/src/__tests__/dynamic-skill-background-guard.test.ts +0 -43
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -27
- package/src/__tests__/edit-propagation.test.ts +1 -8
- package/src/__tests__/email-invite-adapter.test.ts +8 -33
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +0 -8
- package/src/__tests__/emit-event-signal.test.ts +1 -1
- package/src/__tests__/emit-signal-routing-intent.test.ts +0 -7
- package/src/__tests__/empty-state-greeting-cache.test.ts +9 -9
- package/src/__tests__/encrypted-store.test.ts +0 -9
- package/src/__tests__/ensure-conversation-exists.test.ts +1 -18
- package/src/__tests__/events-client-registration.test.ts +1 -19
- package/src/__tests__/events-dev-bypass-actor.test.ts +0 -7
- package/src/__tests__/events-tail-route.test.ts +1 -8
- package/src/__tests__/file-list-tool.test.ts +22 -15
- package/src/__tests__/followup-tools.test.ts +1 -16
- package/src/__tests__/gateway-only-enforcement.test.ts +3 -44
- package/src/__tests__/get-skill-detail-audit.test.ts +0 -7
- package/src/__tests__/google-calendar-watcher.test.ts +175 -0
- package/src/__tests__/guardian-action-sweep.test.ts +0 -7
- package/src/__tests__/guardian-binding-drift-heal.test.ts +0 -7
- package/src/__tests__/guardian-card-withdrawal.test.ts +60 -64
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +172 -135
- package/src/__tests__/guardian-dispatch.test.ts +58 -157
- package/src/__tests__/guardian-expiry-notifier.test.ts +56 -48
- package/src/__tests__/guardian-gateway-sim.ts +626 -0
- package/src/__tests__/guardian-outbound-http.test.ts +0 -7
- package/src/__tests__/guardian-routing-invariants.test.ts +229 -220
- package/src/__tests__/guardian-routing-state.test.ts +2 -9
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -17
- package/src/__tests__/guardian-wait-controller.test.ts +44 -43
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +26 -91
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +18 -103
- package/src/__tests__/headless-browser-interactions.test.ts +0 -7
- package/src/__tests__/headless-browser-mode.test.ts +0 -9
- package/src/__tests__/headless-browser-navigate.test.ts +0 -7
- package/src/__tests__/headless-browser-read-tools.test.ts +0 -7
- package/src/__tests__/headless-browser-snapshot.test.ts +0 -7
- package/src/__tests__/heartbeat-disk-pressure.test.ts +9 -38
- package/src/__tests__/heartbeat-service.test.ts +83 -106
- package/src/__tests__/helpers/channel-test-adapter.ts +10 -0
- package/src/__tests__/helpers/gateway-guardian-requests-store-bridge.ts +155 -0
- package/src/__tests__/helpers/set-config.ts +40 -0
- package/src/__tests__/host-bash-proxy.test.ts +18 -34
- package/src/__tests__/host-browser-proxy.test.ts +15 -20
- package/src/__tests__/host-shell-tool.test.ts +2 -34
- package/src/__tests__/http-conversation-lineage.test.ts +3 -19
- package/src/__tests__/http-user-message-parity.test.ts +3 -95
- package/src/__tests__/identity-routes.test.ts +1 -9
- package/src/__tests__/image-recovery-hook.test.ts +36 -0
- package/src/__tests__/inbound-admitted-introduction-nudge.test.ts +6 -12
- package/src/__tests__/inbound-invite-redemption.test.ts +0 -7
- package/src/__tests__/inbound-slack-persistence.test.ts +0 -5
- package/src/__tests__/inbound-trust-verdict.test.ts +2 -8
- package/src/__tests__/inference-no-mode-boot-e2e.test.ts +52 -8
- package/src/__tests__/inference-profile-reaper.test.ts +1 -7
- package/src/__tests__/inference-profile-session-handler.test.ts +4 -30
- package/src/__tests__/inference-profile-session-ipc.test.ts +3 -20
- package/src/__tests__/ingress-url-consistency.test.ts +1 -23
- package/src/__tests__/injector-background-turn.test.ts +10 -24
- package/src/__tests__/injector-chain.test.ts +4 -13
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +19 -17
- package/src/__tests__/inline-command-runner.test.ts +0 -34
- package/src/__tests__/inline-skill-load-permissions.test.ts +1 -30
- package/src/__tests__/install-skill-routing.test.ts +7 -6
- package/src/__tests__/integration-status.test.ts +25 -17
- package/src/__tests__/intent-routing.test.ts +1 -50
- package/src/__tests__/internal-telemetry-routes.test.ts +41 -22
- package/src/__tests__/interrupted-turn-reconciler.test.ts +1 -8
- package/src/__tests__/introduction-card-resolver.test.ts +108 -117
- package/src/__tests__/invite-redeemed-ipc.test.ts +0 -7
- package/src/__tests__/invite-routes-http.test.ts +12 -23
- package/src/__tests__/jobs-store-has-pending-job.test.ts +59 -0
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +1 -14
- package/src/__tests__/jobs-store-skill-card-upsert.test.ts +191 -0
- package/src/__tests__/jobs-store-upsert-debounced.test.ts +1 -14
- package/src/__tests__/lexical-index-dual-write.test.ts +0 -6
- package/src/__tests__/list-all-apps.test.ts +200 -0
- package/src/__tests__/list-messages-attachments.test.ts +11 -20
- package/src/__tests__/list-messages-background-tool-completion.test.ts +6 -18
- package/src/__tests__/list-messages-client-message-id.test.ts +4 -16
- package/src/__tests__/list-messages-hidden-metadata.test.ts +6 -18
- package/src/__tests__/list-messages-page-latest.test.ts +3 -19
- package/src/__tests__/list-messages-queued.test.ts +1 -18
- package/src/__tests__/list-messages-tool-merge.test.ts +7 -18
- package/src/__tests__/llm-context-resolution.test.ts +32 -56
- package/src/__tests__/llm-context-route-provider.test.ts +1 -8
- package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +1 -19
- package/src/__tests__/llm-request-log-call-site.test.ts +1 -19
- package/src/__tests__/llm-request-log-clickhouse-routing.test.ts +114 -0
- package/src/__tests__/llm-request-log-clickhouse-writer-guards.test.ts +108 -0
- package/src/__tests__/llm-request-log-disabled-writes.test.ts +11 -30
- package/src/__tests__/llm-request-log-sink-clickhouse.test.ts +205 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +1 -22
- package/src/__tests__/llm-request-log-source-factory.test.ts +23 -69
- package/src/__tests__/llm-request-log-turn-query.test.ts +1 -19
- package/src/__tests__/llm-resolver-override-or-default.test.ts +3 -52
- package/src/__tests__/llm-resolver.test.ts +342 -602
- package/src/__tests__/llm-schema.test.ts +79 -37
- package/src/__tests__/llm-usage-store.test.ts +1 -7
- package/src/__tests__/log-export-routes.test.ts +0 -7
- package/src/__tests__/log-export-workspace.test.ts +0 -7
- package/src/__tests__/managed-profile-guard.test.ts +125 -137
- package/src/__tests__/managed-skill-lifecycle.test.ts +6 -50
- package/src/__tests__/managed-speech-defaults.test.ts +138 -0
- package/src/__tests__/managed-store.test.ts +1 -16
- package/src/__tests__/mcp-auth-routes.test.ts +15 -26
- package/src/__tests__/mcp-config-secret-boundary.test.ts +49 -91
- package/src/__tests__/mcp-health-check.test.ts +14 -20
- package/src/__tests__/media-generate-image.test.ts +25 -32
- package/src/__tests__/media-stream-output.test.ts +0 -9
- package/src/__tests__/media-stream-server-integration.test.ts +19 -27
- package/src/__tests__/media-stream-stt-session.test.ts +16 -29
- package/src/__tests__/memory-jobs-worker-backoff.test.ts +6 -19
- package/src/__tests__/memory-jobs-worker-cleanup-cadence.test.ts +33 -12
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +10 -29
- package/src/__tests__/memory-recall-log-store.test.ts +1 -19
- package/src/__tests__/memory-retrieval-hook.test.ts +0 -3
- package/src/__tests__/memory-upsert-concurrency.test.ts +12 -35
- package/src/__tests__/memory-v2-static-injector.test.ts +5 -17
- package/src/__tests__/messages-after-tiebreaker.test.ts +1 -7
- package/src/__tests__/messaging-send-tool.test.ts +67 -7
- package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -18
- package/src/__tests__/migration-export-http.test.ts +10 -23
- package/src/__tests__/migration-export-streaming.test.ts +0 -18
- package/src/__tests__/migration-export-to-gcs.test.ts +0 -19
- package/src/__tests__/migration-import-commit-http.test.ts +11 -23
- package/src/__tests__/migration-import-from-gcs.test.ts +0 -19
- package/src/__tests__/migration-import-from-url.test.ts +0 -19
- package/src/__tests__/migration-import-preflight-http.test.ts +10 -22
- package/src/__tests__/migration-jobs-status.test.ts +8 -23
- package/src/__tests__/migration-validate-http.test.ts +2 -19
- package/src/__tests__/mtime-cache.test.ts +116 -2
- package/src/__tests__/native-web-search.test.ts +0 -21
- package/src/__tests__/non-member-access-request.test.ts +102 -93
- package/src/__tests__/notification-broadcaster.test.ts +32 -21
- package/src/__tests__/notification-candidate-guardian-context.test.ts +36 -34
- package/src/__tests__/notification-decision-fallback.test.ts +0 -7
- package/src/__tests__/notification-decision-identity.test.ts +0 -7
- package/src/__tests__/notification-decision-recipient-context.test.ts +0 -7
- package/src/__tests__/notification-deep-link.test.ts +0 -7
- package/src/__tests__/notification-guardian-path.test.ts +48 -93
- package/src/__tests__/notification-platform-adapter.test.ts +0 -7
- package/src/__tests__/notification-routing-intent.test.ts +1 -9
- package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -9
- package/src/__tests__/notification-telegram-adapter.test.ts +0 -7
- package/src/__tests__/oauth-cli.test.ts +0 -19
- package/src/__tests__/oauth-commands-routes.test.ts +28 -43
- package/src/__tests__/oauth-connect-orchestrator.test.ts +17 -26
- package/src/__tests__/oauth-connect-routes.test.ts +19 -18
- package/src/__tests__/oauth-provider-profiles.test.ts +3 -9
- package/src/__tests__/oauth-provider-visibility.test.ts +0 -7
- package/src/__tests__/oauth-store.test.ts +0 -7
- package/src/__tests__/oauth2-gateway-transport.test.ts +41 -43
- package/src/__tests__/openai-responses-prompt-cache.test.ts +355 -0
- package/src/__tests__/openai-responses-provider.test.ts +98 -9
- package/src/__tests__/openrouter-responses-transport.test.ts +170 -0
- package/src/__tests__/outbound-slack-persistence.test.ts +13 -46
- package/src/__tests__/outlook-email-watcher.test.ts +0 -9
- package/src/__tests__/outlook-messaging-provider.test.ts +71 -0
- package/src/__tests__/path-policy.test.ts +0 -7
- package/src/__tests__/persist-media-references.test.ts +1 -6
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +6 -3
- package/src/__tests__/persist-unsendable-image.test.ts +39 -7
- package/src/__tests__/persistence-secret-redaction.test.ts +7 -28
- package/src/__tests__/platform-bash-auto-approve.test.ts +0 -46
- package/src/__tests__/platform-callback-registration.test.ts +10 -9
- package/src/__tests__/platform-proxy-context.test.ts +0 -8
- package/src/__tests__/playbook-execution.test.ts +0 -14
- package/src/__tests__/playbook-tools.test.ts +0 -14
- package/src/__tests__/plugin-api-model-profiles.test.ts +12 -35
- package/src/__tests__/plugin-app-serve-routes.test.ts +315 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +5 -3
- package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +0 -2
- package/src/__tests__/plugin-types.test.ts +0 -7
- package/src/__tests__/prechat-onboarding-contract.test.ts +0 -27
- package/src/__tests__/pricing.test.ts +45 -0
- package/src/__tests__/process-message-background-slack.test.ts +7 -21
- package/src/__tests__/process-message-display-content.test.ts +37 -6
- package/src/__tests__/processing-flag-persist-failure.test.ts +0 -44
- package/src/__tests__/provider-commit-message-generator.test.ts +57 -63
- package/src/__tests__/provider-error-scenarios.test.ts +5 -6
- package/src/__tests__/provider-platform-proxy-integration.test.ts +21 -57
- package/src/__tests__/provider-registry-ollama.test.ts +8 -18
- package/src/__tests__/provider-send-message-override-profile.test.ts +28 -39
- package/src/__tests__/provider-streaming.benchmark.test.ts +1 -6
- package/src/__tests__/provider-usage-tracking.test.ts +13 -35
- package/src/__tests__/proxy-approval-callback.test.ts +0 -16
- package/src/__tests__/prune-old-conversations-job.test.ts +29 -21
- package/src/__tests__/prune-old-tool-invocations-job.test.ts +1 -9
- package/src/__tests__/public-ingress-urls.test.ts +1 -24
- package/src/__tests__/published-app-updater.test.ts +22 -16
- package/src/__tests__/qdrant-collection-migration.test.ts +0 -7
- package/src/__tests__/qdrant-manager.test.ts +0 -8
- package/src/__tests__/ratelimit.test.ts +1 -8
- package/src/__tests__/reaction-persistence.test.ts +18 -24
- package/src/__tests__/rebuild-index-graph-nodes.test.ts +0 -14
- package/src/__tests__/recording-handler.test.ts +0 -27
- package/src/__tests__/request-secret-standalone-channel-gate.test.ts +4 -16
- package/src/__tests__/require-fresh-approval.test.ts +0 -45
- package/src/__tests__/retry-openrouter-only-normalization.test.ts +24 -36
- package/src/__tests__/retry-prompt-cache-key.test.ts +123 -0
- package/src/__tests__/retry-thinking-adaptive-only.test.ts +45 -61
- package/src/__tests__/retry-thinking-tool-choice.test.ts +60 -80
- package/src/__tests__/retry-verbosity-normalization.test.ts +27 -37
- package/src/__tests__/reveal-success-registry.test.ts +123 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +113 -0
- package/src/__tests__/{scheduler-worker-standdown.test.ts → run-due-schedules.test.ts} +5 -77
- package/src/__tests__/runtime-attachment-metadata.test.ts +5 -18
- package/src/__tests__/runtime-events-sse-bilingual.test.ts +1 -19
- package/src/__tests__/runtime-events-sse-parity.test.ts +1 -20
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -19
- package/src/__tests__/runtime-events-sse.test.ts +1 -20
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +306 -5
- package/src/__tests__/schedule-retry.test.ts +22 -23
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +18 -42
- package/src/__tests__/schedule-routes.test.ts +2 -150
- package/src/__tests__/schedule-store.test.ts +0 -8
- package/src/__tests__/schedule-tools.test.ts +1 -16
- package/src/__tests__/scheduler-disk-pressure.test.ts +0 -26
- package/src/__tests__/scheduler-recurrence.test.ts +43 -76
- package/src/__tests__/scheduler-reuse-conversation.test.ts +19 -35
- package/src/__tests__/scheduler-wake.test.ts +8 -24
- package/src/__tests__/scoped-approval-grants.test.ts +1 -9
- package/src/__tests__/scoped-grant-security-matrix.test.ts +1 -9
- package/src/__tests__/search-skills-unified.test.ts +0 -6
- package/src/__tests__/secret-allowlist.test.ts +1 -8
- package/src/__tests__/secret-fixtures.ts +9 -0
- package/src/__tests__/secret-ingress-channel.test.ts +4 -32
- package/src/__tests__/secret-ingress-cli.test.ts +3 -37
- package/src/__tests__/secret-ingress-http.test.ts +15 -78
- package/src/__tests__/secret-ingress.test.ts +14 -31
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +4 -10
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +3 -9
- package/src/__tests__/secret-routes-platform-proxy.test.ts +3 -40
- package/src/__tests__/secure-keys-managed-failover.test.ts +0 -7
- package/src/__tests__/secure-keys.test.ts +0 -9
- package/src/__tests__/send-endpoint-busy.test.ts +47 -91
- package/src/__tests__/sequence-store.test.ts +0 -9
- package/src/__tests__/server-history-render.test.ts +29 -8
- package/src/__tests__/set-permission-mode.test.ts +8 -16
- package/src/__tests__/settings-routes.test.ts +0 -7
- package/src/__tests__/shell-credential-ref.test.ts +0 -18
- package/src/__tests__/shell-observability.test.ts +0 -21
- package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -34
- package/src/__tests__/skill-load-feature-flag.test.ts +0 -27
- package/src/__tests__/skill-load-inline-command.test.ts +0 -25
- package/src/__tests__/skill-load-inline-includes.test.ts +0 -25
- package/src/__tests__/skill-load-plugin-scope.test.ts +0 -24
- package/src/__tests__/skill-projection-feature-flag.test.ts +14 -33
- package/src/__tests__/skill-projection.benchmark.test.ts +14 -19
- package/src/__tests__/skill-script-runner-sandbox.test.ts +1 -39
- package/src/__tests__/skills-file-content-endpoint.test.ts +0 -7
- package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -14
- package/src/__tests__/slack-channel-config.test.ts +24 -79
- package/src/__tests__/slack-inbound-verification.test.ts +5 -13
- package/src/__tests__/{slack-reaction-canonical-approval.test.ts → slack-reaction-guardian-approval.test.ts} +18 -74
- package/src/__tests__/slack-share-routes.test.ts +0 -1
- package/src/__tests__/slim-skill-category.test.ts +0 -14
- package/src/__tests__/stale-approval-dedup.test.ts +0 -7
- package/src/__tests__/subagent-call-site-routing.test.ts +72 -111
- package/src/__tests__/subagent-detail.test.ts +1 -1
- package/src/__tests__/subagent-fork-prompt-role.test.ts +0 -12
- package/src/__tests__/subagent-notify-parent.test.ts +4 -6
- package/src/__tests__/subagent-spawn-and-await.test.ts +0 -18
- package/src/__tests__/subagent-tool-filtering.test.ts +21 -31
- package/src/__tests__/subagent-tool-gate-mode.test.ts +6 -32
- package/src/__tests__/subagent-tools.test.ts +92 -67
- package/src/__tests__/suggestion-routes.test.ts +28 -42
- package/src/__tests__/summarize-boundary.test.ts +2 -1
- package/src/__tests__/system-prompt-ask-mode.test.ts +0 -25
- package/src/__tests__/system-prompt.test.ts +0 -33
- package/src/__tests__/task-memory-cleanup.test.ts +18 -192
- package/src/__tests__/telegram-bot-username-resolution.test.ts +24 -48
- package/src/__tests__/telegram-config.test.ts +0 -8
- package/src/__tests__/telemetry-routes.test.ts +100 -0
- package/src/__tests__/telephony-credential-preflight.test.ts +7 -11
- package/src/__tests__/telephony-tts-guard.test.ts +38 -21
- package/src/__tests__/terminal-tools.test.ts +0 -21
- package/src/__tests__/thread-backfill.test.ts +0 -7
- package/src/__tests__/title-generate-hook.test.ts +11 -10
- package/src/__tests__/token-manager.test.ts +0 -9
- package/src/__tests__/tool-approval-handler.test.ts +0 -8
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +5 -33
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +3 -23
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -48
- package/src/__tests__/tool-executor.test.ts +3 -49
- package/src/__tests__/tool-grant-request-escalation.test.ts +51 -153
- package/src/__tests__/tool-preview-lifecycle.test.ts +2 -29
- package/src/__tests__/tool-profiler.test.ts +72 -1
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +0 -29
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +0 -1
- package/src/__tests__/tool-start-timestamp.test.ts +4 -31
- package/src/__tests__/tools-get-route.test.ts +2 -1
- package/src/__tests__/trust-context-guards.test.ts +19 -7
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +75 -79
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +14 -18
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -7
- package/src/__tests__/trusted-contact-verification.test.ts +1 -9
- package/src/__tests__/turn-boundary-resolution.test.ts +1 -19
- package/src/__tests__/turn-events-store.test.ts +1 -7
- package/src/__tests__/turn-outcome-read.test.ts +1 -7
- package/src/__tests__/twilio-config.test.ts +11 -28
- package/src/__tests__/twilio-provider.test.ts +2 -13
- package/src/__tests__/twilio-routes-twiml.test.ts +1 -8
- package/src/__tests__/twilio-routes.test.ts +52 -103
- package/src/__tests__/twilio-validation.test.ts +5 -22
- package/src/__tests__/ui-file-upload-surface.test.ts +6 -9
- package/src/__tests__/usage-attribution.test.ts +25 -56
- package/src/__tests__/usage-cache-backfill-migration.test.ts +8 -15
- package/src/__tests__/usage-routes.test.ts +1 -8
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +0 -18
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +0 -24
- package/src/__tests__/vercel-config.test.ts +0 -7
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -45
- package/src/__tests__/voice-approval-resolver-relay.test.ts +106 -75
- package/src/__tests__/voice-config-update.test.ts +114 -21
- package/src/__tests__/voice-ingress-preflight.test.ts +16 -15
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -30
- package/src/__tests__/voice-session-bridge-processing-wait.test.ts +1 -17
- package/src/__tests__/voice-session-bridge.test.ts +14 -46
- package/src/__tests__/web-search-backend-failure.test.ts +0 -21
- package/src/__tests__/whatsapp-invite-adapter.test.ts +11 -30
- package/src/__tests__/workspace-git-service.test.ts +801 -2
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +1 -26
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -26
- package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +1 -26
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +1 -9
- package/src/a2a/__tests__/task-store.test.ts +0 -9
- package/src/acp/__tests__/session-manager-persistence.test.ts +1 -8
- package/src/acp/__tests__/session-manager-resume.test.ts +0 -7
- package/src/acp/__tests__/session-manager-startup.test.ts +1 -8
- package/src/agent/image-optimize.ts +80 -0
- package/src/agent/loop.ts +20 -5
- package/src/api/events/open-conversation.test.ts +64 -0
- package/src/api/events/open-conversation.ts +33 -0
- package/src/api/index.ts +6 -0
- package/src/approvals/AGENTS.md +1 -1
- package/src/approvals/guardian-card-withdrawal.ts +26 -19
- package/src/approvals/guardian-decision-primitive.ts +172 -102
- package/src/approvals/guardian-expiry-notifier.ts +20 -19
- package/src/approvals/guardian-request-resolvers.ts +305 -275
- package/src/apps/app-store.ts +320 -15
- package/src/background-wake/background-wake-routes.test.ts +2 -3
- package/src/background-wake/next-wake.test.ts +23 -20
- package/src/background-wake/wake-intent-hooks.test.ts +0 -10
- package/src/bundler/app-bundler.ts +34 -48
- package/src/bundler/app-compiler.ts +39 -4
- package/src/bundler/bundle-scanner.ts +13 -0
- package/src/bundler/manifest.ts +1 -1
- package/src/calls/__tests__/call-setup-router.test.ts +84 -88
- package/src/calls/__tests__/fish-audio-client.test.ts +6 -11
- package/src/calls/__tests__/voice-control-protocol.test.ts +47 -0
- package/src/calls/__tests__/voice-session-bridge.test.ts +151 -16
- package/src/calls/__tests__/voice-triage-escalate.test.ts +128 -0
- package/src/calls/access-request-wait.ts +35 -35
- package/src/calls/call-controller.ts +48 -45
- package/src/calls/call-setup-flow.ts +2 -2
- package/src/calls/call-setup-router.ts +1 -24
- package/src/calls/guardian-dispatch.ts +47 -30
- package/src/calls/guardian-wait-controller.ts +31 -18
- package/src/calls/media-turn-detector.ts +11 -1
- package/src/calls/telephony-credential-preflight.ts +19 -1
- package/src/calls/telephony-tts-capability.ts +18 -1
- package/src/calls/voice-control-protocol.ts +12 -0
- package/src/calls/voice-session-bridge.ts +110 -15
- package/src/calls/voice-triage-escalate.ts +136 -0
- package/src/channels/__tests__/gateway-guardian-requests.test.ts +669 -0
- package/src/channels/gateway-guardian-requests.ts +410 -0
- package/src/channels/types.ts +10 -5
- package/src/cli/AGENTS.md +77 -51
- package/src/cli/__tests__/cli-command-help-coverage.test.ts +29 -0
- package/src/cli/commands/__tests__/conversations-import.test.ts +23 -24
- package/src/cli/commands/__tests__/gateway.test.ts +55 -0
- package/src/cli/commands/__tests__/inference-models.test.ts +3 -0
- package/src/cli/commands/__tests__/inference-profiles.test.ts +3 -0
- package/src/cli/commands/__tests__/inference-providers.test.ts +3 -0
- package/src/cli/commands/__tests__/inference-send.test.ts +0 -10
- package/src/cli/commands/__tests__/inference-session.test.ts +4 -11
- package/src/cli/commands/__tests__/ui.test.ts +2 -2
- package/src/cli/commands/apps.help.ts +46 -0
- package/src/cli/commands/apps.ts +51 -0
- package/src/cli/commands/avatar.help.ts +229 -0
- package/src/cli/commands/avatar.ts +58 -250
- package/src/cli/commands/backup.help.ts +183 -0
- package/src/cli/commands/backup.ts +107 -276
- package/src/cli/commands/bash.help.ts +38 -0
- package/src/cli/commands/bash.ts +51 -75
- package/src/cli/commands/browser.help.ts +193 -0
- package/src/cli/commands/browser.ts +234 -347
- package/src/cli/commands/cache.help.ts +123 -0
- package/src/cli/commands/cache.ts +72 -166
- package/src/cli/commands/changelog.help.ts +59 -0
- package/src/cli/commands/changelog.ts +29 -61
- package/src/cli/commands/channel-verification-sessions.help.ts +178 -0
- package/src/cli/commands/channel-verification-sessions.ts +71 -226
- package/src/cli/commands/channels/index.help.ts +67 -0
- package/src/cli/commands/channels/index.ts +55 -105
- package/src/cli/commands/clients.help.ts +72 -0
- package/src/cli/commands/clients.ts +100 -153
- package/src/cli/commands/completions.help.ts +33 -0
- package/src/cli/commands/completions.ts +43 -66
- package/src/cli/commands/config.help.ts +126 -0
- package/src/cli/commands/config.ts +59 -174
- package/src/cli/commands/contacts.help.ts +327 -0
- package/src/cli/commands/contacts.ts +318 -603
- package/src/cli/commands/conversations-defer.ts +141 -202
- package/src/cli/commands/conversations-import.ts +80 -113
- package/src/cli/commands/conversations.help.ts +364 -0
- package/src/cli/commands/conversations.ts +143 -328
- package/src/cli/commands/credentials.help.ts +290 -0
- package/src/cli/commands/credentials.ts +271 -487
- package/src/cli/commands/db/index.help.ts +27 -0
- package/src/cli/commands/db/index.ts +7 -3
- package/src/cli/commands/db/refresh.ts +131 -0
- package/src/cli/commands/db/repair-step-conversation-backfill.ts +19 -9
- package/src/cli/commands/db/repair.ts +41 -43
- package/src/cli/commands/db/status.ts +79 -83
- package/src/cli/commands/domain.help.ts +34 -0
- package/src/cli/commands/domain.ts +10 -15
- package/src/cli/commands/email.help.ts +176 -0
- package/src/cli/commands/email.ts +323 -412
- package/src/cli/commands/gateway.help.ts +115 -0
- package/src/cli/commands/gateway.ts +105 -123
- package/src/cli/commands/image-generation.help.ts +72 -0
- package/src/cli/commands/image-generation.ts +13 -62
- package/src/cli/commands/inference-callsites.ts +34 -49
- package/src/cli/commands/inference-models.ts +6 -21
- package/src/cli/commands/inference-profiles.ts +95 -156
- package/src/cli/commands/inference-providers-default.ts +27 -42
- package/src/cli/commands/inference-providers.ts +25 -87
- package/src/cli/commands/inference-session.ts +189 -249
- package/src/cli/commands/inference.help.ts +485 -0
- package/src/cli/commands/inference.ts +104 -165
- package/src/cli/commands/keys.help.ts +46 -0
- package/src/cli/commands/keys.ts +37 -71
- package/src/cli/commands/mcp.help.ts +167 -0
- package/src/cli/commands/mcp.ts +123 -267
- package/src/cli/commands/memory/__tests__/memory-items.test.ts +4 -0
- package/src/cli/commands/memory/__tests__/memory-v2.test.ts +4 -0
- package/src/cli/commands/memory/__tests__/memory-v3.test.ts +4 -0
- package/src/cli/commands/memory/__tests__/worker.test.ts +12 -5
- package/src/cli/commands/memory/index.help.ts +814 -0
- package/src/cli/commands/memory/index.ts +5 -27
- package/src/cli/commands/memory/items.ts +257 -404
- package/src/cli/commands/memory/memory-retrospective.ts +31 -71
- package/src/cli/commands/memory/memory-v2-compare-render.ts +2 -2
- package/src/cli/commands/memory/memory-v2.ts +435 -646
- package/src/cli/commands/memory/memory-v3.ts +158 -283
- package/src/cli/commands/memory/nodes.ts +154 -249
- package/src/cli/commands/memory/worker.ts +83 -128
- package/src/cli/commands/monitoring.help.ts +57 -0
- package/src/cli/commands/monitoring.ts +17 -41
- package/src/cli/commands/notifications.help.ts +293 -0
- package/src/cli/commands/notifications.ts +420 -657
- package/src/cli/commands/oauth/apps.ts +182 -315
- package/src/cli/commands/oauth/connect.ts +4 -35
- package/src/cli/commands/oauth/disconnect.ts +44 -71
- package/src/cli/commands/oauth/index.help.ts +855 -0
- package/src/cli/commands/oauth/index.ts +5 -31
- package/src/cli/commands/oauth/mode.ts +5 -28
- package/src/cli/commands/oauth/ping.ts +44 -66
- package/src/cli/commands/oauth/providers.ts +413 -772
- package/src/cli/commands/oauth/request.ts +6 -35
- package/src/cli/commands/oauth/shared.ts +1 -1
- package/src/cli/commands/oauth/status.test.ts +6 -6
- package/src/cli/commands/oauth/status.ts +45 -62
- package/src/cli/commands/oauth/token.ts +32 -71
- package/src/cli/commands/pending.help.ts +26 -0
- package/src/cli/commands/pending.ts +77 -78
- package/src/cli/commands/platform/__tests__/connect.test.ts +3 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +4 -4
- package/src/cli/commands/platform/__tests__/status.test.ts +0 -90
- package/src/cli/commands/platform/connect.ts +10 -21
- package/src/cli/commands/platform/disconnect.ts +11 -26
- package/src/cli/commands/platform/index.help.ts +187 -0
- package/src/cli/commands/platform/index.ts +22 -169
- package/src/cli/commands/plugins.help.ts +247 -0
- package/src/cli/commands/plugins.ts +356 -437
- package/src/cli/commands/ps.help.ts +26 -0
- package/src/cli/commands/ps.ts +5 -17
- package/src/cli/commands/routes.help.ts +72 -0
- package/src/cli/commands/routes.ts +78 -125
- package/src/cli/commands/schedules-worker.ts +70 -138
- package/src/cli/commands/schedules.help.ts +514 -0
- package/src/cli/commands/schedules.ts +494 -871
- package/src/cli/commands/sequence.help.ts +183 -0
- package/src/cli/commands/sequence.ts +181 -343
- package/src/cli/commands/skills.help.ts +159 -0
- package/src/cli/commands/skills.ts +230 -368
- package/src/cli/commands/status.help.ts +32 -0
- package/src/cli/commands/status.ts +38 -3
- package/src/cli/commands/stt.help.ts +52 -0
- package/src/cli/commands/stt.ts +9 -47
- package/src/cli/commands/telemetry.help.ts +14 -0
- package/src/cli/commands/telemetry.ts +19 -17
- package/src/cli/commands/tools-run.ts +30 -45
- package/src/cli/commands/tools.help.ts +81 -0
- package/src/cli/commands/tools.ts +43 -83
- package/src/cli/commands/trust.help.ts +43 -0
- package/src/cli/commands/trust.ts +82 -109
- package/src/cli/commands/tts.help.ts +88 -0
- package/src/cli/commands/tts.ts +116 -188
- package/src/cli/commands/ui.help.ts +213 -0
- package/src/cli/commands/ui.ts +363 -380
- package/src/cli/commands/usage.help.ts +147 -0
- package/src/cli/commands/usage.ts +87 -206
- package/src/cli/commands/watchers.help.ts +211 -0
- package/src/cli/commands/watchers.ts +261 -417
- package/src/cli/commands/webhooks.help.ts +95 -0
- package/src/cli/commands/webhooks.ts +44 -115
- package/src/cli/index.help.ts +91 -0
- package/src/cli/lib/__tests__/global-json-option.test.ts +97 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +144 -4
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +96 -132
- package/src/cli/lib/__tests__/plugin-catalog-local.test.ts +65 -0
- package/src/cli/lib/__tests__/plugin-catalog-platform.test.ts +167 -0
- package/src/cli/lib/__tests__/plugin-catalog-resolve.test.ts +197 -0
- package/src/cli/lib/__tests__/plugin-details.test.ts +349 -240
- package/src/cli/lib/__tests__/plugin-fingerprint.test.ts +31 -0
- package/src/cli/lib/__tests__/plugin-icon-file.test.ts +50 -1
- package/src/cli/lib/__tests__/plugin-marketplace.test.ts +94 -0
- package/src/cli/lib/__tests__/plugins-install-offline.test.ts +147 -0
- package/src/cli/lib/__tests__/search-plugins.test.ts +193 -309
- package/src/cli/lib/bundled-marketplace.json +439 -0
- package/src/cli/lib/cli-command-help.ts +83 -10
- package/src/cli/lib/global-json-option.ts +41 -0
- package/src/cli/lib/install-from-github.ts +69 -2
- package/src/cli/lib/plugin-catalog-cache.ts +22 -50
- package/src/cli/lib/plugin-catalog-local.ts +71 -0
- package/src/cli/lib/plugin-catalog-platform.ts +117 -0
- package/src/cli/lib/plugin-catalog-resolve.ts +72 -0
- package/src/cli/lib/plugin-details.ts +100 -34
- package/src/cli/lib/plugin-fingerprint.ts +18 -7
- package/src/cli/lib/plugin-icon-file.ts +38 -26
- package/src/cli/lib/plugin-marketplace.ts +15 -2
- package/src/cli/lib/publish-plugin.ts +3 -3
- package/src/cli/lib/search-plugins.ts +48 -111
- package/src/cli/program.ts +7 -0
- package/src/cli.ts +22 -13
- package/src/config/__tests__/default-profile-catalog.test.ts +8 -12
- package/src/config/__tests__/default-provider.test.ts +0 -21
- package/src/config/__tests__/deployment-context-defaults.test.ts +0 -21
- package/src/config/__tests__/feature-flag-registry-bundled.test.ts +2 -2
- package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +0 -21
- package/src/config/__tests__/loader-last-known-good.test.ts +0 -21
- package/src/config/__tests__/loader-sparse-array-cleanup.test.ts +0 -21
- package/src/config/__tests__/platform-rehydration.test.ts +125 -0
- package/src/config/__tests__/profile-materialization.test.ts +1 -88
- package/src/config/__tests__/seed-default-provider.test.ts +0 -21
- package/src/config/__tests__/sync-gated-profiles.test.ts +0 -21
- package/src/config/bundled-skills/app-builder/SKILL.md +24 -1
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +30 -0
- package/src/config/bundled-skills/contacts/SKILL.md +1 -1
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +4 -2
- package/src/config/bundled-skills/messaging/TOOLS.json +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +28 -20
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +7 -7
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
- package/src/config/bundled-skills/schedule/SKILL.md +0 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/TOOLS.json +5 -3
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +84 -10
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +0 -7
- package/src/config/call-site-defaults.ts +3 -3
- package/src/config/feature-flag-registry.json +15 -63
- package/src/config/llm-resolver.ts +88 -475
- package/src/config/managed-speech-defaults.ts +115 -0
- package/src/config/platform-rehydration.ts +76 -0
- package/src/config/profile-materialization.ts +11 -11
- package/src/config/schema.ts +93 -129
- package/src/config/schemas/__tests__/live-voice.test.ts +24 -6
- package/src/config/schemas/__tests__/stt.test.ts +37 -0
- package/src/config/schemas/live-voice.ts +10 -4
- package/src/config/schemas/llm.ts +51 -15
- package/src/config/schemas/memory-lifecycle.ts +1 -13
- package/src/config/schemas/memory-retrospective.ts +8 -0
- package/src/config/schemas/memory.ts +0 -4
- package/src/config/schemas/stt.ts +33 -6
- package/src/config/schemas/tts.ts +53 -6
- package/src/config/schemas/workspace-git.ts +8 -0
- package/src/contacts/contact-store.ts +3 -58
- package/src/contacts/types.ts +1 -1
- package/src/conversations/__tests__/message-consolidation.test.ts +6 -5
- package/src/conversations/message-consolidation.ts +34 -112
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +64 -7
- package/src/daemon/__tests__/conversation-tool-setup-plugin-scope.test.ts +3 -7
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +8 -6
- package/src/daemon/__tests__/embedding-reconcile.test.ts +0 -11
- package/src/daemon/__tests__/inference-profile-notification.test.ts +5 -11
- package/src/daemon/__tests__/inflight-message-content.test.ts +219 -0
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +5 -27
- package/src/daemon/__tests__/route-conversation-post.test.ts +158 -0
- package/src/daemon/__tests__/wake-conversation-ops-completion.test.ts +0 -6
- package/src/daemon/__tests__/web-search-status-text.test.ts +0 -29
- package/src/daemon/app-source-watcher.ts +17 -23
- package/src/daemon/chat-credential-redaction.ts +1365 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +742 -77
- package/src/daemon/conversation-agent-loop.ts +10 -17
- package/src/daemon/conversation-error.ts +53 -16
- package/src/daemon/conversation-history.ts +6 -12
- package/src/daemon/conversation-messaging.ts +13 -1
- package/src/daemon/conversation-process.ts +16 -11
- package/src/daemon/conversation-runtime-assembly.ts +148 -52
- package/src/daemon/conversation-surfaces.ts +217 -100
- package/src/daemon/conversation-tool-setup.ts +59 -112
- package/src/daemon/conversation-turn-finalize.ts +18 -0
- package/src/daemon/conversation.ts +35 -66
- package/src/daemon/event-loop-watchdog.test.ts +1 -6
- package/src/daemon/external-plugins-bootstrap.ts +20 -74
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +0 -7
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +1 -8
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +1 -8
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +1 -8
- package/src/daemon/handlers/__tests__/config-a2a.test.ts +1 -8
- package/src/daemon/handlers/conversation-history.ts +6 -4
- package/src/daemon/handlers/conversations.ts +19 -9
- package/src/daemon/handlers/shared.ts +24 -1
- package/src/daemon/inflight-message-content.ts +228 -0
- package/src/daemon/lifecycle.ts +21 -31
- package/src/daemon/message-protocol.ts +2 -7
- package/src/daemon/message-provenance.ts +17 -8
- package/src/daemon/message-types/conversations.ts +6 -17
- package/src/daemon/message-types/host-ui-snapshot.ts +44 -0
- package/src/daemon/message-types/inbox.ts +3 -46
- package/src/daemon/orphan-reaper.test.ts +1 -6
- package/src/daemon/process-message.ts +9 -0
- package/src/daemon/providers-setup.ts +5 -75
- package/src/daemon/route-conversation-post.ts +158 -0
- package/src/daemon/shutdown-handlers.ts +11 -17
- package/src/daemon/sqlite-corruption-watchdog.test.ts +0 -6
- package/src/documents/document-comments-store.test.ts +1 -7
- package/src/export/__tests__/transcript-formatter.test.ts +8 -8
- package/src/export/formatter.ts +8 -17
- package/src/export/transcript-formatter.ts +4 -1
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +0 -9
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +29 -57
- package/src/home/__tests__/home-content-refresh.test.ts +0 -7
- package/src/home/__tests__/suggested-prompts.test.ts +0 -11
- package/src/ipc/__tests__/contacts-info-ipc.test.ts +12 -10
- package/src/ipc/__tests__/email-ipc.test.ts +90 -0
- package/src/ipc/assistant-server.ts +10 -22
- package/src/ipc/routes/__tests__/guardian-label-ipc-routes.test.ts +74 -0
- package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +0 -7
- package/src/ipc/routes/guardian-label-ipc-routes.ts +42 -0
- package/src/live-voice/__tests__/live-voice-archive.test.ts +1 -8
- package/src/live-voice/__tests__/live-voice-credential-preflight.test.ts +89 -49
- package/src/live-voice/__tests__/live-voice-integration.test.ts +116 -2
- package/src/live-voice/__tests__/live-voice-resume-registry.test.ts +58 -0
- package/src/live-voice/__tests__/live-voice-resume-turn.test.ts +280 -0
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +337 -0
- package/src/live-voice/__tests__/live-voice-tts.test.ts +0 -4
- package/src/live-voice/__tests__/live-voice-vad.test.ts +432 -12
- package/src/live-voice/__tests__/protocol.test.ts +122 -0
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -41
- package/src/live-voice/live-voice-credential-preflight.ts +27 -3
- package/src/live-voice/live-voice-resume-registry.ts +54 -0
- package/src/live-voice/live-voice-session.ts +602 -61
- package/src/live-voice/protocol.ts +143 -1
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +3 -7
- package/src/messaging/provider-types.ts +9 -0
- package/src/messaging/providers/a2a/__tests__/deliver.test.ts +0 -9
- package/src/messaging/providers/outlook/adapter.ts +17 -2
- package/src/messaging/providers/outlook/client.ts +11 -2
- package/src/messaging/providers/outlook/types.ts +9 -0
- package/src/messaging/providers/slack/__tests__/download.test.ts +1 -8
- package/src/messaging/providers/slack/binding-metadata.test.ts +23 -21
- package/src/messaging/providers/slack/send.test.ts +0 -7
- package/src/messaging/providers/slack/withdraw.test.ts +0 -6
- package/src/messaging/providers/telegram-bot/send.test.ts +0 -7
- package/src/monitoring/__tests__/plugin-source-watch.test.ts +40 -1
- package/src/monitoring/plugin-source-watch.ts +56 -62
- package/src/monitoring/recovery/__tests__/inflight-content.test.ts +166 -0
- package/src/monitoring/recovery/inflight-content.ts +260 -0
- package/src/monitoring/recovery/run-recovery.ts +72 -0
- package/src/monitoring/worker.ts +68 -7
- package/src/notifications/AGENTS.md +1 -1
- package/src/notifications/README.md +4 -4
- package/src/notifications/__tests__/broadcaster.test.ts +4 -17
- package/src/notifications/__tests__/connected-channels.test.ts +11 -8
- package/src/notifications/__tests__/decision-engine.test.ts +0 -7
- package/src/notifications/__tests__/destination-resolver.test.ts +18 -12
- package/src/notifications/__tests__/deterministic-checks.test.ts +1 -9
- package/src/notifications/adapters/macos.ts +3 -5
- package/src/notifications/adapters/platform.ts +1 -1
- package/src/notifications/broadcaster.ts +13 -4
- package/src/notifications/conversation-candidates.ts +21 -28
- package/src/notifications/copy-composer.ts +0 -6
- package/src/notifications/decision-engine.ts +1 -1
- package/src/notifications/{canonical-delivery-recorder.ts → guardian-delivery-recorder.ts} +47 -33
- package/src/notifications/home-feed-side-effect.ts +0 -2
- package/src/notifications/signal.ts +0 -4
- package/src/oauth/byo-connection.test.ts +0 -9
- package/src/oauth/connection-resolver.test.ts +18 -46
- package/src/oauth/seed-providers.ts +6 -0
- package/src/onboarding/__tests__/onboarding-events-store.test.ts +122 -44
- package/src/onboarding/onboarding-events-store.ts +67 -115
- package/src/onboarding/onboarding-research-events-store.test.ts +222 -0
- package/src/onboarding/onboarding-research-events-store.ts +92 -0
- package/src/permissions/checker.test.ts +10 -24
- package/src/permissions/confirmation-guardian-request.test.ts +94 -0
- package/src/permissions/{confirmation-canonical-request.ts → confirmation-guardian-request.ts} +44 -29
- package/src/permissions/gateway-threshold-reader.test.ts +0 -8
- package/src/permissions/prompter.ts +6 -4
- package/src/permissions/question-prompter.test.ts +7 -14
- package/src/persistence/__tests__/bulk-write-gate.test.ts +1 -7
- package/src/persistence/__tests__/conversation-queries-search.test.ts +0 -7
- package/src/persistence/__tests__/main-db-readonly-probe.ts +80 -0
- package/src/persistence/__tests__/main-db-readonly.test.ts +35 -0
- package/src/persistence/__tests__/message-content-file.test.ts +161 -52
- package/src/persistence/__tests__/raw-query-telemetry.test.ts +74 -0
- package/src/persistence/conversation-crud.ts +175 -45
- package/src/persistence/conversation-disk-view.ts +32 -15
- package/src/persistence/conversation-group-migration.test.ts +1 -8
- package/src/persistence/conversation-title-service.ts +59 -22
- package/src/persistence/db-connection.ts +46 -1
- package/src/persistence/db-singleton.ts +7 -1
- package/src/persistence/embeddings/__tests__/messages-lexical-index.test.ts +3 -7
- package/src/persistence/embeddings/messages-lexical-index.ts +11 -0
- package/src/persistence/job-handlers/__tests__/message-lexical-backfill.test.ts +0 -7
- package/src/persistence/job-handlers/__tests__/message-lexical-enqueue.test.ts +0 -6
- package/src/persistence/job-handlers/__tests__/message-lexical.test.ts +0 -7
- package/src/persistence/job-handlers/cleanup.ts +30 -16
- package/src/persistence/job-handlers/message-lexical-backfill.ts +8 -5
- package/src/persistence/job-handlers/message-lexical.ts +2 -2
- package/src/persistence/jobs-store.ts +123 -17
- package/src/persistence/lifecycle-events-store.test.ts +84 -0
- package/src/persistence/lifecycle-events-store.ts +27 -52
- package/src/persistence/llm-request-log-sink-clickhouse.ts +325 -0
- package/src/persistence/llm-request-log-store.ts +185 -106
- package/src/persistence/llm-request-log-writer-types.ts +80 -0
- package/src/persistence/llm-usage-store.ts +5 -2
- package/src/persistence/message-content-file.ts +182 -71
- package/src/persistence/message-content.ts +18 -10
- package/src/persistence/migrations/305-drop-contact-acl-columns.ts +3 -2
- package/src/persistence/migrations/325-create-config-setting-events.ts +40 -0
- package/src/persistence/migrations/326-move-injection-events-to-memory-db.ts +104 -0
- package/src/persistence/migrations/327-create-flush-checkpoints.ts +86 -0
- package/src/persistence/migrations/328-drop-memory-v3-learned-edge-tables.ts +16 -0
- package/src/persistence/migrations/329-move-onboarding-events-to-telemetry-db.test.ts +179 -0
- package/src/persistence/migrations/329-move-onboarding-events-to-telemetry-db.ts +119 -0
- package/src/persistence/migrations/330-move-auth-fallback-events-to-telemetry-db.test.ts +197 -0
- package/src/persistence/migrations/330-move-auth-fallback-events-to-telemetry-db.ts +108 -0
- package/src/persistence/migrations/331-move-lifecycle-events-to-telemetry-db.test.ts +159 -0
- package/src/persistence/migrations/331-move-lifecycle-events-to-telemetry-db.ts +97 -0
- package/src/persistence/migrations/332-move-skill-loaded-events-to-telemetry-db.test.ts +219 -0
- package/src/persistence/migrations/332-move-skill-loaded-events-to-telemetry-db.ts +128 -0
- package/src/persistence/migrations/333-create-telemetry-events-table.test.ts +66 -0
- package/src/persistence/migrations/333-create-telemetry-events-table.ts +43 -0
- package/src/persistence/migrations/334-backfill-telemetry-events-outbox.test.ts +584 -0
- package/src/persistence/migrations/334-backfill-telemetry-events-outbox.ts +386 -0
- package/src/persistence/migrations/335-collapse-memory-embed-backlog.test.ts +181 -0
- package/src/persistence/migrations/335-collapse-memory-embed-backlog.ts +177 -0
- package/src/persistence/migrations/__tests__/327-create-flush-checkpoints.test.ts +124 -0
- package/src/persistence/raw-query.ts +27 -1
- package/src/persistence/schema/calls.ts +0 -23
- package/src/persistence/schema/conversation-starters.ts +31 -0
- package/src/persistence/schema/conversations.ts +3 -3
- package/src/persistence/schema/guardian.ts +0 -150
- package/src/persistence/schema/index.ts +1 -0
- package/src/persistence/schema/infrastructure.ts +25 -72
- package/src/persistence/schema/memory-core.ts +0 -25
- package/src/persistence/schema/memory-injection.ts +3 -1
- package/src/persistence/schema/tasks.ts +1 -60
- package/src/persistence/steps.ts +22 -0
- package/src/platform/client.test.ts +110 -0
- package/src/platform/client.ts +24 -4
- package/src/platform/consent-cache.test.ts +5 -18
- package/src/platform/consent-cache.ts +8 -6
- package/src/platform/managed-speech.test.ts +218 -0
- package/src/platform/managed-speech.ts +204 -0
- package/src/plugin-api/conversation-turn.ts +250 -0
- package/src/plugin-api/index.ts +21 -0
- package/src/plugin-api/model-profiles.test.ts +29 -28
- package/src/plugin-api/vision-support.test.ts +25 -38
- package/src/plugin-api/vision-support.ts +26 -17
- package/src/plugins/AGENTS.md +8 -0
- package/src/plugins/__tests__/source-fingerprint.test.ts +41 -0
- package/src/plugins/collect-source-versions.ts +77 -0
- package/src/plugins/defaults/image-recovery/detect.ts +32 -10
- package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +20 -18
- package/src/plugins/defaults/image-recovery/recover.ts +86 -59
- package/src/plugins/defaults/memory/__tests__/activation-session-store.test.ts +1 -8
- package/src/plugins/defaults/memory/__tests__/clear-stale-processing-flags.test.ts +1 -8
- package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +1 -8
- package/src/plugins/defaults/memory/__tests__/conversation-row-batch-delete.test.ts +7 -18
- package/src/plugins/defaults/memory/__tests__/db-memory-attach.test.ts +22 -18
- package/src/plugins/defaults/memory/__tests__/embedding-cache.test.ts +0 -6
- package/src/plugins/defaults/memory/__tests__/find-most-recent-retrospective-for.test.ts +1 -8
- package/src/plugins/defaults/memory/__tests__/fork-message-copy.test.ts +7 -18
- package/src/plugins/defaults/memory/__tests__/jobs-store-enqueue-gate.test.ts +29 -39
- package/src/plugins/defaults/memory/__tests__/jobs-worker-memory-disabled.test.ts +11 -26
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +3 -22
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +215 -1
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +0 -7
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +114 -16
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +180 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-skill-card.test.ts +153 -519
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +0 -7
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +6 -17
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +0 -7
- package/src/plugins/defaults/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -19
- package/src/plugins/defaults/memory/__tests__/memory-v2-concept-frequency.test.ts +0 -18
- package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +8 -7
- package/src/plugins/defaults/memory/__tests__/table-relocation.test.ts +49 -0
- package/src/{persistence → plugins/defaults/memory}/__tests__/worker-control.test.ts +8 -10
- package/src/plugins/defaults/memory/graph/capability-seed.ts +4 -6
- package/src/plugins/defaults/memory/graph/extraction.ts +5 -1
- package/src/plugins/defaults/memory/graph/graph-search.test.ts +2 -8
- package/src/plugins/defaults/memory/graph/tool-handlers.test.ts +0 -6
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +2 -2
- package/src/plugins/defaults/memory/graph/tools.ts +47 -13
- package/src/plugins/defaults/memory/graph-topology/__tests__/build-memory-graph.test.ts +81 -2
- package/src/plugins/defaults/memory/graph-topology/build-memory-graph.ts +67 -32
- package/src/plugins/defaults/memory/hooks/shutdown.ts +8 -11
- package/src/plugins/defaults/memory/indexer.ts +2 -1
- package/src/plugins/defaults/memory/job-handlers/backfill.ts +8 -5
- package/src/plugins/defaults/memory/job-handlers/embedding.test.ts +0 -7
- package/src/plugins/defaults/memory/job-handlers/embedding.ts +2 -2
- package/src/plugins/defaults/memory/job-handlers/index-maintenance.ts +7 -2
- package/src/plugins/defaults/memory/jobs/__tests__/embed-concept-page.test.ts +73 -8
- package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +5 -3
- package/src/plugins/defaults/memory/jobs/embed-pkb-file.test.ts +0 -13
- package/src/plugins/defaults/memory/jobs-worker.ts +139 -107
- package/src/plugins/defaults/memory/memory-db.ts +27 -0
- package/src/plugins/defaults/memory/memory-retrospective-constants.ts +4 -4
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +56 -180
- package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +216 -0
- package/src/plugins/defaults/memory/memory-retrospective-skill-card.ts +122 -202
- package/src/plugins/defaults/memory/message-media.ts +2 -2
- package/src/plugins/defaults/memory/paths.ts +3 -2
- package/src/plugins/defaults/memory/pkb/pkb-index.test.ts +0 -12
- package/src/plugins/defaults/memory/pkb/pkb-reconcile.test.ts +0 -9
- package/src/plugins/defaults/memory/pkb/pkb-search.test.ts +0 -6
- package/src/plugins/defaults/memory/routes/__tests__/memory-v2-simulate-route.test.ts +15 -92
- package/src/plugins/defaults/memory/routes/__tests__/memory-worker-routes.test.ts +201 -0
- package/src/plugins/defaults/memory/routes/memory-item-routes.test.ts +7 -21
- package/src/plugins/defaults/memory/routes/memory-v2-routes.ts +3 -8
- package/src/plugins/defaults/memory/routes/memory-worker-routes.ts +162 -0
- package/src/plugins/defaults/memory/startup.ts +6 -7
- package/src/plugins/defaults/memory/task-memory-cleanup.ts +11 -22
- package/src/plugins/defaults/memory/tools.test.ts +40 -8
- package/src/plugins/defaults/memory/tools.ts +12 -2
- package/src/plugins/defaults/memory/v2/__tests__/activation.test.ts +0 -19
- package/src/plugins/defaults/memory/v2/__tests__/backfill-jobs.test.ts +63 -40
- package/src/plugins/defaults/memory/v2/__tests__/cli-command-store.test.ts +61 -130
- package/src/plugins/defaults/memory/v2/__tests__/consolidation-job.test.ts +406 -10
- package/src/plugins/defaults/memory/v2/__tests__/harness-compare.test.ts +1 -10
- package/src/plugins/defaults/memory/v2/__tests__/harness-oracle.test.ts +1 -10
- package/src/plugins/defaults/memory/v2/__tests__/harness-replay-input.test.ts +1 -10
- package/src/plugins/defaults/memory/v2/__tests__/injection-events.test.ts +61 -69
- package/src/plugins/defaults/memory/v2/__tests__/injection.test.ts +0 -19
- package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +11 -10
- package/src/plugins/defaults/memory/v2/__tests__/page-index.test.ts +0 -5
- package/src/plugins/defaults/memory/v2/__tests__/qdrant.test.ts +6 -22
- package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +3 -5
- package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +7 -20
- package/src/plugins/defaults/memory/v2/__tests__/sim.test.ts +0 -24
- package/src/plugins/defaults/memory/v2/__tests__/skill-content.test.ts +17 -11
- package/src/plugins/defaults/memory/v2/__tests__/skill-store.test.ts +0 -16
- package/src/plugins/defaults/memory/v2/__tests__/static-context.test.ts +0 -10
- package/src/plugins/defaults/memory/v2/__tests__/sweep-job.test.ts +0 -6
- package/src/plugins/defaults/memory/v2/backfill-jobs.ts +5 -2
- package/src/plugins/defaults/memory/v2/cli-command-content.ts +43 -12
- package/src/plugins/defaults/memory/v2/cli-command-store.ts +34 -50
- package/src/plugins/defaults/memory/v2/consolidation-job.ts +216 -10
- package/src/plugins/defaults/memory/v2/harness/router-retriever.ts +1 -8
- package/src/plugins/defaults/memory/v2/injection-events.ts +16 -14
- package/src/plugins/defaults/memory/v2/injection.ts +1 -2
- package/src/plugins/defaults/memory/v2/memory-v2-startup.test.ts +0 -5
- package/src/plugins/defaults/memory/v2/migration.ts +55 -24
- package/src/plugins/defaults/memory/v2/prompts/consolidation.ts +4 -0
- package/src/plugins/defaults/memory/v2/router.ts +4 -14
- package/src/plugins/defaults/memory/v2/sweep-job.ts +1 -0
- package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +10 -22
- package/src/plugins/defaults/memory/v3/__tests__/dense.test.ts +0 -5
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +18 -20
- package/src/plugins/defaults/memory/v3/__tests__/section-dense-store.test.ts +0 -5
- package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +5 -9
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +51 -31
- package/src/plugins/defaults/memory/v3/prune.test.ts +3 -11
- package/src/{persistence → plugins/defaults/memory}/worker-control.ts +12 -21
- package/src/plugins/defaults/memory/worker.ts +19 -2
- package/src/plugins/mtime-cache.ts +166 -70
- package/src/plugins/plugin-tree-walk.ts +41 -4
- package/src/plugins/source-fingerprint.ts +9 -3
- package/src/plugins/surface-import.ts +28 -0
- package/src/plugins/types.ts +9 -23
- package/src/prompts/__tests__/system-prompt.test.ts +0 -28
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +0 -28
- package/src/providers/__tests__/connection-model-compat.test.ts +6 -19
- package/src/providers/__tests__/count-tokens-forwarding.test.ts +1 -21
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +9 -26
- package/src/providers/__tests__/registry-native-web-search.test.ts +4 -10
- package/src/providers/__tests__/retry-callsite.test.ts +240 -235
- package/src/providers/__tests__/satellite-connection-routing.test.ts +11 -36
- package/src/providers/__tests__/vellum-mismatch-routing.test.ts +0 -5
- package/src/providers/anthropic/client.ts +9 -3
- package/src/providers/call-site-routing.ts +7 -3
- package/src/providers/connection-resolution.ts +9 -11
- package/src/providers/content-block-schema.ts +149 -0
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +7 -11
- package/src/providers/inference/__tests__/codex-token-refresh.test.ts +1 -15
- package/src/providers/inference/auth.ts +23 -0
- package/src/providers/inference/backfill.ts +25 -9
- package/src/providers/model-catalog.ts +213 -5
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +54 -0
- package/src/providers/openai/chat-completions-provider.ts +13 -2
- package/src/providers/openai/responses-provider.ts +232 -5
- package/src/providers/openrouter/client.ts +53 -0
- package/src/providers/retry.ts +25 -2
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +13 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +211 -74
- package/src/providers/speech-to-text/__tests__/vellum-managed-realtime.test.ts +408 -0
- package/src/providers/speech-to-text/__tests__/vellum-managed.test.ts +121 -0
- package/src/providers/speech-to-text/__tests__/vellum-speech-relay-connection.test.ts +126 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +167 -37
- package/src/providers/speech-to-text/incremental-batch-stream.ts +413 -0
- package/src/providers/speech-to-text/openai-whisper-stream.ts +16 -363
- package/src/providers/speech-to-text/provider-catalog.ts +26 -1
- package/src/providers/speech-to-text/resolve.ts +74 -13
- package/src/providers/speech-to-text/vellum-managed-realtime.ts +309 -0
- package/src/providers/speech-to-text/vellum-managed.ts +71 -0
- package/src/providers/speech-to-text/vellum-speech-relay-connection.ts +174 -0
- package/src/providers/types.ts +23 -4
- package/src/providers/vellum-model-routing.test.ts +26 -0
- package/src/providers/vellum-model-routing.ts +30 -0
- package/src/runtime/AGENTS.md +1 -1
- package/src/runtime/__tests__/actor-trust-resolver.test.ts +2 -8
- package/src/runtime/__tests__/agent-wake.test.ts +100 -27
- package/src/runtime/__tests__/background-job-runner.test.ts +22 -0
- package/src/runtime/__tests__/guardian-vellum-migration.test.ts +0 -5
- package/src/runtime/__tests__/member-verdict-cache.test.ts +2 -9
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +22 -5
- package/src/runtime/access-request-helper.ts +84 -60
- package/src/runtime/actor-trust-resolver.ts +2 -2
- package/src/runtime/agent-wake.ts +75 -26
- package/src/runtime/assistant-event-hub.ts +1 -0
- package/src/runtime/auth/__tests__/middleware.test.ts +1 -10
- package/src/runtime/auth/__tests__/route-policy.test.ts +0 -7
- package/src/runtime/auth/__tests__/token-service.test.ts +1 -8
- package/src/runtime/auth/same-actor.ts +2 -1
- package/src/runtime/background-job-runner.ts +22 -0
- package/src/runtime/channel-approval-types.ts +1 -1
- package/src/runtime/channel-reply-delivery.ts +38 -19
- package/src/runtime/confirmation-request-guardian-bridge.ts +45 -39
- package/src/runtime/for-chat-mint-registry.ts +118 -0
- package/src/runtime/guardian-action-service.ts +32 -27
- package/src/runtime/guardian-decision-types.ts +2 -2
- package/src/runtime/guardian-reply-router.ts +80 -98
- package/src/runtime/http-server.ts +61 -41
- package/src/runtime/introduction-policy.ts +2 -2
- package/src/runtime/local-actor-identity.ts +19 -7
- package/src/runtime/pending-interactions.ts +1 -0
- package/src/runtime/reveal-nonce.ts +49 -0
- package/src/runtime/reveal-success-registry.ts +306 -0
- package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -7
- package/src/runtime/routes/__tests__/backup-routes.test.ts +195 -125
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +4 -1
- package/src/runtime/routes/__tests__/client-routes.test.ts +0 -7
- package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +1 -19
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +1 -8
- package/src/runtime/routes/__tests__/contact-routes-merge-relay.test.ts +186 -0
- package/src/runtime/routes/__tests__/contact-routes-update-channel-relay.test.ts +2 -3
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +0 -7
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +5 -27
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +0 -7
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +12 -30
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +59 -56
- package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +0 -7
- package/src/runtime/routes/__tests__/default-provider-routes.test.ts +53 -73
- package/src/runtime/routes/__tests__/gateway-status-routes.test.ts +84 -0
- package/src/runtime/routes/__tests__/inference-callsites-routes.test.ts +2 -10
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +58 -90
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +161 -93
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +6 -1
- package/src/runtime/routes/__tests__/monitoring-routes.test.ts +0 -8
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +218 -64
- package/src/runtime/routes/__tests__/question-routes.test.ts +2 -4
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +1 -8
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +0 -7
- package/src/runtime/routes/__tests__/schedule-routes-create.test.ts +2 -1
- package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +16 -56
- package/src/runtime/routes/__tests__/stt-routes.test.ts +0 -9
- package/src/runtime/routes/__tests__/suggest-trust-rule-routes.test.ts +0 -7
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -0
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +354 -1
- package/src/runtime/routes/__tests__/tts-routes.test.ts +0 -11
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +163 -10
- package/src/runtime/routes/__tests__/user-routes-cli.test.ts +154 -0
- package/src/runtime/routes/__tests__/wake-conversation-routes.test.ts +0 -7
- package/src/runtime/routes/acp-routes.ts +21 -9
- package/src/runtime/routes/app-management-routes.ts +231 -60
- package/src/runtime/routes/app-routes.ts +130 -83
- package/src/runtime/routes/auth-routes.ts +3 -1
- package/src/runtime/routes/background-wake-routes.ts +0 -1
- package/src/runtime/routes/cache-routes.ts +3 -3
- package/src/runtime/routes/call-routes.ts +5 -1
- package/src/runtime/routes/channel-verification-routes.ts +2 -1
- package/src/runtime/routes/contact-prompt-routes.ts +11 -5
- package/src/runtime/routes/contact-routes.ts +34 -42
- package/src/runtime/routes/conversation-attention-routes.ts +1 -1
- package/src/runtime/routes/conversation-cli-routes.ts +1 -1
- package/src/runtime/routes/conversation-query-routes.ts +4 -4
- package/src/runtime/routes/conversation-routes.ts +111 -72
- package/src/runtime/routes/credential-routes.ts +116 -3
- package/src/runtime/routes/email-routes.ts +17 -1
- package/src/runtime/routes/events-routes.ts +1 -0
- package/src/runtime/routes/gateway-status-routes.ts +69 -0
- package/src/runtime/routes/guardian-action-routes.ts +18 -16
- package/src/runtime/routes/guardian-approval-interception.ts +6 -4
- package/src/runtime/routes/guardian-approval-prompt.ts +7 -5
- package/src/runtime/routes/guardian-expiry-sweep.ts +130 -0
- package/src/runtime/routes/inbound-message-handler.ts +9 -33
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +0 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +9 -9
- package/src/runtime/routes/inbound-stages/admission-policy.test.ts +24 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +0 -7
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.test.ts +0 -5
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +6 -3
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +5 -1
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +0 -9
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +4 -1
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +3 -12
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +16 -14
- package/src/runtime/routes/inbound-stages/reaction-intercept.test.ts +8 -2
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +15 -7
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +0 -9
- package/src/runtime/routes/index.ts +5 -5
- package/src/runtime/routes/inference-provider-connection-routes.ts +73 -24
- package/src/runtime/routes/inference-send-routes.ts +1 -1
- package/src/runtime/routes/internal-telemetry-routes.ts +11 -2
- package/src/runtime/routes/oauth-connect-routes.ts +27 -7
- package/src/runtime/routes/platform-routes.ts +4 -14
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +0 -4
- package/src/runtime/routes/playground/__tests__/guard.test.ts +0 -4
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +0 -14
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +0 -21
- package/src/runtime/routes/playground/__tests__/seed-conversation.test.ts +0 -4
- package/src/runtime/routes/playground/__tests__/seeded-conversations.test.ts +16 -18
- package/src/runtime/routes/playground/__tests__/state.test.ts +0 -14
- package/src/runtime/routes/playground/seed-conversation.ts +5 -4
- package/src/runtime/routes/playground/seeded-conversations.ts +3 -2
- package/src/runtime/routes/plugins-routes.ts +163 -25
- package/src/runtime/routes/profiler-routes.ts +2 -5
- package/src/runtime/routes/publish-routes.ts +15 -18
- package/src/runtime/routes/question-routes.ts +8 -4
- package/src/runtime/routes/schedule-routes.ts +20 -78
- package/src/runtime/routes/schedule-worker-routes.ts +16 -84
- package/src/runtime/routes/secret-routes.ts +14 -0
- package/src/runtime/routes/settings-routes.ts +21 -25
- package/src/runtime/routes/subagents-routes.ts +17 -18
- package/src/runtime/routes/surface-action-routes.ts +18 -39
- package/src/runtime/routes/surface-content-routes.ts +59 -1
- package/src/runtime/routes/surface-conversation-resolver.ts +148 -4
- package/src/runtime/routes/telemetry-routes.ts +74 -1
- package/src/runtime/routes/tts-routes.ts +9 -5
- package/src/runtime/routes/ui-snapshot-routes.test.ts +219 -0
- package/src/runtime/routes/ui-snapshot-routes.ts +313 -0
- package/src/runtime/routes/user-route-dispatcher.ts +52 -53
- package/src/runtime/routes/user-route-resolution.ts +141 -0
- package/src/runtime/routes/user-routes-cli.ts +56 -35
- package/src/runtime/routes/user-routes.ts +9 -2
- package/src/runtime/routes/vellum-actor-trust.ts +67 -0
- package/src/runtime/services/__tests__/auto-analysis-guard.test.ts +1 -8
- package/src/runtime/tool-grant-request-helper.ts +34 -30
- package/src/runtime/trust-verdict-consumer.ts +4 -6
- package/src/schedule/__tests__/worker-control.test.ts +3 -3
- package/src/schedule/schedule-store.ts +0 -41
- package/src/schedule/scheduler.ts +38 -257
- package/src/schedule/worker-control.ts +11 -21
- package/src/schedule/worker.ts +18 -5
- package/src/security/__tests__/oauth2-device-code.test.ts +12 -60
- package/src/security/__tests__/provider-key-env-fallback.test.ts +0 -10
- package/src/security/auth-fallback-events-store.ts +34 -72
- package/src/security/secret-scanner.ts +26 -1
- package/src/sequence/engine.ts +15 -6
- package/src/services/published-app-updater.ts +6 -11
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +24 -4
- package/src/stt/daemon-batch-transcriber.ts +33 -2
- package/src/stt/stt-stream-session.ts +17 -11
- package/src/stt/types.ts +2 -1
- package/src/subagent/manager.ts +4 -3
- package/src/telemetry/AGENTS.md +44 -0
- package/src/telemetry/__tests__/config-setting-events-store.test.ts +63 -0
- package/src/telemetry/__tests__/config-setting-snapshot.test.ts +107 -0
- package/src/telemetry/__tests__/flush-checkpoints.test.ts +56 -0
- package/src/telemetry/__tests__/outbox-test-harness.ts +83 -0
- package/src/telemetry/__tests__/telemetry-event-fixtures.ts +258 -0
- package/src/telemetry/__tests__/watchdog-events-store.test.ts +32 -122
- package/src/telemetry/config-setting-events-store.ts +40 -0
- package/src/telemetry/config-setting-snapshot.ts +135 -0
- package/src/telemetry/flush-checkpoints.ts +70 -0
- package/src/telemetry/skill-loaded-events-store.test.ts +54 -113
- package/src/telemetry/skill-loaded-events-store.ts +21 -77
- package/src/telemetry/telemetry-event-sources.test.ts +211 -0
- package/src/telemetry/telemetry-event-sources.ts +582 -0
- package/src/telemetry/telemetry-events-outbox.test.ts +330 -0
- package/src/telemetry/telemetry-events-outbox.ts +204 -0
- package/src/telemetry/telemetry-main-db.ts +48 -0
- package/src/telemetry/telemetry-wire-source.json +4 -0
- package/src/telemetry/telemetry-wire-validation.test.ts +157 -0
- package/src/telemetry/telemetry-wire-validation.ts +125 -0
- package/src/telemetry/telemetry-wire.generated.ts +433 -0
- package/src/telemetry/tool-executed-events-store.test.ts +0 -8
- package/src/telemetry/tool-executed-events-store.ts +2 -2
- package/src/telemetry/turn-trace-store.test.ts +86 -7
- package/src/telemetry/turn-trace-store.ts +29 -1
- package/src/telemetry/types.test.ts +38 -0
- package/src/telemetry/types.ts +302 -87
- package/src/telemetry/usage-telemetry-reporter.test.ts +921 -364
- package/src/telemetry/usage-telemetry-reporter.ts +235 -722
- package/src/telemetry/watchdog-direct-emit.test.ts +0 -5
- package/src/telemetry/watchdog-direct-emit.ts +7 -1
- package/src/telemetry/watchdog-events-store.ts +11 -70
- package/src/tools/acp/spawn.test.ts +0 -7
- package/src/tools/apps/definitions.ts +1 -7
- package/src/tools/apps/executors.ts +11 -36
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +11 -24
- package/src/tools/browser/__tests__/browser-status.test.ts +47 -33
- package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +1 -11
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +75 -58
- package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +0 -10
- package/src/tools/browser/network-recorder.test.ts +0 -11
- package/src/tools/document/document-comment-tool.test.ts +1 -7
- package/src/tools/host-terminal/host-shell.test.ts +0 -32
- package/src/tools/host-terminal/host-shell.ts +6 -2
- package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +13 -15
- package/src/tools/network/__tests__/web-search-metadata.test.ts +15 -18
- package/src/tools/network/__tests__/web-search.test.ts +39 -50
- package/src/tools/registry.ts +148 -196
- package/src/tools/skills/find-similar-skills.test.ts +0 -7
- package/src/tools/skills/sandbox-runner.ts +5 -2
- package/src/tools/skills/scaffold-managed.ts +105 -12
- package/src/tools/subagent/read.ts +6 -4
- package/src/tools/subagent/spawn.ts +20 -29
- package/src/tools/terminal/safe-env.ts +7 -2
- package/src/tools/terminal/shell.test.ts +4 -8
- package/src/tools/terminal/shell.ts +5 -2
- package/src/tools/tool-approval-handler.ts +39 -23
- package/src/tools/tool-input-summary.ts +2 -1
- package/src/tools/tool-manifest.ts +20 -6
- package/src/tools/tool-profiler.ts +37 -6
- package/src/tools/ui-surface/definitions.ts +1 -7
- package/src/tools/workflows/run-workflow.test.ts +8 -22
- package/src/tts/__tests__/provider-adapters.test.ts +28 -22
- package/src/tts/__tests__/provider-resolution.test.ts +26 -0
- package/src/tts/__tests__/synthesis-stream.test.ts +6 -6
- package/src/tts/__tests__/vellum-provider.test.ts +251 -0
- package/src/tts/provider-catalog.ts +6 -0
- package/src/tts/providers/__tests__/vellum-tts-socket.test.ts +266 -0
- package/src/tts/providers/vellum-provider.ts +220 -0
- package/src/tts/providers/vellum-tts-socket.ts +377 -0
- package/src/tts/synthesize-text.ts +15 -5
- package/src/tts/tts-config-resolver.ts +2 -7
- package/src/tts/types.ts +1 -0
- package/src/usage/attribution.ts +20 -114
- package/src/util/abort-reasons.ts +1 -3
- package/src/util/image-conversion.ts +23 -5
- package/src/util/logger.ts +8 -3
- package/src/{config/bundled-skills/messaging/tools/gmail-mime-helpers.ts → util/mime-type.ts} +4 -1
- package/src/util/platform.ts +0 -60
- package/src/util/pricing.ts +10 -1
- package/src/util/telemetry-db-path.ts +9 -7
- package/src/watcher/__tests__/telemetry.test.ts +41 -11
- package/src/watcher/providers/google-calendar.ts +81 -49
- package/src/watcher/telemetry.ts +22 -5
- package/src/workflows/engine-integration.test.ts +0 -6
- package/src/workflows/engine.test.ts +1 -9
- package/src/workflows/journal-store.test.ts +1 -9
- package/src/workflows/leaf-runner.test.ts +17 -50
- package/src/workflows/library.test.ts +1 -9
- package/src/workflows/run-manager.test.ts +1 -9
- package/src/workspace/git-service.ts +932 -37
- package/src/workspace/provider-commit-message-generator.ts +6 -4
- package/__tests__/permissions/gateway-threshold-reader.test.ts +0 -450
- package/src/__tests__/canonical-guardian-store.test.ts +0 -928
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -140
- package/src/__tests__/plugin-route-contribution.test.ts +0 -245
- package/src/__tests__/skill-runtime-path.test.ts +0 -63
- package/src/__tests__/task-compiler.test.ts +0 -317
- package/src/__tests__/task-management-tools.test.ts +0 -1128
- package/src/__tests__/task-scheduler.test.ts +0 -786
- package/src/config/schemas/schedules.ts +0 -35
- package/src/contacts/canonical-guardian-store.ts +0 -902
- package/src/daemon/message-types/work-items.ts +0 -243
- package/src/runtime/routes/__tests__/memory-worker-routes.test.ts +0 -306
- package/src/runtime/routes/__tests__/task-routes.test.ts +0 -644
- package/src/runtime/routes/assets/vellum-design-system.css +0 -1959
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +0 -129
- package/src/runtime/routes/inbound-stages/escalation-intercept.test.ts +0 -158
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +0 -187
- package/src/runtime/routes/memory-worker-routes.ts +0 -227
- package/src/runtime/routes/task-routes.ts +0 -380
- package/src/runtime/routes/work-items-routes.test.ts +0 -75
- package/src/runtime/routes/work-items-routes.ts +0 -881
- package/src/runtime/skill-route-registry.ts +0 -131
- package/src/tasks/SPEC.md +0 -132
- package/src/tasks/task-compiler.ts +0 -194
- package/src/tasks/task-runner.ts +0 -119
- package/src/tasks/task-scheduler.ts +0 -22
- package/src/tasks/task-store.ts +0 -153
- package/src/tasks/tool-sanitizer.ts +0 -38
- package/src/tools/apps/registry.ts +0 -16
- package/src/tools/system/register.ts +0 -9
- package/src/tools/tasks/task-delete.ts +0 -121
- package/src/tools/tasks/task-list.ts +0 -56
- package/src/tools/tasks/task-run.ts +0 -122
- package/src/tools/tasks/task-save.ts +0 -64
- package/src/tools/tasks/work-item-enqueue.ts +0 -300
- package/src/tools/tasks/work-item-list.ts +0 -65
- package/src/tools/tasks/work-item-remove.ts +0 -94
- package/src/tools/tasks/work-item-run.ts +0 -99
- package/src/tools/tasks/work-item-update.ts +0 -166
- package/src/tools/ui-surface/registry.ts +0 -14
- package/src/work-items/resolve-required-tools.test.ts +0 -37
- package/src/work-items/resolve-required-tools.ts +0 -26
- package/src/work-items/work-item-runner.ts +0 -187
- package/src/work-items/work-item-store.ts +0 -416
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Guard tests for
|
|
2
|
+
* Guard tests for guardian request routing invariants.
|
|
3
3
|
*
|
|
4
|
-
* These tests verify that the
|
|
4
|
+
* These tests verify that the guardian request system maintains
|
|
5
5
|
* its key architectural invariants:
|
|
6
6
|
*
|
|
7
|
-
* 1. All decision paths route through `
|
|
7
|
+
* 1. All decision paths route through `applyGuardianDecision`
|
|
8
8
|
* 2. Principal-based authorization is enforced before decisions are applied
|
|
9
9
|
* 3. Stale/expired/already-resolved decisions are rejected
|
|
10
10
|
* 4. Code-only messages return clarification (not auto-approve)
|
|
@@ -43,24 +43,17 @@ mock.module("../daemon/conversation-registry.js", () => ({
|
|
|
43
43
|
findConversation: (id: string) => _conversationMocks.get(id),
|
|
44
44
|
}));
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}),
|
|
51
|
-
truncateForLog: (value: string) => value,
|
|
52
|
-
}));
|
|
46
|
+
import { createGuardianGatewaySim } from "./guardian-gateway-sim.js";
|
|
47
|
+
|
|
48
|
+
const sim = createGuardianGatewaySim();
|
|
49
|
+
mock.module("../channels/gateway-guardian-requests.js", () => sim.module);
|
|
53
50
|
|
|
54
|
-
import {
|
|
51
|
+
import { applyGuardianDecision } from "../approvals/guardian-decision-primitive.js";
|
|
55
52
|
import type { ActorContext } from "../approvals/guardian-request-resolvers.js";
|
|
56
53
|
import {
|
|
57
54
|
getRegisteredKinds,
|
|
58
55
|
getResolver,
|
|
59
56
|
} from "../approvals/guardian-request-resolvers.js";
|
|
60
|
-
import {
|
|
61
|
-
createCanonicalGuardianRequest,
|
|
62
|
-
getCanonicalGuardianRequest,
|
|
63
|
-
} from "../contacts/canonical-guardian-store.js";
|
|
64
57
|
import { getDb } from "../persistence/db-connection.js";
|
|
65
58
|
import { initializeDb } from "../persistence/db-init.js";
|
|
66
59
|
import { processGuardianDecision } from "../runtime/guardian-action-service.js";
|
|
@@ -76,10 +69,8 @@ import { listGuardianDecisionPrompts } from "../runtime/routes/guardian-action-r
|
|
|
76
69
|
await initializeDb();
|
|
77
70
|
|
|
78
71
|
function resetTables(): void {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
db.run("DELETE FROM canonical_guardian_deliveries");
|
|
82
|
-
db.run("DELETE FROM canonical_guardian_requests");
|
|
72
|
+
getDb().run("DELETE FROM scoped_approval_grants");
|
|
73
|
+
sim.reset();
|
|
83
74
|
pendingInteractions.clear();
|
|
84
75
|
}
|
|
85
76
|
|
|
@@ -164,15 +155,15 @@ function registerPendingToolApprovalInteraction(
|
|
|
164
155
|
// SECTION 1: Import-verification guard tests
|
|
165
156
|
//
|
|
166
157
|
// These verify that all known decision entrypoints import from and call
|
|
167
|
-
// `
|
|
158
|
+
// `applyGuardianDecision` rather than inlining decision logic.
|
|
168
159
|
// ===========================================================================
|
|
169
160
|
|
|
170
|
-
describe("routing invariant: all decision paths reference
|
|
161
|
+
describe("routing invariant: all decision paths reference applyGuardianDecision", () => {
|
|
171
162
|
const srcRoot = resolve(__dirname, "..");
|
|
172
163
|
|
|
173
164
|
// The files that constitute decision entrypoints. Each must reference
|
|
174
|
-
// `
|
|
175
|
-
// (shared wrapper that calls
|
|
165
|
+
// `applyGuardianDecision` (directly) or `processGuardianDecision`
|
|
166
|
+
// (shared wrapper that calls applyGuardianDecision internally).
|
|
176
167
|
const DECISION_ENTRYPOINTS: Array<{
|
|
177
168
|
path: string;
|
|
178
169
|
symbols: string[];
|
|
@@ -180,10 +171,10 @@ describe("routing invariant: all decision paths reference applyCanonicalGuardian
|
|
|
180
171
|
// Inbound channel router (Telegram/WhatsApp)
|
|
181
172
|
{
|
|
182
173
|
path: "runtime/guardian-reply-router.ts",
|
|
183
|
-
symbols: ["
|
|
174
|
+
symbols: ["applyGuardianDecision"],
|
|
184
175
|
},
|
|
185
176
|
// HTTP API route handler (desktop and API clients) — uses processGuardianDecision
|
|
186
|
-
// which is a shared wrapper around
|
|
177
|
+
// which is a shared wrapper around applyGuardianDecision
|
|
187
178
|
{
|
|
188
179
|
path: "runtime/routes/guardian-action-routes.ts",
|
|
189
180
|
symbols: ["processGuardianDecision"],
|
|
@@ -196,10 +187,10 @@ describe("routing invariant: all decision paths reference applyCanonicalGuardian
|
|
|
196
187
|
},
|
|
197
188
|
// Shared service where processGuardianDecision is defined — must route
|
|
198
189
|
// through the canonical primitive to complete the chain:
|
|
199
|
-
// entrypoint → processGuardianDecision →
|
|
190
|
+
// entrypoint → processGuardianDecision → applyGuardianDecision
|
|
200
191
|
{
|
|
201
192
|
path: "runtime/guardian-action-service.ts",
|
|
202
|
-
symbols: ["
|
|
193
|
+
symbols: ["applyGuardianDecision"],
|
|
203
194
|
},
|
|
204
195
|
];
|
|
205
196
|
|
|
@@ -213,7 +204,7 @@ describe("routing invariant: all decision paths reference applyCanonicalGuardian
|
|
|
213
204
|
}
|
|
214
205
|
|
|
215
206
|
// The inbound message handler and session-process both use routeGuardianReply
|
|
216
|
-
// which itself calls
|
|
207
|
+
// which itself calls applyGuardianDecision. Verify they reference
|
|
217
208
|
// the shared router rather than inlining decision logic.
|
|
218
209
|
const ROUTER_CONSUMERS = [
|
|
219
210
|
"runtime/routes/inbound-message-handler.ts",
|
|
@@ -235,17 +226,17 @@ describe("routing invariant: all decision paths reference applyCanonicalGuardian
|
|
|
235
226
|
expect(source).not.toContain("getPendingDeliveriesByConversation");
|
|
236
227
|
});
|
|
237
228
|
|
|
238
|
-
test("daemon/conversation-process.ts seeds router hints via
|
|
229
|
+
test("daemon/conversation-process.ts seeds router hints via the gateway scope read", () => {
|
|
239
230
|
const fullPath = join(srcRoot, "daemon/conversation-process.ts");
|
|
240
231
|
const source = readFileSync(fullPath, "utf-8");
|
|
241
|
-
expect(source).toContain("
|
|
232
|
+
expect(source).toContain("listPendingRequestsByScopeOrEmpty");
|
|
242
233
|
});
|
|
243
234
|
|
|
244
|
-
test("guardian-reply-router routes all decisions through
|
|
235
|
+
test("guardian-reply-router routes all decisions through applyGuardianDecision", () => {
|
|
245
236
|
const fullPath = join(srcRoot, "runtime/guardian-reply-router.ts");
|
|
246
237
|
const source = readFileSync(fullPath, "utf-8");
|
|
247
238
|
// The router must import and call the canonical decision primitive.
|
|
248
|
-
expect(source).toContain("
|
|
239
|
+
expect(source).toContain("applyGuardianDecision");
|
|
249
240
|
});
|
|
250
241
|
});
|
|
251
242
|
|
|
@@ -257,41 +248,43 @@ describe("routing invariant: principal-based authorization enforced before decis
|
|
|
257
248
|
beforeEach(() => resetTables());
|
|
258
249
|
|
|
259
250
|
test("mismatching actor principal is rejected by canonical primitive", async () => {
|
|
260
|
-
const req =
|
|
251
|
+
const req = sim.seedRequest({
|
|
261
252
|
kind: "tool_approval",
|
|
262
253
|
sourceType: "channel",
|
|
263
|
-
|
|
254
|
+
sourceConversationId: "conv-1",
|
|
264
255
|
guardianExternalUserId: "guardian-1",
|
|
265
256
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
266
257
|
expiresAt: Date.now() + 60_000,
|
|
267
258
|
});
|
|
268
259
|
|
|
269
|
-
const result = await
|
|
260
|
+
const result = await applyGuardianDecision({
|
|
270
261
|
requestId: req.id,
|
|
271
262
|
action: "approve_once",
|
|
272
263
|
actorContext: guardianActor({ guardianPrincipalId: "wrong-principal" }),
|
|
273
264
|
});
|
|
274
265
|
|
|
275
266
|
expect(result.applied).toBe(false);
|
|
276
|
-
if (result.applied)
|
|
267
|
+
if (result.applied) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
277
270
|
expect(result.reason).toBe("identity_mismatch");
|
|
278
271
|
|
|
279
272
|
// Request must remain pending (no state change)
|
|
280
|
-
const unchanged =
|
|
273
|
+
const unchanged = sim.getRequest(req.id);
|
|
281
274
|
expect(unchanged!.status).toBe("pending");
|
|
282
275
|
});
|
|
283
276
|
|
|
284
277
|
test("matching principal authorizes desktop actor", async () => {
|
|
285
|
-
const req =
|
|
278
|
+
const req = sim.seedRequest({
|
|
286
279
|
kind: "tool_approval",
|
|
287
280
|
sourceType: "desktop",
|
|
288
|
-
|
|
281
|
+
sourceConversationId: "conv-1",
|
|
289
282
|
guardianExternalUserId: "guardian-1",
|
|
290
283
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
291
284
|
expiresAt: Date.now() + 60_000,
|
|
292
285
|
});
|
|
293
286
|
|
|
294
|
-
const result = await
|
|
287
|
+
const result = await applyGuardianDecision({
|
|
295
288
|
requestId: req.id,
|
|
296
289
|
action: "approve_once",
|
|
297
290
|
actorContext: trustedActor(),
|
|
@@ -301,30 +294,32 @@ describe("routing invariant: principal-based authorization enforced before decis
|
|
|
301
294
|
});
|
|
302
295
|
|
|
303
296
|
test("actor without guardianPrincipalId is rejected", async () => {
|
|
304
|
-
const req =
|
|
297
|
+
const req = sim.seedRequest({
|
|
305
298
|
kind: "tool_approval",
|
|
306
299
|
sourceType: "channel",
|
|
307
|
-
|
|
300
|
+
sourceConversationId: "conv-1",
|
|
308
301
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
309
302
|
expiresAt: Date.now() + 60_000,
|
|
310
303
|
});
|
|
311
304
|
|
|
312
|
-
const result = await
|
|
305
|
+
const result = await applyGuardianDecision({
|
|
313
306
|
requestId: req.id,
|
|
314
307
|
action: "approve_once",
|
|
315
308
|
actorContext: guardianActor({ guardianPrincipalId: undefined }),
|
|
316
309
|
});
|
|
317
310
|
|
|
318
311
|
expect(result.applied).toBe(false);
|
|
319
|
-
if (result.applied)
|
|
312
|
+
if (result.applied) {
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
320
315
|
expect(result.reason).toBe("identity_mismatch");
|
|
321
316
|
});
|
|
322
317
|
|
|
323
318
|
test("principal mismatch on code-only message blocks detail leakage", async () => {
|
|
324
|
-
|
|
319
|
+
sim.seedRequest({
|
|
325
320
|
kind: "tool_approval",
|
|
326
321
|
sourceType: "channel",
|
|
327
|
-
|
|
322
|
+
sourceConversationId: "conv-1",
|
|
328
323
|
guardianExternalUserId: "guardian-1",
|
|
329
324
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
330
325
|
requestCode: "ABC123",
|
|
@@ -356,38 +351,40 @@ describe("routing invariant: stale/expired/already-resolved decisions rejected",
|
|
|
356
351
|
beforeEach(() => resetTables());
|
|
357
352
|
|
|
358
353
|
test("expired request is rejected by canonical primitive", async () => {
|
|
359
|
-
const req =
|
|
354
|
+
const req = sim.seedRequest({
|
|
360
355
|
kind: "tool_approval",
|
|
361
356
|
sourceType: "channel",
|
|
362
|
-
|
|
357
|
+
sourceConversationId: "conv-1",
|
|
363
358
|
guardianExternalUserId: "guardian-1",
|
|
364
359
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
365
360
|
expiresAt: Date.now() - 10_000, // already expired
|
|
366
361
|
});
|
|
367
362
|
|
|
368
|
-
const result = await
|
|
363
|
+
const result = await applyGuardianDecision({
|
|
369
364
|
requestId: req.id,
|
|
370
365
|
action: "approve_once",
|
|
371
366
|
actorContext: guardianActor(),
|
|
372
367
|
});
|
|
373
368
|
|
|
374
369
|
expect(result.applied).toBe(false);
|
|
375
|
-
if (result.applied)
|
|
370
|
+
if (result.applied) {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
376
373
|
expect(result.reason).toBe("expired");
|
|
377
374
|
});
|
|
378
375
|
|
|
379
376
|
test("already-resolved request is rejected (first-writer-wins)", async () => {
|
|
380
|
-
const req =
|
|
377
|
+
const req = sim.seedRequest({
|
|
381
378
|
kind: "tool_approval",
|
|
382
379
|
sourceType: "channel",
|
|
383
|
-
|
|
380
|
+
sourceConversationId: "conv-1",
|
|
384
381
|
guardianExternalUserId: "guardian-1",
|
|
385
382
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
386
383
|
expiresAt: Date.now() + 60_000,
|
|
387
384
|
});
|
|
388
385
|
|
|
389
386
|
// First decision succeeds
|
|
390
|
-
const first = await
|
|
387
|
+
const first = await applyGuardianDecision({
|
|
391
388
|
requestId: req.id,
|
|
392
389
|
action: "approve_once",
|
|
393
390
|
actorContext: guardianActor(),
|
|
@@ -395,37 +392,41 @@ describe("routing invariant: stale/expired/already-resolved decisions rejected",
|
|
|
395
392
|
expect(first.applied).toBe(true);
|
|
396
393
|
|
|
397
394
|
// Second decision fails — request is no longer pending
|
|
398
|
-
const second = await
|
|
395
|
+
const second = await applyGuardianDecision({
|
|
399
396
|
requestId: req.id,
|
|
400
397
|
action: "reject",
|
|
401
398
|
actorContext: guardianActor(),
|
|
402
399
|
});
|
|
403
400
|
expect(second.applied).toBe(false);
|
|
404
|
-
if (second.applied)
|
|
401
|
+
if (second.applied) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
405
404
|
expect(second.reason).toBe("already_resolved");
|
|
406
405
|
|
|
407
406
|
// First decision stuck
|
|
408
|
-
const final =
|
|
407
|
+
const final = sim.getRequest(req.id);
|
|
409
408
|
expect(final!.status).toBe("approved");
|
|
410
409
|
});
|
|
411
410
|
|
|
412
411
|
test("nonexistent request returns not_found", async () => {
|
|
413
|
-
const result = await
|
|
412
|
+
const result = await applyGuardianDecision({
|
|
414
413
|
requestId: "nonexistent-id",
|
|
415
414
|
action: "approve_once",
|
|
416
415
|
actorContext: guardianActor(),
|
|
417
416
|
});
|
|
418
417
|
|
|
419
418
|
expect(result.applied).toBe(false);
|
|
420
|
-
if (result.applied)
|
|
419
|
+
if (result.applied) {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
421
422
|
expect(result.reason).toBe("not_found");
|
|
422
423
|
});
|
|
423
424
|
|
|
424
425
|
test("already-resolved request via router returns not_consumed (code lookup filters pending only)", async () => {
|
|
425
|
-
const req =
|
|
426
|
+
const req = sim.seedRequest({
|
|
426
427
|
kind: "tool_approval",
|
|
427
428
|
sourceType: "channel",
|
|
428
|
-
|
|
429
|
+
sourceConversationId: "conv-1",
|
|
429
430
|
guardianExternalUserId: "guardian-1",
|
|
430
431
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
431
432
|
requestCode: "ABC123",
|
|
@@ -433,14 +434,14 @@ describe("routing invariant: stale/expired/already-resolved decisions rejected",
|
|
|
433
434
|
});
|
|
434
435
|
|
|
435
436
|
// Resolve the request first
|
|
436
|
-
await
|
|
437
|
+
await applyGuardianDecision({
|
|
437
438
|
requestId: req.id,
|
|
438
439
|
action: "approve_once",
|
|
439
440
|
actorContext: guardianActor(),
|
|
440
441
|
});
|
|
441
442
|
|
|
442
443
|
// Attempt to resolve again via router with code prefix.
|
|
443
|
-
// Since
|
|
444
|
+
// Since getGuardianRequestByCodeOrNull only returns pending requests,
|
|
444
445
|
// the resolved request won't be found and the code won't match.
|
|
445
446
|
const result = await routeGuardianReply(
|
|
446
447
|
replyCtx({
|
|
@@ -455,10 +456,10 @@ describe("routing invariant: stale/expired/already-resolved decisions rejected",
|
|
|
455
456
|
});
|
|
456
457
|
|
|
457
458
|
test("expired request via callback returns stale type", async () => {
|
|
458
|
-
const req =
|
|
459
|
+
const req = sim.seedRequest({
|
|
459
460
|
kind: "tool_approval",
|
|
460
461
|
sourceType: "channel",
|
|
461
|
-
|
|
462
|
+
sourceConversationId: "conv-1",
|
|
462
463
|
guardianExternalUserId: "guardian-1",
|
|
463
464
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
464
465
|
expiresAt: Date.now() - 10_000, // already expired
|
|
@@ -486,10 +487,10 @@ describe("routing invariant: code-only messages return clarification", () => {
|
|
|
486
487
|
beforeEach(() => resetTables());
|
|
487
488
|
|
|
488
489
|
test("code-only message returns clarification with request details", async () => {
|
|
489
|
-
const req =
|
|
490
|
+
const req = sim.seedRequest({
|
|
490
491
|
kind: "tool_approval",
|
|
491
492
|
sourceType: "channel",
|
|
492
|
-
|
|
493
|
+
sourceConversationId: "conv-1",
|
|
493
494
|
guardianExternalUserId: "guardian-1",
|
|
494
495
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
495
496
|
requestCode: "A1B2C3",
|
|
@@ -514,16 +515,16 @@ describe("routing invariant: code-only messages return clarification", () => {
|
|
|
514
515
|
expect(result.replyText).toContain("reject");
|
|
515
516
|
|
|
516
517
|
// The request must remain pending — NOT auto-approved
|
|
517
|
-
const unchanged =
|
|
518
|
+
const unchanged = sim.getRequest(req.id);
|
|
518
519
|
expect(unchanged!.status).toBe("pending");
|
|
519
520
|
});
|
|
520
521
|
|
|
521
522
|
test("code-only pending_question asks for free-text answer (not approve/reject)", async () => {
|
|
522
|
-
const req =
|
|
523
|
+
const req = sim.seedRequest({
|
|
523
524
|
kind: "pending_question",
|
|
524
525
|
sourceType: "voice",
|
|
525
526
|
sourceChannel: "phone",
|
|
526
|
-
|
|
527
|
+
sourceConversationId: "conv-1",
|
|
527
528
|
guardianExternalUserId: "guardian-1",
|
|
528
529
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
529
530
|
callSessionId: "call-1",
|
|
@@ -548,16 +549,16 @@ describe("routing invariant: code-only messages return clarification", () => {
|
|
|
548
549
|
expect(result.replyText).not.toContain("approve");
|
|
549
550
|
expect(result.replyText).not.toContain("reject");
|
|
550
551
|
|
|
551
|
-
const unchanged =
|
|
552
|
+
const unchanged = sim.getRequest(req.id);
|
|
552
553
|
expect(unchanged!.status).toBe("pending");
|
|
553
554
|
});
|
|
554
555
|
|
|
555
556
|
test("code-only tool-backed pending_question asks for approve/reject decision", async () => {
|
|
556
|
-
const req =
|
|
557
|
+
const req = sim.seedRequest({
|
|
557
558
|
kind: "pending_question",
|
|
558
559
|
sourceType: "voice",
|
|
559
560
|
sourceChannel: "phone",
|
|
560
|
-
|
|
561
|
+
sourceConversationId: "conv-1",
|
|
561
562
|
guardianExternalUserId: "guardian-1",
|
|
562
563
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
563
564
|
callSessionId: "call-2",
|
|
@@ -583,15 +584,15 @@ describe("routing invariant: code-only messages return clarification", () => {
|
|
|
583
584
|
expect(result.replyText).toContain("reject");
|
|
584
585
|
expect(result.replyText).not.toContain("<your answer>");
|
|
585
586
|
|
|
586
|
-
const unchanged =
|
|
587
|
+
const unchanged = sim.getRequest(req.id);
|
|
587
588
|
expect(unchanged!.status).toBe("pending");
|
|
588
589
|
});
|
|
589
590
|
|
|
590
591
|
test("code with decision text does apply the decision", async () => {
|
|
591
|
-
const req =
|
|
592
|
+
const req = sim.seedRequest({
|
|
592
593
|
kind: "tool_approval",
|
|
593
594
|
sourceType: "channel",
|
|
594
|
-
|
|
595
|
+
sourceConversationId: "conv-1",
|
|
595
596
|
guardianExternalUserId: "guardian-1",
|
|
596
597
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
597
598
|
requestCode: "A1B2C3",
|
|
@@ -612,15 +613,15 @@ describe("routing invariant: code-only messages return clarification", () => {
|
|
|
612
613
|
expect(result.type).toBe("canonical_decision_applied");
|
|
613
614
|
expect(result.decisionApplied).toBe(true);
|
|
614
615
|
|
|
615
|
-
const resolved =
|
|
616
|
+
const resolved = sim.getRequest(req.id);
|
|
616
617
|
expect(resolved!.status).toBe("approved");
|
|
617
618
|
});
|
|
618
619
|
|
|
619
620
|
test("code with reject text denies the request", async () => {
|
|
620
|
-
const req =
|
|
621
|
+
const req = sim.seedRequest({
|
|
621
622
|
kind: "tool_approval",
|
|
622
623
|
sourceType: "channel",
|
|
623
|
-
|
|
624
|
+
sourceConversationId: "conv-1",
|
|
624
625
|
guardianExternalUserId: "guardian-1",
|
|
625
626
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
626
627
|
requestCode: "D4E5F6",
|
|
@@ -638,7 +639,7 @@ describe("routing invariant: code-only messages return clarification", () => {
|
|
|
638
639
|
expect(result.consumed).toBe(true);
|
|
639
640
|
expect(result.decisionApplied).toBe(true);
|
|
640
641
|
|
|
641
|
-
const resolved =
|
|
642
|
+
const resolved = sim.getRequest(req.id);
|
|
642
643
|
expect(resolved!.status).toBe("denied");
|
|
643
644
|
});
|
|
644
645
|
});
|
|
@@ -651,10 +652,10 @@ describe("routing invariant: channel formatting delimiters stripped from code pa
|
|
|
651
652
|
beforeEach(() => resetTables());
|
|
652
653
|
|
|
653
654
|
test("backtick-wrapped code + approve is parsed correctly", async () => {
|
|
654
|
-
const req =
|
|
655
|
+
const req = sim.seedRequest({
|
|
655
656
|
kind: "tool_approval",
|
|
656
657
|
sourceType: "channel",
|
|
657
|
-
|
|
658
|
+
sourceConversationId: "conv-1",
|
|
658
659
|
guardianExternalUserId: "guardian-1",
|
|
659
660
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
660
661
|
requestCode: "A1B2C3",
|
|
@@ -675,15 +676,15 @@ describe("routing invariant: channel formatting delimiters stripped from code pa
|
|
|
675
676
|
expect(result.type).toBe("canonical_decision_applied");
|
|
676
677
|
expect(result.decisionApplied).toBe(true);
|
|
677
678
|
|
|
678
|
-
const resolved =
|
|
679
|
+
const resolved = sim.getRequest(req.id);
|
|
679
680
|
expect(resolved!.status).toBe("approved");
|
|
680
681
|
});
|
|
681
682
|
|
|
682
683
|
test("bold+backtick code + reject is parsed correctly", async () => {
|
|
683
|
-
const req =
|
|
684
|
+
const req = sim.seedRequest({
|
|
684
685
|
kind: "tool_approval",
|
|
685
686
|
sourceType: "channel",
|
|
686
|
-
|
|
687
|
+
sourceConversationId: "conv-1",
|
|
687
688
|
guardianExternalUserId: "guardian-1",
|
|
688
689
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
689
690
|
requestCode: "D4E5F6",
|
|
@@ -702,15 +703,15 @@ describe("routing invariant: channel formatting delimiters stripped from code pa
|
|
|
702
703
|
expect(result.type).toBe("canonical_decision_applied");
|
|
703
704
|
expect(result.decisionApplied).toBe(true);
|
|
704
705
|
|
|
705
|
-
const resolved =
|
|
706
|
+
const resolved = sim.getRequest(req.id);
|
|
706
707
|
expect(resolved!.status).toBe("denied");
|
|
707
708
|
});
|
|
708
709
|
|
|
709
710
|
test("backtick-wrapped code only returns clarification", async () => {
|
|
710
|
-
const req =
|
|
711
|
+
const req = sim.seedRequest({
|
|
711
712
|
kind: "tool_approval",
|
|
712
713
|
sourceType: "channel",
|
|
713
|
-
|
|
714
|
+
sourceConversationId: "conv-1",
|
|
714
715
|
guardianExternalUserId: "guardian-1",
|
|
715
716
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
716
717
|
requestCode: "A1B2C3",
|
|
@@ -730,15 +731,15 @@ describe("routing invariant: channel formatting delimiters stripped from code pa
|
|
|
730
731
|
expect(result.type).toBe("code_only_clarification");
|
|
731
732
|
expect(result.decisionApplied).toBe(false);
|
|
732
733
|
|
|
733
|
-
const unchanged =
|
|
734
|
+
const unchanged = sim.getRequest(req.id);
|
|
734
735
|
expect(unchanged!.status).toBe("pending");
|
|
735
736
|
});
|
|
736
737
|
|
|
737
738
|
test("asterisk-wrapped code + approve is parsed correctly", async () => {
|
|
738
|
-
const req =
|
|
739
|
+
const req = sim.seedRequest({
|
|
739
740
|
kind: "tool_approval",
|
|
740
741
|
sourceType: "channel",
|
|
741
|
-
|
|
742
|
+
sourceConversationId: "conv-1",
|
|
742
743
|
guardianExternalUserId: "guardian-1",
|
|
743
744
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
744
745
|
requestCode: "A1B2C3",
|
|
@@ -759,15 +760,15 @@ describe("routing invariant: channel formatting delimiters stripped from code pa
|
|
|
759
760
|
expect(result.type).toBe("canonical_decision_applied");
|
|
760
761
|
expect(result.decisionApplied).toBe(true);
|
|
761
762
|
|
|
762
|
-
const resolved =
|
|
763
|
+
const resolved = sim.getRequest(req.id);
|
|
763
764
|
expect(resolved!.status).toBe("approved");
|
|
764
765
|
});
|
|
765
766
|
|
|
766
767
|
test("*CODE* action — formatting wraps only the code portion", async () => {
|
|
767
|
-
const req =
|
|
768
|
+
const req = sim.seedRequest({
|
|
768
769
|
kind: "tool_approval",
|
|
769
770
|
sourceType: "channel",
|
|
770
|
-
|
|
771
|
+
sourceConversationId: "conv-1",
|
|
771
772
|
guardianExternalUserId: "guardian-1",
|
|
772
773
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
773
774
|
requestCode: "A1B2C3",
|
|
@@ -788,15 +789,15 @@ describe("routing invariant: channel formatting delimiters stripped from code pa
|
|
|
788
789
|
expect(result.type).toBe("canonical_decision_applied");
|
|
789
790
|
expect(result.decisionApplied).toBe(true);
|
|
790
791
|
|
|
791
|
-
const resolved =
|
|
792
|
+
const resolved = sim.getRequest(req.id);
|
|
792
793
|
expect(resolved!.status).toBe("approved");
|
|
793
794
|
});
|
|
794
795
|
|
|
795
796
|
test("**CODE** action — double-asterisk formatting wraps only the code portion", async () => {
|
|
796
|
-
const req =
|
|
797
|
+
const req = sim.seedRequest({
|
|
797
798
|
kind: "tool_approval",
|
|
798
799
|
sourceType: "channel",
|
|
799
|
-
|
|
800
|
+
sourceConversationId: "conv-1",
|
|
800
801
|
guardianExternalUserId: "guardian-1",
|
|
801
802
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
802
803
|
requestCode: "D4E5F6",
|
|
@@ -815,7 +816,7 @@ describe("routing invariant: channel formatting delimiters stripped from code pa
|
|
|
815
816
|
expect(result.type).toBe("canonical_decision_applied");
|
|
816
817
|
expect(result.decisionApplied).toBe(true);
|
|
817
818
|
|
|
818
|
-
const resolved =
|
|
819
|
+
const resolved = sim.getRequest(req.id);
|
|
819
820
|
expect(resolved!.status).toBe("denied");
|
|
820
821
|
});
|
|
821
822
|
});
|
|
@@ -828,10 +829,10 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
828
829
|
beforeEach(() => resetTables());
|
|
829
830
|
|
|
830
831
|
test("single hinted pending request accepts explicit plain-text approve without NL generator", async () => {
|
|
831
|
-
const req =
|
|
832
|
+
const req = sim.seedRequest({
|
|
832
833
|
kind: "tool_approval",
|
|
833
834
|
sourceType: "channel",
|
|
834
|
-
|
|
835
|
+
sourceConversationId: "conv-1",
|
|
835
836
|
guardianExternalUserId: "guardian-1",
|
|
836
837
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
837
838
|
requestCode: "DDD444",
|
|
@@ -853,15 +854,15 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
853
854
|
expect(result.type).toBe("canonical_decision_applied");
|
|
854
855
|
expect(result.decisionApplied).toBe(true);
|
|
855
856
|
|
|
856
|
-
const resolved =
|
|
857
|
+
const resolved = sim.getRequest(req.id);
|
|
857
858
|
expect(resolved!.status).toBe("approved");
|
|
858
859
|
});
|
|
859
860
|
|
|
860
861
|
test("single hinted pending request does not auto-approve broad acknowledgment text", async () => {
|
|
861
|
-
const req =
|
|
862
|
+
const req = sim.seedRequest({
|
|
862
863
|
kind: "tool_approval",
|
|
863
864
|
sourceType: "channel",
|
|
864
|
-
|
|
865
|
+
sourceConversationId: "conv-1",
|
|
865
866
|
guardianExternalUserId: "guardian-1",
|
|
866
867
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
867
868
|
requestCode: "GGG777",
|
|
@@ -882,15 +883,15 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
882
883
|
expect(result.type).toBe("not_consumed");
|
|
883
884
|
expect(result.decisionApplied).toBe(false);
|
|
884
885
|
|
|
885
|
-
const unchanged =
|
|
886
|
+
const unchanged = sim.getRequest(req.id);
|
|
886
887
|
expect(unchanged!.status).toBe("pending");
|
|
887
888
|
});
|
|
888
889
|
|
|
889
890
|
test("explicit blocked scope stays fail-closed for desktop actors", async () => {
|
|
890
|
-
|
|
891
|
+
sim.seedRequest({
|
|
891
892
|
kind: "tool_approval",
|
|
892
893
|
sourceType: "channel",
|
|
893
|
-
|
|
894
|
+
sourceConversationId: "conv-other",
|
|
894
895
|
guardianExternalUserId: "guardian-1",
|
|
895
896
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
896
897
|
requestCode: "HHH888",
|
|
@@ -917,10 +918,10 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
917
918
|
// The Slack cross-chat guard blocks identity fallback, but an explicit
|
|
918
919
|
// request code carries its own target and must still resolve — otherwise a
|
|
919
920
|
// guardian could not approve-by-code from a chat where no card was delivered.
|
|
920
|
-
const req =
|
|
921
|
+
const req = sim.seedRequest({
|
|
921
922
|
kind: "tool_approval",
|
|
922
923
|
sourceType: "channel",
|
|
923
|
-
|
|
924
|
+
sourceConversationId: "conv-other",
|
|
924
925
|
guardianExternalUserId: "guardian-1",
|
|
925
926
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
926
927
|
requestCode: "ABC123",
|
|
@@ -942,14 +943,14 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
942
943
|
expect(result.consumed).toBe(true);
|
|
943
944
|
expect(result.requestId).toBe(req.id);
|
|
944
945
|
expect(result.decisionApplied).toBe(true);
|
|
945
|
-
expect(
|
|
946
|
+
expect(sim.getRequest(req.id)!.status).toBe("approved");
|
|
946
947
|
});
|
|
947
948
|
|
|
948
949
|
test("multiple hinted pending requests with plain-text approve returns disambiguation", async () => {
|
|
949
|
-
const req1 =
|
|
950
|
+
const req1 = sim.seedRequest({
|
|
950
951
|
kind: "tool_approval",
|
|
951
952
|
sourceType: "channel",
|
|
952
|
-
|
|
953
|
+
sourceConversationId: "conv-1",
|
|
953
954
|
guardianExternalUserId: "guardian-1",
|
|
954
955
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
955
956
|
requestCode: "EEE555",
|
|
@@ -957,10 +958,10 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
957
958
|
expiresAt: Date.now() + 60_000,
|
|
958
959
|
});
|
|
959
960
|
|
|
960
|
-
const req2 =
|
|
961
|
+
const req2 = sim.seedRequest({
|
|
961
962
|
kind: "tool_approval",
|
|
962
963
|
sourceType: "channel",
|
|
963
|
-
|
|
964
|
+
sourceConversationId: "conv-1",
|
|
964
965
|
guardianExternalUserId: "guardian-1",
|
|
965
966
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
966
967
|
requestCode: "FFF666",
|
|
@@ -983,18 +984,18 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
983
984
|
expect(result.replyText).toContain("EEE555");
|
|
984
985
|
expect(result.replyText).toContain("FFF666");
|
|
985
986
|
|
|
986
|
-
const r1 =
|
|
987
|
-
const r2 =
|
|
987
|
+
const r1 = sim.getRequest(req1.id);
|
|
988
|
+
const r2 = sim.getRequest(req2.id);
|
|
988
989
|
expect(r1!.status).toBe("pending");
|
|
989
990
|
expect(r2!.status).toBe("pending");
|
|
990
991
|
});
|
|
991
992
|
|
|
992
993
|
test("multiple pending requests without target return disambiguation (not auto-resolve)", async () => {
|
|
993
994
|
// Create two pending requests for the same guardian
|
|
994
|
-
const req1 =
|
|
995
|
+
const req1 = sim.seedRequest({
|
|
995
996
|
kind: "tool_approval",
|
|
996
997
|
sourceType: "channel",
|
|
997
|
-
|
|
998
|
+
sourceConversationId: "conv-1",
|
|
998
999
|
guardianExternalUserId: "guardian-1",
|
|
999
1000
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1000
1001
|
requestCode: "AAA111",
|
|
@@ -1002,10 +1003,10 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
1002
1003
|
expiresAt: Date.now() + 60_000,
|
|
1003
1004
|
});
|
|
1004
1005
|
|
|
1005
|
-
const req2 =
|
|
1006
|
+
const req2 = sim.seedRequest({
|
|
1006
1007
|
kind: "tool_approval",
|
|
1007
1008
|
sourceType: "channel",
|
|
1008
|
-
|
|
1009
|
+
sourceConversationId: "conv-1",
|
|
1009
1010
|
guardianExternalUserId: "guardian-1",
|
|
1010
1011
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1011
1012
|
requestCode: "BBB222",
|
|
@@ -1035,8 +1036,8 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
1035
1036
|
expect(result.decisionApplied).toBe(false);
|
|
1036
1037
|
|
|
1037
1038
|
// Both requests must remain pending — fail-closed
|
|
1038
|
-
const r1 =
|
|
1039
|
-
const r2 =
|
|
1039
|
+
const r1 = sim.getRequest(req1.id);
|
|
1040
|
+
const r2 = sim.getRequest(req2.id);
|
|
1040
1041
|
expect(r1!.status).toBe("pending");
|
|
1041
1042
|
expect(r2!.status).toBe("pending");
|
|
1042
1043
|
|
|
@@ -1046,11 +1047,11 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
1046
1047
|
});
|
|
1047
1048
|
|
|
1048
1049
|
test("disambiguation treats tool-backed pending_question as approval request", async () => {
|
|
1049
|
-
const answerRequest =
|
|
1050
|
+
const answerRequest = sim.seedRequest({
|
|
1050
1051
|
kind: "pending_question",
|
|
1051
1052
|
sourceType: "voice",
|
|
1052
1053
|
sourceChannel: "phone",
|
|
1053
|
-
|
|
1054
|
+
sourceConversationId: "conv-1",
|
|
1054
1055
|
guardianExternalUserId: "guardian-1",
|
|
1055
1056
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1056
1057
|
callSessionId: "call-answer",
|
|
@@ -1060,11 +1061,11 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
1060
1061
|
expiresAt: Date.now() + 60_000,
|
|
1061
1062
|
});
|
|
1062
1063
|
|
|
1063
|
-
const approvalRequest =
|
|
1064
|
+
const approvalRequest = sim.seedRequest({
|
|
1064
1065
|
kind: "pending_question",
|
|
1065
1066
|
sourceType: "voice",
|
|
1066
1067
|
sourceChannel: "phone",
|
|
1067
|
-
|
|
1068
|
+
sourceConversationId: "conv-1",
|
|
1068
1069
|
guardianExternalUserId: "guardian-1",
|
|
1069
1070
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1070
1071
|
callSessionId: "call-approval",
|
|
@@ -1102,10 +1103,10 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
1102
1103
|
});
|
|
1103
1104
|
|
|
1104
1105
|
test("single pending request does not need disambiguation", async () => {
|
|
1105
|
-
const req =
|
|
1106
|
+
const req = sim.seedRequest({
|
|
1106
1107
|
kind: "tool_approval",
|
|
1107
1108
|
sourceType: "channel",
|
|
1108
|
-
|
|
1109
|
+
sourceConversationId: "conv-1",
|
|
1109
1110
|
guardianExternalUserId: "guardian-1",
|
|
1110
1111
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1111
1112
|
requestCode: "CCC333",
|
|
@@ -1134,15 +1135,15 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
1134
1135
|
expect(result.consumed).toBe(true);
|
|
1135
1136
|
expect(result.decisionApplied).toBe(true);
|
|
1136
1137
|
|
|
1137
|
-
const resolved =
|
|
1138
|
+
const resolved = sim.getRequest(req.id);
|
|
1138
1139
|
expect(resolved!.status).toBe("approved");
|
|
1139
1140
|
});
|
|
1140
1141
|
|
|
1141
1142
|
test('single pending request accepts "go for it" as deterministic approval', async () => {
|
|
1142
|
-
const req =
|
|
1143
|
+
const req = sim.seedRequest({
|
|
1143
1144
|
kind: "tool_approval",
|
|
1144
1145
|
sourceType: "channel",
|
|
1145
|
-
|
|
1146
|
+
sourceConversationId: "conv-1",
|
|
1146
1147
|
guardianExternalUserId: "guardian-1",
|
|
1147
1148
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1148
1149
|
toolName: "shell",
|
|
@@ -1164,25 +1165,25 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
1164
1165
|
expect(result.decisionApplied).toBe(true);
|
|
1165
1166
|
expect(result.type).toBe("canonical_decision_applied");
|
|
1166
1167
|
|
|
1167
|
-
const resolved =
|
|
1168
|
+
const resolved = sim.getRequest(req.id);
|
|
1168
1169
|
expect(resolved!.status).toBe("approved");
|
|
1169
1170
|
});
|
|
1170
1171
|
|
|
1171
1172
|
test("code-based routing is constrained to caller-provided scope", async () => {
|
|
1172
|
-
const inScope =
|
|
1173
|
+
const inScope = sim.seedRequest({
|
|
1173
1174
|
kind: "tool_approval",
|
|
1174
1175
|
sourceType: "channel",
|
|
1175
|
-
|
|
1176
|
+
sourceConversationId: "conv-1",
|
|
1176
1177
|
guardianExternalUserId: "guardian-1",
|
|
1177
1178
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1178
1179
|
requestCode: "111AAA",
|
|
1179
1180
|
toolName: "shell",
|
|
1180
1181
|
expiresAt: Date.now() + 60_000,
|
|
1181
1182
|
});
|
|
1182
|
-
const outOfScope =
|
|
1183
|
+
const outOfScope = sim.seedRequest({
|
|
1183
1184
|
kind: "tool_approval",
|
|
1184
1185
|
sourceType: "channel",
|
|
1185
|
-
|
|
1186
|
+
sourceConversationId: "conv-2",
|
|
1186
1187
|
guardianExternalUserId: "guardian-1",
|
|
1187
1188
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1188
1189
|
requestCode: "222BBB",
|
|
@@ -1205,8 +1206,8 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
1205
1206
|
expect(result.type).toBe("not_consumed");
|
|
1206
1207
|
expect(result.decisionApplied).toBe(false);
|
|
1207
1208
|
|
|
1208
|
-
const inScopeAfter =
|
|
1209
|
-
const outOfScopeAfter =
|
|
1209
|
+
const inScopeAfter = sim.getRequest(inScope.id);
|
|
1210
|
+
const outOfScopeAfter = sim.getRequest(outOfScope.id);
|
|
1210
1211
|
expect(inScopeAfter!.status).toBe("pending");
|
|
1211
1212
|
expect(outOfScopeAfter!.status).toBe("pending");
|
|
1212
1213
|
});
|
|
@@ -1248,10 +1249,10 @@ describe("routing invariant: only approve_once and reject are valid actions", ()
|
|
|
1248
1249
|
beforeEach(() => resetTables());
|
|
1249
1250
|
|
|
1250
1251
|
test("approve_once is accepted by canonical primitive", async () => {
|
|
1251
|
-
const req =
|
|
1252
|
+
const req = sim.seedRequest({
|
|
1252
1253
|
kind: "tool_approval",
|
|
1253
1254
|
sourceType: "channel",
|
|
1254
|
-
|
|
1255
|
+
sourceConversationId: "conv-1",
|
|
1255
1256
|
guardianExternalUserId: "guardian-1",
|
|
1256
1257
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1257
1258
|
toolName: "shell",
|
|
@@ -1259,7 +1260,7 @@ describe("routing invariant: only approve_once and reject are valid actions", ()
|
|
|
1259
1260
|
expiresAt: Date.now() + 60_000,
|
|
1260
1261
|
});
|
|
1261
1262
|
|
|
1262
|
-
const result = await
|
|
1263
|
+
const result = await applyGuardianDecision({
|
|
1263
1264
|
requestId: req.id,
|
|
1264
1265
|
action: "approve_once",
|
|
1265
1266
|
actorContext: guardianActor(),
|
|
@@ -1267,15 +1268,15 @@ describe("routing invariant: only approve_once and reject are valid actions", ()
|
|
|
1267
1268
|
|
|
1268
1269
|
expect(result.applied).toBe(true);
|
|
1269
1270
|
|
|
1270
|
-
const resolved =
|
|
1271
|
+
const resolved = sim.getRequest(req.id);
|
|
1271
1272
|
expect(resolved!.status).toBe("approved");
|
|
1272
1273
|
});
|
|
1273
1274
|
|
|
1274
1275
|
test("approve_always is rejected as an invalid action", async () => {
|
|
1275
|
-
const req =
|
|
1276
|
+
const req = sim.seedRequest({
|
|
1276
1277
|
kind: "tool_approval",
|
|
1277
1278
|
sourceType: "channel",
|
|
1278
|
-
|
|
1279
|
+
sourceConversationId: "conv-1",
|
|
1279
1280
|
guardianExternalUserId: "guardian-1",
|
|
1280
1281
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1281
1282
|
toolName: "shell",
|
|
@@ -1283,7 +1284,7 @@ describe("routing invariant: only approve_once and reject are valid actions", ()
|
|
|
1283
1284
|
expiresAt: Date.now() + 60_000,
|
|
1284
1285
|
});
|
|
1285
1286
|
|
|
1286
|
-
const result = await
|
|
1287
|
+
const result = await applyGuardianDecision({
|
|
1287
1288
|
requestId: req.id,
|
|
1288
1289
|
// @ts-expect-error - approve_always is no longer a valid action
|
|
1289
1290
|
action: "approve_always",
|
|
@@ -1298,17 +1299,17 @@ describe("routing invariant: only approve_once and reject are valid actions", ()
|
|
|
1298
1299
|
});
|
|
1299
1300
|
|
|
1300
1301
|
// ===========================================================================
|
|
1301
|
-
// SECTION 8: Callback routing uses
|
|
1302
|
+
// SECTION 8: Callback routing uses applyGuardianDecision
|
|
1302
1303
|
// ===========================================================================
|
|
1303
1304
|
|
|
1304
1305
|
describe("routing invariant: callback buttons route through canonical primitive", () => {
|
|
1305
1306
|
beforeEach(() => resetTables());
|
|
1306
1307
|
|
|
1307
1308
|
test("valid callback data applies decision via canonical primitive", async () => {
|
|
1308
|
-
const req =
|
|
1309
|
+
const req = sim.seedRequest({
|
|
1309
1310
|
kind: "tool_approval",
|
|
1310
1311
|
sourceType: "channel",
|
|
1311
|
-
|
|
1312
|
+
sourceConversationId: "conv-1",
|
|
1312
1313
|
guardianExternalUserId: "guardian-1",
|
|
1313
1314
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1314
1315
|
toolName: "shell",
|
|
@@ -1329,15 +1330,15 @@ describe("routing invariant: callback buttons route through canonical primitive"
|
|
|
1329
1330
|
expect(result.type).toBe("canonical_decision_applied");
|
|
1330
1331
|
expect(result.decisionApplied).toBe(true);
|
|
1331
1332
|
|
|
1332
|
-
const resolved =
|
|
1333
|
+
const resolved = sim.getRequest(req.id);
|
|
1333
1334
|
expect(resolved!.status).toBe("approved");
|
|
1334
1335
|
});
|
|
1335
1336
|
|
|
1336
1337
|
test("callback with reject action denies the request", async () => {
|
|
1337
|
-
const req =
|
|
1338
|
+
const req = sim.seedRequest({
|
|
1338
1339
|
kind: "tool_approval",
|
|
1339
1340
|
sourceType: "channel",
|
|
1340
|
-
|
|
1341
|
+
sourceConversationId: "conv-1",
|
|
1341
1342
|
guardianExternalUserId: "guardian-1",
|
|
1342
1343
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1343
1344
|
expiresAt: Date.now() + 60_000,
|
|
@@ -1355,15 +1356,15 @@ describe("routing invariant: callback buttons route through canonical primitive"
|
|
|
1355
1356
|
expect(result.consumed).toBe(true);
|
|
1356
1357
|
expect(result.decisionApplied).toBe(true);
|
|
1357
1358
|
|
|
1358
|
-
const resolved =
|
|
1359
|
+
const resolved = sim.getRequest(req.id);
|
|
1359
1360
|
expect(resolved!.status).toBe("denied");
|
|
1360
1361
|
});
|
|
1361
1362
|
|
|
1362
1363
|
test("callback targeting different conversation is still processed (conversationId scoping removed for cross-channel)", async () => {
|
|
1363
|
-
const req =
|
|
1364
|
+
const req = sim.seedRequest({
|
|
1364
1365
|
kind: "tool_approval",
|
|
1365
1366
|
sourceType: "channel",
|
|
1366
|
-
|
|
1367
|
+
sourceConversationId: "conv-other",
|
|
1367
1368
|
guardianExternalUserId: "guardian-1",
|
|
1368
1369
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1369
1370
|
expiresAt: Date.now() + 60_000,
|
|
@@ -1386,7 +1387,7 @@ describe("routing invariant: callback buttons route through canonical primitive"
|
|
|
1386
1387
|
expect(result.decisionApplied).toBe(true);
|
|
1387
1388
|
|
|
1388
1389
|
// Request should be approved
|
|
1389
|
-
const resolved =
|
|
1390
|
+
const resolved = sim.getRequest(req.id);
|
|
1390
1391
|
expect(resolved!.status).toBe("approved");
|
|
1391
1392
|
});
|
|
1392
1393
|
});
|
|
@@ -1428,10 +1429,10 @@ describe("routing invariant: directResolve interactions resolve via guardian dec
|
|
|
1428
1429
|
}
|
|
1429
1430
|
|
|
1430
1431
|
test("channel approval fires directResolve('allow') with no live Conversation", async () => {
|
|
1431
|
-
const req =
|
|
1432
|
+
const req = sim.seedRequest({
|
|
1432
1433
|
kind: "tool_approval",
|
|
1433
1434
|
sourceType: "channel",
|
|
1434
|
-
|
|
1435
|
+
sourceConversationId: "conv-acp",
|
|
1435
1436
|
guardianExternalUserId: "guardian-1",
|
|
1436
1437
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1437
1438
|
toolName: "acp_spawn",
|
|
@@ -1452,14 +1453,14 @@ describe("routing invariant: directResolve interactions resolve via guardian dec
|
|
|
1452
1453
|
expect(result.decisionApplied).toBe(true);
|
|
1453
1454
|
expect(decisions).toEqual(["allow"]);
|
|
1454
1455
|
expect(pendingInteractions.get(req.id)).toBeUndefined();
|
|
1455
|
-
expect(
|
|
1456
|
+
expect(sim.getRequest(req.id)!.status).toBe("approved");
|
|
1456
1457
|
});
|
|
1457
1458
|
|
|
1458
1459
|
test("channel rejection fires directResolve('deny')", async () => {
|
|
1459
|
-
const req =
|
|
1460
|
+
const req = sim.seedRequest({
|
|
1460
1461
|
kind: "tool_approval",
|
|
1461
1462
|
sourceType: "channel",
|
|
1462
|
-
|
|
1463
|
+
sourceConversationId: "conv-acp",
|
|
1463
1464
|
guardianExternalUserId: "guardian-1",
|
|
1464
1465
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1465
1466
|
toolName: "acp_spawn",
|
|
@@ -1478,7 +1479,7 @@ describe("routing invariant: directResolve interactions resolve via guardian dec
|
|
|
1478
1479
|
expect(result.decisionApplied).toBe(true);
|
|
1479
1480
|
expect(decisions).toEqual(["deny"]);
|
|
1480
1481
|
expect(pendingInteractions.get(req.id)).toBeUndefined();
|
|
1481
|
-
expect(
|
|
1482
|
+
expect(sim.getRequest(req.id)!.status).toBe("denied");
|
|
1482
1483
|
});
|
|
1483
1484
|
});
|
|
1484
1485
|
|
|
@@ -1491,11 +1492,11 @@ describe("routing invariant: destination hints do not bypass tool_approval princ
|
|
|
1491
1492
|
|
|
1492
1493
|
test("explicit scope still fails closed when guardianPrincipalId does not match", async () => {
|
|
1493
1494
|
// Voice-originated tool approval with a different principal than the actor.
|
|
1494
|
-
const req =
|
|
1495
|
+
const req = sim.seedRequest({
|
|
1495
1496
|
kind: "tool_approval",
|
|
1496
1497
|
sourceType: "voice",
|
|
1497
1498
|
sourceChannel: "twilio",
|
|
1498
|
-
|
|
1499
|
+
sourceConversationId: "conv-voice-1",
|
|
1499
1500
|
toolName: "shell",
|
|
1500
1501
|
requestCode: "NL1234",
|
|
1501
1502
|
guardianPrincipalId: "request-principal",
|
|
@@ -1520,17 +1521,17 @@ describe("routing invariant: destination hints do not bypass tool_approval princ
|
|
|
1520
1521
|
expect(result.type).toBe("canonical_decision_stale");
|
|
1521
1522
|
expect(result.decisionApplied).toBe(false);
|
|
1522
1523
|
|
|
1523
|
-
const resolved =
|
|
1524
|
+
const resolved = sim.getRequest(req.id);
|
|
1524
1525
|
expect(resolved!.status).toBe("pending");
|
|
1525
1526
|
});
|
|
1526
1527
|
|
|
1527
1528
|
test("without destination hints, unbound principal means no pending requests found", async () => {
|
|
1528
1529
|
// Voice-originated request: different principal
|
|
1529
|
-
const req =
|
|
1530
|
+
const req = sim.seedRequest({
|
|
1530
1531
|
kind: "tool_approval",
|
|
1531
1532
|
sourceType: "voice",
|
|
1532
1533
|
sourceChannel: "twilio",
|
|
1533
|
-
|
|
1534
|
+
sourceConversationId: "conv-voice-2",
|
|
1534
1535
|
toolName: "shell",
|
|
1535
1536
|
requestCode: "NL5678",
|
|
1536
1537
|
guardianPrincipalId: "voice-principal",
|
|
@@ -1556,7 +1557,7 @@ describe("routing invariant: destination hints do not bypass tool_approval princ
|
|
|
1556
1557
|
expect(result.consumed).toBe(false);
|
|
1557
1558
|
expect(result.type).toBe("not_consumed");
|
|
1558
1559
|
|
|
1559
|
-
const unchanged =
|
|
1560
|
+
const unchanged = sim.getRequest(req.id);
|
|
1560
1561
|
expect(unchanged!.status).toBe("pending");
|
|
1561
1562
|
});
|
|
1562
1563
|
});
|
|
@@ -1569,11 +1570,11 @@ describe("routing invariant: invite handoff bypass for access requests", () => {
|
|
|
1569
1570
|
beforeEach(() => resetTables());
|
|
1570
1571
|
|
|
1571
1572
|
test('pending access_request + message "open invite flow" returns not_consumed with skipApprovalInterception', async () => {
|
|
1572
|
-
const req =
|
|
1573
|
+
const req = sim.seedRequest({
|
|
1573
1574
|
kind: "access_request",
|
|
1574
1575
|
sourceType: "channel",
|
|
1575
1576
|
sourceChannel: "telegram",
|
|
1576
|
-
|
|
1577
|
+
sourceConversationId: "conv-access-1",
|
|
1577
1578
|
guardianExternalUserId: "guardian-1",
|
|
1578
1579
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1579
1580
|
requestCode: "INV001",
|
|
@@ -1596,12 +1597,12 @@ describe("routing invariant: invite handoff bypass for access requests", () => {
|
|
|
1596
1597
|
expect(result.skipApprovalInterception).toBe(true);
|
|
1597
1598
|
|
|
1598
1599
|
// Request remains pending — not resolved by the handoff
|
|
1599
|
-
const unchanged =
|
|
1600
|
+
const unchanged = sim.getRequest(req.id);
|
|
1600
1601
|
expect(unchanged!.status).toBe("pending");
|
|
1601
1602
|
});
|
|
1602
1603
|
|
|
1603
1604
|
test("invite handoff is case-insensitive and punctuation-trimmed", async () => {
|
|
1604
|
-
const req =
|
|
1605
|
+
const req = sim.seedRequest({
|
|
1605
1606
|
kind: "access_request",
|
|
1606
1607
|
sourceType: "channel",
|
|
1607
1608
|
sourceChannel: "telegram",
|
|
@@ -1631,10 +1632,10 @@ describe("routing invariant: invite handoff bypass for access requests", () => {
|
|
|
1631
1632
|
});
|
|
1632
1633
|
|
|
1633
1634
|
test("invite handoff does NOT bypass for non-access-request kinds", async () => {
|
|
1634
|
-
const req =
|
|
1635
|
+
const req = sim.seedRequest({
|
|
1635
1636
|
kind: "tool_approval",
|
|
1636
1637
|
sourceType: "channel",
|
|
1637
|
-
|
|
1638
|
+
sourceConversationId: "conv-1",
|
|
1638
1639
|
guardianExternalUserId: "guardian-1",
|
|
1639
1640
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1640
1641
|
requestCode: "TAP001",
|
|
@@ -1654,16 +1655,16 @@ describe("routing invariant: invite handoff bypass for access requests", () => {
|
|
|
1654
1655
|
// Should NOT return not_consumed via the invite handoff path.
|
|
1655
1656
|
// Without NL generator and no explicit approve/reject, it falls through
|
|
1656
1657
|
// to not_consumed anyway, but the key invariant is the request remains pending.
|
|
1657
|
-
const unchanged =
|
|
1658
|
+
const unchanged = sim.getRequest(req.id);
|
|
1658
1659
|
expect(unchanged!.status).toBe("pending");
|
|
1659
1660
|
});
|
|
1660
1661
|
|
|
1661
1662
|
test("explicit approve/reject messages still consume with pending access_request", async () => {
|
|
1662
|
-
const req =
|
|
1663
|
+
const req = sim.seedRequest({
|
|
1663
1664
|
kind: "access_request",
|
|
1664
1665
|
sourceType: "channel",
|
|
1665
1666
|
sourceChannel: "telegram",
|
|
1666
|
-
|
|
1667
|
+
sourceConversationId: "conv-access-2",
|
|
1667
1668
|
guardianExternalUserId: "guardian-1",
|
|
1668
1669
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1669
1670
|
requestCode: "A00B01",
|
|
@@ -1684,16 +1685,16 @@ describe("routing invariant: invite handoff bypass for access requests", () => {
|
|
|
1684
1685
|
expect(result.consumed).toBe(true);
|
|
1685
1686
|
expect(result.decisionApplied).toBe(true);
|
|
1686
1687
|
|
|
1687
|
-
const resolved =
|
|
1688
|
+
const resolved = sim.getRequest(req.id);
|
|
1688
1689
|
expect(resolved!.status).toBe("approved");
|
|
1689
1690
|
});
|
|
1690
1691
|
|
|
1691
1692
|
test("desktop access-request approval returns a verification code reply", async () => {
|
|
1692
|
-
const req =
|
|
1693
|
+
const req = sim.seedRequest({
|
|
1693
1694
|
kind: "access_request",
|
|
1694
1695
|
sourceType: "channel",
|
|
1695
1696
|
sourceChannel: "telegram",
|
|
1696
|
-
|
|
1697
|
+
sourceConversationId: "conv-access-desktop",
|
|
1697
1698
|
guardianExternalUserId: "guardian-1",
|
|
1698
1699
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1699
1700
|
requestCode: "C0D3A5",
|
|
@@ -1715,16 +1716,16 @@ describe("routing invariant: invite handoff bypass for access requests", () => {
|
|
|
1715
1716
|
expect(result.replyText).toContain("verification code");
|
|
1716
1717
|
expect(result.replyText).toMatch(/\b\d{6}\b/);
|
|
1717
1718
|
|
|
1718
|
-
const resolved =
|
|
1719
|
+
const resolved = sim.getRequest(req.id);
|
|
1719
1720
|
expect(resolved!.status).toBe("approved");
|
|
1720
1721
|
});
|
|
1721
1722
|
|
|
1722
1723
|
test("NL decision path preserves resolver verification code reply text", async () => {
|
|
1723
|
-
const req =
|
|
1724
|
+
const req = sim.seedRequest({
|
|
1724
1725
|
kind: "access_request",
|
|
1725
1726
|
sourceType: "channel",
|
|
1726
1727
|
sourceChannel: "telegram",
|
|
1727
|
-
|
|
1728
|
+
sourceConversationId: "conv-access-desktop-nl",
|
|
1728
1729
|
guardianExternalUserId: "guardian-1",
|
|
1729
1730
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1730
1731
|
requesterExternalUserId: "requester-1",
|
|
@@ -1756,7 +1757,7 @@ describe("routing invariant: invite handoff bypass for access requests", () => {
|
|
|
1756
1757
|
expect(result.replyText).toMatch(/\b\d{6}\b/);
|
|
1757
1758
|
expect(result.replyText).not.toBe("Access approved.");
|
|
1758
1759
|
|
|
1759
|
-
const resolved =
|
|
1760
|
+
const resolved = sim.getRequest(req.id);
|
|
1760
1761
|
expect(resolved!.status).toBe("approved");
|
|
1761
1762
|
});
|
|
1762
1763
|
});
|
|
@@ -1769,10 +1770,10 @@ describe("routing invariant: expired requests are excluded from pending discover
|
|
|
1769
1770
|
beforeEach(() => resetTables());
|
|
1770
1771
|
|
|
1771
1772
|
test("expired request with hinted IDs is excluded from disambiguation", async () => {
|
|
1772
|
-
const expired =
|
|
1773
|
+
const expired = sim.seedRequest({
|
|
1773
1774
|
kind: "tool_approval",
|
|
1774
1775
|
sourceType: "channel",
|
|
1775
|
-
|
|
1776
|
+
sourceConversationId: "conv-1",
|
|
1776
1777
|
guardianExternalUserId: "guardian-1",
|
|
1777
1778
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1778
1779
|
requestCode: "EXP001",
|
|
@@ -1780,10 +1781,10 @@ describe("routing invariant: expired requests are excluded from pending discover
|
|
|
1780
1781
|
expiresAt: Date.now() - 10_000,
|
|
1781
1782
|
});
|
|
1782
1783
|
|
|
1783
|
-
const active =
|
|
1784
|
+
const active = sim.seedRequest({
|
|
1784
1785
|
kind: "tool_approval",
|
|
1785
1786
|
sourceType: "channel",
|
|
1786
|
-
|
|
1787
|
+
sourceConversationId: "conv-1",
|
|
1787
1788
|
guardianExternalUserId: "guardian-1",
|
|
1788
1789
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1789
1790
|
requestCode: "ACT001",
|
|
@@ -1807,19 +1808,19 @@ describe("routing invariant: expired requests are excluded from pending discover
|
|
|
1807
1808
|
expect(result.type).toBe("canonical_decision_applied");
|
|
1808
1809
|
expect(result.decisionApplied).toBe(true);
|
|
1809
1810
|
|
|
1810
|
-
const resolvedActive =
|
|
1811
|
+
const resolvedActive = sim.getRequest(active.id);
|
|
1811
1812
|
expect(resolvedActive!.status).toBe("approved");
|
|
1812
1813
|
|
|
1813
1814
|
// Expired request untouched
|
|
1814
|
-
const resolvedExpired =
|
|
1815
|
+
const resolvedExpired = sim.getRequest(expired.id);
|
|
1815
1816
|
expect(resolvedExpired!.status).toBe("pending");
|
|
1816
1817
|
});
|
|
1817
1818
|
|
|
1818
1819
|
test("backtick-wrapped plain-text approve is normalized and applied", async () => {
|
|
1819
|
-
const req =
|
|
1820
|
+
const req = sim.seedRequest({
|
|
1820
1821
|
kind: "tool_approval",
|
|
1821
1822
|
sourceType: "channel",
|
|
1822
|
-
|
|
1823
|
+
sourceConversationId: "conv-1",
|
|
1823
1824
|
guardianExternalUserId: "guardian-1",
|
|
1824
1825
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1825
1826
|
requestCode: "FMT001",
|
|
@@ -1841,15 +1842,15 @@ describe("routing invariant: expired requests are excluded from pending discover
|
|
|
1841
1842
|
expect(result.type).toBe("canonical_decision_applied");
|
|
1842
1843
|
expect(result.decisionApplied).toBe(true);
|
|
1843
1844
|
|
|
1844
|
-
const resolved =
|
|
1845
|
+
const resolved = sim.getRequest(req.id);
|
|
1845
1846
|
expect(resolved!.status).toBe("approved");
|
|
1846
1847
|
});
|
|
1847
1848
|
|
|
1848
1849
|
test("all expired hinted requests means no pending found — not consumed", async () => {
|
|
1849
|
-
const expired1 =
|
|
1850
|
+
const expired1 = sim.seedRequest({
|
|
1850
1851
|
kind: "tool_approval",
|
|
1851
1852
|
sourceType: "channel",
|
|
1852
|
-
|
|
1853
|
+
sourceConversationId: "conv-1",
|
|
1853
1854
|
guardianExternalUserId: "guardian-1",
|
|
1854
1855
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1855
1856
|
requestCode: "EXP002",
|
|
@@ -1857,10 +1858,10 @@ describe("routing invariant: expired requests are excluded from pending discover
|
|
|
1857
1858
|
expiresAt: Date.now() - 10_000,
|
|
1858
1859
|
});
|
|
1859
1860
|
|
|
1860
|
-
const expired2 =
|
|
1861
|
+
const expired2 = sim.seedRequest({
|
|
1861
1862
|
kind: "tool_approval",
|
|
1862
1863
|
sourceType: "channel",
|
|
1863
|
-
|
|
1864
|
+
sourceConversationId: "conv-1",
|
|
1864
1865
|
guardianExternalUserId: "guardian-1",
|
|
1865
1866
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1866
1867
|
requestCode: "EXP003",
|
|
@@ -1914,21 +1915,23 @@ describe("routing invariant: kind-specific action sets in prompt mapping", () =>
|
|
|
1914
1915
|
});
|
|
1915
1916
|
|
|
1916
1917
|
// Integration tests: verify listGuardianDecisionPrompts returns correct
|
|
1917
|
-
// action sets for each
|
|
1918
|
+
// action sets for each guardian request kind.
|
|
1918
1919
|
|
|
1919
|
-
test("tool_approval prompt uses approve_once + reject only (one-time decision pattern)", () => {
|
|
1920
|
+
test("tool_approval prompt uses approve_once + reject only (one-time decision pattern)", async () => {
|
|
1920
1921
|
const convId = "conv-kind-tool-approval";
|
|
1921
|
-
|
|
1922
|
+
sim.seedRequest({
|
|
1922
1923
|
kind: "tool_approval",
|
|
1923
1924
|
sourceType: "channel",
|
|
1924
|
-
|
|
1925
|
+
sourceConversationId: convId,
|
|
1925
1926
|
guardianExternalUserId: "guardian-1",
|
|
1926
1927
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1927
1928
|
toolName: "shell",
|
|
1928
1929
|
expiresAt: Date.now() + 60_000,
|
|
1929
1930
|
});
|
|
1930
1931
|
|
|
1931
|
-
const prompts = listGuardianDecisionPrompts({
|
|
1932
|
+
const prompts = await listGuardianDecisionPrompts({
|
|
1933
|
+
conversationId: convId,
|
|
1934
|
+
});
|
|
1932
1935
|
expect(prompts).toHaveLength(1);
|
|
1933
1936
|
expect(prompts[0].actions.map((a) => a.action)).toEqual([
|
|
1934
1937
|
"approve_once",
|
|
@@ -1936,13 +1939,13 @@ describe("routing invariant: kind-specific action sets in prompt mapping", () =>
|
|
|
1936
1939
|
]);
|
|
1937
1940
|
});
|
|
1938
1941
|
|
|
1939
|
-
test("pending_question prompt has approve_once + reject only (no temporal actions)", () => {
|
|
1942
|
+
test("pending_question prompt has approve_once + reject only (no temporal actions)", async () => {
|
|
1940
1943
|
const convId = "conv-kind-pending-question";
|
|
1941
|
-
|
|
1944
|
+
sim.seedRequest({
|
|
1942
1945
|
kind: "pending_question",
|
|
1943
1946
|
sourceType: "voice",
|
|
1944
1947
|
sourceChannel: "phone",
|
|
1945
|
-
|
|
1948
|
+
sourceConversationId: convId,
|
|
1946
1949
|
guardianExternalUserId: "guardian-1",
|
|
1947
1950
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1948
1951
|
callSessionId: "call-pq",
|
|
@@ -1951,7 +1954,9 @@ describe("routing invariant: kind-specific action sets in prompt mapping", () =>
|
|
|
1951
1954
|
expiresAt: Date.now() + 60_000,
|
|
1952
1955
|
});
|
|
1953
1956
|
|
|
1954
|
-
const prompts = listGuardianDecisionPrompts({
|
|
1957
|
+
const prompts = await listGuardianDecisionPrompts({
|
|
1958
|
+
conversationId: convId,
|
|
1959
|
+
});
|
|
1955
1960
|
expect(prompts).toHaveLength(1);
|
|
1956
1961
|
|
|
1957
1962
|
const actionIds = prompts[0].actions.map((a) => a.action);
|
|
@@ -1960,20 +1965,22 @@ describe("routing invariant: kind-specific action sets in prompt mapping", () =>
|
|
|
1960
1965
|
expect(actionIds).not.toContain("approve_conversation");
|
|
1961
1966
|
});
|
|
1962
1967
|
|
|
1963
|
-
test("access_request prompt has approve_once + reject only (no temporal actions)", () => {
|
|
1968
|
+
test("access_request prompt has approve_once + reject only (no temporal actions)", async () => {
|
|
1964
1969
|
const convId = "conv-kind-access-request";
|
|
1965
|
-
|
|
1970
|
+
sim.seedRequest({
|
|
1966
1971
|
kind: "access_request",
|
|
1967
1972
|
sourceType: "channel",
|
|
1968
1973
|
sourceChannel: "telegram",
|
|
1969
|
-
|
|
1974
|
+
sourceConversationId: convId,
|
|
1970
1975
|
guardianExternalUserId: "guardian-1",
|
|
1971
1976
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1972
1977
|
toolName: "ingress_access_request",
|
|
1973
1978
|
expiresAt: Date.now() + 60_000,
|
|
1974
1979
|
});
|
|
1975
1980
|
|
|
1976
|
-
const prompts = listGuardianDecisionPrompts({
|
|
1981
|
+
const prompts = await listGuardianDecisionPrompts({
|
|
1982
|
+
conversationId: convId,
|
|
1983
|
+
});
|
|
1977
1984
|
expect(prompts).toHaveLength(1);
|
|
1978
1985
|
|
|
1979
1986
|
const actionIds = prompts[0].actions.map((a) => a.action);
|
|
@@ -1982,19 +1989,21 @@ describe("routing invariant: kind-specific action sets in prompt mapping", () =>
|
|
|
1982
1989
|
expect(actionIds).not.toContain("approve_conversation");
|
|
1983
1990
|
});
|
|
1984
1991
|
|
|
1985
|
-
test("tool_grant_request prompt has approve_once + reject only (no temporal actions)", () => {
|
|
1992
|
+
test("tool_grant_request prompt has approve_once + reject only (no temporal actions)", async () => {
|
|
1986
1993
|
const convId = "conv-kind-tool-grant-request";
|
|
1987
|
-
|
|
1994
|
+
sim.seedRequest({
|
|
1988
1995
|
kind: "tool_grant_request",
|
|
1989
1996
|
sourceType: "channel",
|
|
1990
|
-
|
|
1997
|
+
sourceConversationId: convId,
|
|
1991
1998
|
guardianExternalUserId: "guardian-1",
|
|
1992
1999
|
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
1993
2000
|
toolName: "file_write",
|
|
1994
2001
|
expiresAt: Date.now() + 60_000,
|
|
1995
2002
|
});
|
|
1996
2003
|
|
|
1997
|
-
const prompts = listGuardianDecisionPrompts({
|
|
2004
|
+
const prompts = await listGuardianDecisionPrompts({
|
|
2005
|
+
conversationId: convId,
|
|
2006
|
+
});
|
|
1998
2007
|
expect(prompts).toHaveLength(1);
|
|
1999
2008
|
|
|
2000
2009
|
const actionIds = prompts[0].actions.map((a) => a.action);
|
|
@@ -2030,12 +2039,12 @@ describe("routing invariant: surface action apr:* buttons route through canonica
|
|
|
2030
2039
|
|
|
2031
2040
|
test("processGuardianDecision approves access_request from vellum surface", async () => {
|
|
2032
2041
|
const requestId = `access-req-test-slack-U123-${Date.now()}`;
|
|
2033
|
-
|
|
2042
|
+
sim.seedRequest({
|
|
2034
2043
|
id: requestId,
|
|
2035
2044
|
kind: "access_request",
|
|
2036
2045
|
sourceType: "channel",
|
|
2037
2046
|
sourceChannel: "slack",
|
|
2038
|
-
|
|
2047
|
+
sourceConversationId: "conv-surface-test",
|
|
2039
2048
|
requesterExternalUserId: "U123",
|
|
2040
2049
|
requesterChatId: "D456",
|
|
2041
2050
|
guardianExternalUserId: "guardian-1",
|
|
@@ -2059,18 +2068,18 @@ describe("routing invariant: surface action apr:* buttons route through canonica
|
|
|
2059
2068
|
expect(result.applied).toBe(true);
|
|
2060
2069
|
}
|
|
2061
2070
|
|
|
2062
|
-
const resolved =
|
|
2071
|
+
const resolved = sim.getRequest(requestId);
|
|
2063
2072
|
expect(resolved!.status).toBe("approved");
|
|
2064
2073
|
});
|
|
2065
2074
|
|
|
2066
2075
|
test("processGuardianDecision denies access_request from vellum surface", async () => {
|
|
2067
2076
|
const requestId = `access-req-test-slack-U789-${Date.now()}`;
|
|
2068
|
-
|
|
2077
|
+
sim.seedRequest({
|
|
2069
2078
|
id: requestId,
|
|
2070
2079
|
kind: "access_request",
|
|
2071
2080
|
sourceType: "channel",
|
|
2072
2081
|
sourceChannel: "slack",
|
|
2073
|
-
|
|
2082
|
+
sourceConversationId: "conv-surface-deny",
|
|
2074
2083
|
requesterExternalUserId: "U789",
|
|
2075
2084
|
requesterChatId: "D012",
|
|
2076
2085
|
guardianExternalUserId: "guardian-1",
|
|
@@ -2094,18 +2103,18 @@ describe("routing invariant: surface action apr:* buttons route through canonica
|
|
|
2094
2103
|
expect(result.applied).toBe(true);
|
|
2095
2104
|
}
|
|
2096
2105
|
|
|
2097
|
-
const resolved =
|
|
2106
|
+
const resolved = sim.getRequest(requestId);
|
|
2098
2107
|
expect(resolved!.status).toBe("denied");
|
|
2099
2108
|
});
|
|
2100
2109
|
|
|
2101
2110
|
test("principal mismatch rejects surface action decision", async () => {
|
|
2102
2111
|
const requestId = `access-req-test-slack-U999-${Date.now()}`;
|
|
2103
|
-
|
|
2112
|
+
sim.seedRequest({
|
|
2104
2113
|
id: requestId,
|
|
2105
2114
|
kind: "access_request",
|
|
2106
2115
|
sourceType: "channel",
|
|
2107
2116
|
sourceChannel: "slack",
|
|
2108
|
-
|
|
2117
|
+
sourceConversationId: "conv-surface-mismatch",
|
|
2109
2118
|
requesterExternalUserId: "U999",
|
|
2110
2119
|
requesterChatId: "D345",
|
|
2111
2120
|
guardianExternalUserId: "guardian-1",
|
|
@@ -2129,7 +2138,7 @@ describe("routing invariant: surface action apr:* buttons route through canonica
|
|
|
2129
2138
|
expect(result.applied).toBe(false);
|
|
2130
2139
|
}
|
|
2131
2140
|
|
|
2132
|
-
const req =
|
|
2141
|
+
const req = sim.getRequest(requestId);
|
|
2133
2142
|
expect(req!.status).toBe("pending");
|
|
2134
2143
|
});
|
|
2135
2144
|
});
|