@vellumai/assistant 0.4.48 → 0.4.50
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/ARCHITECTURE.md +26 -35
- package/README.md +5 -26
- package/docs/architecture/integrations.md +45 -41
- package/docs/architecture/keychain-broker.md +3 -3
- package/docs/architecture/memory.md +180 -119
- package/docs/runbook-trusted-contacts.md +3 -8
- package/hook-templates/debug-prompt-logger/hook.json +1 -1
- package/hook-templates/debug-prompt-logger/run.sh +1 -3
- package/package.json +2 -2
- package/src/__tests__/actor-token-service.test.ts +0 -1
- package/src/__tests__/agent-loop.test.ts +3 -1
- package/src/__tests__/anthropic-provider.test.ts +249 -2
- package/src/__tests__/approval-cascade.test.ts +796 -0
- package/src/__tests__/approval-primitive.test.ts +0 -1
- package/src/__tests__/approval-routes-http.test.ts +4 -0
- package/src/__tests__/assistant-attachments.test.ts +12 -34
- package/src/__tests__/assistant-feature-flag-guard.test.ts +0 -23
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +76 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -1
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
- package/src/__tests__/canonical-guardian-store.test.ts +95 -0
- package/src/__tests__/channel-guardian.test.ts +0 -2
- package/src/__tests__/channel-readiness-routes.test.ts +15 -6
- package/src/__tests__/channel-readiness-service.test.ts +10 -9
- package/src/__tests__/checker.test.ts +13 -20
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
- package/src/__tests__/computer-use-tools.test.ts +2 -19
- package/src/__tests__/config-schema.test.ts +1 -68
- package/src/__tests__/config-watcher.test.ts +0 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
- package/src/__tests__/context-image-dimensions.test.ts +332 -0
- package/src/__tests__/context-memory-e2e.test.ts +11 -100
- package/src/__tests__/context-token-estimator.test.ts +196 -13
- package/src/__tests__/conversation-attention-store.test.ts +0 -1
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +152 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -0
- package/src/__tests__/credential-metadata-store.test.ts +64 -73
- package/src/__tests__/credential-security-e2e.test.ts +1 -0
- package/src/__tests__/credential-security-invariants.test.ts +13 -7
- package/src/__tests__/credential-vault-unit.test.ts +284 -49
- package/src/__tests__/credential-vault.test.ts +150 -16
- package/src/__tests__/credentials-cli.test.ts +71 -0
- package/src/__tests__/cu-unified-flow.test.ts +532 -0
- package/src/__tests__/date-context.test.ts +93 -77
- package/src/__tests__/deterministic-verification-control-plane.test.ts +64 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/ephemeral-permissions.test.ts +3 -3
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -1
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +0 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +93 -1
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -39
- package/src/__tests__/heartbeat-service.test.ts +0 -1
- package/src/__tests__/history-repair.test.ts +245 -0
- package/src/__tests__/host-cu-proxy.test.ts +791 -0
- package/src/__tests__/host-shell-tool.test.ts +27 -15
- package/src/__tests__/http-user-message-parity.test.ts +2 -0
- package/src/__tests__/ingress-url-consistency.test.ts +14 -21
- package/src/__tests__/integration-status.test.ts +32 -51
- package/src/__tests__/intent-routing.test.ts +0 -1
- package/src/__tests__/invite-redemption-service.test.ts +65 -1
- package/src/__tests__/invite-routes-http.test.ts +10 -9
- package/src/__tests__/keychain-broker-client.test.ts +14 -46
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +56 -18
- package/src/__tests__/memory-lifecycle-e2e.test.ts +244 -387
- package/src/__tests__/memory-recall-quality.test.ts +244 -407
- package/src/__tests__/memory-regressions.experimental.test.ts +126 -101
- package/src/__tests__/memory-regressions.test.ts +477 -2841
- package/src/__tests__/memory-retrieval.benchmark.test.ts +33 -150
- package/src/__tests__/memory-upsert-concurrency.test.ts +5 -244
- package/src/__tests__/mime-builder.test.ts +28 -0
- package/src/__tests__/native-web-search.test.ts +1 -0
- package/src/__tests__/notification-routing-intent.test.ts +0 -1
- package/src/__tests__/oauth-cli.test.ts +941 -15
- package/src/__tests__/oauth-provider-profiles.test.ts +9 -9
- package/src/__tests__/oauth-scope-policy.test.ts +4 -6
- package/src/__tests__/oauth-store.test.ts +870 -0
- package/src/__tests__/onboarding-starter-tasks.test.ts +0 -1
- package/src/__tests__/provider-error-scenarios.test.ts +0 -1
- package/src/__tests__/provider-streaming.benchmark.test.ts +0 -1
- package/src/__tests__/public-ingress-urls.test.ts +15 -21
- package/src/__tests__/qdrant-collection-migration.test.ts +53 -8
- package/src/__tests__/recording-handler.test.ts +3 -4
- package/src/__tests__/registry.test.ts +2 -3
- package/src/__tests__/relay-server.test.ts +46 -1
- package/src/__tests__/runtime-events-sse.test.ts +55 -7
- package/src/__tests__/schedule-store.test.ts +0 -1
- package/src/__tests__/schedule-tools.test.ts +32 -0
- package/src/__tests__/scheduler-recurrence.test.ts +0 -1
- package/src/__tests__/scoped-approval-grants.test.ts +0 -1
- package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -1
- package/src/__tests__/script-proxy-certs.test.ts +1 -1
- package/src/__tests__/secret-ingress-handler.test.ts +0 -1
- package/src/__tests__/secret-onetime-send.test.ts +1 -0
- package/src/__tests__/secure-keys.test.ts +7 -2
- package/src/__tests__/send-endpoint-busy.test.ts +24 -6
- package/src/__tests__/sequence-store.test.ts +0 -1
- package/src/__tests__/session-abort-tool-results.test.ts +1 -14
- package/src/__tests__/session-agent-loop-overflow.test.ts +1583 -0
- package/src/__tests__/session-agent-loop.test.ts +19 -15
- package/src/__tests__/session-confirmation-signals.test.ts +1 -15
- package/src/__tests__/session-error.test.ts +124 -2
- package/src/__tests__/session-history-web-search.test.ts +918 -0
- package/src/__tests__/session-init.benchmark.test.ts +4 -5
- package/src/__tests__/session-pre-run-repair.test.ts +1 -14
- package/src/__tests__/session-provider-retry-repair.test.ts +25 -28
- package/src/__tests__/session-queue.test.ts +37 -27
- package/src/__tests__/session-runtime-assembly.test.ts +54 -0
- package/src/__tests__/session-slash-known.test.ts +1 -15
- package/src/__tests__/session-slash-queue.test.ts +1 -15
- package/src/__tests__/session-slash-unknown.test.ts +1 -15
- package/src/__tests__/session-workspace-cache-state.test.ts +3 -33
- package/src/__tests__/session-workspace-injection.test.ts +3 -37
- package/src/__tests__/session-workspace-tool-tracking.test.ts +3 -37
- package/src/__tests__/skill-include-graph.test.ts +66 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +0 -1
- package/src/__tests__/skill-load-tool.test.ts +149 -1
- package/src/__tests__/skill-projection-feature-flag.test.ts +0 -1
- package/src/__tests__/skills-install-extract.test.ts +93 -0
- package/src/__tests__/skills-uninstall.test.ts +1 -1
- package/src/__tests__/skills.test.ts +3 -3
- package/src/__tests__/skillssh-registry.test.ts +451 -0
- package/src/__tests__/slack-channel-config.test.ts +67 -3
- package/src/__tests__/slack-share-routes.test.ts +17 -19
- package/src/__tests__/system-prompt.test.ts +0 -1
- package/src/__tests__/telegram-invite-adapter.test.ts +18 -22
- package/src/__tests__/terminal-tools.test.ts +4 -3
- package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
- package/src/__tests__/tool-approval-handler.test.ts +0 -1
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
- package/src/__tests__/tool-executor-shell-integration.test.ts +0 -1
- package/src/__tests__/tool-executor.test.ts +0 -1
- package/src/__tests__/tool-grant-request-escalation.test.ts +0 -1
- package/src/__tests__/trust-store-pattern-matches.test.ts +29 -0
- package/src/__tests__/trust-store.test.ts +7 -13
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
- package/src/__tests__/twilio-routes.test.ts +0 -16
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -1
- package/src/__tests__/voice-invite-redemption.test.ts +32 -1
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
- package/src/agent/ax-tree-compaction.test.ts +286 -0
- package/src/agent/loop.ts +104 -131
- package/src/approvals/AGENTS.md +1 -1
- package/src/approvals/guardian-request-resolvers.ts +14 -2
- package/src/bundler/compiler-tools.ts +66 -2
- package/src/calls/call-domain.ts +133 -6
- package/src/calls/call-store.ts +6 -0
- package/src/calls/relay-server.ts +52 -18
- package/src/calls/relay-setup-router.ts +17 -1
- package/src/calls/twilio-config.ts +3 -8
- package/src/calls/twilio-routes.ts +1 -2
- package/src/calls/types.ts +3 -1
- package/src/calls/voice-ingress-preflight.ts +1 -1
- package/src/cli/commands/browser-relay.ts +18 -12
- package/src/cli/commands/completions.ts +0 -3
- package/src/cli/commands/credentials.ts +101 -15
- package/src/cli/commands/doctor.ts +4 -3
- package/src/cli/commands/mcp.ts +46 -59
- package/src/cli/commands/memory.ts +16 -165
- package/src/cli/commands/oauth/apps.ts +284 -0
- package/src/cli/commands/oauth/connections.ts +633 -0
- package/src/cli/commands/oauth/index.ts +52 -0
- package/src/cli/commands/oauth/providers.ts +256 -0
- package/src/cli/commands/sessions.ts +5 -2
- package/src/cli/commands/skills.ts +177 -339
- package/src/cli/http-client.ts +0 -20
- package/src/cli/main-screen.tsx +2 -2
- package/src/cli/program.ts +6 -11
- package/src/cli/reference.ts +1 -3
- package/src/cli.ts +4 -10
- package/src/config/assistant-feature-flags.ts +0 -3
- package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +1 -1
- package/src/config/bundled-skills/computer-use/SKILL.md +3 -6
- package/src/config/bundled-skills/computer-use/TOOLS.json +23 -5
- package/src/config/bundled-skills/computer-use/tools/{computer-use-request-control.ts → computer-use-observe.ts} +1 -5
- package/src/config/bundled-skills/google-calendar/calendar-client.ts +21 -16
- package/src/config/bundled-skills/messaging/tools/shared.ts +1 -4
- package/src/config/bundled-skills/settings/SKILL.md +1 -1
- package/src/config/bundled-skills/settings/TOOLS.json +2 -8
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +5 -33
- package/src/config/bundled-tool-registry.ts +2 -5
- package/src/config/env-registry.ts +14 -83
- package/src/config/env.ts +11 -50
- package/src/config/feature-flag-registry.json +16 -16
- package/src/config/loader.ts +0 -6
- package/src/config/schema.ts +4 -13
- package/src/config/schemas/memory-lifecycle.ts +0 -9
- package/src/config/schemas/memory-processing.ts +0 -180
- package/src/config/schemas/memory-retrieval.ts +32 -104
- package/src/config/schemas/memory.ts +0 -10
- package/src/config/skills.ts +21 -2
- package/src/config/types.ts +0 -4
- package/src/context/image-dimensions.ts +229 -0
- package/src/context/token-estimator.ts +75 -12
- package/src/context/window-manager.ts +53 -11
- package/src/daemon/assistant-attachments.ts +1 -13
- package/src/daemon/config-watcher.ts +61 -3
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/date-context.ts +114 -31
- package/src/daemon/handlers/config-ingress.ts +8 -33
- package/src/daemon/handlers/config-slack-channel.ts +49 -46
- package/src/daemon/handlers/config-telegram.ts +32 -16
- package/src/daemon/handlers/sessions.ts +27 -36
- package/src/daemon/handlers/shared.ts +0 -130
- package/src/daemon/handlers/skills.ts +20 -1
- package/src/daemon/history-repair.ts +72 -8
- package/src/daemon/host-cu-proxy.ts +430 -0
- package/src/daemon/lifecycle.ts +67 -71
- package/src/daemon/mcp-reload-service.ts +2 -2
- package/src/daemon/message-protocol.ts +3 -0
- package/src/daemon/message-types/computer-use.ts +1 -129
- package/src/daemon/message-types/host-cu.ts +19 -0
- package/src/daemon/message-types/memory.ts +4 -16
- package/src/daemon/message-types/messages.ts +4 -0
- package/src/daemon/message-types/sessions.ts +4 -0
- package/src/daemon/server.ts +25 -21
- package/src/daemon/session-agent-loop-handlers.ts +40 -0
- package/src/daemon/session-agent-loop.ts +334 -48
- package/src/daemon/session-attachments.ts +1 -2
- package/src/daemon/session-error.ts +89 -6
- package/src/daemon/session-history.ts +17 -7
- package/src/daemon/session-media-retry.ts +6 -2
- package/src/daemon/session-memory.ts +69 -149
- package/src/daemon/session-process.ts +10 -1
- package/src/daemon/session-runtime-assembly.ts +49 -19
- package/src/daemon/session-slash.ts +1 -1
- package/src/daemon/session-surfaces.ts +43 -28
- package/src/daemon/session-tool-setup.ts +9 -10
- package/src/daemon/session.ts +150 -17
- package/src/daemon/tool-side-effects.ts +2 -8
- package/src/daemon/watch-handler.ts +2 -2
- package/src/events/tool-metrics-listener.ts +2 -2
- package/src/hooks/manager.ts +1 -4
- package/src/inbound/public-ingress-urls.ts +7 -7
- package/src/instrument.ts +61 -1
- package/src/logfire.ts +16 -5
- package/src/memory/admin.ts +2 -191
- package/src/memory/canonical-guardian-store.ts +38 -2
- package/src/memory/conversation-crud.ts +0 -33
- package/src/memory/conversation-key-store.ts +21 -0
- package/src/memory/conversation-queries.ts +22 -3
- package/src/memory/db-init.ts +32 -0
- package/src/memory/embedding-backend.ts +84 -8
- package/src/memory/embedding-types.ts +9 -1
- package/src/memory/indexer.ts +7 -46
- package/src/memory/items-extractor.ts +274 -76
- package/src/memory/job-handlers/backfill.ts +2 -127
- package/src/memory/job-handlers/cleanup.ts +2 -16
- package/src/memory/job-handlers/extraction.ts +2 -138
- package/src/memory/job-handlers/index-maintenance.ts +1 -6
- package/src/memory/job-handlers/summarization.ts +3 -148
- package/src/memory/job-utils.ts +21 -59
- package/src/memory/jobs-store.ts +1 -159
- package/src/memory/jobs-worker.ts +9 -52
- package/src/memory/migrations/104-core-indexes.ts +3 -3
- package/src/memory/migrations/149-oauth-tables.ts +62 -0
- package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +98 -0
- package/src/memory/migrations/151-oauth-providers-ping-url.ts +11 -0
- package/src/memory/migrations/152-memory-item-supersession.ts +44 -0
- package/src/memory/migrations/153-drop-entity-tables.ts +15 -0
- package/src/memory/migrations/154-drop-fts.ts +20 -0
- package/src/memory/migrations/155-drop-conflicts.ts +7 -0
- package/src/memory/migrations/156-call-session-invite-metadata.ts +24 -0
- package/src/memory/migrations/index.ts +8 -0
- package/src/memory/qdrant-client.ts +148 -51
- package/src/memory/raw-query.ts +1 -1
- package/src/memory/retriever.test.ts +294 -273
- package/src/memory/retriever.ts +421 -645
- package/src/memory/schema/calls.ts +2 -0
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/memory-core.ts +3 -48
- package/src/memory/schema/oauth.ts +67 -0
- package/src/memory/search/formatting.ts +263 -176
- package/src/memory/search/lexical.ts +1 -254
- package/src/memory/search/ranking.ts +0 -455
- package/src/memory/search/semantic.ts +100 -14
- package/src/memory/search/staleness.ts +47 -0
- package/src/memory/search/tier-classifier.ts +21 -0
- package/src/memory/search/types.ts +15 -77
- package/src/memory/task-memory-cleanup.ts +4 -6
- package/src/messaging/provider.ts +4 -4
- package/src/messaging/providers/gmail/client.ts +82 -2
- package/src/messaging/providers/gmail/mime-builder.ts +17 -7
- package/src/messaging/providers/gmail/people-client.ts +10 -10
- package/src/messaging/providers/telegram-bot/adapter.ts +17 -17
- package/src/messaging/providers/whatsapp/adapter.ts +11 -8
- package/src/messaging/registry.ts +2 -32
- package/src/notifications/copy-composer.ts +0 -5
- package/src/notifications/signal.ts +4 -5
- package/src/oauth/byo-connection.test.ts +133 -25
- package/src/oauth/byo-connection.ts +22 -6
- package/src/oauth/connect-orchestrator.ts +113 -57
- package/src/oauth/connect-types.ts +17 -23
- package/src/oauth/connection-resolver.ts +35 -11
- package/src/oauth/connection.ts +1 -1
- package/src/oauth/manual-token-connection.ts +104 -0
- package/src/oauth/oauth-store.ts +582 -0
- package/src/oauth/platform-connection.test.ts +29 -0
- package/src/oauth/platform-connection.ts +6 -5
- package/src/oauth/provider-behaviors.ts +124 -0
- package/src/oauth/scope-policy.ts +9 -2
- package/src/oauth/seed-providers.ts +167 -0
- package/src/oauth/token-persistence.ts +81 -77
- package/src/permissions/checker.ts +3 -3
- package/src/permissions/defaults.ts +1 -1
- package/src/permissions/prompter.ts +10 -1
- package/src/permissions/trust-store.ts +36 -1
- package/src/playbooks/playbook-compiler.ts +1 -1
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +3 -1
- package/src/prompts/system-prompt.ts +46 -42
- package/src/providers/anthropic/client.ts +59 -20
- package/src/providers/retry.ts +1 -27
- package/src/providers/types.ts +7 -1
- package/src/runtime/AGENTS.md +9 -0
- package/src/runtime/auth/route-policy.ts +6 -6
- package/src/runtime/channel-reply-delivery.ts +0 -40
- package/src/runtime/gateway-client.ts +0 -7
- package/src/runtime/guardian-reply-router.ts +24 -22
- package/src/runtime/http-server.ts +10 -8
- package/src/runtime/http-types.ts +2 -2
- package/src/runtime/invite-redemption-service.ts +19 -1
- package/src/runtime/invite-service.ts +25 -0
- package/src/runtime/middleware/twilio-validation.ts +1 -11
- package/src/runtime/pending-interactions.ts +14 -12
- package/src/runtime/routes/brain-graph-routes.ts +10 -90
- package/src/runtime/routes/channel-delivery-routes.ts +0 -1
- package/src/runtime/routes/conversation-routes.ts +81 -19
- package/src/runtime/routes/events-routes.ts +21 -11
- package/src/runtime/routes/host-cu-routes.ts +97 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +21 -12
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +12 -111
- package/src/runtime/routes/integrations/slack/share.ts +6 -7
- package/src/runtime/routes/log-export-routes.ts +126 -8
- package/src/runtime/routes/memory-item-routes.test.ts +754 -0
- package/src/runtime/routes/memory-item-routes.ts +503 -0
- package/src/runtime/routes/session-management-routes.ts +3 -3
- package/src/runtime/routes/settings-routes.ts +55 -48
- package/src/runtime/routes/surface-action-routes.ts +1 -1
- package/src/runtime/routes/trust-rules-routes.ts +14 -0
- package/src/runtime/routes/watch-routes.ts +128 -0
- package/src/runtime/routes/workspace-routes.ts +2 -1
- package/src/schedule/integration-status.ts +10 -9
- package/src/security/credential-key.ts +0 -156
- package/src/security/keychain-broker-client.ts +22 -10
- package/src/security/oauth2.ts +1 -1
- package/src/security/secure-keys.ts +25 -3
- package/src/security/token-manager.ts +137 -64
- package/src/skills/catalog-install.ts +414 -0
- package/src/skills/include-graph.ts +32 -0
- package/src/skills/skillssh-registry.ts +503 -0
- package/src/telegram/bot-username.ts +2 -3
- package/src/tools/assets/search.ts +5 -1
- package/src/tools/browser/network-recorder.ts +1 -1
- package/src/tools/browser/network-recording-types.ts +1 -1
- package/src/tools/computer-use/definitions.ts +36 -11
- package/src/tools/computer-use/registry.ts +5 -6
- package/src/tools/credentials/broker.ts +1 -2
- package/src/tools/credentials/metadata-store.ts +17 -121
- package/src/tools/credentials/vault.ts +92 -167
- package/src/tools/memory/definitions.ts +4 -13
- package/src/tools/memory/handlers.test.ts +83 -103
- package/src/tools/memory/handlers.ts +50 -85
- package/src/tools/registry.ts +2 -7
- package/src/tools/schedule/create.ts +8 -1
- package/src/tools/schedule/update.ts +8 -1
- package/src/tools/skills/load.ts +85 -3
- package/src/tools/watch/watch-state.ts +0 -12
- package/src/util/logger.ts +7 -41
- package/src/util/platform.ts +9 -28
- package/src/watcher/providers/google-calendar.ts +2 -1
- package/src/__tests__/clarification-resolver.test.ts +0 -193
- package/src/__tests__/computer-use-session-compaction.test.ts +0 -143
- package/src/__tests__/computer-use-session-lifecycle.test.ts +0 -322
- package/src/__tests__/computer-use-session-working-dir.test.ts +0 -166
- package/src/__tests__/computer-use-skill-baseline.test.ts +0 -78
- package/src/__tests__/computer-use-skill-endstate.test.ts +0 -105
- package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +0 -249
- package/src/__tests__/conflict-intent-tokenization.test.ts +0 -160
- package/src/__tests__/conflict-policy.test.ts +0 -269
- package/src/__tests__/conflict-store.test.ts +0 -372
- package/src/__tests__/contradiction-checker.test.ts +0 -361
- package/src/__tests__/entity-extractor.test.ts +0 -211
- package/src/__tests__/entity-search.test.ts +0 -1117
- package/src/__tests__/profile-compiler.test.ts +0 -392
- package/src/__tests__/ride-shotgun-handler.test.ts +0 -452
- package/src/__tests__/session-conflict-gate.test.ts +0 -1228
- package/src/__tests__/session-profile-injection.test.ts +0 -557
- package/src/cli/commands/dev.ts +0 -129
- package/src/cli/commands/map.ts +0 -391
- package/src/cli/commands/oauth.ts +0 -77
- package/src/config/bundled-skills/knowledge-graph/SKILL.md +0 -25
- package/src/config/bundled-skills/knowledge-graph/TOOLS.json +0 -66
- package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +0 -211
- package/src/daemon/computer-use-session.ts +0 -1026
- package/src/daemon/ride-shotgun-handler.ts +0 -569
- package/src/daemon/session-conflict-gate.ts +0 -167
- package/src/daemon/session-dynamic-profile.ts +0 -77
- package/src/memory/clarification-resolver.ts +0 -417
- package/src/memory/conflict-intent.ts +0 -205
- package/src/memory/conflict-policy.ts +0 -127
- package/src/memory/conflict-store.ts +0 -410
- package/src/memory/contradiction-checker.ts +0 -508
- package/src/memory/entity-extractor.ts +0 -535
- package/src/memory/format-recall.ts +0 -47
- package/src/memory/fts-reconciler.ts +0 -165
- package/src/memory/job-handlers/conflict.ts +0 -200
- package/src/memory/profile-compiler.ts +0 -195
- package/src/memory/recall-cache.ts +0 -117
- package/src/memory/search/entity.ts +0 -535
- package/src/memory/search/query-expansion.test.ts +0 -70
- package/src/memory/search/query-expansion.ts +0 -118
- package/src/oauth/provider-base-urls.ts +0 -21
- package/src/oauth/provider-profiles.ts +0 -192
- package/src/prompts/computer-use-prompt.ts +0 -98
- package/src/runtime/routes/computer-use-routes.ts +0 -641
- package/src/runtime/routes/mcp-routes.ts +0 -20
- package/src/runtime/telegram-streaming-delivery.test.ts +0 -729
- package/src/runtime/telegram-streaming-delivery.ts +0 -393
- package/src/tools/computer-use/request-computer-control.ts +0 -56
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
import { beforeAll, describe, expect, mock, test } from "bun:test";
|
|
2
|
-
|
|
3
|
-
// Mock config before importing modules that depend on it.
|
|
4
|
-
mock.module("../config/loader.js", () => ({
|
|
5
|
-
getConfig: () => ({
|
|
6
|
-
ui: {},
|
|
7
|
-
|
|
8
|
-
provider: "mock-provider",
|
|
9
|
-
permissions: { mode: "workspace" },
|
|
10
|
-
apiKeys: {},
|
|
11
|
-
sandbox: { enabled: false },
|
|
12
|
-
timeouts: { toolExecutionTimeoutSec: 30, permissionTimeoutSec: 5 },
|
|
13
|
-
skills: { load: { extraDirs: [] } },
|
|
14
|
-
secretDetection: { enabled: false },
|
|
15
|
-
contextWindow: {
|
|
16
|
-
enabled: true,
|
|
17
|
-
maxInputTokens: 180000,
|
|
18
|
-
targetBudgetRatio: 0.30,
|
|
19
|
-
compactThreshold: 0.8, summaryBudgetRatio: 0.05,
|
|
20
|
-
},
|
|
21
|
-
}),
|
|
22
|
-
invalidateConfigCache: () => {},
|
|
23
|
-
}));
|
|
24
|
-
|
|
25
|
-
import { ComputerUseSession } from "../daemon/computer-use-session.js";
|
|
26
|
-
import type { CuObservation } from "../daemon/message-protocol.js";
|
|
27
|
-
import type { Provider, ProviderResponse } from "../providers/types.js";
|
|
28
|
-
import {
|
|
29
|
-
__resetRegistryForTesting,
|
|
30
|
-
getAllTools,
|
|
31
|
-
getSkillRefCount,
|
|
32
|
-
initializeTools,
|
|
33
|
-
} from "../tools/registry.js";
|
|
34
|
-
|
|
35
|
-
function createProvider(responses: ProviderResponse[]): Provider {
|
|
36
|
-
let calls = 0;
|
|
37
|
-
return {
|
|
38
|
-
name: "mock",
|
|
39
|
-
async sendMessage() {
|
|
40
|
-
const response = responses[calls] ?? responses[responses.length - 1];
|
|
41
|
-
calls++;
|
|
42
|
-
return response;
|
|
43
|
-
},
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const doneResponse: ProviderResponse = {
|
|
48
|
-
content: [
|
|
49
|
-
{
|
|
50
|
-
type: "tool_use",
|
|
51
|
-
id: "tu-cleanup",
|
|
52
|
-
name: "computer_use_done",
|
|
53
|
-
input: { summary: "Done" },
|
|
54
|
-
},
|
|
55
|
-
],
|
|
56
|
-
model: "mock-model",
|
|
57
|
-
usage: { inputTokens: 10, outputTokens: 5 },
|
|
58
|
-
stopReason: "tool_use",
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
const observation: CuObservation = {
|
|
62
|
-
type: "cu_observation",
|
|
63
|
-
sessionId: "cleanup-test",
|
|
64
|
-
axTree: 'Window "Test" [1]',
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
describe("CU session skill tool lifecycle cleanup", () => {
|
|
68
|
-
beforeAll(async () => {
|
|
69
|
-
__resetRegistryForTesting();
|
|
70
|
-
await initializeTools();
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test("computer-use skill refcount is 0 after session completes via computer_use_done", async () => {
|
|
74
|
-
const provider = createProvider([doneResponse]);
|
|
75
|
-
const session = new ComputerUseSession(
|
|
76
|
-
"cleanup-done",
|
|
77
|
-
"test cleanup",
|
|
78
|
-
1440,
|
|
79
|
-
900,
|
|
80
|
-
provider,
|
|
81
|
-
() => {},
|
|
82
|
-
"computer_use",
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
expect(getSkillRefCount("computer-use")).toBe(0);
|
|
86
|
-
|
|
87
|
-
await session.handleObservation({
|
|
88
|
-
...observation,
|
|
89
|
-
sessionId: "cleanup-done",
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
expect(session.getState()).toBe("complete");
|
|
93
|
-
expect(getSkillRefCount("computer-use")).toBe(0);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
test("computer-use skill refcount is 0 after session is aborted", async () => {
|
|
97
|
-
// Use a provider that hangs until the abort signal fires, keeping the
|
|
98
|
-
// session active long enough to abort after skill projection has occurred.
|
|
99
|
-
const hangingProvider: Provider = {
|
|
100
|
-
name: "mock",
|
|
101
|
-
sendMessage: (_msgs, _tools, _sys, opts) =>
|
|
102
|
-
new Promise<ProviderResponse>((_, reject) => {
|
|
103
|
-
if (opts?.signal?.aborted) {
|
|
104
|
-
reject(new DOMException("Aborted", "AbortError"));
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
opts?.signal?.addEventListener(
|
|
108
|
-
"abort",
|
|
109
|
-
() => reject(new DOMException("Aborted", "AbortError")),
|
|
110
|
-
{ once: true },
|
|
111
|
-
);
|
|
112
|
-
}),
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
const session = new ComputerUseSession(
|
|
116
|
-
"cleanup-abort",
|
|
117
|
-
"test abort cleanup",
|
|
118
|
-
1440,
|
|
119
|
-
900,
|
|
120
|
-
hangingProvider,
|
|
121
|
-
() => {},
|
|
122
|
-
"computer_use",
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
expect(getSkillRefCount("computer-use")).toBe(0);
|
|
126
|
-
|
|
127
|
-
// Start the session (don't await — it will hang on the provider call).
|
|
128
|
-
// Skill projection happens synchronously at the start of runAgentLoop,
|
|
129
|
-
// so by the time sendMessage is called the refcount has been incremented.
|
|
130
|
-
const sessionPromise = session.handleObservation({
|
|
131
|
-
...observation,
|
|
132
|
-
sessionId: "cleanup-abort",
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
// Yield to let runAgentLoop start and reach the provider call
|
|
136
|
-
await new Promise((r) => setTimeout(r, 50));
|
|
137
|
-
|
|
138
|
-
session.abort();
|
|
139
|
-
|
|
140
|
-
// Let the session finish its cleanup
|
|
141
|
-
await sessionPromise;
|
|
142
|
-
|
|
143
|
-
expect(session.getState()).toBe("error");
|
|
144
|
-
expect(getSkillRefCount("computer-use")).toBe(0);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
test("computer-use skill refcount is 0 after session completes via computer_use_respond", async () => {
|
|
148
|
-
const provider = createProvider([
|
|
149
|
-
{
|
|
150
|
-
content: [
|
|
151
|
-
{
|
|
152
|
-
type: "tool_use",
|
|
153
|
-
id: "tu-respond-cleanup",
|
|
154
|
-
name: "computer_use_respond",
|
|
155
|
-
input: { answer: "Test answer", reasoning: "Test reasoning" },
|
|
156
|
-
},
|
|
157
|
-
],
|
|
158
|
-
model: "mock-model",
|
|
159
|
-
usage: { inputTokens: 10, outputTokens: 5 },
|
|
160
|
-
stopReason: "tool_use",
|
|
161
|
-
},
|
|
162
|
-
]);
|
|
163
|
-
|
|
164
|
-
const session = new ComputerUseSession(
|
|
165
|
-
"cleanup-respond",
|
|
166
|
-
"test respond cleanup",
|
|
167
|
-
1440,
|
|
168
|
-
900,
|
|
169
|
-
provider,
|
|
170
|
-
() => {},
|
|
171
|
-
"computer_use",
|
|
172
|
-
);
|
|
173
|
-
|
|
174
|
-
await session.handleObservation({
|
|
175
|
-
...observation,
|
|
176
|
-
sessionId: "cleanup-respond",
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
expect(session.getState()).toBe("complete");
|
|
180
|
-
expect(getSkillRefCount("computer-use")).toBe(0);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
test("only escalation tool remains in registry after session cleanup", async () => {
|
|
184
|
-
const provider = createProvider([doneResponse]);
|
|
185
|
-
const session = new ComputerUseSession(
|
|
186
|
-
"cleanup-registry-check",
|
|
187
|
-
"test registry cleanup",
|
|
188
|
-
1440,
|
|
189
|
-
900,
|
|
190
|
-
provider,
|
|
191
|
-
() => {},
|
|
192
|
-
"computer_use",
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
await session.handleObservation({
|
|
196
|
-
...observation,
|
|
197
|
-
sessionId: "cleanup-registry-check",
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
expect(session.getState()).toBe("complete");
|
|
201
|
-
|
|
202
|
-
const allTools = getAllTools();
|
|
203
|
-
const cuTools = allTools.filter((t) => t.name.startsWith("computer_use_"));
|
|
204
|
-
expect(cuTools).toHaveLength(1);
|
|
205
|
-
expect(cuTools[0].name).toBe("computer_use_request_control");
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
test("multiple sequential CU sessions do not leak refcounts", async () => {
|
|
209
|
-
for (let i = 0; i < 3; i++) {
|
|
210
|
-
const provider = createProvider([doneResponse]);
|
|
211
|
-
const session = new ComputerUseSession(
|
|
212
|
-
`cleanup-sequential-${i}`,
|
|
213
|
-
"test sequential cleanup",
|
|
214
|
-
1440,
|
|
215
|
-
900,
|
|
216
|
-
provider,
|
|
217
|
-
() => {},
|
|
218
|
-
"computer_use",
|
|
219
|
-
);
|
|
220
|
-
|
|
221
|
-
await session.handleObservation({
|
|
222
|
-
...observation,
|
|
223
|
-
sessionId: `cleanup-sequential-${i}`,
|
|
224
|
-
});
|
|
225
|
-
expect(session.getState()).toBe("complete");
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
expect(getSkillRefCount("computer-use")).toBe(0);
|
|
229
|
-
|
|
230
|
-
const allTools = getAllTools();
|
|
231
|
-
const cuTools = allTools.filter((t) => t.name.startsWith("computer_use_"));
|
|
232
|
-
expect(cuTools).toHaveLength(1);
|
|
233
|
-
expect(cuTools[0].name).toBe("computer_use_request_control");
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
// Cross-suite regression: after CU sessions complete, core registry invariants hold
|
|
237
|
-
test("core registry has 1 computer_use_* tool after CU session lifecycle (escalation only)", () => {
|
|
238
|
-
const allTools = getAllTools();
|
|
239
|
-
const cuTools = allTools.filter((t) => t.name.startsWith("computer_use_"));
|
|
240
|
-
expect(cuTools).toHaveLength(1);
|
|
241
|
-
expect(cuTools[0].name).toBe("computer_use_request_control");
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
test("computer_use_request_control is in core registry after CU session lifecycle", async () => {
|
|
245
|
-
const { getTool } = await import("../tools/registry.js");
|
|
246
|
-
const tool = getTool("computer_use_request_control");
|
|
247
|
-
expect(tool).toBeDefined();
|
|
248
|
-
});
|
|
249
|
-
});
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
areStatementsCoherent,
|
|
5
|
-
computeConflictRelevance,
|
|
6
|
-
overlapRatio as _overlapRatio,
|
|
7
|
-
tokenizeForConflictRelevance as _tokenizeForConflictRelevance,
|
|
8
|
-
} from "../memory/conflict-intent.js";
|
|
9
|
-
|
|
10
|
-
describe("tokenizeForConflictRelevance hardening", () => {
|
|
11
|
-
test("excludes numeric-only tokens from relevance", () => {
|
|
12
|
-
const relevance = computeConflictRelevance("Check PR 5526", {
|
|
13
|
-
existingStatement: "Track PR 5525 for review.",
|
|
14
|
-
candidateStatement: "Track PR 5526 for review.",
|
|
15
|
-
});
|
|
16
|
-
// Numeric tokens "5526" and "5525" should be excluded, so overlap is minimal
|
|
17
|
-
expect(relevance).toBeLessThan(0.5);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
test("excludes URL boilerplate tokens from relevance", () => {
|
|
21
|
-
const relevance = computeConflictRelevance(
|
|
22
|
-
"Check https://github.com/org/repo/pull/123",
|
|
23
|
-
{
|
|
24
|
-
existingStatement: "Review https://github.com/org/repo/pull/456",
|
|
25
|
-
candidateStatement: "Review https://github.com/org/repo/pull/789",
|
|
26
|
-
},
|
|
27
|
-
);
|
|
28
|
-
// URL tokens like "https", "github", "pull" should be excluded;
|
|
29
|
-
// only real content tokens like "repo" remain, keeping relevance low
|
|
30
|
-
expect(relevance).toBeLessThanOrEqual(0.5);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test("URL-embedded tracking tokens are stripped, standalone usage preserved", () => {
|
|
34
|
-
// URLs containing "issue", "pull", etc. are stripped entirely before tokenizing
|
|
35
|
-
const urlRelevance = computeConflictRelevance(
|
|
36
|
-
"Check https://github.com/org/repo/issues/42",
|
|
37
|
-
{
|
|
38
|
-
existingStatement: "Review https://github.com/org/repo/issues/10",
|
|
39
|
-
candidateStatement: "Review https://github.com/org/repo/issues/11",
|
|
40
|
-
},
|
|
41
|
-
);
|
|
42
|
-
expect(urlRelevance).toBeLessThanOrEqual(0.5);
|
|
43
|
-
|
|
44
|
-
// Standalone "issue" is preserved as a meaningful token
|
|
45
|
-
const standaloneRelevance = computeConflictRelevance(
|
|
46
|
-
"should I file an issue?",
|
|
47
|
-
{
|
|
48
|
-
existingStatement: "File an issue when bugs are found.",
|
|
49
|
-
candidateStatement: "Skip filing an issue for minor bugs.",
|
|
50
|
-
},
|
|
51
|
-
);
|
|
52
|
-
expect(standaloneRelevance).toBeGreaterThan(0);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test("strips scheme-less bare domain URLs from relevance", () => {
|
|
56
|
-
const relevance = computeConflictRelevance(
|
|
57
|
-
"Check github.com/org/repo/pull/123",
|
|
58
|
-
{
|
|
59
|
-
existingStatement: "Review gitlab.com/org/repo/issues/456",
|
|
60
|
-
candidateStatement: "Review github.com/org/repo/pull/789",
|
|
61
|
-
},
|
|
62
|
-
);
|
|
63
|
-
// Bare URLs should be stripped entirely; tokens like "pull", "issues"
|
|
64
|
-
// embedded in paths must not contribute to overlap
|
|
65
|
-
expect(relevance).toBeLessThanOrEqual(0.5);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
test("preserves dotted identifiers that look like file paths", () => {
|
|
69
|
-
const relevance = computeConflictRelevance("Use index.ts/runtime parser", {
|
|
70
|
-
existingStatement: "Keep index.ts/runtime approach.",
|
|
71
|
-
candidateStatement: "Switch to config.ts/runtime approach.",
|
|
72
|
-
});
|
|
73
|
-
// File-like identifiers should NOT be stripped as URLs
|
|
74
|
-
expect(relevance).toBeGreaterThan(0);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test("still computes meaningful relevance for real content tokens", () => {
|
|
78
|
-
const relevance = computeConflictRelevance(
|
|
79
|
-
"Should I use React for frontend?",
|
|
80
|
-
{
|
|
81
|
-
existingStatement: "Use React for frontend work.",
|
|
82
|
-
candidateStatement: "Use Vue for frontend work.",
|
|
83
|
-
},
|
|
84
|
-
);
|
|
85
|
-
// Real content tokens like "react", "frontend" should still match
|
|
86
|
-
expect(relevance).toBeGreaterThan(0);
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
describe("statement coherence (areStatementsCoherent)", () => {
|
|
91
|
-
test("unrelated statements are incoherent", () => {
|
|
92
|
-
expect(
|
|
93
|
-
areStatementsCoherent(
|
|
94
|
-
"The default model for the summarize CLI is google/gemini-3-flash-preview.",
|
|
95
|
-
"User's favorite color is blue.",
|
|
96
|
-
),
|
|
97
|
-
).toBe(false);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
test("related statements are coherent", () => {
|
|
101
|
-
expect(
|
|
102
|
-
areStatementsCoherent(
|
|
103
|
-
"User's favorite color is blue.",
|
|
104
|
-
"User's favorite color is green.",
|
|
105
|
-
),
|
|
106
|
-
).toBe(true);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
test("topically similar preferences are coherent", () => {
|
|
110
|
-
expect(
|
|
111
|
-
areStatementsCoherent(
|
|
112
|
-
"Use React for frontend work.",
|
|
113
|
-
"Use Vue for frontend work.",
|
|
114
|
-
),
|
|
115
|
-
).toBe(true);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
test("completely disjoint technical topics are incoherent", () => {
|
|
119
|
-
expect(
|
|
120
|
-
areStatementsCoherent(
|
|
121
|
-
"Always use PostgreSQL for database storage.",
|
|
122
|
-
"The preferred terminal font is JetBrains Mono.",
|
|
123
|
-
),
|
|
124
|
-
).toBe(false);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
test("short technical terms (3 chars) are preserved for coherence", () => {
|
|
128
|
-
// "vim" and "css" are 3 chars — should not be filtered
|
|
129
|
-
expect(
|
|
130
|
-
areStatementsCoherent(
|
|
131
|
-
"Use Vim for editing.",
|
|
132
|
-
"Use Emacs instead of Vim.",
|
|
133
|
-
),
|
|
134
|
-
).toBe(true);
|
|
135
|
-
|
|
136
|
-
expect(
|
|
137
|
-
areStatementsCoherent(
|
|
138
|
-
"Use CSS grid for layouts.",
|
|
139
|
-
"Use CSS flexbox for layouts.",
|
|
140
|
-
),
|
|
141
|
-
).toBe(true);
|
|
142
|
-
|
|
143
|
-
expect(
|
|
144
|
-
areStatementsCoherent(
|
|
145
|
-
"Use npm for installs.",
|
|
146
|
-
"Use npm with --legacy-peer-deps.",
|
|
147
|
-
),
|
|
148
|
-
).toBe(true);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
test("short terms with no shared context are still incoherent", () => {
|
|
152
|
-
// No shared tokens at all — completely different topics
|
|
153
|
-
expect(
|
|
154
|
-
areStatementsCoherent(
|
|
155
|
-
"Vim is the preferred editor.",
|
|
156
|
-
"CSS grid handles page layouts.",
|
|
157
|
-
),
|
|
158
|
-
).toBe(false);
|
|
159
|
-
});
|
|
160
|
-
});
|
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
isConflictKindEligible,
|
|
5
|
-
isConflictKindPairEligible,
|
|
6
|
-
isConflictUserEvidenced,
|
|
7
|
-
isDurableInstructionStatement,
|
|
8
|
-
isStatementConflictEligible,
|
|
9
|
-
isTransientTrackingStatement,
|
|
10
|
-
isUserEvidencedVerificationState,
|
|
11
|
-
} from "../memory/conflict-policy.js";
|
|
12
|
-
|
|
13
|
-
describe("conflict-policy", () => {
|
|
14
|
-
const config = { conflictableKinds: ["preference", "profile", "constraint"] };
|
|
15
|
-
|
|
16
|
-
describe("isConflictKindEligible", () => {
|
|
17
|
-
test("returns true for eligible kind", () => {
|
|
18
|
-
expect(isConflictKindEligible("preference", config)).toBe(true);
|
|
19
|
-
expect(isConflictKindEligible("profile", config)).toBe(true);
|
|
20
|
-
expect(isConflictKindEligible("constraint", config)).toBe(true);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test("returns false for ineligible kind", () => {
|
|
24
|
-
expect(isConflictKindEligible("project", config)).toBe(false);
|
|
25
|
-
expect(isConflictKindEligible("todo", config)).toBe(false);
|
|
26
|
-
expect(isConflictKindEligible("fact", config)).toBe(false);
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
describe("isConflictKindPairEligible", () => {
|
|
31
|
-
test("returns true when both kinds are eligible", () => {
|
|
32
|
-
expect(isConflictKindPairEligible("preference", "profile", config)).toBe(
|
|
33
|
-
true,
|
|
34
|
-
);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test("returns false when existing kind is ineligible", () => {
|
|
38
|
-
expect(isConflictKindPairEligible("project", "preference", config)).toBe(
|
|
39
|
-
false,
|
|
40
|
-
);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test("returns false when candidate kind is ineligible", () => {
|
|
44
|
-
expect(isConflictKindPairEligible("preference", "todo", config)).toBe(
|
|
45
|
-
false,
|
|
46
|
-
);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
test("returns false when both kinds are ineligible", () => {
|
|
50
|
-
expect(isConflictKindPairEligible("project", "todo", config)).toBe(false);
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
describe("isTransientTrackingStatement", () => {
|
|
55
|
-
test("detects PR URLs", () => {
|
|
56
|
-
expect(
|
|
57
|
-
isTransientTrackingStatement(
|
|
58
|
-
"Track https://github.com/org/repo/pull/5526",
|
|
59
|
-
),
|
|
60
|
-
).toBe(true);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
test("detects issue/ticket references", () => {
|
|
64
|
-
expect(isTransientTrackingStatement("Track PR #5526 and #5525")).toBe(
|
|
65
|
-
true,
|
|
66
|
-
);
|
|
67
|
-
expect(isTransientTrackingStatement("See issue #42 for details")).toBe(
|
|
68
|
-
true,
|
|
69
|
-
);
|
|
70
|
-
expect(isTransientTrackingStatement("Filed ticket 1234")).toBe(true);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test("detects tracking language", () => {
|
|
74
|
-
expect(isTransientTrackingStatement("While we wait for CI to pass")).toBe(
|
|
75
|
-
true,
|
|
76
|
-
);
|
|
77
|
-
expect(isTransientTrackingStatement("This PR needs review")).toBe(true);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test("does not flag generic time words as transient", () => {
|
|
81
|
-
expect(isTransientTrackingStatement("The deadline is today")).toBe(false);
|
|
82
|
-
expect(isTransientTrackingStatement("I need this right now")).toBe(false);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
test("does not flag durable statements", () => {
|
|
86
|
-
expect(
|
|
87
|
-
isTransientTrackingStatement(
|
|
88
|
-
"Always answer with concise bullet points",
|
|
89
|
-
),
|
|
90
|
-
).toBe(false);
|
|
91
|
-
expect(isTransientTrackingStatement("User prefers dark mode")).toBe(
|
|
92
|
-
false,
|
|
93
|
-
);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
test("does not false-positive on non-PR URLs", () => {
|
|
97
|
-
expect(
|
|
98
|
-
isTransientTrackingStatement("Visit https://example.com for docs"),
|
|
99
|
-
).toBe(false);
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
describe("isDurableInstructionStatement", () => {
|
|
104
|
-
test("detects durable instruction cues", () => {
|
|
105
|
-
expect(
|
|
106
|
-
isDurableInstructionStatement(
|
|
107
|
-
"Always answer with concise bullet points",
|
|
108
|
-
),
|
|
109
|
-
).toBe(true);
|
|
110
|
-
expect(
|
|
111
|
-
isDurableInstructionStatement("Never use semicolons in JavaScript"),
|
|
112
|
-
).toBe(true);
|
|
113
|
-
expect(
|
|
114
|
-
isDurableInstructionStatement("Use concise format for status updates"),
|
|
115
|
-
).toBe(true);
|
|
116
|
-
expect(
|
|
117
|
-
isDurableInstructionStatement("The default database is Postgres"),
|
|
118
|
-
).toBe(true);
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
test("rejects statements without durable cues", () => {
|
|
122
|
-
expect(isDurableInstructionStatement("Check the build output")).toBe(
|
|
123
|
-
false,
|
|
124
|
-
);
|
|
125
|
-
expect(isDurableInstructionStatement("Run the migration script")).toBe(
|
|
126
|
-
false,
|
|
127
|
-
);
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
describe("isStatementConflictEligible", () => {
|
|
132
|
-
test("rejects transient statements for any kind", () => {
|
|
133
|
-
expect(isStatementConflictEligible("preference", "Track PR #5526")).toBe(
|
|
134
|
-
false,
|
|
135
|
-
);
|
|
136
|
-
expect(
|
|
137
|
-
isStatementConflictEligible("instruction", "This PR needs review"),
|
|
138
|
-
).toBe(false);
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
test("accepts durable instruction statements", () => {
|
|
142
|
-
expect(
|
|
143
|
-
isStatementConflictEligible(
|
|
144
|
-
"instruction",
|
|
145
|
-
"Always use TypeScript strict mode",
|
|
146
|
-
),
|
|
147
|
-
).toBe(true);
|
|
148
|
-
expect(
|
|
149
|
-
isStatementConflictEligible("style", "Default to concise format"),
|
|
150
|
-
).toBe(true);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
test("rejects non-durable instruction statements", () => {
|
|
154
|
-
expect(
|
|
155
|
-
isStatementConflictEligible("instruction", "Run the build first"),
|
|
156
|
-
).toBe(false);
|
|
157
|
-
expect(isStatementConflictEligible("style", "Check the output")).toBe(
|
|
158
|
-
false,
|
|
159
|
-
);
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
test("accepts non-transient statements for non-instruction kinds", () => {
|
|
163
|
-
expect(
|
|
164
|
-
isStatementConflictEligible("preference", "User prefers dark mode"),
|
|
165
|
-
).toBe(true);
|
|
166
|
-
expect(
|
|
167
|
-
isStatementConflictEligible("fact", "User works at Acme Corp"),
|
|
168
|
-
).toBe(true);
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
test("rejects kinds not in conflictableKinds when config is provided", () => {
|
|
172
|
-
const policyConfig = { conflictableKinds: ["preference", "profile"] };
|
|
173
|
-
expect(
|
|
174
|
-
isStatementConflictEligible(
|
|
175
|
-
"fact",
|
|
176
|
-
"User works at Acme Corp",
|
|
177
|
-
policyConfig,
|
|
178
|
-
),
|
|
179
|
-
).toBe(false);
|
|
180
|
-
expect(
|
|
181
|
-
isStatementConflictEligible(
|
|
182
|
-
"preference",
|
|
183
|
-
"User prefers dark mode",
|
|
184
|
-
policyConfig,
|
|
185
|
-
),
|
|
186
|
-
).toBe(true);
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
test("skips kind check when config is omitted", () => {
|
|
190
|
-
expect(
|
|
191
|
-
isStatementConflictEligible("fact", "User works at Acme Corp"),
|
|
192
|
-
).toBe(true);
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
describe("isUserEvidencedVerificationState", () => {
|
|
197
|
-
test("accepts user_reported", () => {
|
|
198
|
-
expect(isUserEvidencedVerificationState("user_reported")).toBe(true);
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
test("accepts user_confirmed", () => {
|
|
202
|
-
expect(isUserEvidencedVerificationState("user_confirmed")).toBe(true);
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
test("accepts legacy_import", () => {
|
|
206
|
-
expect(isUserEvidencedVerificationState("legacy_import")).toBe(true);
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
test("rejects assistant_inferred", () => {
|
|
210
|
-
expect(isUserEvidencedVerificationState("assistant_inferred")).toBe(
|
|
211
|
-
false,
|
|
212
|
-
);
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
test("rejects unknown states", () => {
|
|
216
|
-
expect(isUserEvidencedVerificationState("")).toBe(false);
|
|
217
|
-
expect(isUserEvidencedVerificationState("auto_detected")).toBe(false);
|
|
218
|
-
expect(isUserEvidencedVerificationState("pending")).toBe(false);
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
describe("isConflictUserEvidenced", () => {
|
|
223
|
-
test("returns true when existing side is user-evidenced", () => {
|
|
224
|
-
expect(
|
|
225
|
-
isConflictUserEvidenced("user_reported", "assistant_inferred"),
|
|
226
|
-
).toBe(true);
|
|
227
|
-
expect(
|
|
228
|
-
isConflictUserEvidenced("user_confirmed", "assistant_inferred"),
|
|
229
|
-
).toBe(true);
|
|
230
|
-
expect(
|
|
231
|
-
isConflictUserEvidenced("legacy_import", "assistant_inferred"),
|
|
232
|
-
).toBe(true);
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
test("returns true when candidate side is user-evidenced", () => {
|
|
236
|
-
expect(
|
|
237
|
-
isConflictUserEvidenced("assistant_inferred", "user_reported"),
|
|
238
|
-
).toBe(true);
|
|
239
|
-
expect(
|
|
240
|
-
isConflictUserEvidenced("assistant_inferred", "user_confirmed"),
|
|
241
|
-
).toBe(true);
|
|
242
|
-
expect(
|
|
243
|
-
isConflictUserEvidenced("assistant_inferred", "legacy_import"),
|
|
244
|
-
).toBe(true);
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
test("returns true when both sides are user-evidenced", () => {
|
|
248
|
-
expect(isConflictUserEvidenced("user_reported", "user_confirmed")).toBe(
|
|
249
|
-
true,
|
|
250
|
-
);
|
|
251
|
-
expect(isConflictUserEvidenced("legacy_import", "user_reported")).toBe(
|
|
252
|
-
true,
|
|
253
|
-
);
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
test("returns false when neither side is user-evidenced", () => {
|
|
257
|
-
expect(
|
|
258
|
-
isConflictUserEvidenced("assistant_inferred", "assistant_inferred"),
|
|
259
|
-
).toBe(false);
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
test("returns false for unknown states on both sides", () => {
|
|
263
|
-
expect(isConflictUserEvidenced("auto_detected", "pending")).toBe(false);
|
|
264
|
-
expect(
|
|
265
|
-
isConflictUserEvidenced("assistant_inferred", "auto_detected"),
|
|
266
|
-
).toBe(false);
|
|
267
|
-
});
|
|
268
|
-
});
|
|
269
|
-
});
|