From 02a3636366d9932d46d2dee59e9b44a9fb322852 Mon Sep 17 00:00:00 2001 From: jun Date: Sat, 5 Sep 2026 04:38:18 +0900 Subject: [PATCH 1/3] test(layout): move providers and codex-integration into tests// (#3497) --- .github/scripts/pr-hygiene.test.cjs | 2 +- .../2026-07-26-oauth-reliability-integrity.md | 24 ++--- ...eek-responses-streaming-terminal-repair.md | 26 ++--- .../2026-08-09-routed-computer-use-browser.md | 28 +++--- .../2026-08-13-cl10-deep-review-hardening.md | 2 +- ...-26-discovered-model-display-names-core.md | 40 ++++---- ...ponses-streaming-terminal-repair-design.md | 2 +- scripts/generate-model-metadata.ts | 4 +- scripts/openai-provider-option-final-gates.ts | 10 +- scripts/test-layout/layout.json | 2 + scripts/test-layout/schema.ts | 54 ++++++---- scripts/test.ts | 6 +- src/adapters/cursor/protobuf-request.ts | 4 +- src/clients/config-export.ts | 2 +- src/codex/catalog/metadata.ts | 2 +- src/codex/catalog/provider-fetch.ts | 2 +- src/providers/derive.ts | 2 +- src/providers/registry.ts | 6 +- .../management/agent-settings-routes.ts | 2 +- src/server/responses/core.ts | 2 +- src/service-manager-probe.ts | 2 +- structure/03_catalog-and-subagents.md | 2 +- structure/04_transports-and-sidecars.md | 2 +- structure/11_compatibility-contracts.md | 2 +- tests/bump-dev-version.test.ts | 2 +- tests/ci-workflows.test.ts | 4 +- .../active-registry-admission.test.ts | 18 ++-- .../app-owned-memory.test.ts | 20 ++-- .../bearer-admission-routed-provider.test.ts | 18 ++-- .../catalog-cursor-search.test.ts | 2 +- .../catalog-input-modality-enum.test.ts | 18 ++-- .../catalog-llamacpp-capabilities.test.ts | 4 +- .../catalog-oauth-observation.test.ts | 12 +-- .../catalog-retain-models.test.ts | 12 +-- .../catalog-verbosity-default.test.ts | 8 +- .../catalog-vision-sidecar-modalities.test.ts | 18 ++-- .../codex-account-delete-atomicity.test.ts | 18 ++-- .../codex-account-label.test.ts | 2 +- .../codex-account-namespaces.test.ts | 12 +-- .../codex-account-store.test.ts | 98 +++++++++---------- .../codex-admission-primitives.test.ts | 17 ++-- .../codex-admission.test.ts | 8 +- .../codex-affinity-debug.test.ts | 6 +- .../codex-app-server-path-spaces.test.ts | 2 +- .../codex-app-server-processes.test.ts | 15 +-- .../codex-app-server-restart-service.test.ts | 8 +- .../codex-auth-api.test.ts | 92 ++++++++--------- .../codex-auth-collision.test.ts | 10 +- .../codex-auth-context.test.ts | 32 +++--- .../codex-catalog-admission.test.ts | 10 +- .../codex-catalog-golden.test.ts | 2 +- .../codex-catalog-model-picker-order.test.ts | 4 +- .../codex-catalog-refresh-status.test.ts | 4 +- .../codex-catalog-restore.test.ts | 4 +- .../codex-catalog-sync-hardening.test.ts | 6 +- .../codex-catalog-write-serialization.test.ts | 6 +- .../codex-catalog-writer.test.ts | 10 +- .../codex-catalog.test.ts | 72 +++++++------- .../codex-cli-install-provenance.test.ts | 6 +- .../codex-cli-update-launcher-policy.test.ts | 5 +- .../codex-cli-update-zero-effect.test.ts | 15 +-- .../codex-composed-acceptance.test.ts | 15 +-- .../codex-config-generation.test.ts | 11 ++- ...odex-convergence-account-selectors.test.ts | 32 +++--- .../codex-convergence-contract.test.ts | 35 +++---- .../codex-cooldown-recovery.test.ts | 14 +-- .../codex-coordinator-doctor.test.ts | 12 +-- .../codex-desired-state.test.ts | 8 +- ...odex-envkey-admission-substitution.test.ts | 16 +-- .../codex-exec-invocation.test.ts | 4 +- .../codex-features-cache.test.ts | 6 +- .../codex-features-residual.test.ts | 4 +- .../codex-filesystem-evidence.test.ts | 14 +-- .../codex-gather-authority.test.ts | 12 +-- .../codex-history-job.test.ts | 7 +- .../codex-history-lock.test.ts | 7 +- .../codex-history-provider.test.ts | 4 +- .../codex-history-reachability.test.ts | 3 +- .../codex-history-worker-boundary.test.ts | 10 +- .../codex-history-worker.test.ts | 9 +- .../codex-history-writer.test.ts | 6 +- .../codex-home-wsl.test.ts | 6 +- .../codex-inject-history-wording.test.ts | 11 ++- .../codex-inject-integration.test.ts | 8 +- .../codex-inject-write-lock.test.ts | 11 ++- .../codex-inject.test.ts | 6 +- .../codex-injected-marker.test.ts | 2 +- .../codex-integration-record.test.ts | 8 +- .../codex-journal.test.ts | 10 +- .../codex-log-guard-coderabbit.test.ts | 8 +- .../codex-log-guard-doctor-coderabbit.test.ts | 4 +- .../codex-log-guard-doctor-protection.test.ts | 4 +- .../codex-log-guard-doctor.test.ts | 4 +- .../codex-log-guard-inspect.test.ts | 4 +- .../codex-log-guard-lock.test.ts | 4 +- ...x-log-guard-maintenance-coderabbit.test.ts | 4 +- .../codex-log-guard-maintenance.test.ts | 24 ++--- .../codex-log-guard-policy.test.ts | 4 +- .../codex-log-guard-processes.test.ts | 2 +- .../codex-log-guard-protection.test.ts | 4 +- .../codex-log-guard-status-zero-write.test.ts | 4 +- .../codex-main-account-refresh.test.ts | 6 +- .../codex-main-rotation.test.ts | 18 ++-- .../codex-management-convergence.test.ts | 8 +- .../codex-metadata-integrity.test.ts | 8 +- .../codex-model-entitlements.test.ts | 20 ++-- .../codex-models-cache-invalidate.test.ts | 16 +-- .../codex-native-residue.test.ts | 16 +-- .../codex-plan.test.ts | 16 +-- .../codex-plugins-doctor.test.ts | 6 +- .../codex-pool-rotation.test.ts | 18 ++-- .../codex-prompt-adopt.test.ts | 4 +- .../codex-prompt-base-variants.test.ts | 4 +- .../codex-prompt-journal.test.ts | 6 +- .../codex-prompt-layers-read.test.ts | 4 +- .../codex-prompt-layers-write.test.ts | 6 +- .../codex-prompt-layers.test.ts | 2 +- .../codex-prompt-lock.test.ts | 4 +- .../codex-prompt-route.test.ts | 22 ++--- .../codex-prompt-text-probe.test.ts | 4 +- .../codex-quota-parser-parity.test.ts | 4 +- .../codex-quota-prime.test.ts | 22 ++--- .../codex-quota-rejection.test.ts | 6 +- .../codex-refresh.test.ts | 8 +- .../codex-reset-credit-auto-redeem.test.ts | 4 +- ...odex-reset-credit-operation-ledger.test.ts | 11 ++- .../codex-reset-credit-recovery.test.ts | 4 +- .../codex-restart-contract-parity.test.ts | 4 +- .../codex-restart-route.test.ts | 12 +-- .../codex-restore-app-rewrite.test.ts | 4 +- .../codex-retained-root-serialization.test.ts | 9 +- .../codex-routing.test.ts | 28 +++--- .../codex-runtime.test.ts | 12 +-- ...ex-service-manager-probe-hardening.test.ts | 12 +-- .../codex-service-manager-probe.test.ts | 8 +- .../codex-shim-autorestore.test.ts | 15 +-- .../codex-shim-readiness.test.ts | 6 +- .../codex-shim.test.ts | 15 +-- .../codex-spark-visibility.test.ts | 8 +- .../codex-sqlite-home.test.ts | 8 +- .../codex-sync-api.test.ts | 19 ++-- .../codex-sync-response.test.ts | 4 +- .../codex-tool-mode.test.ts | 24 ++--- .../codex-transition-state-adoption.test.ts | 11 ++- ...nsition-state-first-use-regression.test.ts | 6 +- .../codex-transition-state-race.test.ts | 9 +- .../codex-transition-state.test.ts | 10 +- .../codex-user-identity.test.ts | 7 +- .../codex-v2-gate.test.ts | 18 ++-- .../codex-warmup.test.ts | 2 +- .../codex-websocket-registry.test.ts | 6 +- .../codex-write-lock.test.ts | 11 ++- tests/{ => codex-integration}/combos.test.ts | 28 +++--- .../compatibility-manifest.test.ts | 23 ++--- .../custom-model-catalog-migration.test.ts | 4 +- tests/{ => codex-integration}/doctor.test.ts | 12 +-- .../effort-policy.test.ts | 18 ++-- .../fast-row-listing.test.ts | 8 +- .../{ => codex-integration}/fast-row.test.ts | 10 +- ...gather-routed-models-single-flight.test.ts | 10 +- .../history-migration-guardian.test.ts | 2 +- .../injection-model-api.test.ts | 14 +-- .../issue-452-empty-503.test.ts | 32 +++--- .../issue-702-expired-replay-state.test.ts | 20 ++-- .../issue-914-transport-attribution.test.ts | 16 +-- .../model-cache-generation-tombstone.test.ts | 2 +- .../model-cache.test.ts | 2 +- ...model-display-names-management-api.test.ts | 10 +- .../model-metadata-sync.test.ts | 9 +- .../model-visibility-management-api.test.ts | 22 ++--- .../multi-agent-compat.test.ts | 18 ++-- .../multi-agent-keep-native-v1.test.ts | 18 ++-- ...ative-alias-maintainer-regressions.test.ts | 6 +- .../native-claude-code-toggle.test.ts | 4 +- .../native-claude-desktop-toggle.test.ts | 12 +-- .../native-codex-toggle.test.ts | 8 +- .../native-grok-toggle.test.ts | 23 ++--- .../native-main-auth-temp.test.ts | 8 +- .../native-main-claim-cache.test.ts | 2 +- .../native-main-claim.test.ts | 13 +-- .../native-main-owner-lifetime.test.ts | 23 ++--- .../native-model-toggle.test.ts | 18 ++-- .../native-profile-api.test.ts | 12 +-- .../native-profile-crash-boundaries.test.ts | 27 ++--- .../native-profile-drain-server.test.ts | 36 +++---- .../native-profile-manager.test.ts | 19 ++-- .../native-profile-processes.test.ts | 6 +- .../native-profile-recovery.test.ts | 2 +- .../native-profile-route-security.test.ts | 16 +-- .../native-profile-stage-lifecycle.test.ts | 6 +- .../native-profile-startup.test.ts | 33 ++++--- .../native-profile-store.test.ts | 8 +- .../parallel-tool-calls-optin.test.ts | 8 +- .../project-config-warnings.test.ts | 4 +- .../reasoning-effort.test.ts | 16 +-- .../selected-models.test.ts | 4 +- .../slug-codec.test.ts | 14 +-- .../token-guardian.test.ts | 14 +-- .../ultrafast-tier-honesty.test.ts | 6 +- .../upstream-reachability.test.ts | 10 +- tests/{ => codex-integration}/warmup.test.ts | 2 +- tests/helpers/repo-root.ts | 5 + .../lib/transient-budget-scope-source.test.ts | 2 +- .../alibaba-region-backup.test.ts | 4 +- .../alibaba-region-migration.test.ts | 10 +- .../alibaba-region-startup.test.ts | 8 +- tests/{ => providers}/aside-client.test.ts | 16 +-- .../auto-compact-budget.test.ts | 2 +- tests/{ => providers}/azure-adapter.test.ts | 10 +- .../azure-model-router-tool-schema.test.ts | 4 +- .../{ => providers}/baseten-provider.test.ts | 27 ++--- tests/{ => providers}/chutes-provider.test.ts | 31 +++--- ...cline-pass-deepseek-v4-tool-replay.test.ts | 10 +- .../cline-pass-provider.test.ts | 14 +-- .../cline-pass-reasoning-efforts.test.ts | 8 +- tests/{ => providers}/cline-provider.test.ts | 8 +- .../command-code-error-finish.test.ts | 8 +- .../command-code-provider.test.ts | 14 +-- .../command-code-quota.test.ts | 8 +- .../command-code-workspace-cache.test.ts | 2 +- .../commandcode-provider.test.ts | 31 +++--- .../context-cap-unknown-window.test.ts | 2 +- .../cursor}/cursor-adapter.test.ts | 20 ++-- .../cursor}/cursor-arg-normalize.test.ts | 2 +- .../cursor}/cursor-blob-integrity.test.ts | 2 +- .../cursor}/cursor-blob.test.ts | 22 ++--- .../cursor}/cursor-call-id.test.ts | 8 +- .../cursor}/cursor-cancel-provenance.test.ts | 10 +- .../cursor}/cursor-catalog.test.ts | 4 +- .../cursor}/cursor-claude-id.test.ts | 2 +- ...cursor-default-catalog-suppression.test.ts | 4 +- .../cursor}/cursor-desktop-exec.test.ts | 8 +- .../cursor}/cursor-discovery.test.ts | 2 +- .../cursor}/cursor-display-names.test.ts | 12 +-- .../cursor}/cursor-effort-rows.test.ts | 24 ++--- .../cursor}/cursor-effort-suffix.test.ts | 8 +- .../cursor}/cursor-effort-table.test.ts | 9 +- .../cursor-envelope-echo-retry.test.ts | 10 +- .../cursor}/cursor-eof-terminal.test.ts | 10 +- .../cursor}/cursor-errors.test.ts | 4 +- .../cursor}/cursor-exec-empty-result.test.ts | 2 +- .../cursor}/cursor-fast-listing.test.ts | 18 ++-- .../cursor}/cursor-fast-tier.test.ts | 14 +-- .../cursor}/cursor-framing.test.ts | 4 +- .../cursor}/cursor-h2-pool-shutdown.test.ts | 4 +- .../cursor}/cursor-hardening.test.ts | 18 ++-- .../cursor}/cursor-http1-transport.test.ts | 14 +-- .../cursor}/cursor-images.test.ts | 22 ++--- .../cursor}/cursor-integration-status.test.ts | 23 ++--- .../cursor}/cursor-interaction-query.test.ts | 24 ++--- .../cursor}/cursor-kv-store.test.ts | 4 +- .../cursor}/cursor-live-smoke-gate.test.ts | 2 +- .../cursor}/cursor-live-transport.test.ts | 14 +-- .../cursor-local-models-schema.test.ts | 16 +-- .../cursor}/cursor-mcp-manager.test.ts | 12 +-- .../cursor}/cursor-mcp-stdio.test.ts | 10 +- .../cursor}/cursor-message-mapper.test.ts | 8 +- .../cursor}/cursor-native-exec-common.test.ts | 4 +- .../cursor}/cursor-native-exec-policy.test.ts | 16 +-- .../cursor}/cursor-native-exec-shell.test.ts | 4 +- .../cursor}/cursor-native-exec.test.ts | 6 +- .../cursor}/cursor-oauth-shell.test.ts | 8 +- .../cursor}/cursor-oauth.test.ts | 2 +- .../cursor}/cursor-pool.test.ts | 2 +- .../cursor}/cursor-protobuf-events.test.ts | 10 +- .../cursor}/cursor-repetition-breaker.test.ts | 8 +- .../cursor}/cursor-request-builder.test.ts | 16 +-- .../cursor}/cursor-silent-redirect.test.ts | 2 +- .../cursor}/cursor-static-catalog.test.ts | 16 +-- .../cursor}/cursor-stream-health.test.ts | 10 +- .../cursor}/cursor-structured-edit.test.ts | 12 +-- .../cursor}/cursor-tool-arg-decoding.test.ts | 4 +- .../cursor}/cursor-tool-choice.test.ts | 8 +- .../cursor}/cursor-tool-continuation.test.ts | 14 +-- .../cursor}/cursor-tool-definitions.test.ts | 6 +- .../cursor}/cursor-tool-finalize-race.test.ts | 10 +- .../cursor}/cursor-tool-result-image.test.ts | 8 +- .../cursor-tool-result-invocation.test.ts | 8 +- .../cursor-tool-suspended-checkpoint.test.ts | 12 +-- .../cursor-toolresult-normalize.test.ts | 10 +- .../cursor}/cursor-transport-retry.test.ts | 6 +- .../cursor}/cursor-ultra-mode.test.ts | 10 +- .../cursor}/cursor-umbrella-rows.test.ts | 8 +- .../cursor-uncallable-quarantine.test.ts | 4 +- .../cursor-vision-wire-harness.test.ts | 10 +- .../cyber-policy-error-fidelity.test.ts | 20 ++-- .../deepinfra-provider.test.ts | 29 +++--- .../deepseek-inbound-wire.test.ts | 20 ++-- .../deepseek-reasoning-replay-gaps.test.ts | 12 +-- .../deepseek-reasoning-replay.test.ts | 12 +-- .../deepseek-responses-item-id-repair.test.ts | 12 +-- .../digitalocean-scaleway-provider.test.ts | 31 +++--- tests/{ => providers}/exa-web-search.test.ts | 16 +-- .../{ => providers}/fast-row-ingress.test.ts | 12 +-- .../featherless-provider.test.ts | 33 ++++--- .../forward-admission-separation.test.ts | 10 +- .../github-copilot-account-origin.test.ts | 10 +- .../github-copilot-oauth.test.ts | 10 +- .../github-copilot-sse-rewrite.test.ts | 6 +- .../github-copilot-stream-contract.test.ts | 8 +- .../github-copilot-wire-defaults.test.ts | 12 +-- .../hyperbolic-provider.test.ts | 29 +++--- .../kimi-oauth-identity.test.ts | 6 +- .../kiro}/kiro-account-quota.test.ts | 8 +- .../{ => providers/kiro}/kiro-adapter.test.ts | 30 +++--- .../kiro}/kiro-builder-id-profile.test.ts | 14 +-- .../kiro}/kiro-calibration.test.ts | 2 +- .../{ => providers/kiro}/kiro-images.test.ts | 12 +-- tests/{ => providers/kiro}/kiro-oauth.test.ts | 6 +- .../kiro}/kiro-pool-rank.test.ts | 16 +-- .../kiro}/kiro-reasoning-roundtrip.test.ts | 10 +- tests/{ => providers/kiro}/kiro-retry.test.ts | 6 +- .../kiro}/kiro-review-regressions.test.ts | 14 +-- .../{ => providers/kiro}/kiro-stream.test.ts | 32 +++--- .../kiro}/kiro-usage-quota.test.ts | 2 +- .../kiro}/kiro-windows-cli-db-path.test.ts | 4 +- .../kiro-windows-cli-executable-path.test.ts | 2 +- .../meta-model-api-provider.test.ts | 12 +-- tests/{ => providers}/meta-muse-oauth.test.ts | 12 +-- tests/{ => providers}/mimo-effort.test.ts | 2 +- .../mimo-free-provider.test.ts | 10 +- .../mimo-token-plan-provider.test.ts | 14 +-- tests/{ => providers}/minimax-clients.test.ts | 9 +- .../minimax-reasoning-split.test.ts | 10 +- tests/{ => providers}/model-presets.test.ts | 4 +- .../model-rename-migration.test.ts | 6 +- .../moonshot-endpoints.test.ts | 6 +- .../moonshot-tool-schema.test.ts | 6 +- .../muse-passive-quota-cache.test.ts | 16 +-- .../muse-passive-quota-observation.test.ts | 14 +-- .../muse-spark-web-search-compat.test.ts | 8 +- .../muse-subscription-usage.test.ts | 2 +- .../{ => providers}/new-model-policy.test.ts | 2 +- tests/{ => providers}/nous-oauth-live.test.ts | 8 +- tests/{ => providers}/nous-oauth.test.ts | 12 +-- tests/{ => providers}/novita-provider.test.ts | 31 +++--- .../nscale-vultr-provider.test.ts | 29 +++--- .../nvidia-nim-hardening.test.ts | 14 +-- .../ollama}/ollama-native-parser.test.ts | 12 +-- .../ollama-native-reasoning-wire.test.ts | 10 +- .../ollama-native-structured-output.test.ts | 4 +- .../ollama}/ollama-native-v4.test.ts | 10 +- .../ollama}/ollama-native.test.ts | 12 +-- .../ollama}/ollama-show-enrichment-v7.test.ts | 14 +-- .../ollama}/ollama-show-enrichment.test.ts | 10 +- .../ollama}/ollama-show-ignore-abort.test.ts | 2 +- tests/{ => providers}/opencode-cli.test.ts | 14 +-- .../opencode-free-provider.test.ts | 14 +-- .../opencode-go-deepseek.test.ts | 6 +- .../opencode-go-grok46-responses.test.ts | 12 +-- .../opencode-go-luna-wire.test.ts | 10 +- .../opencode-go-muse-context.test.ts | 8 +- .../opencode-go-muse-vision.test.ts | 8 +- .../{ => providers}/opencode-go-quota.test.ts | 4 +- .../opencode-go-session-header.test.ts | 10 +- .../opencode-zen-deepseek-reasoning.test.ts | 6 +- .../opencode-zen-rate-limit.test.ts | 10 +- .../openrouter-provider-routing.test.ts | 16 +-- ...provider-account-quota-persistence.test.ts | 6 +- .../provider-account-quota.test.ts | 22 ++--- .../{ => providers}/provider-api-keys.test.ts | 12 +-- .../{ => providers}/provider-capacity.test.ts | 2 +- .../provider-config-batch-management.test.ts | 20 ++-- .../provider-config-validation.test.ts | 2 +- .../provider-connection-test.test.ts | 20 ++-- .../provider-cost-overlay-config.test.ts | 10 +- ...provider-discovery-log-suppression.test.ts | 2 +- .../provider-id-rewrite.test.ts | 8 +- .../provider-key-store.test.ts | 18 ++-- .../provider-live-models.test.ts | 6 +- .../provider-model-aliases.test.ts | 6 +- .../provider-model-discovery-contract.test.ts | 29 +++--- .../provider-outbound-private-network.test.ts | 4 +- .../{ => providers}/provider-outbound.test.ts | 28 +++--- .../provider-quota-observed-marker.test.ts | 12 +-- tests/{ => providers}/provider-quota.test.ts | 23 ++--- .../provider-registry-parity.test.ts | 28 +++--- .../provider-static-model-discovery.test.ts | 12 +-- .../qwen38-preserve-reasoning.test.ts | 6 +- .../{ => providers}/rate-limit-retry.test.ts | 6 +- .../sambanova-nebius-provider.test.ts | 33 ++++--- tests/{ => providers}/umans-provider.test.ts | 10 +- .../upstream-transient-retry.test.ts | 6 +- .../vercel-gateway-provider-routing.test.ts | 12 +-- .../volcengine-ark-assistant-content.test.ts | 4 +- .../xai}/grok-attribution.test.ts | 10 +- .../xai}/grok-config-inject.test.ts | 4 +- .../xai}/grok-effort-inject.test.ts | 20 ++-- .../xai}/grok-lifecycle.test.ts | 37 +++---- .../xai}/grok-management-api.test.ts | 14 +-- .../xai}/grok-models-effort-list.test.ts | 12 +-- .../xai}/grok-orphan-adoption.test.ts | 4 +- .../xai}/grok-selection.test.ts | 12 +-- tests/{ => providers/xai}/grok-status.test.ts | 6 +- tests/{ => providers/xai}/grok-sync.test.ts | 14 +-- .../xai}/grok-writer-boundary.test.ts | 2 +- .../xai}/xai-oauth-retry.test.ts | 2 +- .../xai}/xai-refresh-lock.test.ts | 6 +- .../xai}/xai-tool-schema.test.ts | 6 +- .../{ => providers/xai}/xai-transport.test.ts | 16 +-- .../xai}/xai-web-search-compat.test.ts | 6 +- .../xai}/xai-web-search.test.ts | 26 ++--- tests/{ => providers}/zcode-client.test.ts | 6 +- .../zhipu-bigmodel-provider.test.ts | 14 +-- .../responses-inbound-store-default.test.ts | 2 +- .../responses-undeclared-tool-guard.test.ts | 2 +- tests/server-auth.test.ts | 2 +- tests/server-management-auth.test.ts | 2 +- tests/service/stop-deferred-teardown.test.ts | 2 +- tests/test-layout-tooling.test.ts | 22 ++++- tests/windows/windows-tray.test.ts | 2 +- 411 files changed, 2360 insertions(+), 2275 deletions(-) rename tests/{ => codex-integration}/active-registry-admission.test.ts (95%) rename tests/{ => codex-integration}/app-owned-memory.test.ts (95%) rename tests/{ => codex-integration}/bearer-admission-routed-provider.test.ts (96%) rename tests/{ => codex-integration}/catalog-cursor-search.test.ts (99%) rename tests/{ => codex-integration}/catalog-input-modality-enum.test.ts (96%) rename tests/{ => codex-integration}/catalog-llamacpp-capabilities.test.ts (97%) rename tests/{ => codex-integration}/catalog-oauth-observation.test.ts (96%) rename tests/{ => codex-integration}/catalog-retain-models.test.ts (94%) rename tests/{ => codex-integration}/catalog-verbosity-default.test.ts (92%) rename tests/{ => codex-integration}/catalog-vision-sidecar-modalities.test.ts (97%) rename tests/{ => codex-integration}/codex-account-delete-atomicity.test.ts (93%) rename tests/{ => codex-integration}/codex-account-label.test.ts (97%) rename tests/{ => codex-integration}/codex-account-namespaces.test.ts (98%) rename tests/{ => codex-integration}/codex-account-store.test.ts (95%) rename tests/{ => codex-integration}/codex-admission-primitives.test.ts (96%) rename tests/{ => codex-integration}/codex-admission.test.ts (97%) rename tests/{ => codex-integration}/codex-affinity-debug.test.ts (98%) rename tests/{ => codex-integration}/codex-app-server-path-spaces.test.ts (95%) rename tests/{ => codex-integration}/codex-app-server-processes.test.ts (99%) rename tests/{ => codex-integration}/codex-app-server-restart-service.test.ts (98%) rename tests/{ => codex-integration}/codex-auth-api.test.ts (98%) rename tests/{ => codex-integration}/codex-auth-collision.test.ts (93%) rename tests/{ => codex-integration}/codex-auth-context.test.ts (98%) rename tests/{ => codex-integration}/codex-catalog-admission.test.ts (96%) rename tests/{ => codex-integration}/codex-catalog-golden.test.ts (98%) rename tests/{ => codex-integration}/codex-catalog-model-picker-order.test.ts (99%) rename tests/{ => codex-integration}/codex-catalog-refresh-status.test.ts (95%) rename tests/{ => codex-integration}/codex-catalog-restore.test.ts (99%) rename tests/{ => codex-integration}/codex-catalog-sync-hardening.test.ts (99%) rename tests/{ => codex-integration}/codex-catalog-write-serialization.test.ts (97%) rename tests/{ => codex-integration}/codex-catalog-writer.test.ts (97%) rename tests/{ => codex-integration}/codex-catalog.test.ts (99%) rename tests/{ => codex-integration}/codex-cli-install-provenance.test.ts (99%) rename tests/{ => codex-integration}/codex-cli-update-launcher-policy.test.ts (84%) rename tests/{ => codex-integration}/codex-cli-update-zero-effect.test.ts (88%) rename tests/{ => codex-integration}/codex-composed-acceptance.test.ts (98%) rename tests/{ => codex-integration}/codex-config-generation.test.ts (97%) rename tests/{ => codex-integration}/codex-convergence-account-selectors.test.ts (97%) rename tests/{ => codex-integration}/codex-convergence-contract.test.ts (94%) rename tests/{ => codex-integration}/codex-cooldown-recovery.test.ts (98%) rename tests/{ => codex-integration}/codex-coordinator-doctor.test.ts (96%) rename tests/{ => codex-integration}/codex-desired-state.test.ts (98%) rename tests/{ => codex-integration}/codex-envkey-admission-substitution.test.ts (95%) rename tests/{ => codex-integration}/codex-exec-invocation.test.ts (96%) rename tests/{ => codex-integration}/codex-features-cache.test.ts (94%) rename tests/{ => codex-integration}/codex-features-residual.test.ts (86%) rename tests/{ => codex-integration}/codex-filesystem-evidence.test.ts (95%) rename tests/{ => codex-integration}/codex-gather-authority.test.ts (97%) rename tests/{ => codex-integration}/codex-history-job.test.ts (98%) rename tests/{ => codex-integration}/codex-history-lock.test.ts (96%) rename tests/{ => codex-integration}/codex-history-provider.test.ts (99%) rename tests/{ => codex-integration}/codex-history-reachability.test.ts (98%) rename tests/{ => codex-integration}/codex-history-worker-boundary.test.ts (96%) rename tests/{ => codex-integration}/codex-history-worker.test.ts (98%) rename tests/{ => codex-integration}/codex-history-writer.test.ts (96%) rename tests/{ => codex-integration}/codex-home-wsl.test.ts (93%) rename tests/{ => codex-integration}/codex-inject-history-wording.test.ts (94%) rename tests/{ => codex-integration}/codex-inject-integration.test.ts (99%) rename tests/{ => codex-integration}/codex-inject-write-lock.test.ts (98%) rename tests/{ => codex-integration}/codex-inject.test.ts (99%) rename tests/{ => codex-integration}/codex-injected-marker.test.ts (89%) rename tests/{ => codex-integration}/codex-integration-record.test.ts (97%) rename tests/{ => codex-integration}/codex-journal.test.ts (98%) rename tests/{ => codex-integration}/codex-log-guard-coderabbit.test.ts (97%) rename tests/{ => codex-integration}/codex-log-guard-doctor-coderabbit.test.ts (90%) rename tests/{ => codex-integration}/codex-log-guard-doctor-protection.test.ts (94%) rename tests/{ => codex-integration}/codex-log-guard-doctor.test.ts (97%) rename tests/{ => codex-integration}/codex-log-guard-inspect.test.ts (99%) rename tests/{ => codex-integration}/codex-log-guard-lock.test.ts (88%) rename tests/{ => codex-integration}/codex-log-guard-maintenance-coderabbit.test.ts (98%) rename tests/{ => codex-integration}/codex-log-guard-maintenance.test.ts (91%) rename tests/{ => codex-integration}/codex-log-guard-policy.test.ts (93%) rename tests/{ => codex-integration}/codex-log-guard-processes.test.ts (98%) rename tests/{ => codex-integration}/codex-log-guard-protection.test.ts (99%) rename tests/{ => codex-integration}/codex-log-guard-status-zero-write.test.ts (96%) rename tests/{ => codex-integration}/codex-main-account-refresh.test.ts (98%) rename tests/{ => codex-integration}/codex-main-rotation.test.ts (97%) rename tests/{ => codex-integration}/codex-management-convergence.test.ts (95%) rename tests/{ => codex-integration}/codex-metadata-integrity.test.ts (95%) rename tests/{ => codex-integration}/codex-model-entitlements.test.ts (99%) rename tests/{ => codex-integration}/codex-models-cache-invalidate.test.ts (95%) rename tests/{ => codex-integration}/codex-native-residue.test.ts (98%) rename tests/{ => codex-integration}/codex-plan.test.ts (95%) rename tests/{ => codex-integration}/codex-plugins-doctor.test.ts (98%) rename tests/{ => codex-integration}/codex-pool-rotation.test.ts (98%) rename tests/{ => codex-integration}/codex-prompt-adopt.test.ts (98%) rename tests/{ => codex-integration}/codex-prompt-base-variants.test.ts (98%) rename tests/{ => codex-integration}/codex-prompt-journal.test.ts (98%) rename tests/{ => codex-integration}/codex-prompt-layers-read.test.ts (98%) rename tests/{ => codex-integration}/codex-prompt-layers-write.test.ts (99%) rename tests/{ => codex-integration}/codex-prompt-layers.test.ts (99%) rename tests/{ => codex-integration}/codex-prompt-lock.test.ts (98%) rename tests/{ => codex-integration}/codex-prompt-route.test.ts (98%) rename tests/{ => codex-integration}/codex-prompt-text-probe.test.ts (99%) rename tests/{ => codex-integration}/codex-quota-parser-parity.test.ts (98%) rename tests/{ => codex-integration}/codex-quota-prime.test.ts (98%) rename tests/{ => codex-integration}/codex-quota-rejection.test.ts (98%) rename tests/{ => codex-integration}/codex-refresh.test.ts (97%) rename tests/{ => codex-integration}/codex-reset-credit-auto-redeem.test.ts (98%) rename tests/{ => codex-integration}/codex-reset-credit-operation-ledger.test.ts (99%) rename tests/{ => codex-integration}/codex-reset-credit-recovery.test.ts (99%) rename tests/{ => codex-integration}/codex-restart-contract-parity.test.ts (97%) rename tests/{ => codex-integration}/codex-restart-route.test.ts (92%) rename tests/{ => codex-integration}/codex-restore-app-rewrite.test.ts (98%) rename tests/{ => codex-integration}/codex-retained-root-serialization.test.ts (99%) rename tests/{ => codex-integration}/codex-routing.test.ts (99%) rename tests/{ => codex-integration}/codex-runtime.test.ts (99%) rename tests/{ => codex-integration}/codex-service-manager-probe-hardening.test.ts (98%) rename tests/{ => codex-integration}/codex-service-manager-probe.test.ts (99%) rename tests/{ => codex-integration}/codex-shim-autorestore.test.ts (94%) rename tests/{ => codex-integration}/codex-shim-readiness.test.ts (96%) rename tests/{ => codex-integration}/codex-shim.test.ts (99%) rename tests/{ => codex-integration}/codex-spark-visibility.test.ts (94%) rename tests/{ => codex-integration}/codex-sqlite-home.test.ts (94%) rename tests/{ => codex-integration}/codex-sync-api.test.ts (97%) rename tests/{ => codex-integration}/codex-sync-response.test.ts (97%) rename tests/{ => codex-integration}/codex-tool-mode.test.ts (90%) rename tests/{ => codex-integration}/codex-transition-state-adoption.test.ts (90%) rename tests/{ => codex-integration}/codex-transition-state-first-use-regression.test.ts (93%) rename tests/{ => codex-integration}/codex-transition-state-race.test.ts (97%) rename tests/{ => codex-integration}/codex-transition-state.test.ts (98%) rename tests/{ => codex-integration}/codex-user-identity.test.ts (98%) rename tests/{ => codex-integration}/codex-v2-gate.test.ts (99%) rename tests/{ => codex-integration}/codex-warmup.test.ts (99%) rename tests/{ => codex-integration}/codex-websocket-registry.test.ts (96%) rename tests/{ => codex-integration}/codex-write-lock.test.ts (98%) rename tests/{ => codex-integration}/combos.test.ts (98%) rename tests/{ => codex-integration}/compatibility-manifest.test.ts (91%) rename tests/{ => codex-integration}/custom-model-catalog-migration.test.ts (97%) rename tests/{ => codex-integration}/doctor.test.ts (99%) rename tests/{ => codex-integration}/effort-policy.test.ts (97%) rename tests/{ => codex-integration}/fast-row-listing.test.ts (94%) rename tests/{ => codex-integration}/fast-row.test.ts (98%) rename tests/{ => codex-integration}/gather-routed-models-single-flight.test.ts (97%) rename tests/{ => codex-integration}/history-migration-guardian.test.ts (98%) rename tests/{ => codex-integration}/injection-model-api.test.ts (97%) rename tests/{ => codex-integration}/issue-452-empty-503.test.ts (94%) rename tests/{ => codex-integration}/issue-702-expired-replay-state.test.ts (96%) rename tests/{ => codex-integration}/issue-914-transport-attribution.test.ts (93%) rename tests/{ => codex-integration}/model-cache-generation-tombstone.test.ts (98%) rename tests/{ => codex-integration}/model-cache.test.ts (97%) rename tests/{ => codex-integration}/model-display-names-management-api.test.ts (97%) rename tests/{ => codex-integration}/model-metadata-sync.test.ts (86%) rename tests/{ => codex-integration}/model-visibility-management-api.test.ts (95%) rename tests/{ => codex-integration}/multi-agent-compat.test.ts (99%) rename tests/{ => codex-integration}/multi-agent-keep-native-v1.test.ts (96%) rename tests/{ => codex-integration}/native-alias-maintainer-regressions.test.ts (96%) rename tests/{ => codex-integration}/native-claude-code-toggle.test.ts (98%) rename tests/{ => codex-integration}/native-claude-desktop-toggle.test.ts (97%) rename tests/{ => codex-integration}/native-codex-toggle.test.ts (96%) rename tests/{ => codex-integration}/native-grok-toggle.test.ts (95%) rename tests/{ => codex-integration}/native-main-auth-temp.test.ts (94%) rename tests/{ => codex-integration}/native-main-claim-cache.test.ts (97%) rename tests/{ => codex-integration}/native-main-claim.test.ts (95%) rename tests/{ => codex-integration}/native-main-owner-lifetime.test.ts (97%) rename tests/{ => codex-integration}/native-model-toggle.test.ts (98%) rename tests/{ => codex-integration}/native-profile-api.test.ts (98%) rename tests/{ => codex-integration}/native-profile-crash-boundaries.test.ts (95%) rename tests/{ => codex-integration}/native-profile-drain-server.test.ts (93%) rename tests/{ => codex-integration}/native-profile-manager.test.ts (99%) rename tests/{ => codex-integration}/native-profile-processes.test.ts (98%) rename tests/{ => codex-integration}/native-profile-recovery.test.ts (98%) rename tests/{ => codex-integration}/native-profile-route-security.test.ts (95%) rename tests/{ => codex-integration}/native-profile-stage-lifecycle.test.ts (98%) rename tests/{ => codex-integration}/native-profile-startup.test.ts (98%) rename tests/{ => codex-integration}/native-profile-store.test.ts (98%) rename tests/{ => codex-integration}/parallel-tool-calls-optin.test.ts (97%) rename tests/{ => codex-integration}/project-config-warnings.test.ts (99%) rename tests/{ => codex-integration}/reasoning-effort.test.ts (98%) rename tests/{ => codex-integration}/selected-models.test.ts (98%) rename tests/{ => codex-integration}/slug-codec.test.ts (97%) rename tests/{ => codex-integration}/token-guardian.test.ts (96%) rename tests/{ => codex-integration}/ultrafast-tier-honesty.test.ts (97%) rename tests/{ => codex-integration}/upstream-reachability.test.ts (98%) rename tests/{ => codex-integration}/warmup.test.ts (99%) rename tests/{ => providers}/alibaba-region-backup.test.ts (96%) rename tests/{ => providers}/alibaba-region-migration.test.ts (95%) rename tests/{ => providers}/alibaba-region-startup.test.ts (91%) rename tests/{ => providers}/aside-client.test.ts (97%) rename tests/{ => providers}/auto-compact-budget.test.ts (97%) rename tests/{ => providers}/azure-adapter.test.ts (94%) rename tests/{ => providers}/azure-model-router-tool-schema.test.ts (93%) rename tests/{ => providers}/baseten-provider.test.ts (92%) rename tests/{ => providers}/chutes-provider.test.ts (89%) rename tests/{ => providers}/cline-pass-deepseek-v4-tool-replay.test.ts (92%) rename tests/{ => providers}/cline-pass-provider.test.ts (96%) rename tests/{ => providers}/cline-pass-reasoning-efforts.test.ts (95%) rename tests/{ => providers}/cline-provider.test.ts (91%) rename tests/{ => providers}/command-code-error-finish.test.ts (92%) rename tests/{ => providers}/command-code-provider.test.ts (98%) rename tests/{ => providers}/command-code-quota.test.ts (98%) rename tests/{ => providers}/command-code-workspace-cache.test.ts (98%) rename tests/{ => providers}/commandcode-provider.test.ts (91%) rename tests/{ => providers}/context-cap-unknown-window.test.ts (95%) rename tests/{ => providers/cursor}/cursor-adapter.test.ts (97%) rename tests/{ => providers/cursor}/cursor-arg-normalize.test.ts (97%) rename tests/{ => providers/cursor}/cursor-blob-integrity.test.ts (96%) rename tests/{ => providers/cursor}/cursor-blob.test.ts (99%) rename tests/{ => providers/cursor}/cursor-call-id.test.ts (94%) rename tests/{ => providers/cursor}/cursor-cancel-provenance.test.ts (94%) rename tests/{ => providers/cursor}/cursor-catalog.test.ts (99%) rename tests/{ => providers/cursor}/cursor-claude-id.test.ts (98%) rename tests/{ => providers/cursor}/cursor-default-catalog-suppression.test.ts (91%) rename tests/{ => providers/cursor}/cursor-desktop-exec.test.ts (97%) rename tests/{ => providers/cursor}/cursor-discovery.test.ts (99%) rename tests/{ => providers/cursor}/cursor-display-names.test.ts (88%) rename tests/{ => providers/cursor}/cursor-effort-rows.test.ts (93%) rename tests/{ => providers/cursor}/cursor-effort-suffix.test.ts (98%) rename tests/{ => providers/cursor}/cursor-effort-table.test.ts (93%) rename tests/{ => providers/cursor}/cursor-envelope-echo-retry.test.ts (98%) rename tests/{ => providers/cursor}/cursor-eof-terminal.test.ts (96%) rename tests/{ => providers/cursor}/cursor-errors.test.ts (98%) rename tests/{ => providers/cursor}/cursor-exec-empty-result.test.ts (98%) rename tests/{ => providers/cursor}/cursor-fast-listing.test.ts (86%) rename tests/{ => providers/cursor}/cursor-fast-tier.test.ts (91%) rename tests/{ => providers/cursor}/cursor-framing.test.ts (99%) rename tests/{ => providers/cursor}/cursor-h2-pool-shutdown.test.ts (94%) rename tests/{ => providers/cursor}/cursor-hardening.test.ts (98%) rename tests/{ => providers/cursor}/cursor-http1-transport.test.ts (97%) rename tests/{ => providers/cursor}/cursor-images.test.ts (97%) rename tests/{ => providers/cursor}/cursor-integration-status.test.ts (93%) rename tests/{ => providers/cursor}/cursor-interaction-query.test.ts (90%) rename tests/{ => providers/cursor}/cursor-kv-store.test.ts (86%) rename tests/{ => providers/cursor}/cursor-live-smoke-gate.test.ts (97%) rename tests/{ => providers/cursor}/cursor-live-transport.test.ts (96%) rename tests/{ => providers/cursor}/cursor-local-models-schema.test.ts (95%) rename tests/{ => providers/cursor}/cursor-mcp-manager.test.ts (97%) rename tests/{ => providers/cursor}/cursor-mcp-stdio.test.ts (93%) rename tests/{ => providers/cursor}/cursor-message-mapper.test.ts (93%) rename tests/{ => providers/cursor}/cursor-native-exec-common.test.ts (95%) rename tests/{ => providers/cursor}/cursor-native-exec-policy.test.ts (96%) rename tests/{ => providers/cursor}/cursor-native-exec-shell.test.ts (99%) rename tests/{ => providers/cursor}/cursor-native-exec.test.ts (99%) rename tests/{ => providers/cursor}/cursor-oauth-shell.test.ts (83%) rename tests/{ => providers/cursor}/cursor-oauth.test.ts (99%) rename tests/{ => providers/cursor}/cursor-pool.test.ts (96%) rename tests/{ => providers/cursor}/cursor-protobuf-events.test.ts (99%) rename tests/{ => providers/cursor}/cursor-repetition-breaker.test.ts (96%) rename tests/{ => providers/cursor}/cursor-request-builder.test.ts (99%) rename tests/{ => providers/cursor}/cursor-silent-redirect.test.ts (94%) rename tests/{ => providers/cursor}/cursor-static-catalog.test.ts (92%) rename tests/{ => providers/cursor}/cursor-stream-health.test.ts (95%) rename tests/{ => providers/cursor}/cursor-structured-edit.test.ts (99%) rename tests/{ => providers/cursor}/cursor-tool-arg-decoding.test.ts (99%) rename tests/{ => providers/cursor}/cursor-tool-choice.test.ts (94%) rename tests/{ => providers/cursor}/cursor-tool-continuation.test.ts (96%) rename tests/{ => providers/cursor}/cursor-tool-definitions.test.ts (99%) rename tests/{ => providers/cursor}/cursor-tool-finalize-race.test.ts (96%) rename tests/{ => providers/cursor}/cursor-tool-result-image.test.ts (98%) rename tests/{ => providers/cursor}/cursor-tool-result-invocation.test.ts (99%) rename tests/{ => providers/cursor}/cursor-tool-suspended-checkpoint.test.ts (92%) rename tests/{ => providers/cursor}/cursor-toolresult-normalize.test.ts (95%) rename tests/{ => providers/cursor}/cursor-transport-retry.test.ts (98%) rename tests/{ => providers/cursor}/cursor-ultra-mode.test.ts (92%) rename tests/{ => providers/cursor}/cursor-umbrella-rows.test.ts (96%) rename tests/{ => providers/cursor}/cursor-uncallable-quarantine.test.ts (94%) rename tests/{ => providers/cursor}/cursor-vision-wire-harness.test.ts (93%) rename tests/{ => providers}/cyber-policy-error-fidelity.test.ts (97%) rename tests/{ => providers}/deepinfra-provider.test.ts (88%) rename tests/{ => providers}/deepseek-inbound-wire.test.ts (98%) rename tests/{ => providers}/deepseek-reasoning-replay-gaps.test.ts (98%) rename tests/{ => providers}/deepseek-reasoning-replay.test.ts (94%) rename tests/{ => providers}/deepseek-responses-item-id-repair.test.ts (96%) rename tests/{ => providers}/digitalocean-scaleway-provider.test.ts (92%) rename tests/{ => providers}/exa-web-search.test.ts (95%) rename tests/{ => providers}/fast-row-ingress.test.ts (92%) rename tests/{ => providers}/featherless-provider.test.ts (88%) rename tests/{ => providers}/forward-admission-separation.test.ts (93%) rename tests/{ => providers/github-copilot}/github-copilot-account-origin.test.ts (96%) rename tests/{ => providers/github-copilot}/github-copilot-oauth.test.ts (97%) rename tests/{ => providers/github-copilot}/github-copilot-sse-rewrite.test.ts (97%) rename tests/{ => providers/github-copilot}/github-copilot-stream-contract.test.ts (96%) rename tests/{ => providers/github-copilot}/github-copilot-wire-defaults.test.ts (92%) rename tests/{ => providers}/hyperbolic-provider.test.ts (88%) rename tests/{ => providers}/kimi-oauth-identity.test.ts (98%) rename tests/{ => providers/kiro}/kiro-account-quota.test.ts (96%) rename tests/{ => providers/kiro}/kiro-adapter.test.ts (99%) rename tests/{ => providers/kiro}/kiro-builder-id-profile.test.ts (95%) rename tests/{ => providers/kiro}/kiro-calibration.test.ts (99%) rename tests/{ => providers/kiro}/kiro-images.test.ts (96%) rename tests/{ => providers/kiro}/kiro-oauth.test.ts (99%) rename tests/{ => providers/kiro}/kiro-pool-rank.test.ts (97%) rename tests/{ => providers/kiro}/kiro-reasoning-roundtrip.test.ts (94%) rename tests/{ => providers/kiro}/kiro-retry.test.ts (98%) rename tests/{ => providers/kiro}/kiro-review-regressions.test.ts (97%) rename tests/{ => providers/kiro}/kiro-stream.test.ts (99%) rename tests/{ => providers/kiro}/kiro-usage-quota.test.ts (99%) rename tests/{ => providers/kiro}/kiro-windows-cli-db-path.test.ts (97%) rename tests/{ => providers/kiro}/kiro-windows-cli-executable-path.test.ts (98%) rename tests/{ => providers}/meta-model-api-provider.test.ts (95%) rename tests/{ => providers}/meta-muse-oauth.test.ts (97%) rename tests/{ => providers}/mimo-effort.test.ts (92%) rename tests/{ => providers}/mimo-free-provider.test.ts (97%) rename tests/{ => providers}/mimo-token-plan-provider.test.ts (94%) rename tests/{ => providers}/minimax-clients.test.ts (98%) rename tests/{ => providers}/minimax-reasoning-split.test.ts (97%) rename tests/{ => providers}/model-presets.test.ts (97%) rename tests/{ => providers}/model-rename-migration.test.ts (97%) rename tests/{ => providers}/moonshot-endpoints.test.ts (89%) rename tests/{ => providers}/moonshot-tool-schema.test.ts (99%) rename tests/{ => providers}/muse-passive-quota-cache.test.ts (94%) rename tests/{ => providers}/muse-passive-quota-observation.test.ts (96%) rename tests/{ => providers}/muse-spark-web-search-compat.test.ts (96%) rename tests/{ => providers}/muse-subscription-usage.test.ts (98%) rename tests/{ => providers}/new-model-policy.test.ts (98%) rename tests/{ => providers}/nous-oauth-live.test.ts (95%) rename tests/{ => providers}/nous-oauth.test.ts (99%) rename tests/{ => providers}/novita-provider.test.ts (88%) rename tests/{ => providers}/nscale-vultr-provider.test.ts (90%) rename tests/{ => providers}/nvidia-nim-hardening.test.ts (97%) rename tests/{ => providers/ollama}/ollama-native-parser.test.ts (98%) rename tests/{ => providers/ollama}/ollama-native-reasoning-wire.test.ts (94%) rename tests/{ => providers/ollama}/ollama-native-structured-output.test.ts (97%) rename tests/{ => providers/ollama}/ollama-native-v4.test.ts (93%) rename tests/{ => providers/ollama}/ollama-native.test.ts (96%) rename tests/{ => providers/ollama}/ollama-show-enrichment-v7.test.ts (97%) rename tests/{ => providers/ollama}/ollama-show-enrichment.test.ts (97%) rename tests/{ => providers/ollama}/ollama-show-ignore-abort.test.ts (98%) rename tests/{ => providers}/opencode-cli.test.ts (98%) rename tests/{ => providers}/opencode-free-provider.test.ts (95%) rename tests/{ => providers}/opencode-go-deepseek.test.ts (96%) rename tests/{ => providers}/opencode-go-grok46-responses.test.ts (91%) rename tests/{ => providers}/opencode-go-luna-wire.test.ts (90%) rename tests/{ => providers}/opencode-go-muse-context.test.ts (92%) rename tests/{ => providers}/opencode-go-muse-vision.test.ts (95%) rename tests/{ => providers}/opencode-go-quota.test.ts (98%) rename tests/{ => providers}/opencode-go-session-header.test.ts (93%) rename tests/{ => providers}/opencode-zen-deepseek-reasoning.test.ts (95%) rename tests/{ => providers}/opencode-zen-rate-limit.test.ts (94%) rename tests/{ => providers}/openrouter-provider-routing.test.ts (97%) rename tests/{ => providers}/provider-account-quota-persistence.test.ts (94%) rename tests/{ => providers}/provider-account-quota.test.ts (97%) rename tests/{ => providers}/provider-api-keys.test.ts (94%) rename tests/{ => providers}/provider-capacity.test.ts (99%) rename tests/{ => providers}/provider-config-batch-management.test.ts (95%) rename tests/{ => providers}/provider-config-validation.test.ts (99%) rename tests/{ => providers}/provider-connection-test.test.ts (96%) rename tests/{ => providers}/provider-cost-overlay-config.test.ts (98%) rename tests/{ => providers}/provider-discovery-log-suppression.test.ts (98%) rename tests/{ => providers}/provider-id-rewrite.test.ts (97%) rename tests/{ => providers}/provider-key-store.test.ts (94%) rename tests/{ => providers}/provider-live-models.test.ts (98%) rename tests/{ => providers}/provider-model-aliases.test.ts (94%) rename tests/{ => providers}/provider-model-discovery-contract.test.ts (96%) rename tests/{ => providers}/provider-outbound-private-network.test.ts (97%) rename tests/{ => providers}/provider-outbound.test.ts (94%) rename tests/{ => providers}/provider-quota-observed-marker.test.ts (93%) rename tests/{ => providers}/provider-quota.test.ts (99%) rename tests/{ => providers}/provider-registry-parity.test.ts (98%) rename tests/{ => providers}/provider-static-model-discovery.test.ts (94%) rename tests/{ => providers}/qwen38-preserve-reasoning.test.ts (94%) rename tests/{ => providers}/rate-limit-retry.test.ts (98%) rename tests/{ => providers}/sambanova-nebius-provider.test.ts (92%) rename tests/{ => providers}/umans-provider.test.ts (97%) rename tests/{ => providers}/upstream-transient-retry.test.ts (98%) rename tests/{ => providers}/vercel-gateway-provider-routing.test.ts (96%) rename tests/{ => providers}/volcengine-ark-assistant-content.test.ts (98%) rename tests/{ => providers/xai}/grok-attribution.test.ts (88%) rename tests/{ => providers/xai}/grok-config-inject.test.ts (99%) rename tests/{ => providers/xai}/grok-effort-inject.test.ts (96%) rename tests/{ => providers/xai}/grok-lifecycle.test.ts (94%) rename tests/{ => providers/xai}/grok-management-api.test.ts (95%) rename tests/{ => providers/xai}/grok-models-effort-list.test.ts (95%) rename tests/{ => providers/xai}/grok-orphan-adoption.test.ts (99%) rename tests/{ => providers/xai}/grok-selection.test.ts (94%) rename tests/{ => providers/xai}/grok-status.test.ts (96%) rename tests/{ => providers/xai}/grok-sync.test.ts (96%) rename tests/{ => providers/xai}/grok-writer-boundary.test.ts (96%) rename tests/{ => providers/xai}/xai-oauth-retry.test.ts (96%) rename tests/{ => providers/xai}/xai-refresh-lock.test.ts (96%) rename tests/{ => providers/xai}/xai-tool-schema.test.ts (98%) rename tests/{ => providers/xai}/xai-transport.test.ts (98%) rename tests/{ => providers/xai}/xai-web-search-compat.test.ts (96%) rename tests/{ => providers/xai}/xai-web-search.test.ts (92%) rename tests/{ => providers}/zcode-client.test.ts (97%) rename tests/{ => providers}/zhipu-bigmodel-provider.test.ts (92%) diff --git a/.github/scripts/pr-hygiene.test.cjs b/.github/scripts/pr-hygiene.test.cjs index e36435ed33..ff2d5d3c9c 100644 --- a/.github/scripts/pr-hygiene.test.cjs +++ b/.github/scripts/pr-hygiene.test.cjs @@ -225,7 +225,7 @@ describe("collectDeterministicHygieneFailures", () => { const failures = collectDeterministicHygieneFailures({ files: [ { filename: "src/codex/auth-api.ts", patch: "+change" }, - { filename: "tests/codex-auth-api.test.ts", patch: "+test" }, + { filename: "tests/codex-integration/codex-auth-api.test.ts", patch: "+test" }, ], authorHasPushPermission: true, }); diff --git a/docs/superpowers/plans/2026-07-26-oauth-reliability-integrity.md b/docs/superpowers/plans/2026-07-26-oauth-reliability-integrity.md index fb535a1ca4..15bc508f21 100644 --- a/docs/superpowers/plans/2026-07-26-oauth-reliability-integrity.md +++ b/docs/superpowers/plans/2026-07-26-oauth-reliability-integrity.md @@ -209,7 +209,7 @@ EOF **Files:** - Modify: `src/oauth/index.ts` (`refreshAndPersistAccessToken` generic branch ~352–400) -- Test: `tests/oauth/oauth-refresh-generic-lock.test.ts` (new; mirror patterns from `tests/xai-refresh-lock.test.ts` / `tests/oauth/oauth-refresh.test.ts`) +- Test: `tests/oauth/oauth-refresh-generic-lock.test.ts` (new; mirror patterns from `tests/providers/xai/xai-refresh-lock.test.ts` / `tests/oauth/oauth-refresh.test.ts`) **Interfaces:** - Consumes: `createOAuthRefreshIntentLock`, `mergeAccountCredential`, `credentialGeneration`, `markAccountNeedsReauthIfGeneration`, `getAccountCredential`, `logOAuthEvent` @@ -308,7 +308,7 @@ Also log `"OAuth refresh joined existing operation"` when `tokenRefreshes.get(ke Run: ```bash -bun test tests/oauth/oauth-refresh-generic-lock.test.ts tests/oauth/oauth-refresh.test.ts tests/xai-refresh-lock.test.ts +bun test tests/oauth/oauth-refresh-generic-lock.test.ts tests/oauth/oauth-refresh.test.ts tests/providers/xai/xai-refresh-lock.test.ts ``` Expected: PASS (no regressions on xAI/Anthropic) @@ -420,7 +420,7 @@ Set `action` strings: - [ ] **Step 4: Run test to verify it passes** -Run: `bun test tests/oauth/oauth-health.test.ts tests/codex-routing.test.ts` +Run: `bun test tests/oauth/oauth-health.test.ts tests/codex-integration/codex-routing.test.ts` Expected: PASS @@ -502,7 +502,7 @@ EOF **Files:** - Modify: `src/cli/doctor.ts` -- Test: `tests/service/doctor-oauth.test.ts` (or extend `tests/doctor.test.ts`) +- Test: `tests/service/doctor-oauth.test.ts` (or extend `tests/codex-integration/doctor.test.ts`) **Interfaces:** - Consumes: `collectOAuthHealthEntries`, auth store writability checks, refresh lock path helpers if exported @@ -529,7 +529,7 @@ Add `collectOAuthDoctorChecks(): Array<{ level: "OK" | "WARN"; message: string } - [ ] **Step 4: Run tests** -Run: `bun test tests/service/doctor-oauth.test.ts tests/doctor.test.ts` +Run: `bun test tests/service/doctor-oauth.test.ts tests/codex-integration/doctor.test.ts` Expected: PASS @@ -607,9 +607,9 @@ EOF ### Task 8: Codex metadata integrity regressions + 401 replay invariants **Files:** -- Test: `tests/codex-metadata-integrity.test.ts` (new) +- Test: `tests/codex-integration/codex-metadata-integrity.test.ts` (new) - Modify only if a real gap is found: `src/codex/auth-context.ts`, `src/adapters/openai-responses.ts` -- Confirm existing: `tests/server-xai-oauth-401-replay.test.ts`, `tests/server-kiro-oauth-401-replay.test.ts`, `tests/codex-routing.test.ts` (policy A) +- Confirm existing: `tests/server-xai-oauth-401-replay.test.ts`, `tests/server-kiro-oauth-401-replay.test.ts`, `tests/codex-integration/codex-routing.test.ts` (policy A) **Interfaces:** - Consumes: `headersForCodexAuthContext`, `FORWARD_HEADERS` @@ -644,7 +644,7 @@ test("preserves genuine originator", () => { - [ ] **Step 2: Run tests** -Run: `bun test tests/codex-metadata-integrity.test.ts` +Run: `bun test tests/codex-integration/codex-metadata-integrity.test.ts` Expected: FAIL only if implementation gap exists; if PASS immediately, keep tests as regressions and skip code changes. @@ -655,7 +655,7 @@ If fabrication or account-id mismatch is found, fix the minimal header path. Do - [ ] **Step 4: Run related suite** ```bash -bun test tests/codex-metadata-integrity.test.ts tests/codex-auth-context.test.ts tests/codex-routing.test.ts tests/session-affinity.test.ts tests/server-xai-oauth-401-replay.test.ts tests/server-kiro-oauth-401-replay.test.ts +bun test tests/codex-integration/codex-metadata-integrity.test.ts tests/codex-integration/codex-auth-context.test.ts tests/codex-integration/codex-routing.test.ts tests/session-affinity.test.ts tests/server-xai-oauth-401-replay.test.ts tests/server-kiro-oauth-401-replay.test.ts ``` Expected: PASS @@ -663,7 +663,7 @@ Expected: PASS - [ ] **Step 5: Commit** ```bash -git add tests/codex-metadata-integrity.test.ts src/codex/auth-context.ts src/adapters/openai-responses.ts +git add tests/codex-integration/codex-metadata-integrity.test.ts src/codex/auth-context.ts src/adapters/openai-responses.ts git commit -m "$(cat <<'EOF' test(codex): lock metadata pass-through and non-fabrication @@ -713,8 +713,8 @@ EOF - [ ] **Step 1: Run verification commands** ```bash -bun test tests/lib/privacy-mask-account.test.ts tests/oauth/oauth-log.test.ts tests/oauth/oauth-refresh-generic-lock.test.ts tests/oauth/oauth-health.test.ts tests/cli/cli-status-oauth-health.test.ts tests/service/doctor-oauth.test.ts tests/oauth/oauth-accounts-api.test.ts tests/codex-metadata-integrity.test.ts -bun test tests/oauth/oauth-refresh.test.ts tests/xai-refresh-lock.test.ts tests/codex-routing.test.ts tests/session-affinity.test.ts tests/codex-auth-context.test.ts +bun test tests/lib/privacy-mask-account.test.ts tests/oauth/oauth-log.test.ts tests/oauth/oauth-refresh-generic-lock.test.ts tests/oauth/oauth-health.test.ts tests/cli/cli-status-oauth-health.test.ts tests/service/doctor-oauth.test.ts tests/oauth/oauth-accounts-api.test.ts tests/codex-integration/codex-metadata-integrity.test.ts +bun test tests/oauth/oauth-refresh.test.ts tests/providers/xai/xai-refresh-lock.test.ts tests/codex-integration/codex-routing.test.ts tests/session-affinity.test.ts tests/codex-integration/codex-auth-context.test.ts bun run test bun run typecheck bun run lint:gui diff --git a/docs/superpowers/plans/2026-08-06-deepseek-responses-streaming-terminal-repair.md b/docs/superpowers/plans/2026-08-06-deepseek-responses-streaming-terminal-repair.md index 11976200cd..4720749b10 100644 --- a/docs/superpowers/plans/2026-08-06-deepseek-responses-streaming-terminal-repair.md +++ b/docs/superpowers/plans/2026-08-06-deepseek-responses-streaming-terminal-repair.md @@ -27,7 +27,7 @@ - `src/server/responses-terminal-repair.ts` — owns SSE lifecycle tracking, bounded retained state, grace scheduling, and synthetic terminal creation. - `src/server/responses/core.ts` — activates the repair before existing transport-specific relay branches. - `tests/responses/responses-terminal-repair.test.ts` — unit state-machine and stream-race coverage. -- `tests/deepseek-inbound-wire.test.ts` — end-to-end official DeepSeek wire and HTTP activation. +- `tests/providers/deepseek-inbound-wire.test.ts` — end-to-end official DeepSeek wire and HTTP activation. - `tests/responses/ws-endpoint.test.ts` — WebSocket event parity for real and repaired terminals. - `structure/04_transports-and-sidecars.md` — architectural contract for the provider-scoped streaming repair. - `docs/superpowers/specs/2026-08-06-deepseek-responses-streaming-terminal-repair-design.md` — approved design authority; implementation must remain consistent with it. @@ -40,8 +40,8 @@ - Modify: `src/providers/registry.ts:150-170` - Modify: `src/providers/registry.ts:1143-1162` - Modify: `src/providers/registry.ts:1834-1842` -- Modify: `tests/deepseek-inbound-wire.test.ts:1-175` -- Modify: `tests/deepseek-responses-item-id-repair.test.ts` +- Modify: `tests/providers/deepseek-inbound-wire.test.ts:1-175` +- Modify: `tests/providers/deepseek-responses-item-id-repair.test.ts` **Interfaces:** - Produces: `ResponsesTerminalRepairPolicy` @@ -74,7 +74,7 @@ test("Codex HTTP and WebSocket turns keep DeepSeek streaming upstream", async () Delete or rewrite the tests whose asserted contract is specifically `stream:false`/bounded JSON for built-in DeepSeek. Keep the bounded-JSON helper coverage that is provider-neutral. In -`tests/deepseek-responses-item-id-repair.test.ts`, retain the pure +`tests/providers/deepseek-responses-item-id-repair.test.ts`, retain the pure `repairResponsesJsonItemIds()` unit test but remove the built-in-DeepSeek HTTP activation assertion; Task 4 replaces it with streaming repair composition. @@ -83,7 +83,7 @@ activation assertion; Task 4 replaces it with streaming repair composition. Run: ```bash -bun test tests/deepseek-inbound-wire.test.ts +bun test tests/providers/deepseek-inbound-wire.test.ts ``` Expected: compile/test failure because `providerModelResponsesTerminalRepair` @@ -134,7 +134,7 @@ export function providerModelResponsesTerminalRepair( Run: ```bash -bun test tests/deepseek-inbound-wire.test.ts tests/deepseek-responses-item-id-repair.test.ts tests/provider-registry-parity.test.ts +bun test tests/providers/deepseek-inbound-wire.test.ts tests/providers/deepseek-responses-item-id-repair.test.ts tests/providers/provider-registry-parity.test.ts ``` Expected: all selected tests pass; captured HTTP and WebSocket request bodies @@ -143,7 +143,7 @@ carry `stream:true`. - [ ] **Step 5: Commit** ```bash -git add src/providers/registry.ts tests/deepseek-inbound-wire.test.ts tests/deepseek-responses-item-id-repair.test.ts +git add src/providers/registry.ts tests/providers/deepseek-inbound-wire.test.ts tests/providers/deepseek-responses-item-id-repair.test.ts git commit -m "fix(deepseek): restore Responses upstream streaming" ``` @@ -386,8 +386,8 @@ git commit -m "fix(responses): fail closed on unsafe terminal repair" **Files:** - Modify: `src/server/responses/core.ts:95-115` - Modify: `src/server/responses/core.ts:2030-2230` -- Modify: `tests/deepseek-inbound-wire.test.ts:115-330` -- Modify: `tests/deepseek-responses-item-id-repair.test.ts` +- Modify: `tests/providers/deepseek-inbound-wire.test.ts:115-330` +- Modify: `tests/providers/deepseek-responses-item-id-repair.test.ts` - Modify: `tests/responses/ws-endpoint.test.ts` **Interfaces:** @@ -432,7 +432,7 @@ WebSocket handling. Assert the client receives progressive delta frames, one Run: ```bash -bun test tests/deepseek-inbound-wire.test.ts tests/responses/ws-endpoint.test.ts +bun test tests/providers/deepseek-inbound-wire.test.ts tests/responses/ws-endpoint.test.ts ``` Expected: requests now carry `stream:true` from Task 1 but no provider-scoped @@ -482,7 +482,7 @@ streaming resolver still returns `false`. Run: ```bash -bun test tests/deepseek-inbound-wire.test.ts tests/responses/ws-endpoint.test.ts tests/responses/responses-state.test.ts tests/deepseek-responses-item-id-repair.test.ts tests/deepseek-reasoning-replay.test.ts +bun test tests/providers/deepseek-inbound-wire.test.ts tests/responses/ws-endpoint.test.ts tests/responses/responses-state.test.ts tests/providers/deepseek-responses-item-id-repair.test.ts tests/providers/deepseek-reasoning-replay.test.ts ``` Expected: progressive output precedes terminal, both transports close once, @@ -491,7 +491,7 @@ item ids are stable, and continuation state retains reasoning/function output. - [ ] **Step 6: Commit** ```bash -git add src/server/responses/core.ts tests/deepseek-inbound-wire.test.ts tests/deepseek-responses-item-id-repair.test.ts tests/responses/ws-endpoint.test.ts +git add src/server/responses/core.ts tests/providers/deepseek-inbound-wire.test.ts tests/providers/deepseek-responses-item-id-repair.test.ts tests/responses/ws-endpoint.test.ts git commit -m "fix(deepseek): repair terminal-less Responses streams" ``` @@ -560,7 +560,7 @@ git commit -m "docs(deepseek): describe streaming terminal repair" Run: ```bash -bun test tests/responses/responses-terminal-repair.test.ts tests/deepseek-inbound-wire.test.ts tests/responses/ws-endpoint.test.ts tests/responses/sse-failed-tail.test.ts tests/relay-eager.test.ts tests/responses/responses-item-id-repair.test.ts tests/deepseek-responses-item-id-repair.test.ts tests/deepseek-reasoning-replay.test.ts tests/responses/responses-state.test.ts +bun test tests/responses/responses-terminal-repair.test.ts tests/providers/deepseek-inbound-wire.test.ts tests/responses/ws-endpoint.test.ts tests/responses/sse-failed-tail.test.ts tests/relay-eager.test.ts tests/responses/responses-item-id-repair.test.ts tests/providers/deepseek-responses-item-id-repair.test.ts tests/providers/deepseek-reasoning-replay.test.ts tests/responses/responses-state.test.ts ``` Expected: 0 failures. diff --git a/docs/superpowers/plans/2026-08-09-routed-computer-use-browser.md b/docs/superpowers/plans/2026-08-09-routed-computer-use-browser.md index 55121abd8e..ac2a9a6635 100644 --- a/docs/superpowers/plans/2026-08-09-routed-computer-use-browser.md +++ b/docs/superpowers/plans/2026-08-09-routed-computer-use-browser.md @@ -13,9 +13,9 @@ ## Task 1: Lock the routed catalog contract with failing tests **Files:** -- Modify: `tests/codex-catalog.test.ts:280-300` -- Modify: `tests/codex-catalog.test.ts:1011-1045` -- Modify: `tests/codex-catalog.test.ts:1230-1255` +- Modify: `tests/codex-integration/codex-catalog.test.ts:280-300` +- Modify: `tests/codex-integration/codex-catalog.test.ts:1011-1045` +- Modify: `tests/codex-integration/codex-catalog.test.ts:1230-1255` **Step 1: Change the combo assertion to require the explicit routed mode** @@ -68,7 +68,7 @@ expect(rows.find(row => row.slug === "team/gpt-5.5")?.tool_mode).toBe("code"); Run: ```bash -bun test tests/codex-catalog.test.ts +bun test tests/codex-integration/codex-catalog.test.ts ``` Expected: routed/template/combo/fallback assertions fail because current production code deletes or omits `tool_mode`; native preservation assertions remain green. @@ -76,7 +76,7 @@ Expected: routed/template/combo/fallback assertions fail because current product **Step 6: Commit the red tests only** ```bash -git add tests/codex-catalog.test.ts +git add tests/codex-integration/codex-catalog.test.ts git commit -m "test(codex): require code mode for routed models" ``` @@ -86,7 +86,7 @@ git commit -m "test(codex): require code mode for routed models" - Modify: `src/codex/catalog/parsing.ts:341-375` - Modify: `src/codex/catalog/sync.ts:33` - Modify: `src/codex/catalog/sync.ts:276-310` -- Test: `tests/codex-catalog.test.ts` +- Test: `tests/codex-integration/codex-catalog.test.ts` **Step 1: Add a named compatibility helper** @@ -128,7 +128,7 @@ Do not call the full routed normalizer from the fallback branch; that would broa **Step 4: Run the focused tests and confirm GREEN** ```bash -bun test tests/codex-catalog.test.ts +bun test tests/codex-integration/codex-catalog.test.ts ``` Expected: all catalog tests pass, including native/account preservation. @@ -151,8 +151,8 @@ git commit -m "fix(codex): enable code mode for routed models" ## Task 3: Prove on-disk catalog synchronization preserves the policy **Files:** -- Modify: `tests/codex-catalog-sync-hardening.test.ts` -- Test: `tests/codex-catalog-sync-hardening.test.ts` +- Modify: `tests/codex-integration/codex-catalog-sync-hardening.test.ts` +- Test: `tests/codex-integration/codex-catalog-sync-hardening.test.ts` **Step 1: Add a real sync fixture assertion** @@ -169,7 +169,7 @@ Also assert a generated native account-qualified row retains `"code"` if the fix **Step 2: Run the sync test** ```bash -bun test tests/codex-catalog-sync-hardening.test.ts +bun test tests/codex-integration/codex-catalog-sync-hardening.test.ts ``` Expected: pass and prove the serialized catalog, not merely the in-memory builder. @@ -177,7 +177,7 @@ Expected: pass and prove the serialized catalog, not merely the in-memory builde **Step 3: Commit the persistence test** ```bash -git add tests/codex-catalog-sync-hardening.test.ts +git add tests/codex-integration/codex-catalog-sync-hardening.test.ts git commit -m "test(codex): persist routed code mode policy" ``` @@ -229,7 +229,7 @@ git commit -m "docs(codex): explain routed local tool access" Run: ```bash -bun test tests/responses/responses-parser.test.ts tests/adapters/bridge.test.ts tests/multi-agent-compat.test.ts +bun test tests/responses/responses-parser.test.ts tests/adapters/bridge.test.ts tests/codex-integration/multi-agent-compat.test.ts ``` Expected: custom declaration, streaming `custom_tool_call`, exact freeform input, and output replay remain green. Add no production protocol change unless one of these tests proves a real gap. @@ -239,7 +239,7 @@ Expected: custom declaration, streaming `custom_tool_call`, exact freeform input Run: ```bash -bun test tests/responses/responses-terminal-repair.test.ts tests/deepseek-inbound-wire.test.ts tests/deepseek-responses-item-id-repair.test.ts tests/responses/passthrough-abort.test.ts +bun test tests/responses/responses-terminal-repair.test.ts tests/providers/deepseek-inbound-wire.test.ts tests/providers/deepseek-responses-item-id-repair.test.ts tests/responses/passthrough-abort.test.ts ``` Expected: progressive deltas, strict terminal repair, item IDs, and cancellation pass. @@ -249,7 +249,7 @@ Expected: progressive deltas, strict terminal repair, item IDs, and cancellation Run: ```bash -bun test tests/vision/vision-sidecar-e2e.test.ts tests/vision/vision-anthropic.test.ts tests/vision/vision-cache.test.ts tests/vision/vision-fail-closed.test.ts tests/catalog-vision-sidecar-modalities.test.ts tests/responses/openai-responses-passthrough.test.ts +bun test tests/vision/vision-sidecar-e2e.test.ts tests/vision/vision-anthropic.test.ts tests/vision/vision-cache.test.ts tests/vision/vision-fail-closed.test.ts tests/codex-integration/catalog-vision-sidecar-modalities.test.ts tests/responses/openai-responses-passthrough.test.ts ``` Expected: captions replace raw image parts in passthrough bodies, empty references do not consume captions, and partial/failure paths omit pixels safely. diff --git a/docs/superpowers/plans/2026-08-13-cl10-deep-review-hardening.md b/docs/superpowers/plans/2026-08-13-cl10-deep-review-hardening.md index 32abc929e5..ce8233cbf3 100644 --- a/docs/superpowers/plans/2026-08-13-cl10-deep-review-hardening.md +++ b/docs/superpowers/plans/2026-08-13-cl10-deep-review-hardening.md @@ -175,7 +175,7 @@ ### Task 12: Move catalog timeout to the flaky test only **Files:** -- Modify: `tests/codex-catalog-sync-hardening.test.ts` +- Modify: `tests/codex-integration/codex-catalog-sync-hardening.test.ts` - Modify: `scripts/ci/run-bun-test-batches.sh` **Interfaces:** diff --git a/docs/superpowers/plans/2026-08-26-discovered-model-display-names-core.md b/docs/superpowers/plans/2026-08-26-discovered-model-display-names-core.md index 6d7c1776db..81e41fc72d 100644 --- a/docs/superpowers/plans/2026-08-26-discovered-model-display-names-core.md +++ b/docs/superpowers/plans/2026-08-26-discovered-model-display-names-core.md @@ -33,11 +33,11 @@ - `src/codex/catalog/provider-fetch.ts`: resolves operator display names at the shared catalog boundary. - `src/server/management/model-rows.ts`: exposes effective display names and their source. - `src/server/management/model-routes.ts`: sets and resets one provider model display name. -- `tests/provider-config-validation.test.ts`: covers strict validator behavior. +- `tests/providers/provider-config-validation.test.ts`: covers strict validator behavior. - `tests/config/config-load-degrade.test.ts`: covers safe hand edited config loading. - `tests/config/config-user-edits.test.ts`: covers persistence and concurrent unrelated map edits. -- `tests/codex-catalog.test.ts`: covers label precedence and routing invariants. -- `tests/model-display-names-management-api.test.ts`: covers read and mutation API behavior. +- `tests/codex-integration/codex-catalog.test.ts`: covers label precedence and routing invariants. +- `tests/codex-integration/model-display-names-management-api.test.ts`: covers read and mutation API behavior. - `docs-site/src/content/docs/reference/configuration/providers.md`: documents the field and exact key rules. - `structure/02_config-and-codex-home.md`: records the new persisted provider field. - `structure/03_catalog-and-subagents.md`: records display precedence at catalog assembly. @@ -50,7 +50,7 @@ - Modify: `src/types/provider.ts` - Modify: `src/config/provider-validation.ts` - Modify: `src/config.ts` -- Test: `tests/provider-config-validation.test.ts` +- Test: `tests/providers/provider-config-validation.test.ts` - Test: `tests/config/config-load-degrade.test.ts` **Interfaces:** @@ -75,7 +75,7 @@ expect(modelDisplayNamesConfigError({ "grok-4.6": "Grok\n4.6" })).toContain("con Run: ```text -bun test tests/provider-config-validation.test.ts +bun test tests/providers/provider-config-validation.test.ts ``` Expected: failure because `modelDisplayNamesConfigError` does not exist. @@ -105,7 +105,7 @@ The validator accepts only a plain own property object, at most 2,000 entries, e Run: ```text -bun test tests/provider-config-validation.test.ts +bun test tests/providers/provider-config-validation.test.ts ``` Expected: all tests pass. @@ -126,7 +126,7 @@ Write a real config file fixture containing one valid and one invalid label. Ass Run: ```text -bun test tests/config/config-load-degrade.test.ts tests/provider-config-validation.test.ts +bun test tests/config/config-load-degrade.test.ts tests/providers/provider-config-validation.test.ts ``` Expected: the candidate accepts unvalidated values or the load path does not sanitize them. @@ -152,7 +152,7 @@ Add `sanitizeModelDisplayNamesForLoad(parsed)` before `configSchema.safeParse(pa Run: ```text -bun test tests/config/config-load-degrade.test.ts tests/provider-config-validation.test.ts +bun test tests/config/config-load-degrade.test.ts tests/providers/provider-config-validation.test.ts ``` Expected: all tests pass with no unexpected warnings. @@ -160,7 +160,7 @@ Expected: all tests pass with no unexpected warnings. - [ ] **Step 9: Commit the config contract** ```text -git add src/types/provider.ts src/config/provider-validation.ts src/config.ts tests/provider-config-validation.test.ts tests/config/config-load-degrade.test.ts +git add src/types/provider.ts src/config/provider-validation.ts src/config.ts tests/providers/provider-config-validation.test.ts tests/config/config-load-degrade.test.ts git commit -m "feat(config): add discovered model display names" ``` @@ -170,7 +170,7 @@ git commit -m "feat(config): add discovered model display names" **Files:** - Modify: `src/codex/catalog/provider-fetch.ts` -- Test: `tests/codex-catalog.test.ts` +- Test: `tests/codex-integration/codex-catalog.test.ts` **Interfaces:** - Consumes: `OcxProviderConfig.modelDisplayNames` @@ -195,7 +195,7 @@ Cover exact case sensitive matching, same native ID under two providers, operato Run: ```text -bun test tests/codex-catalog.test.ts +bun test tests/codex-integration/codex-catalog.test.ts ``` Expected: the discovered row keeps its old metadata or slug instead of the configured label. @@ -224,7 +224,7 @@ Add `modelDisplayNames` to `providerCatalogFingerprint`, because `gatherFlightKe Run: ```text -bun test tests/codex-catalog.test.ts +bun test tests/codex-integration/codex-catalog.test.ts ``` Expected: all catalog tests pass and routing identity stays byte equivalent. @@ -232,7 +232,7 @@ Expected: all catalog tests pass and routing identity stays byte equivalent. - [ ] **Step 5: Commit catalog propagation** ```text -git add src/codex/catalog/provider-fetch.ts tests/codex-catalog.test.ts +git add src/codex/catalog/provider-fetch.ts tests/codex-integration/codex-catalog.test.ts git commit -m "feat(catalog): apply provider model display names" ``` @@ -243,7 +243,7 @@ git commit -m "feat(catalog): apply provider model display names" **Files:** - Modify: `src/server/management/model-rows.ts` - Modify: `src/server/management/model-routes.ts` -- Create: `tests/model-display-names-management-api.test.ts` +- Create: `tests/codex-integration/model-display-names-management-api.test.ts` **Interfaces:** - Produces: `ManagementModelRow.displayNameSource?: "operator" | "provider" | "fallback"` @@ -261,7 +261,7 @@ Use `listManagementModelRows` with a real provider model fixture. Assert the row Run: ```text -bun test tests/model-display-names-management-api.test.ts +bun test tests/codex-integration/model-display-names-management-api.test.ts ``` Expected: `displayNameOverride` and `displayNameSource` are absent. @@ -282,7 +282,7 @@ Use `operator` when the exact configured map owns the ID, `provider` when `Catal Run: ```text -bun test tests/model-display-names-management-api.test.ts +bun test tests/codex-integration/model-display-names-management-api.test.ts ``` Expected: read tests pass. @@ -309,7 +309,7 @@ Use a persistence seam that clones the actual config snapshot. Assert final stat Run: ```text -bun test tests/model-display-names-management-api.test.ts +bun test tests/codex-integration/model-display-names-management-api.test.ts ``` Expected: route returns `null` or 404 because it is not registered. @@ -345,7 +345,7 @@ Do not require the model ID to exist in live discovery. Run: ```text -bun test tests/model-display-names-management-api.test.ts +bun test tests/codex-integration/model-display-names-management-api.test.ts ``` Expected: all API tests pass. @@ -367,7 +367,7 @@ If the first run passes, record that the existing recursive provider merge alrea - [ ] **Step 11: Commit the management API** ```text -git add src/server/management/model-rows.ts src/server/management/model-routes.ts tests/model-display-names-management-api.test.ts tests/config/config-user-edits.test.ts src/config.ts +git add src/server/management/model-rows.ts src/server/management/model-routes.ts tests/codex-integration/model-display-names-management-api.test.ts tests/config/config-user-edits.test.ts src/config.ts git commit -m "feat(api): manage discovered model display names" ``` @@ -441,7 +441,7 @@ Check exact ID matching, no route identity changes, no secret fields in DTOs, no - [ ] **Step 2: Run focused tests** ```text -bun test tests/provider-config-validation.test.ts tests/config/config-load-degrade.test.ts tests/config/config-user-edits.test.ts tests/codex-catalog.test.ts tests/model-display-names-management-api.test.ts +bun test tests/providers/provider-config-validation.test.ts tests/config/config-load-degrade.test.ts tests/config/config-user-edits.test.ts tests/codex-integration/codex-catalog.test.ts tests/codex-integration/model-display-names-management-api.test.ts ``` Expected: all pass. diff --git a/docs/superpowers/specs/2026-08-06-deepseek-responses-streaming-terminal-repair-design.md b/docs/superpowers/specs/2026-08-06-deepseek-responses-streaming-terminal-repair-design.md index da50bea61a..f8fdc8af50 100644 --- a/docs/superpowers/specs/2026-08-06-deepseek-responses-streaming-terminal-repair-design.md +++ b/docs/superpowers/specs/2026-08-06-deepseek-responses-streaming-terminal-repair-design.md @@ -228,7 +228,7 @@ The implementation is expected to touch these responsibility boundaries: - `src/server/responses/core.ts`: resolve the provider policy and wrap the SSE body before transport-specific relay branches. - `tests/responses/responses-terminal-repair.test.ts`: unit state-machine coverage. -- `tests/deepseek-inbound-wire.test.ts`: end-to-end wire, progressive delivery, +- `tests/providers/deepseek-inbound-wire.test.ts`: end-to-end wire, progressive delivery, repair composition, and WebSocket/HTTP activation. - Existing relay and item-id tests only where an explicit integration contract needs to be pinned. diff --git a/scripts/generate-model-metadata.ts b/scripts/generate-model-metadata.ts index af13fed711..2441e32bc9 100644 --- a/scripts/generate-model-metadata.ts +++ b/scripts/generate-model-metadata.ts @@ -26,7 +26,7 @@ type RawModel = { // the generator runs correctly from any working directory. const sourcePath = resolve(import.meta.dir, "model-metadata.source.json"); // `MODEL_METADATA_OUT` lets the sync guard regenerate into a temp file and byte-compare without -// any risk of clobbering the committed output (tests/model-metadata-sync.test.ts). +// any risk of clobbering the committed output (tests/codex-integration/model-metadata-sync.test.ts). const outPath = process.env.MODEL_METADATA_OUT ? resolve(process.env.MODEL_METADATA_OUT) : resolve(import.meta.dir, "../src/generated/model-metadata.ts"); @@ -52,7 +52,7 @@ const allowedProviders = Array.from( // `opencode-go/hy3-preview` returns `Provider error 400 ... model_not_supported` because it is not // on the Zen Go lite model list, yet upstream keeps re-adding `tencent/hy3-preview`. Without this // block, every regeneration resurrects it as a selectable model and users hit that 400 again. -// Keyed as `/`; `tests/codex-catalog.test.ts` asserts the slug stays absent. +// Keyed as `/`; `tests/codex-integration/codex-catalog.test.ts` asserts the slug stays absent. const EXCLUDED_MODELS = new Set([ "opencode-go/hy3-preview", ]); diff --git a/scripts/openai-provider-option-final-gates.ts b/scripts/openai-provider-option-final-gates.ts index d07458721c..a6cf3f9bd4 100644 --- a/scripts/openai-provider-option-final-gates.ts +++ b/scripts/openai-provider-option-final-gates.ts @@ -47,15 +47,15 @@ const focusedTests = [ "tests/adapters/openai/openai-provider-option-startup.test.ts", "tests/adapters/openai/openai-provider-option-e2e.test.ts", "tests/adapters/openai/openai-provider-option-tooling.test.ts", - "tests/provider-registry-parity.test.ts", + "tests/providers/provider-registry-parity.test.ts", "tests/gui/provider-payload.test.ts", "tests/gui/codex-account-mode-state.test.ts", "tests/routing/router.test.ts", - "tests/codex-routing.test.ts", + "tests/codex-integration/codex-routing.test.ts", "tests/server-auth.test.ts", - "tests/codex-catalog.test.ts", - "tests/codex-quota-prime.test.ts", - "tests/provider-quota.test.ts", + "tests/codex-integration/codex-catalog.test.ts", + "tests/codex-integration/codex-quota-prime.test.ts", + "tests/providers/provider-quota.test.ts", "tests/server-images.test.ts", "tests/server-search.test.ts", ]; diff --git a/scripts/test-layout/layout.json b/scripts/test-layout/layout.json index 654ff71403..a019b79878 100644 --- a/scripts/test-layout/layout.json +++ b/scripts/test-layout/layout.json @@ -1232,11 +1232,13 @@ "claude-integration", "cli", "clients", + "codex-integration", "config", "gui", "lab", "lib", "oauth", + "providers", "responses", "routing", "service", diff --git a/scripts/test-layout/schema.ts b/scripts/test-layout/schema.ts index d88410d6dd..f5cbb2a4ed 100644 --- a/scripts/test-layout/schema.ts +++ b/scripts/test-layout/schema.ts @@ -140,7 +140,7 @@ export function rewriteSource(source: string, depth: number): string { export const LOCAL_MARKER = "// layout: local"; -const HELPER_NAMES = ["helperPath", "repoPath", "repoRoot"] as const; +const HELPER_NAMES = ["fixturePath", "helperPath", "repoPath", "repoRoot"] as const; /** * The source with comments, templates and regex bodies blanked but string literals kept, so @@ -186,8 +186,11 @@ export function rewriteMetaDirEscapes(source: string, depth: number): { source: [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\."\s*,\s*/g, () => "repoPath("], [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\.\/([^"]+)"/g, m => `repoPath("${m[1]}"`], [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"helpers"\s*,\s*/g, () => "helperPath("], - [/\bfileURLToPath\(\s*new\s+URL\(\s*"\.\.\/"\s*,\s*import\.meta\.url\s*\)\s*\)/g, () => "repoRoot()"], - [/\bresolve\(\s*dirname\(\s*fileURLToPath\(\s*import\.meta\.url\s*\)\s*\)\s*,\s*"\.\."\s*\)/g, () => "repoRoot()"], + [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"helpers\/([^"]+)"/g, m => `helperPath("${m[1]}"`], + [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"fixtures"\s*,\s*/g, () => "fixturePath("], + [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"fixtures\/([^"]+)"/g, m => `fixturePath("${m[1]}"`], + [/\bfileURLToPath\(\s*new\s+URL\(\s*"\.\.\/"\s*,\s*import\.meta\.url\s*\)\s*\)/g, () => rootCall], + [/\bresolve\(\s*dirname\(\s*fileURLToPath\(\s*import\.meta\.url\s*\)\s*\)\s*,\s*"\.\."\s*\)/g, () => rootCall], ]; const edits: Array<{ start: number; end: number; text: string }> = []; for (const [re, build] of rules) { @@ -206,9 +209,9 @@ export function rewriteMetaDirEscapes(source: string, depth: number): { source: } out += source.slice(cursor); const codeOut = maskNonCode(out); - const used = HELPER_NAMES.filter(name => new RegExp(`\\b${name}\\(`).test(codeOut)).map(name => (name === "repoRoot" && rebindsRoot ? "repoRoot as resolveRepoRoot" : name)); - if (rebindsRoot && !used.includes("repoRoot as resolveRepoRoot")) used.push("repoRoot as resolveRepoRoot"); - if (/\bpathToFileURL\(repoRoot\(\)/.test(codeOut) && !/\bimport\s*\{[^}]*\bpathToFileURL\b[^}]*\}\s*from\s*["']node:url["']/.test(view)) { + const used: string[] = HELPER_NAMES.filter(name => new RegExp(`\\b${name}\\(`).test(codeOut) && !(rebindsRoot && name === "repoRoot")); + if (rebindsRoot) used.push("repoRoot as resolveRepoRoot"); + if (/\bpathToFileURL\((?:resolveRepoRoot|repoRoot)\(\)/.test(codeOut) && !/\bimport\s*\{[^}]*\bpathToFileURL\b[^}]*\}\s*from\s*["']node:url["']/.test(view)) { out = insertAfterImports(out, 'import { pathToFileURL } from "node:url";'); } const existing = /^import\s*\{([^}]*)\}\s*from\s*(["'])([^"']*helpers\/repo-root)\2;?/m.exec(maskKeepStrings(out)); @@ -225,25 +228,34 @@ export function rewriteMetaDirEscapes(source: string, depth: number): { source: return { source: out, rewrites: applied }; } -/** Insert a line after the last top-level import / export-from statement (multi-line aware). */ +/** + * Insert a line after the leading block of top-level import / export-from statements: the + * run of such statements that starts at the top of the file (comments and blank lines + * allowed between them). An import that appears later, after real code, is not part of that + * block, so the helper never lands at the bottom of a file that happens to end with an import. + */ export function insertAfterImports(source: string, line: string): string { const tokens = tokenize(source); const masked = maskNonCode(source, tokens); let insertAt = 0; - for (const site of specifierSites(source, tokens)) { - // Walk back over the statement to its first non-blank column-0 keyword. - const before = masked.slice(0, site.token.start); - const stmtStart = Math.max(before.lastIndexOf("\nimport"), before.lastIndexOf("\nexport"), before.startsWith("import") || before.startsWith("export") ? 0 : -1); - if (stmtStart === -1) continue; - const between = masked.slice(stmtStart, site.token.start); - if (between.includes(";")) continue; // the keyword belongs to an earlier statement - // The statement ends at the first ";" or line break after the specifier, whichever is - // first: a semicolonless import must not swallow the next statement. - const semi = masked.indexOf(";", site.token.end); - const nl = masked.indexOf("\n", site.token.end); - const stop = semi !== -1 && (nl === -1 || semi < nl) ? semi : site.token.end; + let cursor = 0; + const n = masked.length; + while (cursor < n) { + // Skip blank lines (comments are already blanked in `masked`). + const lineEnd = masked.indexOf("\n", cursor); + const lineStop = lineEnd === -1 ? n : lineEnd; + const text = masked.slice(cursor, lineStop); + if (text.trim() === "") { cursor = lineStop + 1; continue; } + if (!/^(?:import|export)\b/.test(text) || /^(?:import|export)\s*\(/.test(text)) break; + // Statement ends at the first ";" or, failing that, the end of the line holding the closing quote. + const site = specifierSites(source, tokens).find(s => s.token.start >= cursor); + const specEnd = site ? site.token.end : lineStop; + const semi = masked.indexOf(";", specEnd); + const nl = masked.indexOf("\n", specEnd); + const stop = semi !== -1 && (nl === -1 || semi <= nl) ? semi : specEnd; const eol = masked.indexOf("\n", stop); - insertAt = Math.max(insertAt, eol === -1 ? source.length : eol + 1); + insertAt = eol === -1 ? n : eol + 1; + cursor = insertAt; } return source.slice(0, insertAt) + line + "\n" + source.slice(insertAt); } @@ -307,3 +319,5 @@ export function scanEscapes(source: string): EscapeHit[] { export function layoutDir(): string { return dirname(LAYOUT_PATH); } + + diff --git a/scripts/test.ts b/scripts/test.ts index 7b95acf35e..d69549a824 100644 --- a/scripts/test.ts +++ b/scripts/test.ts @@ -325,9 +325,9 @@ export function resolveBunTestArgs( // Paths relative to tests/. An entry moves with its file (scripts/test-layout/move.ts rewrites // it); the lane label, the ignore glob, and the timeout table all key on the basename. export const SERIAL_FULL_SUITE_FILES = [ - "codex-shim.test.ts", - "cursor-native-exec-shell.test.ts", - "issue-452-empty-503.test.ts", + "codex-integration/codex-shim.test.ts", + "providers/cursor/cursor-native-exec-shell.test.ts", + "codex-integration/issue-452-empty-503.test.ts", "adapters/openai/openai-provider-option-e2e.test.ts", "release-helper.test.ts", "update/update-stop-first.test.ts", diff --git a/src/adapters/cursor/protobuf-request.ts b/src/adapters/cursor/protobuf-request.ts index f3dec71d78..c4378540d2 100644 --- a/src/adapters/cursor/protobuf-request.ts +++ b/src/adapters/cursor/protobuf-request.ts @@ -379,7 +379,7 @@ function rootPromptMessages( } // Assistant tool CALLS are NOT replayed as a separate visible "[Tool Call]" entry: a model // few-shot-mimics that marker and emits later tool calls as inert text (363-B guard in - // tests/cursor-tool-continuation.test.ts). The invocation is instead named INSIDE the paired + // tests/providers/cursor/cursor-tool-continuation.test.ts). The invocation is instead named INSIDE the paired // "[Tool Result]" envelope below, which carries the same information without a mimickable // call template (devlog 260829 002_audit_round2). } else if (message.role === "toolResult") { @@ -954,7 +954,7 @@ function toolCallArgumentsText(args: Record): string { * * Why not a separate "[Tool Call]" entry: a model few-shot-mimics that marker and starts emitting * later tool calls as inert text instead of real tool frames, which halts multi-tool continuations - * (363-B guard, tests/cursor-tool-continuation.test.ts). Why it must exist at all: without any + * (363-B guard, tests/providers/cursor/cursor-tool-continuation.test.ts). Why it must exist at all: without any * record of the invocation, the replayed result is orphaned — its `call_id` refers to nothing the * model can see — and live cursor/grok-4.6 turns re-ran commands that had already succeeded while * narrating a phantom interrupt (devlog 260829 000_rca). A prose line inside the result satisfies diff --git a/src/clients/config-export.ts b/src/clients/config-export.ts index eb2c29aa9d..ea1b623f31 100644 --- a/src/clients/config-export.ts +++ b/src/clients/config-export.ts @@ -740,7 +740,7 @@ function outputBudgetFor(context: number): number { * single `audio` model takes every routed model down with it. That is not * hypothetical: zenmux/meta-muse-spark-1.1 advertises audio and did exactly * this. It is also the same defect the Codex catalog had with `video`, where - * the app showed zero apps (tests/catalog-input-modality-enum.test.ts). + * the app showed zero apps (tests/codex-integration/catalog-input-modality-enum.test.ts). * * UNKNOWN and INCOMPATIBLE are different inputs, and the Codex fix could * conflate them safely only because its enum is wider. A model with nothing diff --git a/src/codex/catalog/metadata.ts b/src/codex/catalog/metadata.ts index 439633f1e7..dce891ac82 100644 --- a/src/codex/catalog/metadata.ts +++ b/src/codex/catalog/metadata.ts @@ -671,7 +671,7 @@ function isAccountBoundOpenAiNativeSlug(slug: string): boolean { * malformed and minimal hand-written rows. It cannot distinguish a genuine upstream observation * from a complete row typed by hand into `$CODEX_HOME/models_cache.json`: there is no signature, * source identity, or server attestation to check. A full-shape forged row is accepted, and - * `observedFullShapeRowIsAccepted` in tests/native-model-toggle.test.ts pins that so nobody + * `observedFullShapeRowIsAccepted` in tests/codex-integration/native-model-toggle.test.ts pins that so nobody * later mistakes this predicate for a security boundary. * * That is acceptable here because the file is user-owned and written by Codex itself: anyone diff --git a/src/codex/catalog/provider-fetch.ts b/src/codex/catalog/provider-fetch.ts index fee52029ec..99e6eafc10 100644 --- a/src/codex/catalog/provider-fetch.ts +++ b/src/codex/catalog/provider-fetch.ts @@ -717,7 +717,7 @@ function configuredVerbositySupport(name: string, prov: OcxProviderConfig | unde // Read from the PROVIDER CONFIG, never from PROVIDER_REGISTRY. A gather flight captures its // registry authority up front and forbids any later registry read, so consulting the registry // here made a custom-destination flight fall back to "configured" instead of serving its own - // discovery result (tests/codex-gather-authority.test.ts). `applyVerbosityDefaults` in + // discovery result (tests/codex-integration/codex-gather-authority.test.ts). `applyVerbosityDefaults` in // providers/derive.ts materializes the registry default into the config at seed/enrich time. return prov.supportsVerbosity; } diff --git a/src/providers/derive.ts b/src/providers/derive.ts index 5852e9c89e..f17ff4d690 100644 --- a/src/providers/derive.ts +++ b/src/providers/derive.ts @@ -403,7 +403,7 @@ function serviceTierModelDefaultsFor( * The catalog hint pass must not read PROVIDER_REGISTRY: a gather flight captures its registry * authority up front and forbids any later read, so consulting the registry per model turned * every hint pass into a post-lookup read and dropped a custom-destination flight's own - * discovery result (tests/codex-gather-authority.test.ts). + * discovery result (tests/codex-integration/codex-gather-authority.test.ts). * * Registry values go in first so an explicit user entry still wins, matching * `applyReasoningSummaryDefaults`. `supportsVerbosity` is the provider-wide default, expanded diff --git a/src/providers/registry.ts b/src/providers/registry.ts index 5598f4f531..888cf2cfc4 100644 --- a/src/providers/registry.ts +++ b/src/providers/registry.ts @@ -632,7 +632,7 @@ const OPENCODE_FREE_DEEPSEEK_MODELS = ["deepseek-v4-flash-free"]; * `mimo-v2.5-free` and `longcat-2.0-free` ACCEPT images and are deliberately * absent. Adding them would silently replace a working image with a caption, * which is worse than the loud 400 this list exists to prevent — see the negative - * assertion in tests/provider-registry-parity.test.ts. + * assertion in tests/providers/provider-registry-parity.test.ts. * * Zen's roster is discovered live while this list is static, so it is a dated * exception list, not a capability model. Re-probe before extending it. @@ -688,7 +688,7 @@ const DEEPSEEK_FLASH_REASONING_MAP: Record = { /** * Flash-versus-Pro classification for DeepSeek V4 model ids, including prefixed * (`deepseek/deepseek-v4-pro`) and suffixed (`deepseek-v4-flash-free`) forms. - * `tests/provider-registry-parity.test.ts` enumerates every id the registry + * `tests/providers/provider-registry-parity.test.ts` enumerates every id the registry * actually passes here, so a future id this substring test would misread cannot * land silently. */ @@ -1541,7 +1541,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [ modelContextWindows: Object.fromEntries(META_MUSE_MODELS.map(id => [id, META_MUSE_CONTEXT_WINDOW])), // text+image only. Meta also documents video, audio (degraded on 1.3), and PDF, but // the catalog modality enum is text/image and over-advertising poisons the exported - // client config (see tests/catalog-input-modality-enum.test.ts). + // client config (see tests/codex-integration/catalog-input-modality-enum.test.ts). modelInputModalities: Object.fromEntries(META_MUSE_MODELS.map(id => [id, ["text", "image"] as ["text", "image"]])), modelReasoningEfforts: Object.fromEntries(META_MUSE_MODELS.map(id => [id, META_MUSE_REASONING_EFFORTS])), modelReasoningEffortMap: Object.fromEntries(META_MUSE_MODELS.map(id => [id, META_MUSE_REASONING_EFFORT_MAP])), diff --git a/src/server/management/agent-settings-routes.ts b/src/server/management/agent-settings-routes.ts index 193f9841fa..75bcaf36ae 100644 --- a/src/server/management/agent-settings-routes.ts +++ b/src/server/management/agent-settings-routes.ts @@ -377,7 +377,7 @@ export async function handleAgentSettingsRoutes(ctx: ManagementContext): Promise // sequence after the transition. A failure here is a persistence failure (the // writers' ok:false result or a throw from the underlying atomic write helper), // reported as 502 naming the failed key plus the writes that already landed. - // NOTE: do not name that helper literally here — tests/grok-writer-boundary.test.ts + // NOTE: do not name that helper literally here — tests/providers/xai/grok-writer-boundary.test.ts // asserts this route file contains no direct write primitive, and matches on the // symbol name even inside a comment. const scalarWrites: Array<{ field: string; run: () => { ok: true; changed: boolean } | { ok: false; error: string } }> = []; diff --git a/src/server/responses/core.ts b/src/server/responses/core.ts index cb1e00678e..edc958087f 100644 --- a/src/server/responses/core.ts +++ b/src/server/responses/core.ts @@ -3826,7 +3826,7 @@ async function handleResponsesInner( // The guard needs a catalog to compare against, so it stands down when the request omits one. // An explicit empty catalog is still authoritative: it declares that no client tools may be // called. A passthrough request can legitimately omit `tools` entirely and still receive a call - // the client understands — `tests/github-copilot-stream-contract.test.ts` sends + // the client understands — `tests/providers/github-copilot/github-copilot-stream-contract.test.ts` sends // `{model, input, stream}` with no tools and Copilot answers with a `custom_tool_call` for // `apply_patch`. Policing an absent catalog truncates that turn. An unreadable body lands there // too because the proxy cannot establish the caller's declared authorization boundary. diff --git a/src/service-manager-probe.ts b/src/service-manager-probe.ts index 2e612a69a9..d3d722bcfb 100644 --- a/src/service-manager-probe.ts +++ b/src/service-manager-probe.ts @@ -619,7 +619,7 @@ function windowsTaskListContains(body: string, taskName: string): boolean { * denied", so a locked-down host answers the control and the real query * identically, and comparing them yields a false `absent` — the one direction * that lets an unattended write proceed into a home another process owns. - * `tests/codex-service-manager-probe.test.ts` covers exactly that host. + * `tests/codex-integration/codex-service-manager-probe.test.ts` covers exactly that host. */ const SCHTASKS_TASK_NOT_FOUND_EN = /cannot find the file specified/i; diff --git a/structure/03_catalog-and-subagents.md b/structure/03_catalog-and-subagents.md index d30e3737b3..20170f90c7 100644 --- a/structure/03_catalog-and-subagents.md +++ b/structure/03_catalog-and-subagents.md @@ -230,7 +230,7 @@ is omitted *and* the `model`/`reasoning_effort` schema fields are removed). And Codex-visible `priority` while `SPAWN_PRIORITY_FIELD` preserves the natural priority the roster sorts by, so a display reorder can never change candidate membership. That divergence from upstream's own ordering is the feature's purpose, not a defect — -`tests/codex-catalog-model-picker-order.test.ts` pins it. +`tests/codex-integration/codex-catalog-model-picker-order.test.ts` pins it. Full derivation with per-line citations: `devlog/_plan/260816_codexrs_multiagent_v2_and_history_perf/013_five_cap_v1_vs_v2.md`. diff --git a/structure/04_transports-and-sidecars.md b/structure/04_transports-and-sidecars.md index d652a99082..4c47dd0233 100644 --- a/structure/04_transports-and-sidecars.md +++ b/structure/04_transports-and-sidecars.md @@ -590,7 +590,7 @@ sentinel, and live probes (2026-08-07) confirm the stream closes on the terminal terminal-output boundary (`src/server/relay.ts`) cuts the stream at that event and synthesizes `[DONE]` itself, so DeepSeek streams live again; the registry knob remains as a one-line rollback for upstreams that regress, kept suite-reachable by a synthetic-registry fixture in -`tests/deepseek-inbound-wire.test.ts`. +`tests/providers/deepseek-inbound-wire.test.ts`. Synthesized output is capped at 10,000 items across HTTP and WebSocket reframing. HTTP frames are encoded incrementally, so bounded upstream JSON cannot expand into an unbounded event array or SSE string. diff --git a/structure/11_compatibility-contracts.md b/structure/11_compatibility-contracts.md index d8be62e253..27a446eb2a 100644 --- a/structure/11_compatibility-contracts.md +++ b/structure/11_compatibility-contracts.md @@ -18,7 +18,7 @@ evidence before they can be added. | `src/compatibility/openai-responses.ts` | First bundled compatibility manifest. | | `src/compatibility/index.ts` | Manifest catalog for future CLI and GUI readers. | | `tests/fixtures/compatibility/` | Secret-free request vectors plus destination, header-boundary, and assertion-level expected behavior. | -| `tests/compatibility-manifest.test.ts` | Executes fixtures against production adapters and proves every claim has evidence. | +| `tests/codex-integration/compatibility-manifest.test.ts` | Executes fixtures against production adapters and proves every claim has evidence. | ## Dispositions diff --git a/tests/bump-dev-version.test.ts b/tests/bump-dev-version.test.ts index 9e9630a373..87c42daf7a 100644 --- a/tests/bump-dev-version.test.ts +++ b/tests/bump-dev-version.test.ts @@ -156,7 +156,7 @@ describe("dev version bump rule", () => { // Skipped on Windows: `chmod 0500` is not access control there, so the write would // succeed and this test would fail red for a reason that has nothing to do with the - // behavior under test. Same guard as tests/codex-native-residue.test.ts uses for its + // behavior under test. Same guard as tests/codex-integration/codex-native-residue.test.ts uses for its // EACCES case. The POSIX runners still cover the failure path. const unwritableTest = process.platform === "win32" ? test.skip : test; unwritableTest("an unwritable target fails closed with the original intact", () => { diff --git a/tests/ci-workflows.test.ts b/tests/ci-workflows.test.ts index cf85e49189..e2f8ab0b5e 100644 --- a/tests/ci-workflows.test.ts +++ b/tests/ci-workflows.test.ts @@ -1716,7 +1716,7 @@ describe("GitHub Actions hardening", () => { maintainersFile: MAINTAINERS_FIXTURE, files: [ { filename: "src/codex/auth-api.ts", patch: "+change" }, - { filename: "tests/codex-auth-api.test.ts", patch: "+test" }, + { filename: "tests/codex-integration/codex-auth-api.test.ts", patch: "+test" }, ], }); @@ -1753,7 +1753,7 @@ describe("GitHub Actions hardening", () => { labels: ["maintainer-sponsored"], files: [ { filename: "src/codex/auth-api.ts", patch: "+change" }, - { filename: "tests/codex-auth-api.test.ts", patch: "+test" }, + { filename: "tests/codex-integration/codex-auth-api.test.ts", patch: "+test" }, ], }); diff --git a/tests/active-registry-admission.test.ts b/tests/codex-integration/active-registry-admission.test.ts similarity index 95% rename from tests/active-registry-admission.test.ts rename to tests/codex-integration/active-registry-admission.test.ts index 38d023b965..88bbeb5790 100644 --- a/tests/active-registry-admission.test.ts +++ b/tests/codex-integration/active-registry-admission.test.ts @@ -2,29 +2,29 @@ import { describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { MAX_ACTIVE_TURNS, abortAndReleaseAllTurns, activeRegistryMetrics, trackStreamLifetime, tryAdmitTurn, unregisterTurn } from "../src/server/lifecycle"; +import { MAX_ACTIVE_TURNS, abortAndReleaseAllTurns, activeRegistryMetrics, trackStreamLifetime, tryAdmitTurn, unregisterTurn } from "../../src/server/lifecycle"; import { MAX_TRACKED_CODEX_WEBSOCKETS, getTrackedCodexWebSocketCountForAccount, tryReserveCodexWebSocket, -} from "../src/codex/websocket-registry"; +} from "../../src/codex/websocket-registry"; import { MAX_ACTIVE_STORAGE_HOME_SLOTS, tryBeginStorageMutation, -} from "../src/storage/storage-mutation-coordinator"; +} from "../../src/storage/storage-mutation-coordinator"; import { tryReserveStorageWorker, withStorageWorkerSpawnGate, -} from "../src/storage/worker-lifecycle"; +} from "../../src/storage/worker-lifecycle"; import { anthropicSessionAffinitySizeForTests, bindAnthropicSessionAffinity, clearAnthropicAccountPoolState, -} from "../src/oauth/anthropic-routing"; -import { saveConfig } from "../src/config"; -import { startServer } from "../src/server"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/oauth/anthropic-routing"; +import { saveConfig } from "../../src/config"; +import { startServer } from "../../src/server"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; describe("active registry admission", () => { test("active turn 257 returns structured server_busy before handler work", async () => { diff --git a/tests/app-owned-memory.test.ts b/tests/codex-integration/app-owned-memory.test.ts similarity index 95% rename from tests/app-owned-memory.test.ts rename to tests/codex-integration/app-owned-memory.test.ts index 51feebf86c..375dabd36c 100644 --- a/tests/app-owned-memory.test.ts +++ b/tests/codex-integration/app-owned-memory.test.ts @@ -9,27 +9,27 @@ import { resetAppOwnedMemoryForTests, type AppOwnedRetainedCategory, type RetainedStoreSnapshot, -} from "../src/lib/app-owned-memory"; -import { CURSOR_BLOB_MAX_TOTAL_BYTES } from "../src/adapters/cursor/native-exec"; -import { MAX_STORED_RESPONSE_BYTES } from "../src/responses/state"; -import { IMAGE_NORMALIZE_CACHE_MAX_BYTES } from "../src/adapters/anthropic-image-normalize"; -import { VISION_DESCRIPTION_CACHE_MAX_BYTES } from "../src/vision"; -import { ANTIGRAVITY_REPLAY_MAX_TOTAL_BYTES } from "../src/adapters/google-antigravity-replay"; +} from "../../src/lib/app-owned-memory"; +import { CURSOR_BLOB_MAX_TOTAL_BYTES } from "../../src/adapters/cursor/native-exec"; +import { MAX_STORED_RESPONSE_BYTES } from "../../src/responses/state"; +import { IMAGE_NORMALIZE_CACHE_MAX_BYTES } from "../../src/adapters/anthropic-image-normalize"; +import { VISION_DESCRIPTION_CACHE_MAX_BYTES } from "../../src/vision"; +import { ANTIGRAVITY_REPLAY_MAX_TOTAL_BYTES } from "../../src/adapters/google-antigravity-replay"; import { clearRequestLogsForTests, evictOldestRequestLogForBudget, hydrateRequestLogsFromDisk, requestLogEntryFromPersistedUsage, requestLogRetainedStoreSnapshot, -} from "../src/server/request-log"; +} from "../../src/server/request-log"; import { clearModelCache, evictOldestModelCacheForBudget, modelCacheRetainedStoreSnapshot, setCached, -} from "../src/codex/model-cache"; -import type { PersistedUsageEntry } from "../src/usage/log"; -import { registerDefaultAppOwnedObservedBuffers } from "../src/lib/app-owned-memory-stores"; +} from "../../src/codex/model-cache"; +import type { PersistedUsageEntry } from "../../src/usage/log"; +import { registerDefaultAppOwnedObservedBuffers } from "../../src/lib/app-owned-memory-stores"; interface Row { bytes: number; at: number; pinned?: boolean } diff --git a/tests/bearer-admission-routed-provider.test.ts b/tests/codex-integration/bearer-admission-routed-provider.test.ts similarity index 96% rename from tests/bearer-admission-routed-provider.test.ts rename to tests/codex-integration/bearer-admission-routed-provider.test.ts index 1e049fc77c..e74cd0ce21 100644 --- a/tests/bearer-admission-routed-provider.test.ts +++ b/tests/codex-integration/bearer-admission-routed-provider.test.ts @@ -2,18 +2,18 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; -import { startServer } from "../src/server"; +import { saveConfig } from "../../src/config"; +import { startServer } from "../../src/server"; import { acquireNativeMainProfileDrain, getNativeMainProfileRequestCount, -} from "../src/server/lifecycle"; -import { waitForNativeMainStartupGate } from "../src/codex/native-profile-startup"; -import { handleNativeProfileAPI } from "../src/codex/native-profile-api"; -import type { NativeProfileManager } from "../src/codex/native-profile-manager"; -import type { OcxConfig } from "../src/types"; -import { ownedServiceHomeInspection } from "./helpers/owned-service-home-inspection"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/server/lifecycle"; +import { waitForNativeMainStartupGate } from "../../src/codex/native-profile-startup"; +import { handleNativeProfileAPI } from "../../src/codex/native-profile-api"; +import type { NativeProfileManager } from "../../src/codex/native-profile-manager"; +import type { OcxConfig } from "../../src/types"; +import { ownedServiceHomeInspection } from "../helpers/owned-service-home-inspection"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * Issue #2132: bearer admission must not require a stored ChatGPT credential. diff --git a/tests/catalog-cursor-search.test.ts b/tests/codex-integration/catalog-cursor-search.test.ts similarity index 99% rename from tests/catalog-cursor-search.test.ts rename to tests/codex-integration/catalog-cursor-search.test.ts index 72990c3bc2..c60bc0d812 100644 --- a/tests/catalog-cursor-search.test.ts +++ b/tests/codex-integration/catalog-cursor-search.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { buildCatalogEntries, normalizeRoutedCatalogEntry } from "../src/codex/catalog"; +import { buildCatalogEntries, normalizeRoutedCatalogEntry } from "../../src/codex/catalog"; describe("routed catalog search advertising", () => { test("cursor entries enable deferred discovery without advertising hosted web search", () => { diff --git a/tests/catalog-input-modality-enum.test.ts b/tests/codex-integration/catalog-input-modality-enum.test.ts similarity index 96% rename from tests/catalog-input-modality-enum.test.ts rename to tests/codex-integration/catalog-input-modality-enum.test.ts index 37d245ffac..4d9342eba4 100644 --- a/tests/catalog-input-modality-enum.test.ts +++ b/tests/codex-integration/catalog-input-modality-enum.test.ts @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, test } from "bun:test"; -import { ensureStrictCatalogFields } from "../src/codex/catalog/parsing"; -import { catalogHintsFromModelsApiItem } from "../src/codex/catalog/provider-fetch"; -import type { OcxConfig } from "../src/types"; +import { ensureStrictCatalogFields } from "../../src/codex/catalog/parsing"; +import { catalogHintsFromModelsApiItem } from "../../src/codex/catalog/provider-fetch"; +import type { OcxConfig } from "../../src/types"; /** * Codex parses `input_modalities` as a closed enum of text | image | audio. A single out-of-enum @@ -79,7 +79,7 @@ describe("custom-model API rejects out-of-enum input modalities", () => { body: unknown, pathname = "/api/custom-models", ): Promise { - const { handleModelRoutes } = await import("../src/server/management/model-routes"); + const { handleModelRoutes } = await import("../../src/server/management/model-routes"); const url = new URL(`http://127.0.0.1:10199${pathname}`); const req = new Request(url, { method, @@ -207,7 +207,7 @@ describe("custom-model API validates reasoning-effort ladders", () => { body: unknown, pathname = "/api/custom-models", ): Promise { - const { handleModelRoutes } = await import("../src/server/management/model-routes"); + const { handleModelRoutes } = await import("../../src/server/management/model-routes"); const url = new URL(`http://127.0.0.1:10199${pathname}`); const req = new Request(url, { method, @@ -441,7 +441,7 @@ describe("custom-model API allows slash model ids", () => { body: unknown, pathname = "/api/custom-models", ): Promise { - const { handleModelRoutes } = await import("../src/server/management/model-routes"); + const { handleModelRoutes } = await import("../../src/server/management/model-routes"); const url = new URL(`http://127.0.0.1:10199${pathname}`); const req = new Request(url, { method, @@ -500,7 +500,7 @@ describe("custom-model API allows slash model ids", () => { test("POST rejects a slash id that encodes to an existing native id", async () => { persistCalls = 0; - const { handleModelRoutes } = await import("../src/server/management/model-routes"); + const { handleModelRoutes } = await import("../../src/server/management/model-routes"); const url = new URL("http://127.0.0.1:10199/api/custom-models"); const req = new Request(url, { method: "POST", @@ -538,7 +538,7 @@ describe("custom-model API allows slash model ids", () => { test("PUT rejects renaming onto a colliding native id", async () => { persistCalls = 0; - const { handleModelRoutes } = await import("../src/server/management/model-routes"); + const { handleModelRoutes } = await import("../../src/server/management/model-routes"); const url = new URL("http://127.0.0.1:10199/api/custom-models/existing-uuid"); const req = new Request(url, { method: "PUT", @@ -579,7 +579,7 @@ describe("custom-model API allows slash model ids", () => { test("POST rejects a slash id that encodes to defaultModel only", async () => { persistCalls = 0; - const { handleModelRoutes } = await import("../src/server/management/model-routes"); + const { handleModelRoutes } = await import("../../src/server/management/model-routes"); const url = new URL("http://127.0.0.1:10199/api/custom-models"); const req = new Request(url, { method: "POST", diff --git a/tests/catalog-llamacpp-capabilities.test.ts b/tests/codex-integration/catalog-llamacpp-capabilities.test.ts similarity index 97% rename from tests/catalog-llamacpp-capabilities.test.ts rename to tests/codex-integration/catalog-llamacpp-capabilities.test.ts index 1eb433fd80..bac43cf66a 100644 --- a/tests/catalog-llamacpp-capabilities.test.ts +++ b/tests/codex-integration/catalog-llamacpp-capabilities.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { catalogHintsFromModelsApiItem } from "../src/codex/catalog/provider-fetch"; -import { extractProviderModelItems } from "../src/providers/model-discovery"; +import { catalogHintsFromModelsApiItem } from "../../src/codex/catalog/provider-fetch"; +import { extractProviderModelItems } from "../../src/providers/model-discovery"; /** * Regression coverage for #1797 (llama.cpp dual-envelope metadata). diff --git a/tests/catalog-oauth-observation.test.ts b/tests/codex-integration/catalog-oauth-observation.test.ts similarity index 96% rename from tests/catalog-oauth-observation.test.ts rename to tests/codex-integration/catalog-oauth-observation.test.ts index adeba1e633..b8bba6fcd5 100644 --- a/tests/catalog-oauth-observation.test.ts +++ b/tests/codex-integration/catalog-oauth-observation.test.ts @@ -14,16 +14,16 @@ import { join } from "node:path"; import { observeActiveOAuthAccessToken, OAUTH_PROVIDERS, -} from "../src/oauth"; +} from "../../src/oauth"; import { gatherRoutedModelsForCatalogGather, type CatalogGatherProviderAuthOutcome, type CatalogGatherProviderModelOutcome, -} from "../src/codex/catalog/provider-fetch"; -import { clearModelCache } from "../src/codex/model-cache"; -import { getAuthRefreshIntentPath } from "../src/oauth/store"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/catalog/provider-fetch"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { getAuthRefreshIntentPath } from "../../src/oauth/store"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; interface FileSnapshot { readonly bytes: Buffer; diff --git a/tests/catalog-retain-models.test.ts b/tests/codex-integration/catalog-retain-models.test.ts similarity index 94% rename from tests/catalog-retain-models.test.ts rename to tests/codex-integration/catalog-retain-models.test.ts index 0b8e45eea7..2067af0029 100644 --- a/tests/catalog-retain-models.test.ts +++ b/tests/codex-integration/catalog-retain-models.test.ts @@ -2,12 +2,12 @@ import { afterEach, describe, expect, test } from "bun:test"; import { mergeConfiguredModelsIntoLiveCatalog, shouldRetainConfiguredProviderModel, -} from "../src/codex/catalog/provider-fetch"; -import { gatherRoutedModels as gatherRoutedModelsDirect, resetCatalogRuntimeStateForTests } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import type { OcxConfig } from "../src/types"; -import type { OcxProviderConfig } from "../src/types"; +} from "../../src/codex/catalog/provider-fetch"; +import { gatherRoutedModels as gatherRoutedModelsDirect, resetCatalogRuntimeStateForTests } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import type { OcxConfig } from "../../src/types"; +import type { OcxProviderConfig } from "../../src/types"; const originalFetch = globalThis.fetch; diff --git a/tests/catalog-verbosity-default.test.ts b/tests/codex-integration/catalog-verbosity-default.test.ts similarity index 92% rename from tests/catalog-verbosity-default.test.ts rename to tests/codex-integration/catalog-verbosity-default.test.ts index 75a07cca66..1ed5c8f164 100644 --- a/tests/catalog-verbosity-default.test.ts +++ b/tests/codex-integration/catalog-verbosity-default.test.ts @@ -1,8 +1,8 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { buildCatalogEntries, gatherRoutedModels as gatherRoutedModelsDirect, upstreamNativeEntry } from "../src/codex/catalog"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import { resetCatalogRuntimeStateForTests, resetOpenAiApiCatalogWarningStateForTests } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; +import { buildCatalogEntries, gatherRoutedModels as gatherRoutedModelsDirect, upstreamNativeEntry } from "../../src/codex/catalog"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { resetCatalogRuntimeStateForTests, resetOpenAiApiCatalogWarningStateForTests } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; const gatherRoutedModels: typeof gatherRoutedModelsDirect = (config, options) => gatherRoutedModelsDirect(withStubbedProviderFetch(config), options); diff --git a/tests/catalog-vision-sidecar-modalities.test.ts b/tests/codex-integration/catalog-vision-sidecar-modalities.test.ts similarity index 97% rename from tests/catalog-vision-sidecar-modalities.test.ts rename to tests/codex-integration/catalog-vision-sidecar-modalities.test.ts index 8e71876dff..3e51ac0d01 100644 --- a/tests/catalog-vision-sidecar-modalities.test.ts +++ b/tests/codex-integration/catalog-vision-sidecar-modalities.test.ts @@ -1,13 +1,13 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { applyProviderConfigHints, gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import type { OcxProviderConfig } from "../src/types"; -import { deriveComboCatalogModel } from "../src/codex/catalog"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { enrichProviderFromRegistry } from "../src/providers/derive"; -import { CURSOR_NO_VISION_MODELS, CURSOR_STATIC_MODELS } from "../src/adapters/cursor/discovery"; -import { modelInList } from "../src/types"; -import type { CatalogModel } from "../src/types"; +import { applyProviderConfigHints, gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import type { OcxProviderConfig } from "../../src/types"; +import { deriveComboCatalogModel } from "../../src/codex/catalog"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { enrichProviderFromRegistry } from "../../src/providers/derive"; +import { CURSOR_NO_VISION_MODELS, CURSOR_STATIC_MODELS } from "../../src/adapters/cursor/discovery"; +import { modelInList } from "../../src/types"; +import type { CatalogModel } from "../../src/types"; const base: OcxProviderConfig = { adapter: "openai-chat", diff --git a/tests/codex-account-delete-atomicity.test.ts b/tests/codex-integration/codex-account-delete-atomicity.test.ts similarity index 93% rename from tests/codex-account-delete-atomicity.test.ts rename to tests/codex-integration/codex-account-delete-atomicity.test.ts index 8b25bf2e9b..fccaa8abe5 100644 --- a/tests/codex-account-delete-atomicity.test.ts +++ b/tests/codex-integration/codex-account-delete-atomicity.test.ts @@ -1,27 +1,27 @@ import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test"; import { existsSync, mkdirSync, readFileSync} from "node:fs"; import { join } from "node:path"; -import * as accountStoreModule from "../src/codex/account-store"; +import * as accountStoreModule from "../../src/codex/account-store"; import { getCodexAccountCredential, saveCodexAccountCredential, -} from "../src/codex/account-store"; +} from "../../src/codex/account-store"; import { CodexAccountDeleteCleanupError, deleteCodexAccount, -} from "../src/codex/account-lifecycle"; +} from "../../src/codex/account-lifecycle"; import { isAccountNeedsReauth, markAccountNeedsReauth, -} from "../src/codex/account-runtime-state"; +} from "../../src/codex/account-runtime-state"; import { getAccountQuota, updateAccountQuota, -} from "../src/codex/quota"; -import { getConfigPath, loadConfig, saveConfig } from "../src/config"; -import * as configModule from "../src/config"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/quota"; +import { getConfigPath, loadConfig, saveConfig } from "../../src/config"; +import * as configModule from "../../src/config"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-codex-account-delete-atomicity"); const ACCOUNT_ID = "delete-atomicity"; diff --git a/tests/codex-account-label.test.ts b/tests/codex-integration/codex-account-label.test.ts similarity index 97% rename from tests/codex-account-label.test.ts rename to tests/codex-integration/codex-account-label.test.ts index 914b3f8c6c..9680e3f8b9 100644 --- a/tests/codex-account-label.test.ts +++ b/tests/codex-integration/codex-account-label.test.ts @@ -5,7 +5,7 @@ import { createCodexAccountLogLabel, fallbackCodexAccountLogLabel, withCodexAccountLogLabel, -} from "../src/codex/account-label"; +} from "../../src/codex/account-label"; describe("codex account privacy labels", () => { test("generates non-PII log labels", () => { diff --git a/tests/codex-account-namespaces.test.ts b/tests/codex-integration/codex-account-namespaces.test.ts similarity index 98% rename from tests/codex-account-namespaces.test.ts rename to tests/codex-integration/codex-account-namespaces.test.ts index 948d160db3..d5ca029960 100644 --- a/tests/codex-account-namespaces.test.ts +++ b/tests/codex-integration/codex-account-namespaces.test.ts @@ -1,15 +1,15 @@ import { describe, expect, spyOn, test } from "bun:test"; -import * as accountLabels from "../src/codex/account-label"; +import * as accountLabels from "../../src/codex/account-label"; import { CODEX_ACCOUNT_LOG_LABEL_RE, fallbackCodexAccountLogLabel, -} from "../src/codex/account-label"; +} from "../../src/codex/account-label"; import { codexAccountIdNamespaceCollisionError, codexAccountNamespaceProviderCollisionError, codexAccountNamespaceForModel, hasCodexAccountNamespace, -} from "../src/codex/account-namespace-match"; +} from "../../src/codex/account-namespace-match"; import { appendDefaultCodexAccountNamespace, codexAccountPickerEnabled, @@ -18,9 +18,9 @@ import { initializeDefaultCodexAccountNamespaces, isMainCodexAccountTarget, isValidCodexAccountNamespaceTarget, -} from "../src/codex/account-namespaces"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/main-account"; -import type { OcxConfig } from "../src/types"; +} from "../../src/codex/account-namespaces"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/main-account"; +import type { OcxConfig } from "../../src/types"; type InitializableAccountNamespaceConfig = Pick< OcxConfig, diff --git a/tests/codex-account-store.test.ts b/tests/codex-integration/codex-account-store.test.ts similarity index 95% rename from tests/codex-account-store.test.ts rename to tests/codex-integration/codex-account-store.test.ts index 5c8f52af4e..8b9ad8d9ab 100644 --- a/tests/codex-account-store.test.ts +++ b/tests/codex-integration/codex-account-store.test.ts @@ -3,9 +3,9 @@ import { createHash } from "node:crypto"; import { existsSync, mkdtempSync, readdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { setAsyncIcaclsRunnerForTests, setIcaclsRunnerForTests } from "../src/lib/windows-secret-acl"; -import { flushConfigDirHardeningForTests } from "../src/config/paths"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { setAsyncIcaclsRunnerForTests, setIcaclsRunnerForTests } from "../../src/lib/windows-secret-acl"; +import { flushConfigDirHardeningForTests } from "../../src/config/paths"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * Per-test scratch home. A fixed repo-local directory meant that ONE failed teardown (Windows @@ -61,7 +61,7 @@ describe("codex-account-store CRUD", () => { afterEach(async () => { await removeScratchHome(); }); test("save and load credential round-trip", async () => { - const { saveCodexAccountCredential, getCodexAccountCredential } = await import("../src/codex/account-store"); + const { saveCodexAccountCredential, getCodexAccountCredential } = await import("../../src/codex/account-store"); const cred = { accessToken: "tk_a", refreshToken: "rf_a", expiresAt: Date.now() + 3600_000, chatgptAccountId: "acc_a" }; saveCodexAccountCredential("work", cred); expect(existsSync(ACCOUNTS_PATH)).toBe(true); @@ -70,7 +70,7 @@ describe("codex-account-store CRUD", () => { }); test("legacy flat credential JSON loads through the compatibility projection", async () => { - const { getCodexAccountCredential, loadCodexAccountStore, readCodexAccountRecord } = await import("../src/codex/account-store"); + const { getCodexAccountCredential, loadCodexAccountStore, readCodexAccountRecord } = await import("../../src/codex/account-store"); const cred = { accessToken: "legacy_tk", refreshToken: "legacy_rf", expiresAt: Date.now() + 3600_000, chatgptAccountId: "legacy_acc" }; writeFileSync(ACCOUNTS_PATH, JSON.stringify({ legacy: cred }, null, 2)); @@ -80,7 +80,7 @@ describe("codex-account-store CRUD", () => { }); test("malformed credential store is backed up before a new save overwrites it", async () => { - const { saveCodexAccountCredential } = await import("../src/codex/account-store"); + const { saveCodexAccountCredential } = await import("../../src/codex/account-store"); writeFileSync(ACCOUNTS_PATH, "{not valid json", "utf8"); saveCodexAccountCredential("fresh", { @@ -96,7 +96,7 @@ describe("codex-account-store CRUD", () => { }); test("new saves write generation wrapper records", async () => { - const { readCodexAccountRecord, saveCodexAccountCredential } = await import("../src/codex/account-store"); + const { readCodexAccountRecord, saveCodexAccountCredential } = await import("../../src/codex/account-store"); const cred = { accessToken: "tk_a", refreshToken: "rf_a", expiresAt: Date.now() + 3600_000, chatgptAccountId: "acc_a" }; saveCodexAccountCredential("wrapped", cred); @@ -113,8 +113,8 @@ describe("codex-account-store CRUD", () => { saveCodexAccountCredential, saveCodexAccountCredentialIfGeneration, tombstoneCodexAccount, - } = await import("../src/codex/account-store"); - const { codexCredentialMutationEpoch } = await import("../src/codex/credential-mutation-epoch"); + } = await import("../../src/codex/account-store"); + const { codexCredentialMutationEpoch } = await import("../../src/codex/credential-mutation-epoch"); const first = { accessToken: "epoch-a", refreshToken: "epoch-r-a", expiresAt: Date.now() + 3600_000, chatgptAccountId: "epoch-account" }; const second = { ...first, accessToken: "epoch-b", refreshToken: "epoch-r-b" }; const third = { ...second, accessToken: "epoch-c", refreshToken: "epoch-r-c" }; @@ -141,7 +141,7 @@ describe("codex-account-store CRUD", () => { }); test("remove credential deletes entry", async () => { - const { saveCodexAccountCredential, removeCodexAccountCredential, getCodexAccountCredential, listCodexAccountIds, readCodexAccountRecord } = await import("../src/codex/account-store"); + const { saveCodexAccountCredential, removeCodexAccountCredential, getCodexAccountCredential, listCodexAccountIds, readCodexAccountRecord } = await import("../../src/codex/account-store"); saveCodexAccountCredential("temp", { accessToken: "t", refreshToken: "r", expiresAt: 0, chatgptAccountId: "c" }); removeCodexAccountCredential("temp"); expect(getCodexAccountCredential("temp")).toBeNull(); @@ -151,7 +151,7 @@ describe("codex-account-store CRUD", () => { }); test("tokenful tombstone is treated as absent", async () => { - const { getCodexAccountCredential, listCodexAccountIds, loadCodexAccountStore } = await import("../src/codex/account-store"); + const { getCodexAccountCredential, listCodexAccountIds, loadCodexAccountStore } = await import("../../src/codex/account-store"); const cred = { accessToken: "deleted_tk", refreshToken: "deleted_rf", expiresAt: Date.now() + 3600_000, chatgptAccountId: "deleted_acc" }; writeFileSync(ACCOUNTS_PATH, JSON.stringify({ deleted: { credential: cred, generation: 2, deletedAt: Date.now() }, @@ -163,7 +163,7 @@ describe("codex-account-store CRUD", () => { }); test("listCodexAccountIds returns stored ids", async () => { - const { saveCodexAccountCredential, listCodexAccountIds } = await import("../src/codex/account-store"); + const { saveCodexAccountCredential, listCodexAccountIds } = await import("../../src/codex/account-store"); saveCodexAccountCredential("a", { accessToken: "1", refreshToken: "1", expiresAt: 0, chatgptAccountId: "1" }); saveCodexAccountCredential("b", { accessToken: "2", refreshToken: "2", expiresAt: 0, chatgptAccountId: "2" }); expect(listCodexAccountIds()).toContain("a"); @@ -171,7 +171,7 @@ describe("codex-account-store CRUD", () => { }); test("getValidCodexToken returns cached token when not expired", async () => { - const { saveCodexAccountCredential, getValidCodexToken } = await import("../src/codex/account-store"); + const { saveCodexAccountCredential, getValidCodexToken } = await import("../../src/codex/account-store"); const future = Date.now() + 3600_000; saveCodexAccountCredential("fresh", { accessToken: "valid_tk", refreshToken: "rf", expiresAt: future, chatgptAccountId: "acc_id" }); const result = await getValidCodexToken("fresh"); @@ -181,7 +181,7 @@ describe("codex-account-store CRUD", () => { }); test("getValidCodexToken throws when account not found", async () => { - const { getValidCodexToken } = await import("../src/codex/account-store"); + const { getValidCodexToken } = await import("../../src/codex/account-store"); try { await getValidCodexToken("nonexistent-local-alias"); throw new Error("expected getValidCodexToken to reject"); @@ -197,7 +197,7 @@ describe("codex-account-store CRUD", () => { getValidCodexToken, saveCodexAccountCredential, TokenRefreshError, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("sensitive-local-alias", { accessToken: "sensitive-access-token", refreshToken: "sensitive-refresh-token", @@ -234,7 +234,7 @@ describe("codex-account-store CRUD", () => { readCodexAccountRecord, saveCodexAccountCredential, saveCodexAccountCredentialIfGeneration, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); const first = { accessToken: "first", refreshToken: "first-r", expiresAt: 1, chatgptAccountId: "acc" }; const second = { accessToken: "second", refreshToken: "second-r", expiresAt: 2, chatgptAccountId: "acc" }; saveCodexAccountCredential("cas", first); @@ -253,7 +253,7 @@ describe("codex-account-store CRUD", () => { readCodexAccountRecord, saveCodexAccountCredential, saveCodexAccountCredentialIfGeneration, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); const first = { accessToken: "first", refreshToken: "first-r", expiresAt: 1, chatgptAccountId: "acc" }; const second = { accessToken: "second", refreshToken: "second-r", expiresAt: 2, chatgptAccountId: "acc" }; const third = { accessToken: "third", refreshToken: "third-r", expiresAt: 3, chatgptAccountId: "acc" }; @@ -282,7 +282,7 @@ describe("codex-account-store CRUD", () => { markCodexAccountValidationFailed, readCodexAccountRecord, saveCodexAccountCredential, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("failed-warmup", { accessToken: "sensitive-access", refreshToken: "sensitive-refresh", expiresAt: 1, chatgptAccountId: "sensitive-account" }); markCodexAccountValidated("failed-warmup", 1234); markCodexAccountValidationFailed("failed-warmup", "http_status:401"); @@ -301,7 +301,7 @@ describe("codex-account-store CRUD", () => { readCodexAccountRecord, saveCodexAccountCredential, refreshGrantFingerprintForToken, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("refresh-success", { accessToken: "old", refreshToken: "old-r", expiresAt: 0, chatgptAccountId: "acc" }); const startGeneration = readCodexAccountRecord("refresh-success")!.generation; const startFingerprint = readCodexAccountRecord("refresh-success")!.refreshGrantFingerprint; @@ -328,7 +328,7 @@ describe("codex-account-store CRUD", () => { getCodexAccountCredential, getValidCodexToken, saveCodexAccountCredential, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("refresh-bad-expiry", { accessToken: "old", refreshToken: "old-r", expiresAt: 0, chatgptAccountId: "acc" }); const originalFetch = globalThis.fetch; // JSON.stringify turns NaN into null; hand-write 1e999 so JSON.parse yields Infinity, @@ -355,7 +355,7 @@ describe("codex-account-store CRUD", () => { getCodexAccountCredential, getValidCodexToken, saveCodexAccountCredential, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("refresh-overflow-expiry", { accessToken: "old", refreshToken: "old-r", expiresAt: 0, chatgptAccountId: "acc" }); const originalFetch = globalThis.fetch; // Number.MAX_VALUE passes Number.isFinite but overflows to Infinity when @@ -382,7 +382,7 @@ describe("codex-account-store CRUD", () => { getCodexAccountCredential, getValidCodexToken, saveCodexAccountCredential, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("refresh-negative-expiry", { accessToken: "old", refreshToken: "old-r", expiresAt: 0, chatgptAccountId: "acc" }); const originalFetch = globalThis.fetch; globalThis.fetch = (async () => new Response( @@ -408,7 +408,7 @@ describe("codex-account-store CRUD", () => { readCodexAccountRecord, saveCodexAccountCredential, saveCodexAccountCredentialIfGeneration, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("refresh-wait", { accessToken: "old", refreshToken: "old-r", expiresAt: 0, chatgptAccountId: "acc" }); const generation = readCodexAccountRecord("refresh-wait")!.generation; const lockPath = refreshLockPathForToken("old-r"); @@ -435,7 +435,7 @@ describe("codex-account-store CRUD", () => { }); test("stale refresh lock is reclaimed", async () => { - const { getValidCodexToken, saveCodexAccountCredential } = await import("../src/codex/account-store"); + const { getValidCodexToken, saveCodexAccountCredential } = await import("../../src/codex/account-store"); saveCodexAccountCredential("refresh-stale-lock", { accessToken: "old", refreshToken: "old-r", expiresAt: 0, chatgptAccountId: "acc" }); writeFileSync(refreshLockPathForToken("old-r"), JSON.stringify({ acquiredAt: Date.now() - 61_000, pid: 12345 }) + "\n"); const originalFetch = globalThis.fetch; @@ -455,7 +455,7 @@ describe("codex-account-store CRUD", () => { getCodexAccountCredential, getValidCodexToken, saveCodexAccountCredential, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("alias-a", { accessToken: "old-a", refreshToken: "shared-r", expiresAt: 0, chatgptAccountId: "acc" }); saveCodexAccountCredential("alias-b", { accessToken: "old-b", refreshToken: "shared-r", expiresAt: 0, chatgptAccountId: "acc" }); let fetchCalls = 0; @@ -490,7 +490,7 @@ describe("codex-account-store CRUD", () => { CodexCredentialRefreshBusyError, getValidCodexToken, saveCodexAccountCredential, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); for (let index = 0; index < 33; index++) { saveCodexAccountCredential(`flight-${index}`, { accessToken: `old-${index}`, @@ -526,7 +526,7 @@ describe("codex-account-store CRUD", () => { CodexCredentialRefreshStaleError, getValidCodexToken, saveCodexAccountCredential, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("stale-flight", { accessToken: "old", refreshToken: "stale-refresh", @@ -567,7 +567,7 @@ describe("codex-account-store CRUD", () => { readCodexAccountRecord, saveCodexAccountCredential, saveCodexAccountCredentialIfGeneration, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); const original = { accessToken: "original", refreshToken: "original-r", expiresAt: 1, chatgptAccountId: "acc" }; const replacement = { accessToken: "replacement", refreshToken: "replacement-r", expiresAt: 2, chatgptAccountId: "acc" }; const stale = { accessToken: "stale", refreshToken: "stale-r", expiresAt: 3, chatgptAccountId: "acc" }; @@ -586,7 +586,7 @@ describe("codex-account-store CRUD", () => { removeCodexAccountCredential, saveCodexAccountCredential, saveCodexAccountCredentialIfGeneration, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); const original = { accessToken: "original", refreshToken: "original-r", expiresAt: 1, chatgptAccountId: "acc" }; const stale = { accessToken: "stale", refreshToken: "stale-r", expiresAt: 2, chatgptAccountId: "acc" }; saveCodexAccountCredential("delete-race", original); @@ -606,7 +606,7 @@ describe("codex-account-store CRUD", () => { readCodexAccountRecord, removeCodexAccountCredential, saveCodexAccountCredential, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("refresh-delete", { accessToken: "old", refreshToken: "old-r", expiresAt: 0, chatgptAccountId: "acc" }); const originalFetch = globalThis.fetch; globalThis.fetch = (async () => { @@ -629,7 +629,7 @@ describe("codex-account-store CRUD", () => { getCodexAccountCredential, getValidCodexToken, saveCodexAccountCredential, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); const replacement = { accessToken: "replacement", refreshToken: "replacement-r", expiresAt: Date.now() + 3600_000, chatgptAccountId: "acc" }; saveCodexAccountCredential("refresh-replace", { accessToken: "old", refreshToken: "old-r", expiresAt: 0, chatgptAccountId: "acc" }); const originalFetch = globalThis.fetch; @@ -648,7 +648,7 @@ describe("codex-account-store CRUD", () => { test("a forced refresh rotates a time-valid credential that upstream rejected (#2887)", async () => { const { forceRefreshCodexPoolToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); // Far beyond the refresh skew: getValidCodexToken would return this untouched, which is // exactly why a 401 on it was unrecoverable. saveCodexAccountCredential("forced", { @@ -681,7 +681,7 @@ describe("codex-account-store CRUD", () => { test("a forced refresh whose generation was already superseded spends no rotation (#2887)", async () => { const { forceRefreshCodexPoolToken, saveCodexAccountCredential, readCodexAccountRecord } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); saveCodexAccountCredential("forced-stale", { accessToken: "rejected", refreshToken: "grant", @@ -720,7 +720,7 @@ describe("codex-account-store CRUD", () => { test("concurrent forced refreshes of one rejected generation collapse to a single token call (#2887)", async () => { const { forceRefreshCodexPoolToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); saveCodexAccountCredential("forced-concurrent", { accessToken: "rejected", refreshToken: "grant", @@ -761,7 +761,7 @@ describe("codex-account-store CRUD", () => { */ test("cancelling the caller that opened a refresh flight does not cancel a live joiner (#2892)", async () => { const { forceRefreshCodexPoolToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); saveCodexAccountCredential("cancel-owner", { accessToken: "rejected", refreshToken: "cancel-grant", @@ -825,7 +825,7 @@ describe("codex-account-store CRUD", () => { // written from the lock-acquisition hook rather than from inside `fetch`: by fetch time // the grant comparison has already happened and a different branch handles the case. const { forceRefreshCodexPoolToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); const shared = { refreshToken: "shared-grant", expiresAt: Date.now() + 3600_000, chatgptAccountId: "acc" }; saveCodexAccountCredential("owner", { ...shared, accessToken: "owner-rejected" }); saveCodexAccountCredential("joiner", { ...shared, accessToken: "joiner-rejected" }); @@ -880,7 +880,7 @@ describe("codex-account-store CRUD", () => { // caller that quarantines on rotated===false must fence on the RETURNED generation — // fencing on the one it rejected silently suppresses its own quarantine. const { forceRefreshCodexPoolToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); saveCodexAccountCredential("same-bearer", { accessToken: "still-rejected", refreshToken: "grant", @@ -914,7 +914,7 @@ describe("codex-account-store CRUD", () => { // same-account joiner that re-writes the identical credential would move it to G+2 and // invalidate that handoff. const { forceRefreshCodexPoolToken, getValidCodexToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); saveCodexAccountCredential("double-bump", { accessToken: "rejected", refreshToken: "grant", @@ -956,7 +956,7 @@ describe("codex-account-store CRUD", () => { // Upstream sends invalid_grant with no description. Classified "unknown" it reads as // transient, so a dead grant is never retired and every request repeats the refresh. const { forceRefreshCodexPoolToken, readCodexAccountRecord, saveCodexAccountCredential, TokenRefreshError } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); saveCodexAccountCredential("dead-grant", { accessToken: "rejected", refreshToken: "grant", @@ -988,7 +988,7 @@ describe("codex-account-store CRUD", () => { // lineage from the stored record instead is tautological — the caller reads the same // record the check would re-read. const { forceRefreshCodexPoolToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); saveCodexAccountCredential("external", { accessToken: "rejected", refreshToken: "grant", @@ -1029,7 +1029,7 @@ describe("codex-account-store CRUD", () => { // Matching the phrase anywhere in the combined code+description text would retire a // healthy account on an upstream blip — reintroducing the defect this path fixes. const { forceRefreshCodexPoolToken, readCodexAccountRecord, saveCodexAccountCredential, TokenRefreshError } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); saveCodexAccountCredential("blip", { accessToken: "rejected", refreshToken: "grant", @@ -1059,7 +1059,7 @@ describe("codex-account-store CRUD", () => { test("a successful refresh advances an untouched dormant same-grant alias in the same write (#2892 gap 3)", async () => { const { getValidCodexToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); const expiresAt = 0; const shared = { refreshToken: "dormant-grant", expiresAt, chatgptAccountId: "acc" }; // Owner drives the refresh. `dormant` is an untouched duplicate that never calls in — the @@ -1129,7 +1129,7 @@ describe("codex-account-store CRUD", () => { test("a tombstoned same-grant record is not resurrected by grant propagation (#2892 gap 3)", async () => { const { getValidCodexToken, readCodexAccountRecord, saveCodexAccountCredential, tombstoneCodexAccount } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); const shared = { accessToken: "tomb-old", refreshToken: "tomb-grant", expiresAt: 0, chatgptAccountId: "acc" }; saveCodexAccountCredential("tomb-owner", { ...shared }); saveCodexAccountCredential("tomb-deleted", { ...shared }); @@ -1159,7 +1159,7 @@ describe("codex-account-store CRUD", () => { // or a tombstone raced by a concurrent save, produces exactly this record. `tokenful tombstone is // treated as absent` earlier in this file pins the same shape for the read path. const { getValidCodexToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); const shared = { accessToken: "tokenful-old", refreshToken: "tokenful-grant", @@ -1198,7 +1198,7 @@ describe("codex-account-store CRUD", () => { test("a same-grant sibling on a DIFFERENT upstream identity is never adopted (#2892 review)", async () => { const { forceRefreshCodexPoolToken, getCodexAccountCredential, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); // Both records share one stored grant, but they claim different upstream accounts. Adoption // copies BOTH tokens, so treating a shared fingerprint as proof of identity would hand this // caller another account's credential. @@ -1250,9 +1250,9 @@ describe("shared refresh flight plan reconciliation (#2892 gap 2 follow-up)", () // chatgpt_plan_type would otherwise commit while codexAccounts[].plan stayed stale // for the rest of the process, skewing plan-selected quota projection. const { forceRefreshCodexPoolToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); - const { loadConfig, saveConfig } = await import("../src/config"); - const { resetJwtPlanNotesForTests } = await import("../src/codex/plan-from-token"); + await import("../../src/codex/account-store"); + const { loadConfig, saveConfig } = await import("../../src/config"); + const { resetJwtPlanNotesForTests } = await import("../../src/codex/plan-from-token"); resetJwtPlanNotesForTests(); saveConfig({ @@ -1317,7 +1317,7 @@ describe("shared refresh flight plan reconciliation (#2892 gap 2 follow-up)", () test("records with EMPTY account ids are never treated as the same identity (#2892 review)", async () => { const { getValidCodexToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); // Grant fingerprint, access token and expiry all match, and both ids are "". Two empty strings // compare equal but prove nothing about which upstream account either record was meant to use, // so propagation must fail closed rather than write a credential into an unidentified record. diff --git a/tests/codex-admission-primitives.test.ts b/tests/codex-integration/codex-admission-primitives.test.ts similarity index 96% rename from tests/codex-admission-primitives.test.ts rename to tests/codex-integration/codex-admission-primitives.test.ts index a9326ea021..b2f1746a80 100644 --- a/tests/codex-admission-primitives.test.ts +++ b/tests/codex-integration/codex-admission-primitives.test.ts @@ -19,13 +19,14 @@ import { readConfigGenerationInCurrentMutationTransaction, saveConfig, withConfigMutationLockSync, -} from "../src/config"; -import { hashAuthority } from "../src/codex/admission"; -import { captureCatalogAdmissionSnapshot } from "../src/codex/catalog-admission"; -import { JOURNAL_PATH } from "../src/codex/journal"; -import type { AdmissionSnapshot } from "../src/codex/convergence-types"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/config"; +import { hashAuthority } from "../../src/codex/admission"; +import { captureCatalogAdmissionSnapshot } from "../../src/codex/catalog-admission"; +import { JOURNAL_PATH } from "../../src/codex/journal"; +import type { AdmissionSnapshot } from "../../src/codex/convergence-types"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath } from "../helpers/repo-root"; let root = ""; let previousOpencodexHome: string | undefined; @@ -326,7 +327,7 @@ describe("the journal has one owner", () => { */ test("admission derives no journal path of its own", async () => { const source = await Bun.file( - join(import.meta.dir, "..", "src", "codex", "admission.ts"), + repoPath("src", "codex", "admission.ts"), ).text(); expect(source).toContain("JOURNAL_PATH"); expect(source).not.toContain("codex-journal.json"); diff --git a/tests/codex-admission.test.ts b/tests/codex-integration/codex-admission.test.ts similarity index 97% rename from tests/codex-admission.test.ts rename to tests/codex-integration/codex-admission.test.ts index d2cb92f6c4..8fdc5629be 100644 --- a/tests/codex-admission.test.ts +++ b/tests/codex-integration/codex-admission.test.ts @@ -12,8 +12,8 @@ import { existsSync, mkdirSync, mkdtempSync, readdirSync, writeFileSync } from " import { tmpdir } from "node:os"; import { join } from "node:path"; -import { admitCodexWrite as admitRaw, hashAuthority } from "../src/codex/admission"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { admitCodexWrite as admitRaw, hashAuthority } from "../../src/codex/admission"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /* * Ownership is proven by shelling out to the platform service manager, and a @@ -23,8 +23,8 @@ import { removeTreeWithRetry } from "./helpers/remove-tree"; */ const admitCodexWrite = (): ReturnType => admitRaw({ inspectOwnership: () => ({ ownership: "owned", reason: "pinned by fixture" }) }); -import { JOURNAL_PATH } from "../src/codex/journal"; -import type { OcxConfig } from "../src/types"; +import { JOURNAL_PATH } from "../../src/codex/journal"; +import type { OcxConfig } from "../../src/types"; let root = ""; let codexHome = ""; diff --git a/tests/codex-affinity-debug.test.ts b/tests/codex-integration/codex-affinity-debug.test.ts similarity index 98% rename from tests/codex-affinity-debug.test.ts rename to tests/codex-integration/codex-affinity-debug.test.ts index 42221f95b2..d2c25c536c 100644 --- a/tests/codex-affinity-debug.test.ts +++ b/tests/codex-integration/codex-affinity-debug.test.ts @@ -2,9 +2,9 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { captureCodexAffinityDiagnostic, CODEX_AFFINITY_DEBUG_SAFE_HEADERS, -} from "../src/codex/affinity-debug"; -import { getDebugLogEntries, resetDebugLogBufferForTests } from "../src/lib/debug-log-buffer"; -import { resetDebugSettingsForTests, setDebugSettings } from "../src/lib/debug-settings"; +} from "../../src/codex/affinity-debug"; +import { getDebugLogEntries, resetDebugLogBufferForTests } from "../../src/lib/debug-log-buffer"; +import { resetDebugSettingsForTests, setDebugSettings } from "../../src/lib/debug-settings"; function diagnosticPayload(): Record { const line = getDebugLogEntries().at(-1)?.line ?? ""; diff --git a/tests/codex-app-server-path-spaces.test.ts b/tests/codex-integration/codex-app-server-path-spaces.test.ts similarity index 95% rename from tests/codex-app-server-path-spaces.test.ts rename to tests/codex-integration/codex-app-server-path-spaces.test.ts index 2d9ef0cef0..738bf8e48e 100644 --- a/tests/codex-app-server-path-spaces.test.ts +++ b/tests/codex-integration/codex-app-server-path-spaces.test.ts @@ -3,7 +3,7 @@ import { describe, expect, test } from "bun:test"; import { isCodexAppServerCommandLine, listCodexAppServerProcesses, -} from "../src/codex/app-server-processes"; +} from "../../src/codex/app-server-processes"; describe("Codex app-server flattened command lines", () => { test("matches unquoted official executable paths containing spaces", () => { diff --git a/tests/codex-app-server-processes.test.ts b/tests/codex-integration/codex-app-server-processes.test.ts similarity index 99% rename from tests/codex-app-server-processes.test.ts rename to tests/codex-integration/codex-app-server-processes.test.ts index cb51e3abbc..d98f5abbc3 100644 --- a/tests/codex-app-server-processes.test.ts +++ b/tests/codex-integration/codex-app-server-processes.test.ts @@ -2,12 +2,12 @@ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test } fr import { spawn } from "node:child_process"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { setTrustedWindowsElevationExecutablesForTests } from "../src/lib/windows-elevation"; +import { setTrustedWindowsElevationExecutablesForTests } from "../../src/lib/windows-elevation"; import { createWindowsPowerShellFixture, probeWindowsPowerShellFixture, type WindowsPowerShellFixture, -} from "./helpers/windows-power-shell-fixture"; +} from "../helpers/windows-power-shell-fixture"; import { afterCatalogWriteHandleAppServers, attachStaleAppServerHint, @@ -26,7 +26,8 @@ import { STALE_CODEX_APP_SERVER_HINT, warnIfStaleCodexAppServersAfterStartupWrite, WINDOWS_CODEX_BASENAME_CANDIDATE_RE, -} from "../src/codex/app-server-processes"; +} from "../../src/codex/app-server-processes"; +import { repoPath } from "../helpers/repo-root"; describe("collectCodexAppServerCatalogState (#857)", () => { const APP_SERVER_CMD = "/usr/local/bin/codex app-server"; @@ -702,9 +703,9 @@ describe("Codex app-server process matching (#476)", () => { }); describe("CLI /api sync wiring for stale app-servers (#476)", () => { - const dispatchSource = readFileSync(join(import.meta.dir, "..", "src", "cli", "dispatch.ts"), "utf8"); + const dispatchSource = readFileSync(repoPath("src", "cli", "dispatch.ts"), "utf8"); const configRoutesSource = readFileSync( - join(import.meta.dir, "..", "src", "server", "management", "config-routes.ts"), + repoPath("src", "server", "management", "config-routes.ts"), "utf8", ); @@ -809,7 +810,7 @@ describe("CLI /api sync wiring for stale app-servers (#476)", () => { describe("process utility invocation source guards", () => { const processSource = readFileSync( - join(import.meta.dir, "..", "src", "codex", "app-server-processes.ts"), + repoPath("src", "codex", "app-server-processes.ts"), "utf8", ); @@ -821,7 +822,7 @@ describe("process utility invocation source guards", () => { describe("Windows Win32_Process owner enumeration (#476)", () => { const processSource = readFileSync( - join(import.meta.dir, "..", "src", "codex", "app-server-processes.ts"), + repoPath("src", "codex", "app-server-processes.ts"), "utf8", ); diff --git a/tests/codex-app-server-restart-service.test.ts b/tests/codex-integration/codex-app-server-restart-service.test.ts similarity index 98% rename from tests/codex-app-server-restart-service.test.ts rename to tests/codex-integration/codex-app-server-restart-service.test.ts index 9884ea9de9..64c1d1c3bb 100644 --- a/tests/codex-app-server-restart-service.test.ts +++ b/tests/codex-integration/codex-app-server-restart-service.test.ts @@ -12,10 +12,10 @@ import { performCodexRestart, readCodexAppServerState, resetCodexRestartInFlightForTests, -} from "../src/codex/app-server-restart-service"; -import type { CodexRestartServiceIo } from "../src/codex/app-server-restart-service"; -import type { CodexAppServerProcess } from "../src/codex/app-server-processes"; -import { isCodexRestartResponse } from "../src/lib/codex-restart-contract"; +} from "../../src/codex/app-server-restart-service"; +import type { CodexRestartServiceIo } from "../../src/codex/app-server-restart-service"; +import type { CodexAppServerProcess } from "../../src/codex/app-server-processes"; +import { isCodexRestartResponse } from "../../src/lib/codex-restart-contract"; function proc(pid: number, commandLine = `/opt/codex app-server --pid ${pid}`): CodexAppServerProcess { return { pid, commandLine }; diff --git a/tests/codex-auth-api.test.ts b/tests/codex-integration/codex-auth-api.test.ts similarity index 98% rename from tests/codex-auth-api.test.ts rename to tests/codex-integration/codex-auth-api.test.ts index 75cf062c5e..1cba651ee5 100644 --- a/tests/codex-auth-api.test.ts +++ b/tests/codex-integration/codex-auth-api.test.ts @@ -8,8 +8,8 @@ import { acquireNativeMainProfileDrain, getNativeMainProfileRequestCount, resetLifecycleDrainStateForTests, -} from "../src/server/lifecycle"; -import { fallbackCodexAccountLogLabel } from "../src/codex/account-label"; +} from "../../src/server/lifecycle"; +import { fallbackCodexAccountLogLabel } from "../../src/codex/account-label"; import { handleCodexAuthAPI, updateAccountQuota, getAccountQuota, checkAccountIdCollision, getMainChatgptAccountId, @@ -19,14 +19,14 @@ import { type CodexAuthAccountDto, listCodexAuthAccounts, setAccountQuotaFromParsed, -} from "../src/codex/auth-api"; +} from "../../src/codex/auth-api"; import { getCodexAccountCredential, listCodexAccountIds, readCodexAccountRecord, saveCodexAccountCredential, -} from "../src/codex/account-store"; -import * as accountStoreModule from "../src/codex/account-store"; +} from "../../src/codex/account-store"; +import * as accountStoreModule from "../../src/codex/account-store"; import { clearCodexUpstreamHealth, clearThreadAccountMap, @@ -34,47 +34,47 @@ import { recordCodexUpstreamOutcome, resetCodexRoutingForManualSelection, resolveCodexAccountForThread, -} from "../src/codex/routing"; -import { clearPoolRotationState } from "../src/codex/pool-rotation"; +} from "../../src/codex/routing"; +import { clearPoolRotationState } from "../../src/codex/pool-rotation"; import { clearCodexWebSocketRegistry, getTrackedCodexWebSocketCountForAccount, registerCodexWebSocket, -} from "../src/codex/websocket-registry"; -import type { OcxConfig } from "../src/types"; -import type { WsData } from "../src/server/ws-bridge"; -import { handleNativeProfileAPI } from "../src/codex/native-profile-api"; -import type { NativeProfileManager } from "../src/codex/native-profile-manager"; -import { MAIN_CODEX_ACCOUNT_ID, setMainAccountPlan } from "../src/codex/main-account"; -import { reconcileCodexPlansFromTokens, resetJwtPlanNotesForTests } from "../src/codex/plan-from-token"; +} from "../../src/codex/websocket-registry"; +import type { OcxConfig } from "../../src/types"; +import type { WsData } from "../../src/server/ws-bridge"; +import { handleNativeProfileAPI } from "../../src/codex/native-profile-api"; +import type { NativeProfileManager } from "../../src/codex/native-profile-manager"; +import { MAIN_CODEX_ACCOUNT_ID, setMainAccountPlan } from "../../src/codex/main-account"; +import { reconcileCodexPlansFromTokens, resetJwtPlanNotesForTests } from "../../src/codex/plan-from-token"; import { deleteCodexAccount, reconcileMainCodexAccountRuntimeState, resetMainCodexAccountIdentityTrackingForTests, -} from "../src/codex/account-lifecycle"; +} from "../../src/codex/account-lifecycle"; import { ConfigMutationLockError, getConfigPath, loadConfig, saveConfig, setPersistedConfigMutationBeforeCommitForTests, -} from "../src/config"; -import * as configModule from "../src/config"; -import type { CatalogDisposition } from "../src/codex/convergence-types"; -import { captureConfigGeneration, registerStateStore } from "../src/lib/state-store-sweeper"; +} from "../../src/config"; +import * as configModule from "../../src/config"; +import type { CatalogDisposition } from "../../src/codex/convergence-types"; +import { captureConfigGeneration, registerStateStore } from "../../src/lib/state-store-sweeper"; import { reconcileLiveStateStores, setLiveStateStoreConfig, STATE_STORE_REGISTRATIONS, -} from "../src/lib/state-store-registrations"; +} from "../../src/lib/state-store-registrations"; import { listOpenAiForwardSidecarCandidates, resolveFirstUsableOpenAiSidecar, -} from "../src/providers/openai-sidecar"; -import { BOUNDED_BODY_MAX_BYTES } from "../src/lib/bounded-body"; -import { flushConfigDirHardeningForTests } from "../src/config/paths"; -import { setAsyncIcaclsRunnerForTests, setIcaclsRunnerForTests } from "../src/lib/windows-secret-acl"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/openai-sidecar"; +import { BOUNDED_BODY_MAX_BYTES } from "../../src/lib/bounded-body"; +import { flushConfigDirHardeningForTests } from "../../src/config/paths"; +import { setAsyncIcaclsRunnerForTests, setIcaclsRunnerForTests } from "../../src/lib/windows-secret-acl"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let TEST_DIR = ""; let TEST_CODEX_HOME = ""; @@ -134,9 +134,9 @@ async function completeMockCodexOAuth(options: { catalogRefreshPending?: boolean; }; }> { - const oauth = await import("../src/oauth"); - const oauthStore = await import("../src/oauth/store"); - const openUrlMod = await import("../src/lib/open-url"); + const oauth = await import("../../src/oauth"); + const oauthStore = await import("../../src/oauth/store"); + const openUrlMod = await import("../../src/lib/open-url"); await oauthStore.saveCredential("chatgpt", { access: `access-${options.requestBody.id}`, refresh: `refresh-${options.requestBody.id}`, @@ -3436,7 +3436,7 @@ describe("codex-auth API", () => { // Deliberately no NaN case: JSON.stringify turns NaN into null, which this route // legitimately reads as a reset, so asserting a 400 would assert something unreachable. // NaN is covered where it can occur, against parseAccountPriority in - // tests/codex-pool-rotation.test.ts. + // tests/codex-integration/codex-pool-rotation.test.ts. ["a missing value", undefined], ] as const)("rejects %s as a selection order", async (_label, priority) => { const config = makeConfig(); @@ -4083,8 +4083,8 @@ describe("codex-auth API", () => { * type and a browser spawn that cannot work. */ test("POST /api/codex-auth/login with device:true returns the code and opens no browser", async () => { - const oauth = await import("../src/oauth"); - const openUrlModule = await import("../src/lib/open-url"); + const oauth = await import("../../src/oauth"); + const openUrlModule = await import("../../src/lib/open-url"); const startSpy = spyOn(oauth, "startLoginFlow").mockImplementation(async () => ({ url: "https://auth.openai.com/codex/device", instructions: "Enter code: ABCD-EFGH", @@ -4115,7 +4115,7 @@ describe("codex-auth API", () => { test("the device poll budget covers the 15-minute grant", async () => { // The budget is a loop bound with no observable output, so a regression to // the 5-minute browser budget would pass every behavioral test above. - const source = await Bun.file(new URL("../src/codex/auth-api.ts", import.meta.url)).text(); + const source = await Bun.file(new URL("../../src/codex/auth-api.ts", import.meta.url)).text(); const budget = /const pollAttempts = useDeviceFlow \? (\d+) : (\d+);/.exec(source); expect(budget).toBeTruthy(); // 900s is the grant; the extra margin covers post-grant settlement, so an @@ -4125,7 +4125,7 @@ describe("codex-auth API", () => { }); test("Codex OAuth login responses project raw provider errors", async () => { - const oauth = await import("../src/oauth"); + const oauth = await import("../../src/oauth"); const startSpy = spyOn(oauth, "startLoginFlow").mockImplementation(async () => { throw new Error("already in progress at C:\\Users\\Alice\\.opencodex\\auth.json.ocx-tmp sk-secret-provider-key"); }); @@ -4148,8 +4148,8 @@ describe("codex-auth API", () => { }); test("Codex OAuth login responses preserve actionable OAuth errors", async () => { - const oauth = await import("../src/oauth"); - const { OAuthMutationBusyError } = await import("../src/oauth/store"); + const oauth = await import("../../src/oauth"); + const { OAuthMutationBusyError } = await import("../../src/oauth/store"); const startSpy = spyOn(oauth, "startLoginFlow"); const cases: Array<{ error: Error; expected: string }> = [ { @@ -4189,8 +4189,8 @@ describe("codex-auth API", () => { }); test("Codex OAuth login status projects late provider errors", async () => { - const oauth = await import("../src/oauth"); - const openUrlMod = await import("../src/lib/open-url"); + const oauth = await import("../../src/oauth"); + const openUrlMod = await import("../../src/lib/open-url"); const originalLogin = oauth.OAUTH_PROVIDERS.chatgpt.login; oauth.OAUTH_PROVIDERS.chatgpt.login = async (controller) => { controller.onAuth({ url: "https://example.test/oauth" }); @@ -4240,9 +4240,9 @@ describe("codex-auth API", () => { }); test("Codex OAuth login status preserves actionable late OAuth errors", async () => { - const oauth = await import("../src/oauth"); - const { OAuthMutationBusyError } = await import("../src/oauth/store"); - const openUrlMod = await import("../src/lib/open-url"); + const oauth = await import("../../src/oauth"); + const { OAuthMutationBusyError } = await import("../../src/oauth/store"); + const openUrlMod = await import("../../src/lib/open-url"); const originalLogin = oauth.OAUTH_PROVIDERS.chatgpt.login; const openSpy = spyOn(openUrlMod, "openUrl").mockImplementation(() => {}); const timeoutSpy = spyOn(globalThis, "setTimeout").mockImplementation((( @@ -4324,8 +4324,8 @@ describe("codex-auth API", () => { describe("POST /api/codex-auth/login/code", () => { async function startPendingFlow() { - const oauth = await import("../src/oauth"); - const openUrlMod = await import("../src/lib/open-url"); + const oauth = await import("../../src/oauth"); + const openUrlMod = await import("../../src/lib/open-url"); const startSpy = spyOn(oauth, "startLoginFlow").mockResolvedValue({ url: "https://example.test/oauth" }); const statusSpy = spyOn(oauth, "getLoginStatus").mockReturnValue({ done: false, @@ -4384,7 +4384,7 @@ describe("codex-auth API", () => { }); test("rejects missing and unknown flow ids before submitting", async () => { - const oauth = await import("../src/oauth"); + const oauth = await import("../../src/oauth"); const submitSpy = spyOn(oauth, "submitManualLoginCode"); try { for (const body of [{ input: "code" }, { flowId: "", input: "code" }, { flowId: "unknown", input: "code" }]) { @@ -4561,7 +4561,7 @@ describe("codex-auth API", () => { }); test("POST /api/codex-auth/login rejects an id owned by a namespace before OAuth starts", async () => { - const oauth = await import("../src/oauth"); + const oauth = await import("../../src/oauth"); const startSpy = spyOn(oauth, "startLoginFlow"); try { const config = makeConfig({ codexAccountNamespaces: { work: "pool-a" } }); @@ -4650,8 +4650,8 @@ describe("codex-auth API", () => { chatgptAccountId: "acc-pool-reauth", }); - const oauth = await import("../src/oauth"); - const openUrlMod = await import("../src/lib/open-url"); + const oauth = await import("../../src/oauth"); + const openUrlMod = await import("../../src/lib/open-url"); const startSpy = spyOn(oauth, "startLoginFlow").mockResolvedValue({ url: "https://example.test/oauth" }); const statusSpy = spyOn(oauth, "getLoginStatus").mockReturnValue({ done: true, diff --git a/tests/codex-auth-collision.test.ts b/tests/codex-integration/codex-auth-collision.test.ts similarity index 93% rename from tests/codex-auth-collision.test.ts rename to tests/codex-integration/codex-auth-collision.test.ts index a4fe5889cb..ceeff1a0da 100644 --- a/tests/codex-auth-collision.test.ts +++ b/tests/codex-integration/codex-auth-collision.test.ts @@ -1,11 +1,11 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, writeFileSync } from "node:fs"; import { join } from "node:path"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { checkAccountIdCollision } from "../src/codex/auth-api"; -import { saveConfig } from "../src/config"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { checkAccountIdCollision } from "../../src/codex/auth-api"; +import { saveConfig } from "../../src/config"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-codex-auth-collision-test"); const TEST_CODEX_HOME = join(TEST_DIR, "codex"); diff --git a/tests/codex-auth-context.test.ts b/tests/codex-integration/codex-auth-context.test.ts similarity index 98% rename from tests/codex-auth-context.test.ts rename to tests/codex-integration/codex-auth-context.test.ts index b002caee30..bb4f24a098 100644 --- a/tests/codex-auth-context.test.ts +++ b/tests/codex-integration/codex-auth-context.test.ts @@ -23,7 +23,7 @@ import { resolveCodexAuthContext, shouldMarkAccountNeedsReauthForCodexAuthFailure, stripCodexRuntimeProviderFields, -} from "../src/codex/auth-context"; +} from "../../src/codex/auth-context"; import { CodexCredentialGenerationConflictError, CodexCredentialRefreshLockTimeoutError, @@ -34,13 +34,13 @@ import { readCodexAccountRecord, removeCodexAccountCredential, saveCodexAccountCredential, -} from "../src/codex/account-store"; -import { ConfigMutationLockError, getConfigPath } from "../src/config"; +} from "../../src/codex/account-store"; +import { ConfigMutationLockError, getConfigPath } from "../../src/config"; import { getMainAccountPlan, MAIN_CODEX_ACCOUNT_ID, setMainAccountPlan, -} from "../src/codex/main-account"; +} from "../../src/codex/main-account"; import { clearAccountNeedsReauth, clearAccountQuota, @@ -48,8 +48,8 @@ import { isAccountNeedsReauth, markAccountNeedsReauth, setAccountQuotaFromParsed, -} from "../src/codex/auth-api"; -import { __resetGuardianState, guardianSweep } from "../src/oauth/token-guardian"; +} from "../../src/codex/auth-api"; +import { __resetGuardianState, guardianSweep } from "../../src/oauth/token-guardian"; import { CODEX_THREAD_AFFINITY_IDLE_TTL_MS, CODEX_QUOTA_PROBE_INTERVAL_MS, @@ -57,23 +57,23 @@ import { clearThreadAccountMap, recordCodexUpstreamOutcome, resetCodexRoutingForManualSelection, -} from "../src/codex/routing"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { setIcaclsRunnerForTests } from "../src/lib/windows-secret-acl"; +} from "../../src/codex/routing"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { setIcaclsRunnerForTests } from "../../src/lib/windows-secret-acl"; import { blockNativeMainStartupForUnownedServiceHome, completeNativeMainRecovery, initializeNativeMainStartupGate, -} from "../src/codex/native-profile-startup"; -import type { NativeProfileManager } from "../src/codex/native-profile-manager"; +} from "../../src/codex/native-profile-startup"; +import type { NativeProfileManager } from "../../src/codex/native-profile-manager"; import { acquireNativeMainProfileDrain, codexAccountSelectionForTurn, tryAdmitTurn, -} from "../src/server/lifecycle"; -import type { CodexModelEntitlementSnapshot } from "../src/codex/model-entitlements"; -import { hasForwardableCodexBearer } from "../src/server/auth-cors"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/server/lifecycle"; +import type { CodexModelEntitlementSnapshot } from "../../src/codex/model-entitlements"; +import { hasForwardableCodexBearer } from "../../src/server/auth-cors"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testDir: string; let previousOpencodexHome: string | undefined; @@ -2000,7 +2000,7 @@ describe("Codex auth context", () => { ["busy", new CodexCredentialRefreshBusyError()], ["stale", new CodexCredentialRefreshStaleError()], ])("login returns a retryable response for a %s credential refresh failure", async (_kind, refreshError) => { - const oauth = await import("../src/oauth"); + const oauth = await import("../../src/oauth"); const startLogin = spyOn(oauth, "startLoginFlow").mockRejectedValue(refreshError); const cfg = config(); try { diff --git a/tests/codex-catalog-admission.test.ts b/tests/codex-integration/codex-catalog-admission.test.ts similarity index 96% rename from tests/codex-catalog-admission.test.ts rename to tests/codex-integration/codex-catalog-admission.test.ts index 1abe9a853e..3867fe1469 100644 --- a/tests/codex-catalog-admission.test.ts +++ b/tests/codex-integration/codex-catalog-admission.test.ts @@ -11,17 +11,17 @@ import { import { tmpdir } from "node:os"; import { join } from "node:path"; -import { captureCatalogAdmissionSnapshot } from "../src/codex/catalog-admission"; +import { captureCatalogAdmissionSnapshot } from "../../src/codex/catalog-admission"; import type { CatalogConditionalSourceObservations, CatalogConditionalSourceRole, CatalogRequiredSourceObservations, CatalogRequiredSourceRole, CatalogSourceEvidence, -} from "../src/codex/convergence-types"; -import { saveConfig } from "../src/config"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/convergence-types"; +import { saveConfig } from "../../src/config"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const CONDITIONAL_SOURCE_ROLES = [ "active-catalog-merge", diff --git a/tests/codex-catalog-golden.test.ts b/tests/codex-integration/codex-catalog-golden.test.ts similarity index 98% rename from tests/codex-catalog-golden.test.ts rename to tests/codex-integration/codex-catalog-golden.test.ts index eacc50003b..35eeb82bbc 100644 --- a/tests/codex-catalog-golden.test.ts +++ b/tests/codex-integration/codex-catalog-golden.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { buildCatalogEntries } from "../src/codex/catalog"; +import { buildCatalogEntries } from "../../src/codex/catalog"; // Behavior-preservation ORACLE for the future codex-catalog.ts split (devlog 260701). // buildCatalogEntries is the pure core (no fs/network). This snapshots its full serialized diff --git a/tests/codex-catalog-model-picker-order.test.ts b/tests/codex-integration/codex-catalog-model-picker-order.test.ts similarity index 99% rename from tests/codex-catalog-model-picker-order.test.ts rename to tests/codex-integration/codex-catalog-model-picker-order.test.ts index 17be566104..7ef43e0c3f 100644 --- a/tests/codex-catalog-model-picker-order.test.ts +++ b/tests/codex-integration/codex-catalog-model-picker-order.test.ts @@ -3,8 +3,8 @@ import { buildCatalogEntriesFromObservedState, effectiveSubagentRoster, MAX_SPAWN_AGENT_MODEL_OVERRIDES, -} from "../src/codex/catalog/sync"; -import type { CatalogModel } from "../src/types"; +} from "../../src/codex/catalog/sync"; +import type { CatalogModel } from "../../src/types"; // #1649: config.modelPickerOrder assigns a deterministic priority band to non-featured routed // rows so a catalog with more than 5 routed models keeps a stable picker order across rebuilds, diff --git a/tests/codex-catalog-refresh-status.test.ts b/tests/codex-integration/codex-catalog-refresh-status.test.ts similarity index 95% rename from tests/codex-catalog-refresh-status.test.ts rename to tests/codex-integration/codex-catalog-refresh-status.test.ts index 85e0d299cf..ed4e97ab24 100644 --- a/tests/codex-catalog-refresh-status.test.ts +++ b/tests/codex-integration/codex-catalog-refresh-status.test.ts @@ -2,8 +2,8 @@ import { describe, expect, test } from "bun:test"; import { catalogRefreshIsPending, normalizeCatalogDisposition, -} from "../src/codex/catalog-refresh-status"; -import type { CatalogDisposition } from "../src/codex/convergence-types"; +} from "../../src/codex/catalog-refresh-status"; +import type { CatalogDisposition } from "../../src/codex/convergence-types"; describe("catalogRefreshIsPending", () => { test("only committed catalog state is complete", () => { diff --git a/tests/codex-catalog-restore.test.ts b/tests/codex-integration/codex-catalog-restore.test.ts similarity index 99% rename from tests/codex-catalog-restore.test.ts rename to tests/codex-integration/codex-catalog-restore.test.ts index 64465a7c9d..a211701578 100644 --- a/tests/codex-catalog-restore.test.ts +++ b/tests/codex-integration/codex-catalog-restore.test.ts @@ -5,9 +5,9 @@ import { spawnSync } from "node:child_process"; import { tmpdir } from "node:os"; import { dirname, join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); function backupPathForTestCatalog(codexHome: string, opencodexHome: string, catalogName: string): string { const catalogPath = join(realpathSync.native(codexHome), catalogName); diff --git a/tests/codex-catalog-sync-hardening.test.ts b/tests/codex-integration/codex-catalog-sync-hardening.test.ts similarity index 99% rename from tests/codex-catalog-sync-hardening.test.ts rename to tests/codex-integration/codex-catalog-sync-hardening.test.ts index 39da672c99..6f7e7e38fd 100644 --- a/tests/codex-catalog-sync-hardening.test.ts +++ b/tests/codex-integration/codex-catalog-sync-hardening.test.ts @@ -4,10 +4,10 @@ import { spawnSync } from "node:child_process"; import { tmpdir } from "node:os"; import { dirname, join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; -import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../src/codex/catalog/native-models"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../../src/codex/catalog/native-models"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); function runScript( codexHome: string, diff --git a/tests/codex-catalog-write-serialization.test.ts b/tests/codex-integration/codex-catalog-write-serialization.test.ts similarity index 97% rename from tests/codex-catalog-write-serialization.test.ts rename to tests/codex-integration/codex-catalog-write-serialization.test.ts index 873d82806c..3cd1fa0cc1 100644 --- a/tests/codex-catalog-write-serialization.test.ts +++ b/tests/codex-integration/codex-catalog-write-serialization.test.ts @@ -8,13 +8,13 @@ import { isCatalogWritePermitLive, withCatalogWriteSerialization, type CatalogWritePermit, -} from "../src/codex/catalog-write-serialization"; +} from "../../src/codex/catalog-write-serialization"; import { resolveCodexCatalogSerializationDatabasePath, resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/user-identity"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let codexHome = ""; let otherHome = ""; diff --git a/tests/codex-catalog-writer.test.ts b/tests/codex-integration/codex-catalog-writer.test.ts similarity index 97% rename from tests/codex-catalog-writer.test.ts rename to tests/codex-integration/codex-catalog-writer.test.ts index ed7bf313bc..b73789ef20 100644 --- a/tests/codex-catalog-writer.test.ts +++ b/tests/codex-integration/codex-catalog-writer.test.ts @@ -18,16 +18,16 @@ import { import { tmpdir } from "node:os"; import { join } from "node:path"; -import type { AtomicWriteIO } from "../src/config"; +import type { AtomicWriteIO } from "../../src/config"; import { type CatalogWritePermit, CatalogWritePermitRefusal, withCatalogWriteSerialization, -} from "../src/codex/catalog-write-serialization"; +} from "../../src/codex/catalog-write-serialization"; import { resolveCodexCatalogSerializationDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; +} from "../../src/codex/user-identity"; import { type CatalogBackupWriteIO, type PreparedCatalogFileWrite, @@ -35,8 +35,8 @@ import { publishLegacyCodexCatalogBackup, replaceActiveCodexCatalog, replaceCodexModelsCache, -} from "../src/codex/internal/catalog-writer"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/internal/catalog-writer"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; interface MutatorCase { readonly name: string; diff --git a/tests/codex-catalog.test.ts b/tests/codex-integration/codex-catalog.test.ts similarity index 99% rename from tests/codex-catalog.test.ts rename to tests/codex-integration/codex-catalog.test.ts index a46fc64115..d8cd9d068b 100644 --- a/tests/codex-catalog.test.ts +++ b/tests/codex-integration/codex-catalog.test.ts @@ -2,21 +2,21 @@ import { afterEach, describe, expect, spyOn, test } from "bun:test"; import { existsSync, mkdtempSync, readFileSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { codexAccountGatedCanonicalWireModel } from "../src/server/responses/core"; -import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../src/codex/catalog/native-models"; -import { isGpt56NativeSlug } from "../src/codex/catalog/effort"; -import { nativeOpenAiContextTier, nativeOpenAiMaxInputTokens } from "../src/codex/catalog"; -import { shouldUpgradeToUpstreamEntry } from "../src/codex/catalog/metadata"; -import { applyNativeVisibility, augmentRoutedModelsWithMetadata, augmentRoutedModelsWithRegistryOpenAiApiRows, buildCatalogEntries, buildComboCatalogOmission, catalogModelSlug, clampCatalogModelsToCodexSupport, clampEntryToCodexSupportedEfforts, clampedDefaultEffort, CODEX_ACCOUNT_BOUND_CATALOG_KIND, CODEX_NATIVE_ALIAS_CATALOG_KIND, comboCatalogOmissionReason, deriveComboCatalogModel, exactComboCatalogSlugs, filterCatalogVisibleModels, filterSupportedNativeSlugs, gatherRoutedModels as gatherRoutedModelsDirect, isDatedVariantId, isMediaGenerationModelId, loadBundledCodexCatalog, materializeBundledCodexCatalog, mergeCatalogEntriesForSync, NATIVE_DAYBREAK_BLUE_MODEL, NATIVE_GPT6_ASTRA_MODEL, NATIVE_OPENAI_MODELS, nativeDefaultReasoningEffort, nativeInputModalities, nativeOpenAiCapabilitySourceSlug, nativeOpenAiContextWindow, nativeReasoningEfforts, normalizeRoutedCatalogEntry, resetCatalogRuntimeStateForTests, resetOpenAiApiCatalogWarningStateForTests, resolveComboCatalogMember, shouldExposeRoutedModel, upstreamNativeEntry } from "../src/codex/catalog"; -import { applyProviderConfigHints, mergeConfiguredModelsIntoLiveCatalog } from "../src/codex/catalog/provider-fetch"; +import { codexAccountGatedCanonicalWireModel } from "../../src/server/responses/core"; +import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../../src/codex/catalog/native-models"; +import { isGpt56NativeSlug } from "../../src/codex/catalog/effort"; +import { nativeOpenAiContextTier, nativeOpenAiMaxInputTokens } from "../../src/codex/catalog"; +import { shouldUpgradeToUpstreamEntry } from "../../src/codex/catalog/metadata"; +import { applyNativeVisibility, augmentRoutedModelsWithMetadata, augmentRoutedModelsWithRegistryOpenAiApiRows, buildCatalogEntries, buildComboCatalogOmission, catalogModelSlug, clampCatalogModelsToCodexSupport, clampEntryToCodexSupportedEfforts, clampedDefaultEffort, CODEX_ACCOUNT_BOUND_CATALOG_KIND, CODEX_NATIVE_ALIAS_CATALOG_KIND, comboCatalogOmissionReason, deriveComboCatalogModel, exactComboCatalogSlugs, filterCatalogVisibleModels, filterSupportedNativeSlugs, gatherRoutedModels as gatherRoutedModelsDirect, isDatedVariantId, isMediaGenerationModelId, loadBundledCodexCatalog, materializeBundledCodexCatalog, mergeCatalogEntriesForSync, NATIVE_DAYBREAK_BLUE_MODEL, NATIVE_GPT6_ASTRA_MODEL, NATIVE_OPENAI_MODELS, nativeDefaultReasoningEffort, nativeInputModalities, nativeOpenAiCapabilitySourceSlug, nativeOpenAiContextWindow, nativeReasoningEfforts, normalizeRoutedCatalogEntry, resetCatalogRuntimeStateForTests, resetOpenAiApiCatalogWarningStateForTests, resolveComboCatalogMember, shouldExposeRoutedModel, upstreamNativeEntry } from "../../src/codex/catalog"; +import { applyProviderConfigHints, mergeConfiguredModelsIntoLiveCatalog } from "../../src/codex/catalog/provider-fetch"; import { CODEX_CUSTOM_MODEL_CATALOG_KIND, CODEX_PROVIDER_MODEL_CATALOG_KIND, ensureStrictCatalogFields, findNativeTemplate, findSupportedNativeTemplate, -} from "../src/codex/catalog/parsing"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; +} from "../../src/codex/catalog/parsing"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; import { CURSOR_STATIC_MODELS, filterCursorConfiguredModelsByLiveDiscovery, @@ -24,9 +24,9 @@ import { cursorModelIds, cursorModelInputModalities, cursorModelReasoningEfforts, -} from "../src/adapters/cursor/discovery"; -import { getModelMetadata, resolveMetadataProvider } from "../src/generated/model-metadata"; -import { resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests } from "../src/codex/model-entitlements"; +} from "../../src/adapters/cursor/discovery"; +import { getModelMetadata, resolveMetadataProvider } from "../../src/generated/model-metadata"; +import { resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests } from "../../src/codex/model-entitlements"; import { clearModelCache, getProviderDiscoveryStatus, @@ -34,25 +34,25 @@ import { markProviderDiscoveryFailed, setCached, type ProviderModelDiscoveryStatus, -} from "../src/codex/model-cache"; -import type { OcxConfig } from "../src/types"; -import { COMBO_NAMESPACE } from "../src/combos"; -import type { NormalizedComboConfig } from "../src/combos/types"; -import { enrichProviderFromRegistry, providerConfigSeed } from "../src/providers/derive"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { enrichProviderFromCatalog } from "../src/oauth/key-providers"; -import { handleManagementAPI } from "../src/server/management-api"; -import { OAUTH_PROVIDERS } from "../src/oauth"; +} from "../../src/codex/model-cache"; +import type { OcxConfig } from "../../src/types"; +import { COMBO_NAMESPACE } from "../../src/combos"; +import type { NormalizedComboConfig } from "../../src/combos/types"; +import { enrichProviderFromRegistry, providerConfigSeed } from "../../src/providers/derive"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { enrichProviderFromCatalog } from "../../src/oauth/key-providers"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { OAUTH_PROVIDERS } from "../../src/oauth"; import { clampCatalogModelsToObservedCodexSupport, supportedCodexReasoningEffortsFromObservedCatalog, -} from "../src/codex/catalog/effort"; +} from "../../src/codex/catalog/effort"; import { CANONICAL_NATIVE_CATALOG_CONTENT_POLICY, mergeCatalogEntriesFromObservedState, type ObservedCatalogMergeInput, -} from "../src/codex/catalog/sync"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/catalog/sync"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const originalFetch = globalThis.fetch; @@ -1073,7 +1073,7 @@ describe("combo catalog capability intersection", () => { expect(String(warn.mock.calls[0]?.[0])).toContain("[REDACTED]"); expect(String(warn.mock.calls[0]?.[0])).not.toContain(warningSentinel); expect(second).toEqual(first); - const { getLastComboCatalogOmissions } = await import("../src/codex/catalog"); + const { getLastComboCatalogOmissions } = await import("../../src/codex/catalog"); const hidden = getLastComboCatalogOmissions().find(item => item.id === "hidden"); expect(hidden).toMatchObject({ id: "hidden", @@ -1123,7 +1123,7 @@ describe("combo catalog capability intersection", () => { resetCatalogRuntimeStateForTests(); const models = await gatherRoutedModels(config); expect(models.some(model => model.provider === "combo" && model.id === "disjoint")).toBe(false); - const { getLastComboCatalogOmissions } = await import("../src/codex/catalog"); + const { getLastComboCatalogOmissions } = await import("../../src/codex/catalog"); const omission = getLastComboCatalogOmissions().find(item => item.id === "disjoint"); expect(omission).toMatchObject({ id: "disjoint", @@ -1433,7 +1433,7 @@ describe("combo catalog capability intersection", () => { expect(combo!.reasoningEfforts).toEqual(["low", "medium"]); // Synthesized member must not leak as a standalone routed row. expect(rows.some(r => r.provider === "a" && r.id === "unlisted")).toBe(false); - const { getLastComboCatalogOmissions } = await import("../src/codex/catalog"); + const { getLastComboCatalogOmissions } = await import("../../src/codex/catalog"); expect(getLastComboCatalogOmissions().some(item => item.id === "recovered")).toBe(false); } finally { warn.mockRestore(); @@ -1685,7 +1685,7 @@ describe("combo catalog capability intersection", () => { const rows = await gatherRoutedModels(config); expect(rows.some(r => r.provider === "combo" && r.id === "disjoint")).toBe(false); expect(rows.some(r => r.provider === "combo" && r.id === "ghost")).toBe(false); - const { getLastComboCatalogOmissions } = await import("../src/codex/catalog"); + const { getLastComboCatalogOmissions } = await import("../../src/codex/catalog"); const omissions = getLastComboCatalogOmissions(); expect(omissions.find(item => item.id === "disjoint")).toMatchObject({ reason: "incompatible_modalities", @@ -1778,7 +1778,7 @@ describe("combo catalog capability intersection", () => { const warningText = warning.mock.calls.flat().join(" "); expect(warningText).not.toContain("member capabilities are incomplete"); expect(warningText).not.toContain("omitted configured model ids"); - const { getLastComboCatalogOmissions } = await import("../src/codex/catalog"); + const { getLastComboCatalogOmissions } = await import("../../src/codex/catalog"); expect(getLastComboCatalogOmissions().some(item => item.id === "failover")).toBe(false); } finally { warning.mockRestore(); @@ -6490,7 +6490,7 @@ describe("Codex reasoning-effort capability clamp", () => { describe("auto_review_model configuration (#1225)", () => { test("applyAutoReviewModelOverride sets auto_review_model_override across all entries", () => { - const { applyAutoReviewModelOverride } = require("../src/codex/catalog/sync"); + const { applyAutoReviewModelOverride } = require("../../src/codex/catalog/sync"); const entries = [ { slug: "gpt-5.5", auto_review_model_override: null }, { slug: "opencode-go/deepseek-v4-flash", auto_review_model_override: null }, @@ -6502,7 +6502,7 @@ describe("auto_review_model configuration (#1225)", () => { }); test("applyAutoReviewModelOverride clears routed state when autoReviewModel is null or empty", () => { - const { applyAutoReviewModelOverride } = require("../src/codex/catalog/sync"); + const { applyAutoReviewModelOverride } = require("../../src/codex/catalog/sync"); const entries = [ { slug: "gpt-5.5", auto_review_model_override: "existing-model" }, { slug: "opencode-go/glm-5.2", auto_review_model_override: "old-model" }, @@ -6517,7 +6517,7 @@ describe("auto_review_model configuration (#1225)", () => { }); test("applyAutoReviewModelOverride rejects invalid format with control chars or inner spaces", () => { - const { applyAutoReviewModelOverride, isValidAutoReviewModel } = require("../src/codex/catalog/sync"); + const { applyAutoReviewModelOverride, isValidAutoReviewModel } = require("../../src/codex/catalog/sync"); const entries = [ { slug: "gpt-5.5", auto_review_model_override: "native-preserved" }, ]; @@ -6530,13 +6530,13 @@ describe("auto_review_model configuration (#1225)", () => { }); test("readConfiguredAutoReviewModel reads auto_review_model from config.toml", () => { - const { readConfiguredAutoReviewModel } = require("../src/codex/catalog/parsing"); + const { readConfiguredAutoReviewModel } = require("../../src/codex/catalog/parsing"); expect(typeof readConfiguredAutoReviewModel).toBe("function"); }); test("writeRetainedCatalogSync stamps auto_review_model_override into persisted catalog", () => { - const { applyAutoReviewModelOverride } = require("../src/codex/catalog/sync"); - const { readConfiguredAutoReviewModel } = require("../src/codex/catalog/parsing"); + const { applyAutoReviewModelOverride } = require("../../src/codex/catalog/sync"); + const { readConfiguredAutoReviewModel } = require("../../src/codex/catalog/parsing"); // Simulate a config-driven write path: entries are regenerated from a template, // then the override is stamped before serialization. @@ -6560,7 +6560,7 @@ describe("auto_review_model configuration (#1225)", () => { expect(entries[1].auto_review_model_override).toBe(trimmedValue); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; describe("#2465 model preset management routes", () => { const originalFetchForPresets = globalThis.fetch; diff --git a/tests/codex-cli-install-provenance.test.ts b/tests/codex-integration/codex-cli-install-provenance.test.ts similarity index 99% rename from tests/codex-cli-install-provenance.test.ts rename to tests/codex-integration/codex-cli-install-provenance.test.ts index 1914f2b07b..31635b2afd 100644 --- a/tests/codex-cli-install-provenance.test.ts +++ b/tests/codex-integration/codex-cli-install-provenance.test.ts @@ -7,9 +7,9 @@ import { isAppBundledCodexPath, isCodexCliUpdateVersionManagerPath, type CodexCliInstallProvenanceDeps, -} from "../src/codex/cli-install-provenance"; -import { buildUnixCodexShim } from "../src/codex/shim"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/cli-install-provenance"; +import { buildUnixCodexShim } from "../../src/codex/shim"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-cli-update-launcher-policy.test.ts b/tests/codex-integration/codex-cli-update-launcher-policy.test.ts similarity index 84% rename from tests/codex-cli-update-launcher-policy.test.ts rename to tests/codex-integration/codex-cli-update-launcher-policy.test.ts index b8e4cf84ec..b9bc83299b 100644 --- a/tests/codex-cli-update-launcher-policy.test.ts +++ b/tests/codex-integration/codex-cli-update-launcher-policy.test.ts @@ -1,7 +1,8 @@ import { describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { isCodexCliUpdateInspectionArgv } from "../src/update/codex-cli-update-launch-policy.mjs"; +import { isCodexCliUpdateInspectionArgv } from "../../src/update/codex-cli-update-launch-policy.mjs"; +import { repoPath } from "../helpers/repo-root"; describe("Codex CLI updater launcher policy", () => { test("covers the whole exact namespace including malformed actions", () => { @@ -17,7 +18,7 @@ describe("Codex CLI updater launcher policy", () => { }); test("launcher skips boot repair and lazy Bun installation for this namespace", () => { - const source = readFileSync(join(import.meta.dir, "..", "bin", "ocx.mjs"), "utf8"); + const source = readFileSync(repoPath("bin", "ocx.mjs"), "utf8"); expect(source).toContain("!codexCliUpdateInspection && isNodeModulesInstall()"); expect(source).toContain("resolveBun({ allowInstall: !codexCliUpdateInspection })"); expect(source).toContain("if (allowInstall && existsSync(installJs))"); diff --git a/tests/codex-cli-update-zero-effect.test.ts b/tests/codex-integration/codex-cli-update-zero-effect.test.ts similarity index 88% rename from tests/codex-cli-update-zero-effect.test.ts rename to tests/codex-integration/codex-cli-update-zero-effect.test.ts index 2cedd734bc..bc878b80e2 100644 --- a/tests/codex-cli-update-zero-effect.test.ts +++ b/tests/codex-integration/codex-cli-update-zero-effect.test.ts @@ -3,7 +3,8 @@ import { spawnSync } from "node:child_process"; import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath, repoRoot } from "../helpers/repo-root"; const roots: string[] = []; afterEach(() => { @@ -13,10 +14,10 @@ afterEach(() => { describe("Codex CLI updater zero-effect boundary", () => { test("direct Bun execution of the Node launcher fails before updater inspection", () => { const result = spawnSync(process.execPath, [ - join(import.meta.dir, "..", "bin", "ocx.mjs"), + repoPath("bin", "ocx.mjs"), "system", "codex-cli-update", "check", "--json", ], { - cwd: join(import.meta.dir, ".."), encoding: "utf8", timeout: 15_000, + cwd: repoRoot(), encoding: "utf8", timeout: 15_000, env: { ...process.env }, windowsHide: true, }); expect(result.error).toBeUndefined(); @@ -38,8 +39,8 @@ describe("Codex CLI updater zero-effect boundary", () => { const statePath = join(home, "codex-shim.json"); writeFileSync(statePath, "{broken", "utf8"); const before = readFileSync(statePath); - const result = spawnSync("node", [join(import.meta.dir, "..", "bin", "ocx.mjs"), "system", "codex-cli-update", "check", "--json"], { - cwd: join(import.meta.dir, ".."), + const result = spawnSync("node", [repoPath("bin", "ocx.mjs"), "system", "codex-cli-update", "check", "--json"], { + cwd: repoRoot(), encoding: "utf8", timeout: 15_000, env: { ...process.env, OPENCODEX_HOME: home, CODEX_CLI_PATH: launcher }, @@ -75,11 +76,11 @@ describe("Codex CLI updater zero-effect boundary", () => { writeFileSync(statePath, "{broken", "utf8"); const before = readFileSync(statePath); const result = spawnSync("node", [ - join(import.meta.dir, "..", "bin", "ocx.mjs"), + repoPath("bin", "ocx.mjs"), "--ocx-internal-launch-proof=bad", "system", "codex-cli-update", "invalid", ], { - cwd: join(import.meta.dir, ".."), encoding: "utf8", timeout: 15_000, + cwd: repoRoot(), encoding: "utf8", timeout: 15_000, env: { ...process.env, OPENCODEX_HOME: home, CODEX_CLI_PATH: launcher }, windowsHide: true, }); expect(result.error).toBeUndefined(); diff --git a/tests/codex-composed-acceptance.test.ts b/tests/codex-integration/codex-composed-acceptance.test.ts similarity index 98% rename from tests/codex-composed-acceptance.test.ts rename to tests/codex-integration/codex-composed-acceptance.test.ts index 32312b3e7f..4dac153f14 100644 --- a/tests/codex-composed-acceptance.test.ts +++ b/tests/codex-integration/codex-composed-acceptance.test.ts @@ -23,8 +23,8 @@ import { join, relative, resolve } from "node:path"; import { createHash } from "node:crypto"; import { Database } from "bun:sqlite"; -import { watchdogMs } from "./helpers/ci-watchdog"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { watchdogMs } from "../helpers/ci-watchdog"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * Per-case budget. A case can start a server twice and stop it, so it must exceed the sum of @@ -35,15 +35,16 @@ const CASE_TIMEOUT_MS = process.env.CI === "true" ? 150_000 : 45_000; import { canonicalizeCodexHome, -} from "../src/codex/codex-write-lock"; +} from "../../src/codex/codex-write-lock"; import { resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import { claimOwnedServiceHome, withOwnedServiceHomePreload } from "./helpers/owned-service-home"; -import { SERVER_BUDGET_MS } from "./helpers/test-budget"; +} from "../../src/codex/user-identity"; +import { claimOwnedServiceHome, withOwnedServiceHomePreload } from "../helpers/owned-service-home"; +import { SERVER_BUDGET_MS } from "../helpers/test-budget"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; -const repoRoot = resolve(import.meta.dir, ".."); +const repoRoot = resolveRepoRoot(); const cliPath = resolve(repoRoot, "src/cli/index.ts"); const lockChildPath = resolve(repoRoot, "tests/helpers/codex-write-lock-child.ts"); const roots: Fixture[] = []; diff --git a/tests/codex-config-generation.test.ts b/tests/codex-integration/codex-config-generation.test.ts similarity index 97% rename from tests/codex-config-generation.test.ts rename to tests/codex-integration/codex-config-generation.test.ts index e45df077db..59a6377a71 100644 --- a/tests/codex-config-generation.test.ts +++ b/tests/codex-integration/codex-config-generation.test.ts @@ -22,12 +22,13 @@ import { saveConfig, saveConfigPreservingClaudeCode, withExpectedConfigGenerationSync, -} from "../src/config"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/config"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath, repoRoot } from "../helpers/repo-root"; const CHILD_TIMEOUT_MS = 10_000; -const configModuleUrl = pathToFileURL(join(import.meta.dir, "../src/config.ts")).href; +const configModuleUrl = pathToFileURL(repoPath("src/config.ts")).href; const generationGuardRaceScript = ` import { existsSync, writeFileSync } from "node:fs"; import { withExpectedConfigGenerationSync } from ${JSON.stringify(configModuleUrl)}; @@ -272,7 +273,7 @@ test("two real processes racing one generation run exactly one callback", async peerOutcomePath: join(testRoot, `${peerId}.outcome`), }; return Bun.spawn([process.execPath, "--eval", generationGuardRaceScript], { - cwd: join(import.meta.dir, ".."), + cwd: repoRoot(), env: { ...process.env, HOME: testRoot, diff --git a/tests/codex-convergence-account-selectors.test.ts b/tests/codex-integration/codex-convergence-account-selectors.test.ts similarity index 97% rename from tests/codex-convergence-account-selectors.test.ts rename to tests/codex-integration/codex-convergence-account-selectors.test.ts index 4512d225fd..ae83c1f2bf 100644 --- a/tests/codex-convergence-account-selectors.test.ts +++ b/tests/codex-integration/codex-convergence-account-selectors.test.ts @@ -12,42 +12,42 @@ import { import { tmpdir } from "node:os"; import { join } from "node:path"; -import { captureCatalogAdmissionSnapshot } from "../src/codex/catalog-admission"; +import { captureCatalogAdmissionSnapshot } from "../../src/codex/catalog-admission"; import { CODEX_ACCOUNT_BOUND_CATALOG_KIND, loadBundledCodexCatalog, NATIVE_OPENAI_MODELS, resetCatalogRuntimeStateForTests, syncCatalogModels, -} from "../src/codex/catalog"; +} from "../../src/codex/catalog"; import { commitCodexCatalogCandidate, convergeCodexCatalog, gatherCodexCatalogCandidate, -} from "../src/codex/convergence"; +} from "../../src/codex/convergence"; import { catalogBackupPathFor, type RawCatalog, type RawEntry, -} from "../src/codex/catalog/parsing"; +} from "../../src/codex/catalog/parsing"; import { resolveCodexCatalogSerializationDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import { getConfigPath, saveConfig } from "../src/config"; -import { CODEX_FORWARD_BASE_URL } from "../src/providers/openai-tiers"; -import type { OcxConfig } from "../src/types"; -import { setBundledCatalogCacheForTests } from "../src/codex/catalog/bundled"; +} from "../../src/codex/user-identity"; +import { getConfigPath, saveConfig } from "../../src/config"; +import { CODEX_FORWARD_BASE_URL } from "../../src/providers/openai-tiers"; +import type { OcxConfig } from "../../src/types"; +import { setBundledCatalogCacheForTests } from "../../src/codex/catalog/bundled"; import { resetCodexRuntimeResolveCacheForTests, setCodexRuntimeResolveCacheForTests, -} from "../src/codex/runtime"; -import { markModelsFetchFailure } from "../src/codex/model-cache"; -import { legacyCustomModelCatalogSlugs } from "../src/codex/custom-model-catalog-migration"; -import { resetCodexModelEntitlementCacheForTests } from "../src/codex/model-entitlements"; -import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../src/codex/catalog/native-models"; -import { removeCodexAccountCredential, saveCodexAccountCredential } from "../src/codex/account-store"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/runtime"; +import { markModelsFetchFailure } from "../../src/codex/model-cache"; +import { legacyCustomModelCatalogSlugs } from "../../src/codex/custom-model-catalog-migration"; +import { resetCodexModelEntitlementCacheForTests } from "../../src/codex/model-entitlements"; +import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../../src/codex/catalog/native-models"; +import { removeCodexAccountCredential, saveCodexAccountCredential } from "../../src/codex/account-store"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; // The canonical-bytes case spawns real syncs and runs ~2.5s in isolation, on this // tree and on a clean baseline alike. That is half of bun's 5s default, but full diff --git a/tests/codex-convergence-contract.test.ts b/tests/codex-integration/codex-convergence-contract.test.ts similarity index 94% rename from tests/codex-convergence-contract.test.ts rename to tests/codex-integration/codex-convergence-contract.test.ts index 98e9d97b95..db37963095 100644 --- a/tests/codex-convergence-contract.test.ts +++ b/tests/codex-integration/codex-convergence-contract.test.ts @@ -15,32 +15,33 @@ import { import { tmpdir } from "node:os"; import { join, relative } from "node:path"; -import { captureCatalogAdmissionSnapshot } from "../src/codex/catalog-admission"; +import { captureCatalogAdmissionSnapshot } from "../../src/codex/catalog-admission"; import { commitCodexCatalogCandidate, gatherCodexCatalogCandidate, type CodexCatalogCandidate, -} from "../src/codex/convergence"; -import { CODEX_NATIVE_ALIAS_CATALOG_KIND, resetCatalogRuntimeStateForTests } from "../src/codex/catalog"; +} from "../../src/codex/convergence"; +import { CODEX_NATIVE_ALIAS_CATALOG_KIND, resetCatalogRuntimeStateForTests } from "../../src/codex/catalog"; import { persistCodexRuntime, resetCodexRuntimeResolveCacheForTests, setCodexRuntimeResolveCacheForTests, -} from "../src/codex/runtime"; +} from "../../src/codex/runtime"; import { invalidateBundledCatalogCache, setBundledCatalogCacheForTests, -} from "../src/codex/catalog/bundled"; +} from "../../src/codex/catalog/bundled"; import { resolveCodexCatalogSerializationDatabasePath, resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import { saveConfig } from "../src/config"; -import { handleManagementAPI } from "../src/server/management-api"; -import type { OcxConfig } from "../src/types"; -import { ManagementRequest } from "./helpers/management-auth"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/user-identity"; +import { saveConfig } from "../../src/config"; +import { handleManagementAPI } from "../../src/server/management-api"; +import type { OcxConfig } from "../../src/types"; +import { ManagementRequest } from "../helpers/management-auth"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath } from "../helpers/repo-root"; let root = ""; let codexHome = ""; @@ -380,7 +381,7 @@ test("the route inventory contains exactly the specified 8 + 14 + 2 + 2 converge ["combo-routes.ts", 2], ["agent-settings-routes.ts", 2], ].map(([file, expected]) => { - const source = readFileSync(join(import.meta.dir, "..", "src", "server", "management", file as string), "utf8"); + const source = readFileSync(repoPath("src", "server", "management", file as string), "utf8"); const count = source.match(/await convergeCodexCatalog\(\)/g)?.length ?? 0; expect(count).toBe(expected); expect(source).not.toContain("refreshCodexCatalogBestEffort"); @@ -395,7 +396,7 @@ test("the route inventory contains exactly the specified 8 + 14 + 2 + 2 converge }); test("both model-discovery write paths converge the Codex catalog", () => { - const source = readFileSync(join(import.meta.dir, "..", "src", "server", "management", "model-routes.ts"), "utf8"); + const source = readFileSync(repoPath("src", "server", "management", "model-routes.ts"), "utf8"); const settings = source.slice(source.indexOf('url.pathname === "/api/model-discovery" && req.method === "PUT"'), source.indexOf('url.pathname === "/api/model-discovery/acknowledge"')); // Sliced to the NEXT route rather than to /api/catalog: the alias routes (#2463) landed // between them, so a fixed far boundary would swallow their convergence calls and count @@ -406,7 +407,7 @@ test("both model-discovery write paths converge the Codex catalog", () => { }); test("all three alias write routes converge the Codex catalog", () => { - const source = readFileSync(join(import.meta.dir, "..", "src", "server", "management", "model-routes.ts"), "utf8"); + const source = readFileSync(repoPath("src", "server", "management", "model-routes.ts"), "utf8"); for (const marker of ["providerAliasMatch && req.method", "modelAliasMatch && req.method", 'url.pathname === "/api/default-aliases"']) { const start = source.indexOf(marker); expect(start).toBeGreaterThan(-1); @@ -426,7 +427,7 @@ test("all three alias write routes converge the Codex catalog", () => { */ test("both model-preset write paths converge the Codex catalog", () => { const source = readFileSync( - join(import.meta.dir, "..", "src", "server", "management", "model-routes.ts"), + repoPath("src", "server", "management", "model-routes.ts"), "utf8", ); const handlerStart = source.indexOf('url.pathname === "/api/model-presets" && req.method === "PUT"'); @@ -447,7 +448,7 @@ test("both model-preset write paths converge the Codex catalog", () => { */ test("the attested reload route converges the Codex catalog like the other write paths", () => { const source = readFileSync( - join(import.meta.dir, "..", "src", "server", "management", "provider-routes.ts"), + repoPath("src", "server", "management", "provider-routes.ts"), "utf8", ); const handlerStart = source.indexOf("LOCAL_PROVIDER_RELOAD_PATH && req.method === \"POST\""); @@ -465,7 +466,7 @@ test("the attested reload route converges the Codex catalog like the other write */ test("the atomic provider batch route converges the Codex catalog once", () => { const source = readFileSync( - join(import.meta.dir, "..", "src", "server", "management", "provider-routes.ts"), + repoPath("src", "server", "management", "provider-routes.ts"), "utf8", ); const handlerStart = source.indexOf('url.pathname === "/api/providers" && req.method === "PUT"'); diff --git a/tests/codex-cooldown-recovery.test.ts b/tests/codex-integration/codex-cooldown-recovery.test.ts similarity index 98% rename from tests/codex-cooldown-recovery.test.ts rename to tests/codex-integration/codex-cooldown-recovery.test.ts index 1fc6fcaf41..a196adcfe8 100644 --- a/tests/codex-cooldown-recovery.test.ts +++ b/tests/codex-integration/codex-cooldown-recovery.test.ts @@ -6,8 +6,8 @@ import { clearAccountQuota, runCodexCooldownRecoveryProbes, seedCodexAuthAdmissionForTests, -} from "../src/codex/auth-api"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; +} from "../../src/codex/auth-api"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; import { codexQuotaWindowForPlan, getAccountQuota, @@ -15,17 +15,17 @@ import { parseUsageQuota, setAccountQuotaFromParsed, updateAccountQuota, -} from "../src/codex/quota"; -import upstreamModels from "../src/codex/data/upstream-models.json"; +} from "../../src/codex/quota"; +import upstreamModels from "../../src/codex/data/upstream-models.json"; import { CODEX_QUOTA_PROBE_INTERVAL_MS, clearCodexUpstreamHealth, getCodexQuotaHealthSnapshot, recordCodexUpstreamOutcome, resolveCodexAccountForThread, -} from "../src/codex/routing"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/routing"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-codex-cooldown-recovery-test"); const TEST_CODEX_HOME = join(TEST_DIR, "codex"); diff --git a/tests/codex-coordinator-doctor.test.ts b/tests/codex-integration/codex-coordinator-doctor.test.ts similarity index 96% rename from tests/codex-coordinator-doctor.test.ts rename to tests/codex-integration/codex-coordinator-doctor.test.ts index 531a73f214..acbf312ca2 100644 --- a/tests/codex-coordinator-doctor.test.ts +++ b/tests/codex-integration/codex-coordinator-doctor.test.ts @@ -8,20 +8,20 @@ import { Database } from "bun:sqlite"; import { inspectCodexCoordinator, recoverZeroByteCodexCoordinator, -} from "../src/codex/coordinator-doctor"; +} from "../../src/codex/coordinator-doctor"; import { codexWriteCoordinationEligibility, STABLE_ZERO_BYTE_COORDINATOR_AGE_MS, -} from "../src/codex/inject-coordination"; +} from "../../src/codex/inject-coordination"; import { openCodexCoordinatorTransaction, -} from "../src/codex/transition-state"; +} from "../../src/codex/transition-state"; import { resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import { formatCoordinatorDoctorLines } from "../src/cli/doctor"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/user-identity"; +import { formatCoordinatorDoctorLines } from "../../src/cli/doctor"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let codexHome = ""; let opencodexHome = ""; diff --git a/tests/codex-desired-state.test.ts b/tests/codex-integration/codex-desired-state.test.ts similarity index 98% rename from tests/codex-desired-state.test.ts rename to tests/codex-integration/codex-desired-state.test.ts index 43c82d6acc..92651f2293 100644 --- a/tests/codex-desired-state.test.ts +++ b/tests/codex-integration/codex-desired-state.test.ts @@ -12,7 +12,7 @@ import { mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { loadConfig, saveConfig } from "../src/config"; +import { loadConfig, saveConfig } from "../../src/config"; import { codexIntegrationEnabled, codexIntegrationEnabledNow, @@ -22,9 +22,9 @@ import { shouldSyncCodexOnStart, shouldSyncGrokOnStart, syncCodexOnStartIfEnabled, -} from "../src/codex/desired-state"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/desired-state"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testRoot = ""; let previousOpencodexHome: string | undefined; diff --git a/tests/codex-envkey-admission-substitution.test.ts b/tests/codex-integration/codex-envkey-admission-substitution.test.ts similarity index 95% rename from tests/codex-envkey-admission-substitution.test.ts rename to tests/codex-integration/codex-envkey-admission-substitution.test.ts index 32fe999cdf..cb1a0853d1 100644 --- a/tests/codex-envkey-admission-substitution.test.ts +++ b/tests/codex-integration/codex-envkey-admission-substitution.test.ts @@ -2,20 +2,20 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; -import { startServer } from "../src/server"; -import type { OcxConfig } from "../src/types"; -import { getDebugLogEntries, resetDebugLogBufferForTests } from "../src/lib/debug-log-buffer"; -import { resetDebugSettingsForTests, setDebugSettings } from "../src/lib/debug-settings"; -import { waitForNativeMainStartupGate } from "../src/codex/native-profile-startup"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { saveConfig } from "../../src/config"; +import { startServer } from "../../src/server"; +import type { OcxConfig } from "../../src/types"; +import { getDebugLogEntries, resetDebugLogBufferForTests } from "../../src/lib/debug-log-buffer"; +import { resetDebugSettingsForTests, setDebugSettings } from "../../src/lib/debug-settings"; +import { waitForNativeMainStartupGate } from "../../src/codex/native-profile-startup"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * #1686 end to end: a Codex client injected with `env_key` presents the proxy admission * secret as `Authorization: Bearer`. Direct must ADMIT that request and substitute the * stored main credential; the admission secret must never appear upstream. * - * The unit matrix in tests/codex-auth-context.test.ts proves the materializer in isolation. + * The unit matrix in tests/codex-integration/codex-auth-context.test.ts proves the materializer in isolation. * It cannot prove the HTTP handler passes the presentation source down to it, which is the * half that was missing: the source was resolved at the door and dropped one frame later. */ diff --git a/tests/codex-exec-invocation.test.ts b/tests/codex-integration/codex-exec-invocation.test.ts similarity index 96% rename from tests/codex-exec-invocation.test.ts rename to tests/codex-integration/codex-exec-invocation.test.ts index ace665fa17..bb632b505f 100644 --- a/tests/codex-exec-invocation.test.ts +++ b/tests/codex-integration/codex-exec-invocation.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { escapeCmdArg, escapeCmdCommand } from "../src/lib/win-exec"; -import { codexExecInvocation, isSpawnableCodexCandidate } from "../src/codex/catalog"; +import { escapeCmdArg, escapeCmdCommand } from "../../src/lib/win-exec"; +import { codexExecInvocation, isSpawnableCodexCandidate } from "../../src/codex/catalog"; describe("codexExecInvocation", () => { test("routes Windows .cmd/.bat through ComSpec with escaped args (no shell:true)", () => { diff --git a/tests/codex-features-cache.test.ts b/tests/codex-integration/codex-features-cache.test.ts similarity index 94% rename from tests/codex-features-cache.test.ts rename to tests/codex-integration/codex-features-cache.test.ts index 4b802a7149..8f748689fa 100644 --- a/tests/codex-features-cache.test.ts +++ b/tests/codex-integration/codex-features-cache.test.ts @@ -7,12 +7,12 @@ import { MODE_HINT_CAPABILITY_CACHE_MAX_ENTRIES, modeHintCapabilityCache, probeCodexSupportsModeHint, -} from "../src/codex/features"; +} from "../../src/codex/features"; import { resetCodexRuntimeResolveCacheForTests, setCodexRuntimeResolveCacheForTests, -} from "../src/codex/runtime"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/runtime"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-features-residual.test.ts b/tests/codex-integration/codex-features-residual.test.ts similarity index 86% rename from tests/codex-features-residual.test.ts rename to tests/codex-integration/codex-features-residual.test.ts index 737be1a6fe..ecef951406 100644 --- a/tests/codex-features-residual.test.ts +++ b/tests/codex-integration/codex-features-residual.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { isAtomicResidualError } from "../src/codex/features"; -import { AtomicWriteResidualTempError, AtomicWriteSecretResidualError } from "../src/config"; +import { isAtomicResidualError } from "../../src/codex/features"; +import { AtomicWriteResidualTempError, AtomicWriteSecretResidualError } from "../../src/config"; describe("migration memo release gate", () => { test("both residual classes retain the destination memo", () => { diff --git a/tests/codex-filesystem-evidence.test.ts b/tests/codex-integration/codex-filesystem-evidence.test.ts similarity index 95% rename from tests/codex-filesystem-evidence.test.ts rename to tests/codex-integration/codex-filesystem-evidence.test.ts index 74c3552e90..39bfe9ca58 100644 --- a/tests/codex-filesystem-evidence.test.ts +++ b/tests/codex-integration/codex-filesystem-evidence.test.ts @@ -13,11 +13,11 @@ import { import { tmpdir } from "node:os"; import { join } from "node:path"; -import { captureCatalogAdmissionSnapshot } from "../src/codex/catalog-admission"; +import { captureCatalogAdmissionSnapshot } from "../../src/codex/catalog-admission"; import { resetBundledCatalogCacheForTests, resolveCatalogSourceForGather, -} from "../src/codex/catalog/bundled"; +} from "../../src/codex/catalog/bundled"; import { acceptCatalogGatherSourcePath, captureAndSealCatalogHomeSelection, @@ -26,11 +26,11 @@ import { readCatalogGatherSource, sealCatalogGatherEvidenceSession, type CatalogGatherProviderAuthEvidence, -} from "../src/codex/catalog/filesystem-evidence"; -import type { CatalogSourceEvidence } from "../src/codex/convergence-types"; -import { saveConfig } from "../src/config"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/catalog/filesystem-evidence"; +import type { CatalogSourceEvidence } from "../../src/codex/convergence-types"; +import { saveConfig } from "../../src/config"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; interface ManifestEntry { readonly path: string; diff --git a/tests/codex-gather-authority.test.ts b/tests/codex-integration/codex-gather-authority.test.ts similarity index 97% rename from tests/codex-gather-authority.test.ts rename to tests/codex-integration/codex-gather-authority.test.ts index 5b9724971e..ae3204a0a7 100644 --- a/tests/codex-gather-authority.test.ts +++ b/tests/codex-integration/codex-gather-authority.test.ts @@ -4,12 +4,12 @@ import { createHash } from "node:crypto"; import { clearGatherRoutedModelsInflight, gatherRoutedModels, -} from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { PROVIDER_REGISTRY, type ProviderModelDiscoverySpec } from "../src/providers/registry"; -import type { OcxConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import { withRegistryDiscovery } from "./helpers/provider-registry-discovery"; +} from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { PROVIDER_REGISTRY, type ProviderModelDiscoverySpec } from "../../src/providers/registry"; +import type { OcxConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { withRegistryDiscovery } from "../helpers/provider-registry-discovery"; const originalFetch = globalThis.fetch; diff --git a/tests/codex-history-job.test.ts b/tests/codex-integration/codex-history-job.test.ts similarity index 98% rename from tests/codex-history-job.test.ts rename to tests/codex-integration/codex-history-job.test.ts index 210f3c5123..219575e045 100644 --- a/tests/codex-history-job.test.ts +++ b/tests/codex-integration/codex-history-job.test.ts @@ -11,8 +11,9 @@ import { describeHistoryJobFailure, deriveCodexHistoryOperation, runCodexHistoryJob, -} from "../src/codex/history-job"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/history-job"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; const sandboxes: string[] = []; let previousCodexHome: string | undefined; @@ -284,7 +285,7 @@ test("a hard history error reaches the caller with its real message", async () = * must leave it tagged, and the default must restore its exact original tuple. */ test("the synchronous restore body is gated on skipHistory", () => { - const repoRoot = join(import.meta.dir, ".."); + const repoRoot = resolveRepoRoot(); const root = mkdtempSync(join(tmpdir(), "ocx-restore-skiphistory-")); const fixtureCodexHome = join(root, ".codex"); const fixtureOcxHome = join(root, ".opencodex"); diff --git a/tests/codex-history-lock.test.ts b/tests/codex-integration/codex-history-lock.test.ts similarity index 96% rename from tests/codex-history-lock.test.ts rename to tests/codex-integration/codex-history-lock.test.ts index 63ba943e04..b752b60e53 100644 --- a/tests/codex-history-lock.test.ts +++ b/tests/codex-integration/codex-history-lock.test.ts @@ -8,10 +8,11 @@ import { isHistoryWritePermitLive, withHistoryWriteSerialization, type HistoryWritePermit, -} from "../src/codex/history-lock"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/history-lock"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; -const repoRoot = resolve(import.meta.dir, ".."); +const repoRoot = resolveRepoRoot(); const sandboxes: string[] = []; interface Sandbox { diff --git a/tests/codex-history-provider.test.ts b/tests/codex-integration/codex-history-provider.test.ts similarity index 99% rename from tests/codex-history-provider.test.ts rename to tests/codex-integration/codex-history-provider.test.ts index 1fd083e138..fbc97238de 100644 --- a/tests/codex-history-provider.test.ts +++ b/tests/codex-integration/codex-history-provider.test.ts @@ -3,8 +3,8 @@ import { tmpdir } from "node:os"; import { join } from "node:path"; import { Database } from "bun:sqlite"; import { afterEach, describe, expect, setDefaultTimeout, test } from "bun:test"; -import { classifyRecoverableHistoryError, countPendingOpencodexHistory, historyBackupPathFor, isRecoverableHistoryError, migrateHistoryToOpenai, restoreLegacyOpenaiHistory, restoredUserEventFor, setAfterNoopPendingCountForTests, setAfterStrictHistoryRolloutAppendForTests, setBeforeHistoryApplyTransactionForTests, setBeforeHistoryBackupConsumeForTests, setBeforeStrictHistoryRolloutAppendForTests, setHistoryDbBusyTimeoutForTests, snapshotCodexHistoryNoop, syncCodexHistoryProvider, withHistoryRetry } from "../src/codex/history-provider"; -import { INVALID_HISTORY_BACKUP_FIXTURES, validHistoryBackupFixture } from "./helpers/codex-history-manifest-fixtures"; +import { classifyRecoverableHistoryError, countPendingOpencodexHistory, historyBackupPathFor, isRecoverableHistoryError, migrateHistoryToOpenai, restoreLegacyOpenaiHistory, restoredUserEventFor, setAfterNoopPendingCountForTests, setAfterStrictHistoryRolloutAppendForTests, setBeforeHistoryApplyTransactionForTests, setBeforeHistoryBackupConsumeForTests, setBeforeStrictHistoryRolloutAppendForTests, setHistoryDbBusyTimeoutForTests, snapshotCodexHistoryNoop, syncCodexHistoryProvider, withHistoryRetry } from "../../src/codex/history-provider"; +import { INVALID_HISTORY_BACKUP_FIXTURES, validHistoryBackupFixture } from "../helpers/codex-history-manifest-fixtures"; // Windows CI: a transient file lock can consume the full production 5s busy timeout, tripping // bun's 5s default per-test timeout by itself. Fail fast into withHistoryRetry instead. diff --git a/tests/codex-history-reachability.test.ts b/tests/codex-integration/codex-history-reachability.test.ts similarity index 98% rename from tests/codex-history-reachability.test.ts rename to tests/codex-integration/codex-history-reachability.test.ts index af95102ac7..553049da4d 100644 --- a/tests/codex-history-reachability.test.ts +++ b/tests/codex-integration/codex-history-reachability.test.ts @@ -1,6 +1,7 @@ import { expect, test } from "bun:test"; import { readFileSync, readdirSync, statSync } from "node:fs"; import { join, relative, resolve } from "node:path"; +import { repoPath } from "../helpers/repo-root"; /** * Who may reach a history writer, checked by walking imports rather than counting @@ -15,7 +16,7 @@ import { join, relative, resolve } from "node:path"; * mutates the database, the manifest and the rollouts; only `history-worker.ts` * runs inside H, so only it may reach those symbols. */ -const SRC = resolve(import.meta.dir, "..", "src"); +const SRC = repoPath("src"); /** Modules whose exports mutate Codex history. */ const HISTORY_WRITER = "codex/internal/history-writer.ts"; diff --git a/tests/codex-history-worker-boundary.test.ts b/tests/codex-integration/codex-history-worker-boundary.test.ts similarity index 96% rename from tests/codex-history-worker-boundary.test.ts rename to tests/codex-integration/codex-history-worker-boundary.test.ts index c2ea56cbb2..f92ff49442 100644 --- a/tests/codex-history-worker-boundary.test.ts +++ b/tests/codex-integration/codex-history-worker-boundary.test.ts @@ -11,8 +11,8 @@ import { mkdirSync, mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { runCodexHistoryJob } from "../src/codex/history-job"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { runCodexHistoryJob } from "../../src/codex/history-job"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let root = ""; let previousCodexHome: string | undefined; @@ -65,7 +65,7 @@ describe("the result validator", () => { // {requestId, type:"done"} with nothing else used to read as converged with // undefined rows. The module-level validator is the contract, exercised // through the job's own classification seam rather than a fabricated cast. - const { isPlausibleWorkerResultForTests } = await import("../src/codex/history-job"); + const { isPlausibleWorkerResultForTests } = await import("../../src/codex/history-job"); expect(isPlausibleWorkerResultForTests( { requestId: "r", type: "done" }, "r", "j", )).toBe(false); @@ -131,7 +131,7 @@ describe("the result validator", () => { }); test("blocked carries exactly its three reasons", async () => { - const { isPlausibleWorkerResultForTests } = await import("../src/codex/history-job"); + const { isPlausibleWorkerResultForTests } = await import("../../src/codex/history-job"); for (const reason of ["busy", "database", "unsafe-path"] as const) { expect(isPlausibleWorkerResultForTests( { requestId: "r", jobId: "j", type: "blocked", reason }, "r", "j", @@ -143,7 +143,7 @@ describe("the result validator", () => { }); test("the parent preserves partial progress from a valid worker error", async () => { - const { classifyWorkerResultForTests } = await import("../src/codex/history-job"); + const { classifyWorkerResultForTests } = await import("../../src/codex/history-job"); expect(classifyWorkerResultForTests({ requestId: "r", jobId: "j", diff --git a/tests/codex-history-worker.test.ts b/tests/codex-integration/codex-history-worker.test.ts similarity index 98% rename from tests/codex-history-worker.test.ts rename to tests/codex-integration/codex-history-worker.test.ts index c269947cdd..454efa72e5 100644 --- a/tests/codex-history-worker.test.ts +++ b/tests/codex-integration/codex-history-worker.test.ts @@ -5,20 +5,21 @@ import { dirname, join, resolve } from "node:path"; import { Database } from "bun:sqlite"; -import { historyBackupPathFor, setBeforeHistoryBackupConsumeForTests, setHistoryDbBusyTimeoutForTests } from "../src/codex/history-provider"; +import { historyBackupPathFor, setBeforeHistoryBackupConsumeForTests, setHistoryDbBusyTimeoutForTests } from "../../src/codex/history-provider"; import { isHistoryWorkerRunMessage, runHistoryUnitUnderLock, type HistoryWorkerRunMessage, -} from "../src/codex/history-worker"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/history-worker"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; // A held write lock otherwise costs the full production 5s busy timeout per // attempt, tripping bun's 5s default per-test timeout. setHistoryDbBusyTimeoutForTests(250); setDefaultTimeout(30_000); -const repoRoot = resolve(import.meta.dir, ".."); +const repoRoot = resolveRepoRoot(); const sandboxes: string[] = []; const backupArtifacts: string[] = []; diff --git a/tests/codex-history-writer.test.ts b/tests/codex-integration/codex-history-writer.test.ts similarity index 96% rename from tests/codex-history-writer.test.ts rename to tests/codex-integration/codex-history-writer.test.ts index 1c72aeeaa2..db8d672245 100644 --- a/tests/codex-history-writer.test.ts +++ b/tests/codex-integration/codex-history-writer.test.ts @@ -8,13 +8,13 @@ import { Database } from "bun:sqlite"; import { withHistoryWriteSerialization, type HistoryWritePermit, -} from "../src/codex/history-lock"; +} from "../../src/codex/history-lock"; import { writeHistoryProviderTransition, writeLegacyOpenaiHistoryRecovery, type HistoryWriteTarget, -} from "../src/codex/internal/history-writer"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/internal/history-writer"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const sandboxes: string[] = []; diff --git a/tests/codex-home-wsl.test.ts b/tests/codex-integration/codex-home-wsl.test.ts similarity index 93% rename from tests/codex-home-wsl.test.ts rename to tests/codex-integration/codex-home-wsl.test.ts index 2441776ece..671eb4a5a6 100644 --- a/tests/codex-home-wsl.test.ts +++ b/tests/codex-integration/codex-home-wsl.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { wslAutomountRoot, listWslWindowsCodexHomes } from "../src/codex/home"; -import { isWindowsInteropDir } from "../src/codex/shim"; -import { currentServiceHomes } from "../src/service"; +import { wslAutomountRoot, listWslWindowsCodexHomes } from "../../src/codex/home"; +import { isWindowsInteropDir } from "../../src/codex/shim"; +import { currentServiceHomes } from "../../src/service"; describe("wsl.conf automount root", () => { test("defaults to /mnt when wsl.conf is absent or silent", () => { diff --git a/tests/codex-inject-history-wording.test.ts b/tests/codex-integration/codex-inject-history-wording.test.ts similarity index 94% rename from tests/codex-inject-history-wording.test.ts rename to tests/codex-integration/codex-inject-history-wording.test.ts index ab867a6767..9a681f120f 100644 --- a/tests/codex-inject-history-wording.test.ts +++ b/tests/codex-integration/codex-inject-history-wording.test.ts @@ -5,13 +5,14 @@ import { resolve } from "node:path"; import { failedHistoryRestoreFromOutcome, formatApplyHistoryFailure, -} from "../src/codex/inject"; +} from "../../src/codex/inject"; +import { repoPath } from "../helpers/repo-root"; -const injectSource = readFileSync(resolve(import.meta.dir, "../src/codex/inject.ts"), "utf8"); -const doctorSource = readFileSync(resolve(import.meta.dir, "../src/cli/doctor.ts"), "utf8"); -const cliSource = readFileSync(resolve(import.meta.dir, "../src/cli/index.ts"), "utf8"); +const injectSource = readFileSync(repoPath("src/codex/inject.ts"), "utf8"); +const doctorSource = readFileSync(repoPath("src/cli/doctor.ts"), "utf8"); +const cliSource = readFileSync(repoPath("src/cli/index.ts"), "utf8"); const integrationGuide = readFileSync( - resolve(import.meta.dir, "../docs-site/src/content/docs/guides/codex-integration.md"), + repoPath("docs-site/src/content/docs/guides/codex-integration.md"), "utf8", ); diff --git a/tests/codex-inject-integration.test.ts b/tests/codex-integration/codex-inject-integration.test.ts similarity index 99% rename from tests/codex-inject-integration.test.ts rename to tests/codex-integration/codex-inject-integration.test.ts index 8c1ca474a2..3a5345098e 100644 --- a/tests/codex-inject-integration.test.ts +++ b/tests/codex-integration/codex-inject-integration.test.ts @@ -8,11 +8,11 @@ import { Database } from "bun:sqlite"; import { MANAGED_AGENTS_TABLE_MARKER, MANAGED_SUBAGENT_DEFAULT_MARKER, -} from "../src/codex/subagent-defaults"; -import { SPAWN_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/subagent-defaults"; +import { SPAWN_BUDGET_MS } from "../helpers/test-budget"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); setDefaultTimeout(SPAWN_BUDGET_MS); diff --git a/tests/codex-inject-write-lock.test.ts b/tests/codex-integration/codex-inject-write-lock.test.ts similarity index 98% rename from tests/codex-inject-write-lock.test.ts rename to tests/codex-integration/codex-inject-write-lock.test.ts index 044c60b1c8..824e75f21f 100644 --- a/tests/codex-inject-write-lock.test.ts +++ b/tests/codex-integration/codex-inject-write-lock.test.ts @@ -14,17 +14,18 @@ import { join } from "node:path"; import { resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; +} from "../../src/codex/user-identity"; import { boundProvenanceEntries, CODEX_PROVENANCE_MAX_BYTES, CODEX_PROVENANCE_MAX_TRANSACTIONS, STABLE_ZERO_BYTE_COORDINATOR_AGE_MS, -} from "../src/codex/inject-coordination"; -import { SPAWN_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/inject-coordination"; +import { SPAWN_BUDGET_MS } from "../helpers/test-budget"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; -const repoRoot = join(import.meta.dir, ".."); +const repoRoot = resolveRepoRoot(); const CHILD = join(repoRoot, "tests", "helpers", "codex-inject-race-child.ts"); const LOCK_CHILD = join(repoRoot, "tests", "helpers", "codex-write-lock-child.ts"); // Leave teardown and assertion headroom inside the surrounding test budget. A real diff --git a/tests/codex-inject.test.ts b/tests/codex-integration/codex-inject.test.ts similarity index 99% rename from tests/codex-inject.test.ts rename to tests/codex-integration/codex-inject.test.ts index 4133d333bc..84ac5f67b6 100644 --- a/tests/codex-inject.test.ts +++ b/tests/codex-integration/codex-inject.test.ts @@ -12,12 +12,12 @@ import { stripOpencodexConfig, stripRootContextWindowOverrides, standaloneCodexRoutingTarget, -} from "../src/codex/inject"; -import { stripJournaledOpenaiBaseUrl } from "../src/codex/injected-marker"; +} from "../../src/codex/inject"; +import { stripJournaledOpenaiBaseUrl } from "../../src/codex/injected-marker"; import { MANAGED_AGENTS_TABLE_MARKER, MANAGED_SUBAGENT_DEFAULT_MARKER, -} from "../src/codex/subagent-defaults"; +} from "../../src/codex/subagent-defaults"; describe("Codex config injection", () => { test("standalone routing-target wrappers remain byte-compatible", () => { diff --git a/tests/codex-injected-marker.test.ts b/tests/codex-integration/codex-injected-marker.test.ts similarity index 89% rename from tests/codex-injected-marker.test.ts rename to tests/codex-integration/codex-injected-marker.test.ts index 2d4dee47de..84f892fbf3 100644 --- a/tests/codex-injected-marker.test.ts +++ b/tests/codex-integration/codex-injected-marker.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { providerTableString, rootTomlString } from "../src/codex/injected-marker"; +import { providerTableString, rootTomlString } from "../../src/codex/injected-marker"; describe("Codex injected marker TOML strings", () => { test("decodes escaped basic strings", () => { diff --git a/tests/codex-integration-record.test.ts b/tests/codex-integration/codex-integration-record.test.ts similarity index 97% rename from tests/codex-integration-record.test.ts rename to tests/codex-integration/codex-integration-record.test.ts index e9e87550ec..dce96985af 100644 --- a/tests/codex-integration-record.test.ts +++ b/tests/codex-integration/codex-integration-record.test.ts @@ -5,14 +5,14 @@ import { join } from "node:path"; import { readIntegrationRecord, updateIntegrationRecord, -} from "../src/codex/integration-record"; -import { boundProvenanceEntries } from "../src/codex/inject-coordination"; +} from "../../src/codex/integration-record"; +import { boundProvenanceEntries } from "../../src/codex/inject-coordination"; import type { CodexArtifactId, CodexIntegrationRecord, CodexProvenanceEntry, -} from "../src/codex/convergence-types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/convergence-types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let opencodexHome = ""; let previousOpencodexHome: string | undefined; diff --git a/tests/codex-journal.test.ts b/tests/codex-integration/codex-journal.test.ts similarity index 98% rename from tests/codex-journal.test.ts rename to tests/codex-integration/codex-journal.test.ts index 847f298f08..3b46be997a 100644 --- a/tests/codex-journal.test.ts +++ b/tests/codex-integration/codex-journal.test.ts @@ -8,11 +8,11 @@ import { fileURLToPath } from "node:url"; import { MANAGED_AGENTS_TABLE_MARKER, MANAGED_SUBAGENT_DEFAULT_MARKER, -} from "../src/codex/subagent-defaults"; -import { SPAWN_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/subagent-defaults"; +import { SPAWN_BUDGET_MS } from "../helpers/test-budget"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); setDefaultTimeout(SPAWN_BUDGET_MS); @@ -544,7 +544,7 @@ describe("codex-journal", () => { /** * The reachable case a "replace only when a journal exists" gate would miss: * an injected config with NO journal, which is exactly where the legacy upgrade - * path in tests/codex-inject-integration.test.ts starts. + * path in tests/codex-integration/codex-inject-integration.test.ts starts. */ test("an injected config with no journal is never captured as the original (#477)", () => { const injected = [ diff --git a/tests/codex-log-guard-coderabbit.test.ts b/tests/codex-integration/codex-log-guard-coderabbit.test.ts similarity index 97% rename from tests/codex-log-guard-coderabbit.test.ts rename to tests/codex-integration/codex-log-guard-coderabbit.test.ts index 307eb8058b..2b79bb7d5f 100644 --- a/tests/codex-log-guard-coderabbit.test.ts +++ b/tests/codex-integration/codex-log-guard-coderabbit.test.ts @@ -4,14 +4,14 @@ import { mkdirSync, mkdtempSync, realpathSync, symlinkSync, writeFileSync } from import { tmpdir } from "node:os"; import { join } from "node:path"; -import { codexLogGuardLockDigest } from "../src/codex/log-guard/lock"; -import { sameLogGuardPathIdentity } from "../src/codex/log-guard/path-safety"; +import { codexLogGuardLockDigest } from "../../src/codex/log-guard/lock"; +import { sameLogGuardPathIdentity } from "../../src/codex/log-guard/path-safety"; import { getCodexLogGuardProtectionStatus, protectCodexLogs, unprotectCodexLogs, -} from "../src/codex/log-guard/protection"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/log-guard/protection"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-log-guard-doctor-coderabbit.test.ts b/tests/codex-integration/codex-log-guard-doctor-coderabbit.test.ts similarity index 90% rename from tests/codex-log-guard-doctor-coderabbit.test.ts rename to tests/codex-integration/codex-log-guard-doctor-coderabbit.test.ts index 036708d4a0..7dc0637afe 100644 --- a/tests/codex-log-guard-doctor-coderabbit.test.ts +++ b/tests/codex-integration/codex-log-guard-doctor-coderabbit.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { formatCodexLogGuardDoctor } from "../src/cli/codex-log-guard-doctor"; -import type { CodexLogGuardStatus } from "../src/codex/log-guard/protection"; +import { formatCodexLogGuardDoctor } from "../../src/cli/codex-log-guard-doctor"; +import type { CodexLogGuardStatus } from "../../src/codex/log-guard/protection"; function status(schema: CodexLogGuardStatus["schema"]): CodexLogGuardStatus { const supported = schema.state === "compatible"; diff --git a/tests/codex-log-guard-doctor-protection.test.ts b/tests/codex-integration/codex-log-guard-doctor-protection.test.ts similarity index 94% rename from tests/codex-log-guard-doctor-protection.test.ts rename to tests/codex-integration/codex-log-guard-doctor-protection.test.ts index 7d4c0d18d4..43f1556bb8 100644 --- a/tests/codex-log-guard-doctor-protection.test.ts +++ b/tests/codex-integration/codex-log-guard-doctor-protection.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { formatCodexLogGuardDoctor, printCodexLogGuardDoctor } from "../src/cli/codex-log-guard-doctor"; -import type { CodexLogGuardStatus } from "../src/codex/log-guard/protection"; +import { formatCodexLogGuardDoctor, printCodexLogGuardDoctor } from "../../src/cli/codex-log-guard-doctor"; +import type { CodexLogGuardStatus } from "../../src/codex/log-guard/protection"; function status(state: CodexLogGuardStatus["protection"]): CodexLogGuardStatus { return { diff --git a/tests/codex-log-guard-doctor.test.ts b/tests/codex-integration/codex-log-guard-doctor.test.ts similarity index 97% rename from tests/codex-log-guard-doctor.test.ts rename to tests/codex-integration/codex-log-guard-doctor.test.ts index de9be399d0..7a7c29188c 100644 --- a/tests/codex-log-guard-doctor.test.ts +++ b/tests/codex-integration/codex-log-guard-doctor.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { formatCodexLogGuardDoctor, printCodexLogGuardDoctor } from "../src/cli/codex-log-guard-doctor"; -import type { CodexLogGuardInspection } from "../src/codex/log-guard/inspect"; +import { formatCodexLogGuardDoctor, printCodexLogGuardDoctor } from "../../src/cli/codex-log-guard-doctor"; +import type { CodexLogGuardInspection } from "../../src/codex/log-guard/inspect"; function report(overrides: Partial = {}): CodexLogGuardInspection { return { diff --git a/tests/codex-log-guard-inspect.test.ts b/tests/codex-integration/codex-log-guard-inspect.test.ts similarity index 99% rename from tests/codex-log-guard-inspect.test.ts rename to tests/codex-integration/codex-log-guard-inspect.test.ts index 3c3538eb51..063a64a605 100644 --- a/tests/codex-log-guard-inspect.test.ts +++ b/tests/codex-integration/codex-log-guard-inspect.test.ts @@ -14,8 +14,8 @@ import { import { tmpdir } from "node:os"; import { join } from "node:path"; -import { inspectCodexLogs, resetCodexLogGuardInspectionCache } from "../src/codex/log-guard/inspect"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { inspectCodexLogs, resetCodexLogGuardInspectionCache } from "../../src/codex/log-guard/inspect"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-log-guard-lock.test.ts b/tests/codex-integration/codex-log-guard-lock.test.ts similarity index 88% rename from tests/codex-log-guard-lock.test.ts rename to tests/codex-integration/codex-log-guard-lock.test.ts index bd7e1b7a2a..c1f72ebf54 100644 --- a/tests/codex-log-guard-lock.test.ts +++ b/tests/codex-integration/codex-log-guard-lock.test.ts @@ -3,8 +3,8 @@ import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { withCodexLogGuardLock } from "../src/codex/log-guard/lock"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { withCodexLogGuardLock } from "../../src/codex/log-guard/lock"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-log-guard-maintenance-coderabbit.test.ts b/tests/codex-integration/codex-log-guard-maintenance-coderabbit.test.ts similarity index 98% rename from tests/codex-log-guard-maintenance-coderabbit.test.ts rename to tests/codex-integration/codex-log-guard-maintenance-coderabbit.test.ts index 32edb54706..54e83bba2a 100644 --- a/tests/codex-log-guard-maintenance-coderabbit.test.ts +++ b/tests/codex-integration/codex-log-guard-maintenance-coderabbit.test.ts @@ -13,8 +13,8 @@ import { join } from "node:path"; import { compactCodexLogs, type CodexLogGuardMaintenanceDeps, -} from "../src/codex/log-guard/maintenance"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/log-guard/maintenance"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-log-guard-maintenance.test.ts b/tests/codex-integration/codex-log-guard-maintenance.test.ts similarity index 91% rename from tests/codex-log-guard-maintenance.test.ts rename to tests/codex-integration/codex-log-guard-maintenance.test.ts index 53afbc43e1..dfeec4194f 100644 --- a/tests/codex-log-guard-maintenance.test.ts +++ b/tests/codex-integration/codex-log-guard-maintenance.test.ts @@ -3,7 +3,7 @@ import { Database } from "bun:sqlite"; import { mkdirSync, mkdtempSync, statSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; @@ -122,7 +122,7 @@ afterEach(() => { describe("Codex Log Guard reclaim", () => { test("incrementally reclaims freelist pages while preserving every logical row and trigger", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); expect(mod).not.toBeNull(); if (!mod) return; @@ -146,7 +146,7 @@ describe("Codex Log Guard reclaim", () => { }); test("is a safe no-op when there is nothing reclaimable", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); expect(mod).not.toBeNull(); if (!mod) return; @@ -159,7 +159,7 @@ describe("Codex Log Guard reclaim", () => { }); test("refuses databases that are not already auto_vacuum=INCREMENTAL", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); expect(mod).not.toBeNull(); if (!mod) return; @@ -175,7 +175,7 @@ describe("Codex Log Guard reclaim", () => { }); test("refuses unknown log schemas before maintenance", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); expect(mod).not.toBeNull(); if (!mod) return; @@ -191,7 +191,7 @@ describe("Codex Log Guard reclaim", () => { }); test("fails closed when Codex is running or process enumeration is uncertain", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); expect(mod).not.toBeNull(); if (!mod) return; @@ -208,7 +208,7 @@ describe("Codex Log Guard reclaim", () => { }); test("fails closed when the Log Guard lock is busy", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); expect(mod).not.toBeNull(); if (!mod) return; const { codexHome } = fixture(); @@ -218,7 +218,7 @@ describe("Codex Log Guard reclaim", () => { }); test("requires quick_check before changing any pages", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); expect(mod).not.toBeNull(); if (!mod) return; const { codexHome, databasePath } = fixture(); @@ -238,7 +238,7 @@ describe("Codex Log Guard reclaim", () => { }); test("reports a post-maintenance quick_check failure explicitly", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); expect(mod).not.toBeNull(); if (!mod) return; const { codexHome } = fixture(); @@ -256,7 +256,7 @@ describe("Codex Log Guard reclaim", () => { }); test("stops at the per-run page budget and reports remaining work", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); expect(mod).not.toBeNull(); if (!mod) return; const { codexHome } = fixture(); @@ -273,7 +273,7 @@ describe("Codex Log Guard reclaim", () => { expect(result.report.after.freelistPages).toBeGreaterThan(0); }); test("derives batch budgets from the real page size, not a fixed page count", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); if (!mod) return; // The guide promises ~8 MiB batches and ~256 MiB per run, converted with the // database's page size. Fixed page counts meant something different at every @@ -291,7 +291,7 @@ describe("Codex Log Guard reclaim", () => { }); test("reports logicalBytesReclaimed alongside the physical figure", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); if (!mod) return; // Documented before it existed. It is deliberately distinct from the // physical figure: an incremental vacuum can return pages to the free list diff --git a/tests/codex-log-guard-policy.test.ts b/tests/codex-integration/codex-log-guard-policy.test.ts similarity index 93% rename from tests/codex-log-guard-policy.test.ts rename to tests/codex-integration/codex-log-guard-policy.test.ts index 3f76d3f59d..5c85c7fd73 100644 --- a/tests/codex-log-guard-policy.test.ts +++ b/tests/codex-integration/codex-log-guard-policy.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { readCodexLogGuardMode, writeCodexLogGuardMode } from "../src/codex/log-guard/policy"; -import type { OcxConfig } from "../src/types"; +import { readCodexLogGuardMode, writeCodexLogGuardMode } from "../../src/codex/log-guard/policy"; +import type { OcxConfig } from "../../src/types"; describe("Codex Log Guard desired-state policy", () => { test("defaults missing or invalid modes to off", () => { diff --git a/tests/codex-log-guard-processes.test.ts b/tests/codex-integration/codex-log-guard-processes.test.ts similarity index 98% rename from tests/codex-log-guard-processes.test.ts rename to tests/codex-integration/codex-log-guard-processes.test.ts index b733a956c1..a2f42a07e9 100644 --- a/tests/codex-log-guard-processes.test.ts +++ b/tests/codex-integration/codex-log-guard-processes.test.ts @@ -3,7 +3,7 @@ import { describe, expect, test } from "bun:test"; import { isCodexWriterCommandLine, listRunningCodexProcesses, -} from "../src/codex/log-guard/processes"; +} from "../../src/codex/log-guard/processes"; describe("Codex Log Guard process gate", () => { test("matches official Codex writer command lines without broad codex substring matching", () => { diff --git a/tests/codex-log-guard-protection.test.ts b/tests/codex-integration/codex-log-guard-protection.test.ts similarity index 99% rename from tests/codex-log-guard-protection.test.ts rename to tests/codex-integration/codex-log-guard-protection.test.ts index d9dec0cf7a..1b2deee7f3 100644 --- a/tests/codex-log-guard-protection.test.ts +++ b/tests/codex-integration/codex-log-guard-protection.test.ts @@ -9,8 +9,8 @@ import { protectCodexLogs, repairCodexLogGuardProtection, unprotectCodexLogs, -} from "../src/codex/log-guard/protection"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/log-guard/protection"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-log-guard-status-zero-write.test.ts b/tests/codex-integration/codex-log-guard-status-zero-write.test.ts similarity index 96% rename from tests/codex-log-guard-status-zero-write.test.ts rename to tests/codex-integration/codex-log-guard-status-zero-write.test.ts index d11a7a104a..615ecf128e 100644 --- a/tests/codex-log-guard-status-zero-write.test.ts +++ b/tests/codex-integration/codex-log-guard-status-zero-write.test.ts @@ -4,8 +4,8 @@ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, statSync, wri import { tmpdir } from "node:os"; import { join } from "node:path"; -import { getCodexLogGuardProtectionStatus } from "../src/codex/log-guard/protection"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { getCodexLogGuardProtectionStatus } from "../../src/codex/log-guard/protection"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-main-account-refresh.test.ts b/tests/codex-integration/codex-main-account-refresh.test.ts similarity index 98% rename from tests/codex-main-account-refresh.test.ts rename to tests/codex-integration/codex-main-account-refresh.test.ts index d60beb0fb0..d1ae380795 100644 --- a/tests/codex-main-account-refresh.test.ts +++ b/tests/codex-integration/codex-main-account-refresh.test.ts @@ -5,9 +5,9 @@ import { join } from "node:path"; import { getValidMainAccountToken, setMainAuthJsonBeforeRenameHookForTests, -} from "../src/codex/main-account"; -import { codexCredentialMutationEpoch } from "../src/codex/credential-mutation-epoch"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/main-account"; +import { codexCredentialMutationEpoch } from "../../src/codex/credential-mutation-epoch"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let home: string; let previousCodexHome: string | undefined; diff --git a/tests/codex-main-rotation.test.ts b/tests/codex-integration/codex-main-rotation.test.ts similarity index 97% rename from tests/codex-main-rotation.test.ts rename to tests/codex-integration/codex-main-rotation.test.ts index 9f596da5a9..d8fa96db86 100644 --- a/tests/codex-main-rotation.test.ts +++ b/tests/codex-integration/codex-main-rotation.test.ts @@ -9,20 +9,20 @@ import { pickLowestUsageCodexAccount, recordCodexUpstreamOutcome, resolveCodexAccountForThread, -} from "../src/codex/routing"; +} from "../../src/codex/routing"; import { CodexPoolAuthenticationError, headersForCodexAuthContext, isCodexAuthContextUsable, resolveCodexAuthContext, -} from "../src/codex/auth-context"; -import { isCodexAccountUsable } from "../src/codex/account-usability"; +} from "../../src/codex/auth-context"; +import { isCodexAccountUsable } from "../../src/codex/account-usability"; import { reconcileMainCodexAccountRuntimeState, resetMainCodexAccountIdentityTrackingForTests, -} from "../src/codex/account-lifecycle"; -import { MAIN_CODEX_ACCOUNT_ID, setMainAccountPlan } from "../src/codex/main-account"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; +} from "../../src/codex/account-lifecycle"; +import { MAIN_CODEX_ACCOUNT_ID, setMainAccountPlan } from "../../src/codex/main-account"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; import { clearAccountNeedsReauth, clearAccountQuota, @@ -33,9 +33,9 @@ import { markAccountNeedsReauth, primeCodexPoolQuotas, updateAccountQuota, -} from "../src/codex/auth-api"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/auth-api"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const STORE_DIR = join(import.meta.dir, ".tmp-main-rotation-store"); const CODEX_DIR = join(import.meta.dir, ".tmp-main-rotation-codex"); diff --git a/tests/codex-management-convergence.test.ts b/tests/codex-integration/codex-management-convergence.test.ts similarity index 95% rename from tests/codex-management-convergence.test.ts rename to tests/codex-integration/codex-management-convergence.test.ts index 6f9df06da1..69a4303482 100644 --- a/tests/codex-management-convergence.test.ts +++ b/tests/codex-integration/codex-management-convergence.test.ts @@ -1,12 +1,12 @@ import { expect, test } from "bun:test"; -import { createCatalogConvergeRequest } from "../src/codex/catalog-admission"; +import { createCatalogConvergeRequest } from "../../src/codex/catalog-admission"; import { createManagementConvergeCodex, projectCatalogOnlyOutcome, -} from "../src/codex/management-convergence"; -import type { CatalogDisposition } from "../src/codex/convergence-types"; -import type { OcxConfig } from "../src/types"; +} from "../../src/codex/management-convergence"; +import type { CatalogDisposition } from "../../src/codex/convergence-types"; +import type { OcxConfig } from "../../src/types"; function config(): OcxConfig { return { port: 10100, providers: {}, defaultProvider: "openai" }; diff --git a/tests/codex-metadata-integrity.test.ts b/tests/codex-integration/codex-metadata-integrity.test.ts similarity index 95% rename from tests/codex-metadata-integrity.test.ts rename to tests/codex-integration/codex-metadata-integrity.test.ts index 4182770d38..79cdeea250 100644 --- a/tests/codex-metadata-integrity.test.ts +++ b/tests/codex-integration/codex-metadata-integrity.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { FORWARD_HEADERS, createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../src/adapters/openai-responses"; -import { headersForCodexAuthContext } from "../src/codex/auth-context"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { FORWARD_HEADERS, createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../../src/adapters/openai-responses"; +import { headersForCodexAuthContext } from "../../src/codex/auth-context"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; const createResponsesPassthroughAdapter = (...args: Parameters) => withTestTranslatorBudget(createResponsesPassthroughAdapterProduction(...args)); diff --git a/tests/codex-model-entitlements.test.ts b/tests/codex-integration/codex-model-entitlements.test.ts similarity index 99% rename from tests/codex-model-entitlements.test.ts rename to tests/codex-integration/codex-model-entitlements.test.ts index 9ca38fb9a5..219ec7dcc8 100644 --- a/tests/codex-model-entitlements.test.ts +++ b/tests/codex-integration/codex-model-entitlements.test.ts @@ -24,21 +24,21 @@ import { seedCodexModelEntitlementsForTests, type CodexModelEntitlementCredentialSnapshot, type CodexModelEntitlementState, -} from "../src/codex/model-entitlements"; +} from "../../src/codex/model-entitlements"; import { forceRefreshMainAccountToken, MAIN_CODEX_ACCOUNT_ID, -} from "../src/codex/main-account"; +} from "../../src/codex/main-account"; import { readCodexAccountRecord, saveCodexAccountCredential, -} from "../src/codex/account-store"; -import { clearCodexRuntimeResolveCache, loadPersistedCodexRuntime } from "../src/codex/runtime"; -import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../src/codex/catalog/native-models"; -import upstreamModelsSnapshot from "../src/codex/data/upstream-models.json"; -import { readCodexAccountRecord, saveCodexAccountCredential } from "../src/codex/account-store"; -import { installIsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/account-store"; +import { clearCodexRuntimeResolveCache, loadPersistedCodexRuntime } from "../../src/codex/runtime"; +import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../../src/codex/catalog/native-models"; +import upstreamModelsSnapshot from "../../src/codex/data/upstream-models.json"; +import { readCodexAccountRecord, saveCodexAccountCredential } from "../../src/codex/account-store"; +import { installIsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_CLIENT_VERSION = "0.146.0"; const DAYBREAK = "gpt-daybreak-blue-latest"; @@ -1084,7 +1084,7 @@ describe("entitlement client version (#2886)", () => { // been resolved, no persisted runtime either — yet it is the path that publishes // account-confirmed native rows. An earlier revision of this fix skipped discovery in // that state, which suppressed exactly the rows the fix exists to restore - // (tests/claude-integration/claude-models-discovery.test.ts and tests/codex-catalog-sync-hardening.test.ts + // (tests/claude-integration/claude-models-discovery.test.ts and tests/codex-integration/codex-catalog-sync-hardening.test.ts // both failed on it). The last tier therefore has to be a real, answerable version. expect(resolveCodexEntitlementClientVersion(null, () => null)) .toBe(GATED_MODEL_CLIENT_VERSION_FLOOR); diff --git a/tests/codex-models-cache-invalidate.test.ts b/tests/codex-integration/codex-models-cache-invalidate.test.ts similarity index 95% rename from tests/codex-models-cache-invalidate.test.ts rename to tests/codex-integration/codex-models-cache-invalidate.test.ts index cd222a8f51..3efb316511 100644 --- a/tests/codex-models-cache-invalidate.test.ts +++ b/tests/codex-integration/codex-models-cache-invalidate.test.ts @@ -2,14 +2,14 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { invalidateCodexModelsCache } from "../src/codex/catalog"; -import { invalidateCodexModelsCacheWithPermit } from "../src/codex/catalog/sync"; -import { withCatalogWriteSerialization } from "../src/codex/catalog-write-serialization"; -import { afterCatalogWriteHandleAppServers } from "../src/codex/app-server-processes"; -import { refreshCodexModelCatalog } from "../src/codex/refresh"; -import { syncModelsToCodex } from "../src/codex/sync"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { invalidateCodexModelsCache } from "../../src/codex/catalog"; +import { invalidateCodexModelsCacheWithPermit } from "../../src/codex/catalog/sync"; +import { withCatalogWriteSerialization } from "../../src/codex/catalog-write-serialization"; +import { afterCatalogWriteHandleAppServers } from "../../src/codex/app-server-processes"; +import { refreshCodexModelCatalog } from "../../src/codex/refresh"; +import { syncModelsToCodex } from "../../src/codex/sync"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const emptyConfig = { port: 10100, diff --git a/tests/codex-native-residue.test.ts b/tests/codex-integration/codex-native-residue.test.ts similarity index 98% rename from tests/codex-native-residue.test.ts rename to tests/codex-integration/codex-native-residue.test.ts index 61b9759355..07dcffe46a 100644 --- a/tests/codex-native-residue.test.ts +++ b/tests/codex-integration/codex-native-residue.test.ts @@ -21,17 +21,17 @@ import { buildCatalogEntries, readCodexCatalogPath, syncCatalogModels, -} from "../src/codex/catalog"; -import { buildProfileFile } from "../src/codex/inject"; -import { classifyNativeRoutedResidue } from "../src/codex/native-residue"; -import { readCodexTransitionState } from "../src/codex/transition-state"; +} from "../../src/codex/catalog"; +import { buildProfileFile } from "../../src/codex/inject"; +import { classifyNativeRoutedResidue } from "../../src/codex/native-residue"; +import { readCodexTransitionState } from "../../src/codex/transition-state"; import { resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import type { OcxConfig } from "../src/types"; -import { INVALID_HISTORY_BACKUP_FIXTURES, validHistoryBackupFixture } from "./helpers/codex-history-manifest-fixtures"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/user-identity"; +import type { OcxConfig } from "../../src/types"; +import { INVALID_HISTORY_BACKUP_FIXTURES, validHistoryBackupFixture } from "../helpers/codex-history-manifest-fixtures"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let codexHome = ""; let opencodexHome = ""; diff --git a/tests/codex-plan.test.ts b/tests/codex-integration/codex-plan.test.ts similarity index 95% rename from tests/codex-plan.test.ts rename to tests/codex-integration/codex-plan.test.ts index c4bf31fa2c..df02a8167e 100644 --- a/tests/codex-plan.test.ts +++ b/tests/codex-integration/codex-plan.test.ts @@ -1,16 +1,16 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, writeFileSync } from "node:fs"; import { join } from "node:path"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { getMainAccountPlan, setMainAccountPlan } from "../src/codex/main-account"; -import { extractChatgptPlanType } from "../src/codex/plan"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { getMainAccountPlan, setMainAccountPlan } from "../../src/codex/main-account"; +import { extractChatgptPlanType } from "../../src/codex/plan"; import { reconcileCodexPlansFromTokens, resetJwtPlanNotesForTests, -} from "../src/codex/plan-from-token"; -import { loadConfig, saveConfig } from "../src/config"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/plan-from-token"; +import { loadConfig, saveConfig } from "../../src/config"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-codex-plan-test"); const TEST_CODEX_HOME = join(TEST_DIR, "codex"); @@ -202,7 +202,7 @@ describe("WHAM-wins plan provenance gate (release-audit fix)", () => { describe("rotated-JWT plan reconciliation across propagated aliases (#2892 gap 3)", () => { test("a plan-changing rotated JWT reconciles the alias, not just the refresh owner", async () => { - const { getValidCodexToken, readCodexAccountRecord } = await import("../src/codex/account-store"); + const { getValidCodexToken, readCodexAccountRecord } = await import("../../src/codex/account-store"); const oldJwt = chatgptPlanJwt("plus"); const shared = { refreshToken: "plan-grant", expiresAt: 0, chatgptAccountId: "acct" }; saveCodexAccountCredential("plan-owner", { accessToken: oldJwt, ...shared }); diff --git a/tests/codex-plugins-doctor.test.ts b/tests/codex-integration/codex-plugins-doctor.test.ts similarity index 98% rename from tests/codex-plugins-doctor.test.ts rename to tests/codex-integration/codex-plugins-doctor.test.ts index 939d31c783..ce47b8c4c5 100644 --- a/tests/codex-plugins-doctor.test.ts +++ b/tests/codex-integration/codex-plugins-doctor.test.ts @@ -4,10 +4,10 @@ import { mkdtempSync, mkdirSync, readdirSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import { diagnoseCodexBundledPlugins, locateCurrentBundledMarketplace } from "../src/codex/plugins-doctor"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { diagnoseCodexBundledPlugins, locateCurrentBundledMarketplace } from "../../src/codex/plugins-doctor"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); const cliPath = join(repoRoot, "src", "cli", "index.ts"); function makeConfig(body: string): { dir: string; configPath: string } { diff --git a/tests/codex-pool-rotation.test.ts b/tests/codex-integration/codex-pool-rotation.test.ts similarity index 98% rename from tests/codex-pool-rotation.test.ts rename to tests/codex-integration/codex-pool-rotation.test.ts index 5fed0251e0..1a69a0e269 100644 --- a/tests/codex-pool-rotation.test.ts +++ b/tests/codex-integration/codex-pool-rotation.test.ts @@ -7,14 +7,14 @@ import { peekRoundRobinAccount, pickRoundRobinAccount, selectPriorityTier, -} from "../src/codex/pool-rotation"; +} from "../../src/codex/pool-rotation"; import { clearCodexAccountPin, codexAccountPriorityLookup, forgetCodexAccountPriority, getCodexAccountPriority, setCodexAccountPriority, -} from "../src/codex/account-priority"; +} from "../../src/codex/account-priority"; import { clearCodexUpstreamHealth, clearThreadAccountMap, @@ -26,16 +26,16 @@ import { recordCodexUpstreamOutcome, resetCodexRoutingForManualSelection, resolveCodexAccountForThread, -} from "../src/codex/routing"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/account-id"; -import { clearAccountQuota, updateAccountQuota } from "../src/codex/auth-api"; -import { getConfigPath } from "../src/config"; -import type { OcxConfig } from "../src/types"; +} from "../../src/codex/routing"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/account-id"; +import { clearAccountQuota, updateAccountQuota } from "../../src/codex/auth-api"; +import { getConfigPath } from "../../src/config"; +import type { OcxConfig } from "../../src/types"; import { existsSync, mkdirSync, rmSync } from "node:fs"; import { join } from "node:path"; import { describe, expect, test, beforeEach, afterEach } from "bun:test"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-codex-pool-rotation-test"); let previousOpencodexHome: string | undefined; diff --git a/tests/codex-prompt-adopt.test.ts b/tests/codex-integration/codex-prompt-adopt.test.ts similarity index 98% rename from tests/codex-prompt-adopt.test.ts rename to tests/codex-integration/codex-prompt-adopt.test.ts index f750a8f10c..7bffd6dedc 100644 --- a/tests/codex-prompt-adopt.test.ts +++ b/tests/codex-integration/codex-prompt-adopt.test.ts @@ -16,8 +16,8 @@ import { previewSalvage, readPromptLayers, salvageProjection, -} from "../src/codex/prompt-layers"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/prompt-layers"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const MARKER = "# Auto-injected by opencodex"; const roots: string[] = []; diff --git a/tests/codex-prompt-base-variants.test.ts b/tests/codex-integration/codex-prompt-base-variants.test.ts similarity index 98% rename from tests/codex-prompt-base-variants.test.ts rename to tests/codex-integration/codex-prompt-base-variants.test.ts index 935c75d9ec..e80be5391e 100644 --- a/tests/codex-prompt-base-variants.test.ts +++ b/tests/codex-integration/codex-prompt-base-variants.test.ts @@ -13,8 +13,8 @@ import { readPromptLayers, selectBaseVariant, writeBaseVariant, -} from "../src/codex/prompt-layers"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/prompt-layers"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-prompt-journal.test.ts b/tests/codex-integration/codex-prompt-journal.test.ts similarity index 98% rename from tests/codex-prompt-journal.test.ts rename to tests/codex-integration/codex-prompt-journal.test.ts index 3d04f1e24d..7034c6da06 100644 --- a/tests/codex-prompt-journal.test.ts +++ b/tests/codex-integration/codex-prompt-journal.test.ts @@ -19,14 +19,14 @@ import { recoverIfNeeded, sameRecoveryPath, type JournalRecord, -} from "../src/codex/prompt-journal"; +} from "../../src/codex/prompt-journal"; import { hardenedSecretPathCountForTests, resetHardenedStateForTests, setIcaclsRunnerForTests, setPlatformForTests, -} from "../src/lib/windows-secret-acl"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/lib/windows-secret-acl"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-prompt-layers-read.test.ts b/tests/codex-integration/codex-prompt-layers-read.test.ts similarity index 98% rename from tests/codex-prompt-layers-read.test.ts rename to tests/codex-integration/codex-prompt-layers-read.test.ts index 54af244f7d..7d74628d49 100644 --- a/tests/codex-prompt-layers-read.test.ts +++ b/tests/codex-integration/codex-prompt-layers-read.test.ts @@ -13,8 +13,8 @@ import { inspectOwnership, parseStore, readPromptLayers, -} from "../src/codex/prompt-layers"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/prompt-layers"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const MARKER = "# Auto-injected by opencodex"; const roots: string[] = []; diff --git a/tests/codex-prompt-layers-write.test.ts b/tests/codex-integration/codex-prompt-layers-write.test.ts similarity index 99% rename from tests/codex-prompt-layers-write.test.ts rename to tests/codex-integration/codex-prompt-layers-write.test.ts index 103ba9496c..09c7d6da09 100644 --- a/tests/codex-prompt-layers-write.test.ts +++ b/tests/codex-integration/codex-prompt-layers-write.test.ts @@ -12,13 +12,13 @@ import { setToggle, writeCustomLayers, type CustomLayer, -} from "../src/codex/prompt-layers"; +} from "../../src/codex/prompt-layers"; import { encodeJournal, hashBytes, type JournalRecord, -} from "../src/codex/prompt-journal"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/prompt-journal"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const MARKER = "# Auto-injected by opencodex"; const roots: string[] = []; diff --git a/tests/codex-prompt-layers.test.ts b/tests/codex-integration/codex-prompt-layers.test.ts similarity index 99% rename from tests/codex-prompt-layers.test.ts rename to tests/codex-integration/codex-prompt-layers.test.ts index 64e715ab26..fa95b7c3df 100644 --- a/tests/codex-prompt-layers.test.ts +++ b/tests/codex-integration/codex-prompt-layers.test.ts @@ -17,7 +17,7 @@ import { findInvalidCharacter, isToggleId, normalizeBody, -} from "../src/codex/prompt-layers"; +} from "../../src/codex/prompt-layers"; /** TOML basic-string grammar, hand-written so it does not share code with the encoder. */ const BASIC_STRING = /^"(?:[^"\\\u0000-\u001f]|\\["\\bfnrt]|\\u[0-9A-Fa-f]{4})*"$/; diff --git a/tests/codex-prompt-lock.test.ts b/tests/codex-integration/codex-prompt-lock.test.ts similarity index 98% rename from tests/codex-prompt-lock.test.ts rename to tests/codex-integration/codex-prompt-lock.test.ts index dcd9d46cd3..b2ff4741a3 100644 --- a/tests/codex-prompt-lock.test.ts +++ b/tests/codex-integration/codex-prompt-lock.test.ts @@ -17,8 +17,8 @@ import { stillHeld, tryAcquire, type LockDeps, -} from "../src/codex/prompt-lock"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/prompt-lock"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-prompt-route.test.ts b/tests/codex-integration/codex-prompt-route.test.ts similarity index 98% rename from tests/codex-prompt-route.test.ts rename to tests/codex-integration/codex-prompt-route.test.ts index 8b13007b33..f69dd8ea2d 100644 --- a/tests/codex-prompt-route.test.ts +++ b/tests/codex-integration/codex-prompt-route.test.ts @@ -10,16 +10,16 @@ import { afterEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; -import { handleManagementAPI } from "../src/server/management-api"; -import { LAYER_INVENTORY, readPromptLayers } from "../src/codex/prompt-layers"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { LAYER_INVENTORY, readPromptLayers } from "../../src/codex/prompt-layers"; import { promptTextProbeSpawnAttemptsForTests, resetPromptTextProbeForTests, setPromptTextProbeCommandForTests, -} from "../src/codex/prompt-text-probe"; -import type { ManagementPrincipal } from "../src/server/management-auth"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/prompt-text-probe"; +import type { ManagementPrincipal } from "../../src/server/management-auth"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const MARKER = "# Auto-injected by opencodex"; const config = { port: 10100, defaultProvider: "openai", providers: {} } as OcxConfig; @@ -470,7 +470,7 @@ describe("dispatch and safety", () => { test("20. every mapped write error carries a client-facing status", async () => { // A TypeScript union does not exist at runtime, so exhaustiveness is a // typecheck property of Record. This asserts the values. - const { WRITE_ERROR_STATUS_FOR_TESTS } = await import("../src/server/management/codex-prompt-routes"); + const { WRITE_ERROR_STATUS_FOR_TESTS } = await import("../../src/server/management/codex-prompt-routes"); const statuses = Object.values(WRITE_ERROR_STATUS_FOR_TESTS); expect(statuses.length).toBeGreaterThanOrEqual(10); for (const status of statuses) expect(status).toBeGreaterThanOrEqual(400); @@ -598,7 +598,7 @@ describe("020 coverage completions", () => { test("20d. each write error keeps its exact status, not merely a 4xx", async () => { // A range assertion would still pass if unknown_layer silently became a 409. - const { WRITE_ERROR_STATUS_FOR_TESTS } = await import("../src/server/management/codex-prompt-routes"); + const { WRITE_ERROR_STATUS_FOR_TESTS } = await import("../../src/server/management/codex-prompt-routes"); expect(WRITE_ERROR_STATUS_FOR_TESTS).toEqual({ config_unreadable: 409, stale_revision: 409, @@ -803,12 +803,12 @@ describe("020 coverage completions", () => { // A cwd parameter let an authenticated request read any readable folder's // AGENTS.md through the dashboard, and described a prompt from wherever the // caller pointed rather than the configuration this page reports on. - const source = await Bun.file(new URL("../src/server/management/codex-prompt-routes.ts", import.meta.url)).text(); + const source = await Bun.file(new URL("../../src/server/management/codex-prompt-routes.ts", import.meta.url)).text(); const textRoute = source.slice(source.indexOf("/api/codex-prompt/text")); expect(textRoute).not.toContain("searchParams.get(\"cwd\")"); expect(textRoute.slice(0, 900)).not.toContain("process.cwd()"); - const probe = await Bun.file(new URL("../src/codex/prompt-text-probe.ts", import.meta.url)).text(); + const probe = await Bun.file(new URL("../../src/codex/prompt-text-probe.ts", import.meta.url)).text(); // The probe resolves CODEX_HOME itself; it must not accept a directory. expect(probe).toContain("resolveCodexHomeDir()"); expect(probe).toMatch(/export async function probePromptText\(\s*timeoutMs/); @@ -817,7 +817,7 @@ describe("020 coverage completions", () => { test("26. the probe is bounded in bytes as well as in time", async () => { // A 15-second window with no output ceiling let a noisy binary balloon the // server. Both bounds must exist, and the process must settle exactly once. - const probe = await Bun.file(new URL("../src/codex/prompt-text-probe.ts", import.meta.url)).text(); + const probe = await Bun.file(new URL("../../src/codex/prompt-text-probe.ts", import.meta.url)).text(); expect(probe).toContain("MAX_PROBE_OUTPUT_BYTES"); expect(probe).toContain("if (settled) return;"); // Decoding per chunk corrupts UTF-8 that straddles a chunk boundary. diff --git a/tests/codex-prompt-text-probe.test.ts b/tests/codex-integration/codex-prompt-text-probe.test.ts similarity index 99% rename from tests/codex-prompt-text-probe.test.ts rename to tests/codex-integration/codex-prompt-text-probe.test.ts index cf3252543b..f9c70e1729 100644 --- a/tests/codex-prompt-text-probe.test.ts +++ b/tests/codex-integration/codex-prompt-text-probe.test.ts @@ -17,8 +17,8 @@ import { resetPromptTextProbeForTests, setPromptTextProbeCloseBarrierForTests, setPromptTextProbeCommandForTests, -} from "../src/codex/prompt-text-probe"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/prompt-text-probe"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const lifecycleRoots: string[] = []; const VALID_PROBE_OUTPUT = JSON.stringify([{ diff --git a/tests/codex-quota-parser-parity.test.ts b/tests/codex-integration/codex-quota-parser-parity.test.ts similarity index 98% rename from tests/codex-quota-parser-parity.test.ts rename to tests/codex-integration/codex-quota-parser-parity.test.ts index 1f909f4f4e..172168ada8 100644 --- a/tests/codex-quota-parser-parity.test.ts +++ b/tests/codex-integration/codex-quota-parser-parity.test.ts @@ -4,8 +4,8 @@ import { parseUpstreamQuotaHeaders, parseUsageQuota, setAccountQuotaFromParsed, -} from "../src/codex/quota"; -import { codexPoolQuotaEvidence } from "../src/routing/quota"; +} from "../../src/codex/quota"; +import { codexPoolQuotaEvidence } from "../../src/routing/quota"; /** * The two quota parsers, pinned against each other. diff --git a/tests/codex-quota-prime.test.ts b/tests/codex-integration/codex-quota-prime.test.ts similarity index 98% rename from tests/codex-quota-prime.test.ts rename to tests/codex-integration/codex-quota-prime.test.ts index 2e2f446945..94a605d5f2 100644 --- a/tests/codex-quota-prime.test.ts +++ b/tests/codex-integration/codex-quota-prime.test.ts @@ -11,29 +11,29 @@ import { clearMainAccountInfoCache, seedCodexAuthAdmissionForTests, setCodexPoolQuotaTokenResolverForTests, -} from "../src/codex/auth-api"; +} from "../../src/codex/auth-api"; import { CodexCredentialGenerationConflictError, CodexCredentialRefreshLockTimeoutError, readCodexAccountRecord, saveCodexAccountCredential, -} from "../src/codex/account-store"; -import { resetMainCodexAccountIdentityTrackingForTests } from "../src/codex/account-lifecycle"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/main-account"; +} from "../../src/codex/account-store"; +import { resetMainCodexAccountIdentityTrackingForTests } from "../../src/codex/account-lifecycle"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/main-account"; import { completeNativeMainRecovery, initializeNativeMainStartupGate, -} from "../src/codex/native-profile-startup"; -import { handleNativeProfileAPI } from "../src/codex/native-profile-api"; -import type { NativeProfileManager } from "../src/codex/native-profile-manager"; -import { resolveCodexAccountForThread, clearThreadAccountMap } from "../src/codex/routing"; +} from "../../src/codex/native-profile-startup"; +import { handleNativeProfileAPI } from "../../src/codex/native-profile-api"; +import type { NativeProfileManager } from "../../src/codex/native-profile-manager"; +import { resolveCodexAccountForThread, clearThreadAccountMap } from "../../src/codex/routing"; import { acquireNativeMainProfileDrain, getNativeMainProfileRequestCount, resetLifecycleDrainStateForTests, -} from "../src/server/lifecycle"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/server/lifecycle"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; // Phase 20 (260630_wsl-account-autoswitch): startup/lazy quota priming. diff --git a/tests/codex-quota-rejection.test.ts b/tests/codex-integration/codex-quota-rejection.test.ts similarity index 98% rename from tests/codex-quota-rejection.test.ts rename to tests/codex-integration/codex-quota-rejection.test.ts index 7cf0310c01..1183cac607 100644 --- a/tests/codex-quota-rejection.test.ts +++ b/tests/codex-integration/codex-quota-rejection.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { classifyCodexPreStreamRejection } from "../src/codex/quota-rejection"; -import { BOUNDED_BODY_MAX_BYTES } from "../src/lib/bounded-body"; -import { shouldRetryCodexPoolAccountQuota } from "../src/server/responses/core"; +import { classifyCodexPreStreamRejection } from "../../src/codex/quota-rejection"; +import { BOUNDED_BODY_MAX_BYTES } from "../../src/lib/bounded-body"; +import { shouldRetryCodexPoolAccountQuota } from "../../src/server/responses/core"; function jsonRejection(status: number, error: Record): Response { return Response.json({ error }, { status }); diff --git a/tests/codex-refresh.test.ts b/tests/codex-integration/codex-refresh.test.ts similarity index 97% rename from tests/codex-refresh.test.ts rename to tests/codex-integration/codex-refresh.test.ts index 4000eb9e7c..d31add73ca 100644 --- a/tests/codex-refresh.test.ts +++ b/tests/codex-integration/codex-refresh.test.ts @@ -2,10 +2,10 @@ import { afterEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { invalidateCodexModelsCache, syncCatalogModels } from "../src/codex/catalog"; -import { refreshCodexModelCatalog } from "../src/codex/refresh"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { invalidateCodexModelsCache, syncCatalogModels } from "../../src/codex/catalog"; +import { refreshCodexModelCatalog } from "../../src/codex/refresh"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const config = { port: 10100, diff --git a/tests/codex-reset-credit-auto-redeem.test.ts b/tests/codex-integration/codex-reset-credit-auto-redeem.test.ts similarity index 98% rename from tests/codex-reset-credit-auto-redeem.test.ts rename to tests/codex-integration/codex-reset-credit-auto-redeem.test.ts index 21f651eef9..f19f208cc1 100644 --- a/tests/codex-reset-credit-auto-redeem.test.ts +++ b/tests/codex-integration/codex-reset-credit-auto-redeem.test.ts @@ -7,8 +7,8 @@ import { planAutoRedeem, resolveResetCreditAutoRedeemSettings, type ResetCredit, -} from "../src/codex/reset-credit-auto-redeem"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/reset-credit-auto-redeem"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const T0 = Date.parse("2026-09-02T10:00:00Z"); const MIN = 60_000; diff --git a/tests/codex-reset-credit-operation-ledger.test.ts b/tests/codex-integration/codex-reset-credit-operation-ledger.test.ts similarity index 99% rename from tests/codex-reset-credit-operation-ledger.test.ts rename to tests/codex-integration/codex-reset-credit-operation-ledger.test.ts index e5eaf39ac6..d47c3cdc97 100644 --- a/tests/codex-reset-credit-operation-ledger.test.ts +++ b/tests/codex-integration/codex-reset-credit-operation-ledger.test.ts @@ -8,8 +8,8 @@ import { NestedConfigMutationError, prepareConfigMutationDatabasePathForWrite, withConfigMutationLockSync, -} from "../src/config"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/account-id"; +} from "../../src/config"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/account-id"; import { MAX_MANUAL_RESET_CREDIT_OPERATION_IDS, MAX_RESET_CREDIT_OPERATION_ACCOUNTS, @@ -21,12 +21,13 @@ import { settleManualResetCreditOperation, settleResetCreditOperation, type ManualResetCreditOperationIdentity, -} from "../src/codex/reset-credit-operation-ledger"; +} from "../../src/codex/reset-credit-operation-ledger"; import { compareCodexResetCreditRecoveryGenerationOrder, isCodexResetCreditOperationId, type CodexResetCreditRecoveryGeneration, -} from "../src/codex/reset-credit-recovery"; +} from "../../src/codex/reset-credit-recovery"; +import { repoRoot } from "../helpers/repo-root"; const GENERATION: CodexResetCreditRecoveryGeneration = { accountId: "pool-a", @@ -1192,7 +1193,7 @@ describe("Codex reset-credit operation ledger", () => { writeFileSync(process.env.OCX_LEDGER_READY_PATH, "ready"); while (true) Bun.sleepSync(50); `], { - cwd: join(import.meta.dir, ".."), + cwd: repoRoot(), env: { ...process.env, OCX_LEDGER_DB_PATH: databasePath(), diff --git a/tests/codex-reset-credit-recovery.test.ts b/tests/codex-integration/codex-reset-credit-recovery.test.ts similarity index 99% rename from tests/codex-reset-credit-recovery.test.ts rename to tests/codex-integration/codex-reset-credit-recovery.test.ts index d26f8ec9ad..27919163a7 100644 --- a/tests/codex-reset-credit-recovery.test.ts +++ b/tests/codex-integration/codex-reset-credit-recovery.test.ts @@ -11,8 +11,8 @@ import { type CodexResetCreditRecoveryDependencies, type CodexResetCreditRecoveryGeneration, type CodexResetCreditRevalidationResult, -} from "../src/codex/reset-credit-recovery"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/account-id"; +} from "../../src/codex/reset-credit-recovery"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/account-id"; const BASE_GENERATION: CodexResetCreditRecoveryGeneration = { accountId: "account-a", diff --git a/tests/codex-restart-contract-parity.test.ts b/tests/codex-integration/codex-restart-contract-parity.test.ts similarity index 97% rename from tests/codex-restart-contract-parity.test.ts rename to tests/codex-integration/codex-restart-contract-parity.test.ts index 0545c9395b..cb9435c32c 100644 --- a/tests/codex-restart-contract-parity.test.ts +++ b/tests/codex-integration/codex-restart-contract-parity.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { performCodexRestart, resetCodexRestartInFlightForTests } from "../src/codex/app-server-restart-service"; -import { isCodexRestartResponse } from "../src/lib/codex-restart-contract"; +import { performCodexRestart, resetCodexRestartInFlightForTests } from "../../src/codex/app-server-restart-service"; +import { isCodexRestartResponse } from "../../src/lib/codex-restart-contract"; /** * The GUI rejects a response that fails isCodexRestartResponse, so an invariant diff --git a/tests/codex-restart-route.test.ts b/tests/codex-integration/codex-restart-route.test.ts similarity index 92% rename from tests/codex-restart-route.test.ts rename to tests/codex-integration/codex-restart-route.test.ts index 94351c4713..f917c83a33 100644 --- a/tests/codex-restart-route.test.ts +++ b/tests/codex-integration/codex-restart-route.test.ts @@ -3,24 +3,24 @@ * * The service seam is injected through ManagementApiDeps so this suite never * enumerates or signals a real process. Service-level branch coverage lives in - * tests/codex-app-server-restart-service.test.ts. + * tests/codex-integration/codex-app-server-restart-service.test.ts. * * Plan: devlog/_fin/260815_gui_codex_restart/010_phase1_backend_endpoint.md */ import { describe, expect, test } from "bun:test"; -import { handleSystemRoutes } from "../src/server/management/system-routes"; -import type { ManagementContext } from "../src/server/management/context"; +import { handleSystemRoutes } from "../../src/server/management/system-routes"; +import type { ManagementContext } from "../../src/server/management/context"; import { CODEX_APP_SERVER_STATE_PATH, CODEX_RESTART_PATH, isCodexAppServerStateResponse, isCodexRestartResponse, -} from "../src/lib/codex-restart-contract"; +} from "../../src/lib/codex-restart-contract"; import type { CodexAppServerStateResponse, CodexRestartResponse, -} from "../src/lib/codex-restart-contract"; -import { loadConfig } from "../src/config"; +} from "../../src/lib/codex-restart-contract"; +import { loadConfig } from "../../src/config"; const STOPPED: CodexRestartResponse = { success: true, diff --git a/tests/codex-restore-app-rewrite.test.ts b/tests/codex-integration/codex-restore-app-rewrite.test.ts similarity index 98% rename from tests/codex-restore-app-rewrite.test.ts rename to tests/codex-integration/codex-restore-app-rewrite.test.ts index af24378a25..d81324960a 100644 --- a/tests/codex-restore-app-rewrite.test.ts +++ b/tests/codex-integration/codex-restore-app-rewrite.test.ts @@ -4,7 +4,7 @@ import { spawnSync } from "node:child_process"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * #1798: the Codex app rewrites config.toml AFTER injection, so the journal's @@ -18,7 +18,7 @@ import { removeTreeWithRetry } from "./helpers/remove-tree"; * reserializer would (values kept, comments gone), then restore. */ -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); /** Inject, simulate the app's comment-dropping rewrite, then restore. */ const INJECT_REWRITE_RESTORE = [ diff --git a/tests/codex-retained-root-serialization.test.ts b/tests/codex-integration/codex-retained-root-serialization.test.ts similarity index 99% rename from tests/codex-retained-root-serialization.test.ts rename to tests/codex-integration/codex-retained-root-serialization.test.ts index 5befb5b73c..b0c56bffbf 100644 --- a/tests/codex-retained-root-serialization.test.ts +++ b/tests/codex-integration/codex-retained-root-serialization.test.ts @@ -15,11 +15,12 @@ import { join, resolve } from "node:path"; import { resolveCodexCatalogSerializationDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import { claimOwnedServiceHome, withOwnedServiceHomePreload } from "./helpers/owned-service-home"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/user-identity"; +import { claimOwnedServiceHome, withOwnedServiceHomePreload } from "../helpers/owned-service-home"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; -const repoRoot = resolve(import.meta.dir, ".."); +const repoRoot = resolveRepoRoot(); const sandboxes: Sandbox[] = []; interface Sandbox { diff --git a/tests/codex-routing.test.ts b/tests/codex-integration/codex-routing.test.ts similarity index 99% rename from tests/codex-routing.test.ts rename to tests/codex-integration/codex-routing.test.ts index 8a27f92bd3..96ab4e75b9 100644 --- a/tests/codex-routing.test.ts +++ b/tests/codex-integration/codex-routing.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test, beforeEach, afterEach } from "bun:test"; import { existsSync, mkdirSync, writeFileSync } from "node:fs"; import { join } from "node:path"; -import { STORE_BUDGET_MS } from "./helpers/test-budget"; +import { STORE_BUDGET_MS } from "../helpers/test-budget"; import { CODEX_FAILURE_WINDOW_MS, CODEX_QUOTA_PROBE_INTERVAL_MS, @@ -32,10 +32,10 @@ import { resolveCodexAccountForThread, resolveCodexAccountForThreadDetailed, tryAcquireCodexQuotaProbeLease, -} from "../src/codex/routing"; -import { clearPoolRotationState } from "../src/codex/pool-rotation"; -import { captureConfigGeneration } from "../src/lib/state-store-sweeper"; -import { readCodexAccountRecord, removeCodexAccountCredential, saveCodexAccountCredential } from "../src/codex/account-store"; +} from "../../src/codex/routing"; +import { clearPoolRotationState } from "../../src/codex/pool-rotation"; +import { captureConfigGeneration } from "../../src/lib/state-store-sweeper"; +import { readCodexAccountRecord, removeCodexAccountCredential, saveCodexAccountCredential } from "../../src/codex/account-store"; import { clearAccountNeedsReauth, clearAccountQuota, @@ -45,14 +45,14 @@ import { parseUsageQuota, setAccountQuotaFromParsed, updateAccountQuota, -} from "../src/codex/auth-api"; -import { CODEX_UNKNOWN_USAGE_SCORE, isCodexQuotaExhausted } from "../src/codex/quota"; -import { setCodexAccountPriority } from "../src/codex/account-priority"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/main-account"; -import { routeModel } from "../src/router"; -import { consumeForInspection } from "../src/server/relay"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/auth-api"; +import { CODEX_UNKNOWN_USAGE_SCORE, isCodexQuotaExhausted } from "../../src/codex/quota"; +import { setCodexAccountPriority } from "../../src/codex/account-priority"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/main-account"; +import { routeModel } from "../../src/router"; +import { consumeForInspection } from "../../src/server/relay"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-codex-routing-test"); let previousOpencodexHome: string | undefined; @@ -686,7 +686,7 @@ describe("codex routing", () => { test("a sidecar 401 does not quarantine the credential that replaced it (#2892 gap 4 review)", async () => { - const { sidecarOutcomeRecorder } = await import("../src/server/responses/core"); + const { sidecarOutcomeRecorder } = await import("../../src/server/responses/core"); const config = makeConfig(); updateAccountQuota("a", 10); updateAccountQuota("b", 20); diff --git a/tests/codex-runtime.test.ts b/tests/codex-integration/codex-runtime.test.ts similarity index 99% rename from tests/codex-runtime.test.ts rename to tests/codex-integration/codex-runtime.test.ts index 55fbc2e066..2dc5d6347d 100644 --- a/tests/codex-runtime.test.ts +++ b/tests/codex-integration/codex-runtime.test.ts @@ -34,7 +34,7 @@ import { resetCodexRuntimeResolveCacheForTests, setCodexRuntimeResolveCacheForTests, type RuntimeExecFile, -} from "../src/codex/runtime"; +} from "../../src/codex/runtime"; import { bundledCatalogCacheState, invalidateBundledCatalogCache, @@ -43,7 +43,7 @@ import { resolveCatalogSourceForGather, setBundledCatalogCacheForTests, type CatalogGatherEvidenceSession, -} from "../src/codex/catalog/bundled"; +} from "../../src/codex/catalog/bundled"; function tempConfigDir(): string { return mkdtempSync(join(tmpdir(), "ocx-runtime-")); @@ -661,7 +661,7 @@ describe("resolveCodexRuntime", () => { const { loadBundledCodexCatalog, resetBundledCatalogCacheForTests, - } = await import("../src/codex/catalog/bundled"); + } = await import("../../src/codex/catalog/bundled"); const home = tempConfigDir(); const binDir = join(home, "bin"); @@ -813,7 +813,7 @@ describe("resolveCodexRuntime", () => { }); test("catalog clamp clears diagnostics inside deps.configDir when probe fails", async () => { - const { clampCatalogModelsToCodexSupport } = await import("../src/codex/catalog/effort"); + const { clampCatalogModelsToCodexSupport } = await import("../../src/codex/catalog/effort"); const nested = join(tempConfigDir(), "nested", "opencodex-home"); const configured = join(nested, "codex.exe"); persistEffortClamp({ @@ -844,7 +844,7 @@ describe("resolveCodexRuntime", () => { const { loadBundledCodexCatalog, resetBundledCatalogCacheForTests, - } = await import("../src/codex/catalog/bundled"); + } = await import("../../src/codex/catalog/bundled"); const home = tempConfigDir(); const oldDir = join(home, "old"); @@ -938,7 +938,7 @@ describe("resolveCodexRuntime", () => { }); test("clamp diagnostics include unsupported default_reasoning_level changes", async () => { - const { clampCatalogModelsToCodexSupport } = await import("../src/codex/catalog/effort"); + const { clampCatalogModelsToCodexSupport } = await import("../../src/codex/catalog/effort"); const diagnostics: Array<{ removedEfforts: string[]; affectedModels: string[] }> = []; const models = [{ slug: "openrouter/example", diff --git a/tests/codex-service-manager-probe-hardening.test.ts b/tests/codex-integration/codex-service-manager-probe-hardening.test.ts similarity index 98% rename from tests/codex-service-manager-probe-hardening.test.ts rename to tests/codex-integration/codex-service-manager-probe-hardening.test.ts index e353e50cff..2f9e3b6bfa 100644 --- a/tests/codex-service-manager-probe-hardening.test.ts +++ b/tests/codex-integration/codex-service-manager-probe-hardening.test.ts @@ -8,12 +8,12 @@ import { inspectServiceManagerInstallation, type ServiceManagerInstallation, type RawProbeRunner, -} from "../src/service-manager-probe"; -import { inspectNativeCodexOwnership } from "../src/integrations/native/ownership-preflight"; -import { setTrustedWindowsSystemDirectoryResolverForTests } from "../src/lib/windows-elevation"; -import { getDefaultConfig } from "../src/config"; -import { startServer } from "../src/server"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/service-manager-probe"; +import { inspectNativeCodexOwnership } from "../../src/integrations/native/ownership-preflight"; +import { setTrustedWindowsSystemDirectoryResolverForTests } from "../../src/lib/windows-elevation"; +import { getDefaultConfig } from "../../src/config"; +import { startServer } from "../../src/server"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let home = ""; let configDir = ""; diff --git a/tests/codex-service-manager-probe.test.ts b/tests/codex-integration/codex-service-manager-probe.test.ts similarity index 99% rename from tests/codex-service-manager-probe.test.ts rename to tests/codex-integration/codex-service-manager-probe.test.ts index 69232cc5fb..7d0dff0cba 100644 --- a/tests/codex-service-manager-probe.test.ts +++ b/tests/codex-integration/codex-service-manager-probe.test.ts @@ -16,10 +16,10 @@ import { inspectServiceManagerInstallation, type ProbeRunner, type RawProbeRunner, -} from "../src/service-manager-probe"; -import { inspectNativeCodexOwnership } from "../src/integrations/native/ownership-preflight"; -import { setTrustedWindowsSystemDirectoryResolverForTests } from "../src/lib/windows-elevation"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/service-manager-probe"; +import { inspectNativeCodexOwnership } from "../../src/integrations/native/ownership-preflight"; +import { setTrustedWindowsSystemDirectoryResolverForTests } from "../../src/lib/windows-elevation"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let home = ""; const cleanup: string[] = []; diff --git a/tests/codex-shim-autorestore.test.ts b/tests/codex-integration/codex-shim-autorestore.test.ts similarity index 94% rename from tests/codex-shim-autorestore.test.ts rename to tests/codex-integration/codex-shim-autorestore.test.ts index 6d2ac3110a..75562bbc56 100644 --- a/tests/codex-shim-autorestore.test.ts +++ b/tests/codex-integration/codex-shim-autorestore.test.ts @@ -3,15 +3,16 @@ import { spawnSync } from "node:child_process"; import { chmodSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import type { CodexShimAutoRestoreResult } from "../src/codex/shim"; -import { getDefaultConfig } from "../src/config"; +import type { CodexShimAutoRestoreResult } from "../../src/codex/shim"; +import { getDefaultConfig } from "../../src/config"; import { maybeAutoRestoreCodexShim, skipsCodexShimAutoRestore, type CodexShimAutoRestoreCliDeps, -} from "../src/cli/codex-shim-autorestore"; -import { autoRestoreCodexShim, CODEX_SHIM_STATE_MAX_BYTES, installCodexShim } from "../src/codex/shim"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/cli/codex-shim-autorestore"; +import { autoRestoreCodexShim, CODEX_SHIM_STATE_MAX_BYTES, installCodexShim } from "../../src/codex/shim"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath } from "../helpers/repo-root"; const SHIM_MARKER = "opencodex codex autostart shim"; @@ -154,7 +155,7 @@ describe("Codex shim CLI auto-restore policy", () => { const beforeState = readFileSync(statePath); const result = spawnSync(process.execPath, [ - join(import.meta.dir, "..", "src", "cli", "index.ts"), + repoPath("src", "cli", "index.ts"), "system", "codex-cli-update", "check", "--json", ], { encoding: "utf8", @@ -196,7 +197,7 @@ describe("Codex shim CLI auto-restore policy", () => { chmodSync(wrapper, 0o755); await Bun.sleep(120); - const result = spawnSync(process.execPath, [join(import.meta.dir, "..", "src", "cli", "index.ts"), "codex-shim", "status"], { + const result = spawnSync(process.execPath, [repoPath("src", "cli", "index.ts"), "codex-shim", "status"], { encoding: "utf8", env: { ...process.env, PATH: binDir, OPENCODEX_HOME: home }, }); diff --git a/tests/codex-shim-readiness.test.ts b/tests/codex-integration/codex-shim-readiness.test.ts similarity index 96% rename from tests/codex-shim-readiness.test.ts rename to tests/codex-integration/codex-shim-readiness.test.ts index 080f3a3e63..9780321d48 100644 --- a/tests/codex-shim-readiness.test.ts +++ b/tests/codex-integration/codex-shim-readiness.test.ts @@ -9,10 +9,10 @@ import { import { tmpdir } from "node:os"; import { delimiter, dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import { codexShimReadinessWarnings } from "../src/cli/codex-shim-readiness"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { codexShimReadinessWarnings } from "../../src/cli/codex-shim-readiness"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); const cliPath = join(repoRoot, "src", "cli", "index.ts"); const ready = { diff --git a/tests/codex-shim.test.ts b/tests/codex-integration/codex-shim.test.ts similarity index 99% rename from tests/codex-shim.test.ts rename to tests/codex-integration/codex-shim.test.ts index f1a3e5bc95..fc36d7c8b0 100644 --- a/tests/codex-shim.test.ts +++ b/tests/codex-integration/codex-shim.test.ts @@ -3,8 +3,9 @@ import { spawnSync } from "node:child_process"; import { chmodSync, copyFileSync, existsSync, linkSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, statSync, symlinkSync, utimesSync, writeFileSync } from "node:fs"; import { delimiter, dirname, join } from "node:path"; import { tmpdir } from "node:os"; -import { autoRestoreCodexShim, buildUnixCodexShim, buildWindowsCodexShim, buildWindowsPowerShellCodexShim, diagnoseCodexShim, findCodexOnPath, inspectCodexShimBackingForCommand, installCodexShim, isLocalAbsoluteInspectionPath, isVersionManagerOwnedCodexPath, isWindowsInteropDir, lastCodexDiscoveryError, setCodexShimFreshWriteHookForTests, setCodexShimGuardedWriteHookForTests, setCodexShimProbeHookForTests, setCodexShimProbeObservationMsForTests, setCodexShimProbeShellForTests, setCodexShimRollbackRestoreHookForTests, uninstallCodexShim } from "../src/codex/shim"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { autoRestoreCodexShim, buildUnixCodexShim, buildWindowsCodexShim, buildWindowsPowerShellCodexShim, diagnoseCodexShim, findCodexOnPath, inspectCodexShimBackingForCommand, installCodexShim, isLocalAbsoluteInspectionPath, isVersionManagerOwnedCodexPath, isWindowsInteropDir, lastCodexDiscoveryError, setCodexShimFreshWriteHookForTests, setCodexShimGuardedWriteHookForTests, setCodexShimProbeHookForTests, setCodexShimProbeObservationMsForTests, setCodexShimProbeShellForTests, setCodexShimRollbackRestoreHookForTests, uninstallCodexShim } from "../../src/codex/shim"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath, repoRoot } from "../helpers/repo-root"; const SHIM_MARKER = "opencodex codex autostart shim"; const UNIX_SHIM_REVISION_MARKER = "opencodex unix codex shim revision 2"; @@ -234,13 +235,13 @@ describe("Codex autostart shim", () => { }); test("PowerShell shim is written with a UTF-8 BOM (Windows PowerShell 5.1 decodes BOM-less ps1 as ANSI)", async () => { - const source = readFileSync(join(import.meta.dir, "..", "src", "codex", "shim.ts"), "utf8"); + const source = readFileSync(repoPath("src", "codex", "shim.ts"), "utf8"); expect(source).toContain("`\\uFEFF${buildWindowsPowerShellCodexShim(realCodexPath, bun, cli, bunRuntimeSource)}`"); }); test("Windows target discovery includes the extensionless Git-Bash launcher and writeShim emits a forward-slash sh shim for it", () => { - const source = readFileSync(join(import.meta.dir, "..", "src", "codex", "shim.ts"), "utf8"); + const source = readFileSync(repoPath("src", "codex", "shim.ts"), "utf8"); expect(source).toContain('const gitBashLauncher = join(dir, "codex");'); expect(source).toContain("for (const path of [cmd, ps1, gitBashLauncher])"); @@ -1667,7 +1668,7 @@ exit 127 writeFileSync(wrapper, replacement, "utf8"); if (process.platform !== "win32") chmodSync(wrapper, 0o755); - const shimModule = join(import.meta.dir, "..", "src", "codex", "shim.ts"); + const shimModule = repoPath("src", "codex", "shim.ts"); const firstScript = ` import { existsSync, readFileSync, readdirSync, utimesSync, writeFileSync } from "node:fs"; import { join } from "node:path"; @@ -1695,7 +1696,7 @@ exit 127 `; const childEnv = { ...process.env, PATH: binDir, OPENCODEX_HOME: home }; first = Bun.spawn([process.execPath, "-e", firstScript], { - cwd: join(import.meta.dir, ".."), + cwd: repoRoot(), env: childEnv, stdout: "pipe", stderr: "pipe", @@ -1705,7 +1706,7 @@ exit 127 expect(existsSync(readyPath)).toBe(true); const second = spawnSync(process.execPath, ["-e", secondScript], { - cwd: join(import.meta.dir, ".."), + cwd: repoRoot(), env: childEnv, encoding: "utf8", }); diff --git a/tests/codex-spark-visibility.test.ts b/tests/codex-integration/codex-spark-visibility.test.ts similarity index 94% rename from tests/codex-spark-visibility.test.ts rename to tests/codex-integration/codex-spark-visibility.test.ts index 2ddd285ab3..c5dfe1c8a7 100644 --- a/tests/codex-spark-visibility.test.ts +++ b/tests/codex-integration/codex-spark-visibility.test.ts @@ -1,12 +1,12 @@ import { describe, expect, test } from "bun:test"; -import { withSparkVisibility } from "../src/codex/auth-api"; -import { loadConfig, saveConfig } from "../src/config"; +import { withSparkVisibility } from "../../src/codex/auth-api"; +import { loadConfig, saveConfig } from "../../src/config"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { beforeEach, afterEach } from "bun:test"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const SPARK = "GPT-5.3-Codex-Spark Weekly"; const originalHome = process.env.OPENCODEX_HOME; diff --git a/tests/codex-sqlite-home.test.ts b/tests/codex-integration/codex-sqlite-home.test.ts similarity index 94% rename from tests/codex-sqlite-home.test.ts rename to tests/codex-integration/codex-sqlite-home.test.ts index 4d676feffe..f8f7c088bb 100644 --- a/tests/codex-sqlite-home.test.ts +++ b/tests/codex-integration/codex-sqlite-home.test.ts @@ -3,10 +3,10 @@ import { mkdtempSync, mkdirSync, unlinkSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; -import { resolveCodexHistoryJobTarget } from "../src/codex/history-job"; -import { historyBackupPathFor } from "../src/codex/history-provider"; -import { resolveCodexLogsDbPath, resolveCodexSqliteHome, resolveCodexStateDbPath } from "../src/codex/paths"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { resolveCodexHistoryJobTarget } from "../../src/codex/history-job"; +import { historyBackupPathFor } from "../../src/codex/history-provider"; +import { resolveCodexLogsDbPath, resolveCodexSqliteHome, resolveCodexStateDbPath } from "../../src/codex/paths"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const originalCodexHome = process.env.CODEX_HOME; const originalSqliteHome = process.env.CODEX_SQLITE_HOME; diff --git a/tests/codex-sync-api.test.ts b/tests/codex-integration/codex-sync-api.test.ts similarity index 97% rename from tests/codex-sync-api.test.ts rename to tests/codex-integration/codex-sync-api.test.ts index cafc181f83..496952d5d8 100644 --- a/tests/codex-sync-api.test.ts +++ b/tests/codex-integration/codex-sync-api.test.ts @@ -3,18 +3,19 @@ import { spawnSync } from "node:child_process"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { syncModelsToCodex } from "../src/codex/sync"; -import { MANAGED_AGENTS_TABLE_MARKER, MANAGED_SUBAGENT_DEFAULT_MARKER } from "../src/codex/subagent-defaults"; -import type { OcxConfig } from "../src/types"; -import type { OrcaCodexHomeDiagnostic } from "../src/codex/home"; -import { claimOwnedServiceHome, withOwnedServiceHomePreload } from "./helpers/owned-service-home"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { syncModelsToCodex } from "../../src/codex/sync"; +import { MANAGED_AGENTS_TABLE_MARKER, MANAGED_SUBAGENT_DEFAULT_MARKER } from "../../src/codex/subagent-defaults"; +import type { OcxConfig } from "../../src/types"; +import type { OrcaCodexHomeDiagnostic } from "../../src/codex/home"; +import { claimOwnedServiceHome, withOwnedServiceHomePreload } from "../helpers/owned-service-home"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; const TEST_DIR = join(import.meta.dir, ".tmp-codex-sync-api"); const TEST_CODEX_HOME = join(TEST_DIR, "codex"); const TEST_OCX_HOME = join(TEST_DIR, "ocx"); const TEST_HOME = join(TEST_DIR, "home"); -const repoRoot = join(import.meta.dir, ".."); +const repoRoot = resolveRepoRoot(); let prevCodexHome: string | undefined; let prevOpenCodexHome: string | undefined; let prevHome: string | undefined; @@ -514,7 +515,7 @@ describe("GUI/CLI Codex sync backend", () => { ); console.log(JSON.stringify({ status: response.status, body: await response.json() })); `]), { - cwd: join(import.meta.dir, ".."), + cwd: resolveRepoRoot(), env: childEnv({ CODEX_HOME: TEST_CODEX_HOME, OPENCODEX_HOME: ocxHome }), encoding: "utf8", }); @@ -577,4 +578,4 @@ describe("GUI/CLI Codex sync backend", () => { ]); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/codex-sync-response.test.ts b/tests/codex-integration/codex-sync-response.test.ts similarity index 97% rename from tests/codex-sync-response.test.ts rename to tests/codex-integration/codex-sync-response.test.ts index e7b4c29688..61c1ee4939 100644 --- a/tests/codex-sync-response.test.ts +++ b/tests/codex-integration/codex-sync-response.test.ts @@ -4,8 +4,8 @@ import type { CodexHistoryState, CodexObservedState, ConvergeOutcome, -} from "../src/codex/convergence-types"; -import { toSyncResponse } from "../src/server/management/sync-response"; +} from "../../src/codex/convergence-types"; +import { toSyncResponse } from "../../src/server/management/sync-response"; const history: CodexHistoryState = { status: "converged", diff --git a/tests/codex-tool-mode.test.ts b/tests/codex-integration/codex-tool-mode.test.ts similarity index 90% rename from tests/codex-tool-mode.test.ts rename to tests/codex-integration/codex-tool-mode.test.ts index 92d80ffcd9..2f703d03f0 100644 --- a/tests/codex-tool-mode.test.ts +++ b/tests/codex-integration/codex-tool-mode.test.ts @@ -4,12 +4,12 @@ import { normalizeRoutedCatalogEntry, ROUTED_CODEX_TOOL_MODE, type RawEntry, -} from "../src/codex/catalog/parsing"; -import { buildCatalogEntries } from "../src/codex/catalog"; +} from "../../src/codex/catalog/parsing"; +import { buildCatalogEntries } from "../../src/codex/catalog"; import { collectDeclaredWireToolNames, undeclaredToolCallName, -} from "../src/server/responses-undeclared-tool-guard"; +} from "../../src/server/responses-undeclared-tool-guard"; describe("Codex tool mode configuration (#2106)", () => { test("applyRoutedCodexToolMode defaults to code_mode_only", () => { @@ -100,7 +100,7 @@ describe("Codex tool mode configuration (#2106)", () => { }); test("catalogHintsFromProviderConfig propagates codexToolMode", () => { - const { catalogHintsFromProviderConfig } = require("../src/codex/catalog/provider-fetch"); + const { catalogHintsFromProviderConfig } = require("../../src/codex/catalog/provider-fetch"); const hints = catalogHintsFromProviderConfig( "deepseek", { @@ -114,7 +114,7 @@ describe("Codex tool mode configuration (#2106)", () => { }); test("deriveComboCatalogModel sets codexToolMode = shell when all members specify shell", () => { - const { deriveComboCatalogModel } = require("../src/codex/catalog/aggregation"); + const { deriveComboCatalogModel } = require("../../src/codex/catalog/aggregation"); const combo = { name: "all-shell-combo", targets: [ @@ -138,8 +138,8 @@ describe("Codex tool mode configuration (#2106)", () => { }); test("gatherRoutedModels custom model inherits provider codexToolMode when undiscovered", async () => { - const { gatherRoutedModels } = require("../src/codex/catalog"); - const { withStubbedProviderFetch } = require("./helpers/catalog-provider-fetch"); + const { gatherRoutedModels } = require("../../src/codex/catalog"); + const { withStubbedProviderFetch } = require("../helpers/catalog-provider-fetch"); const config = { providers: { customprov: { @@ -163,8 +163,8 @@ describe("Codex tool mode configuration (#2106)", () => { }); test("gatherRoutedModels custom model explicit codexToolMode overrides provider setting", async () => { - const { gatherRoutedModels } = require("../src/codex/catalog"); - const { withStubbedProviderFetch } = require("./helpers/catalog-provider-fetch"); + const { gatherRoutedModels } = require("../../src/codex/catalog"); + const { withStubbedProviderFetch } = require("../helpers/catalog-provider-fetch"); const config = { providers: { customprov: { @@ -189,8 +189,8 @@ describe("Codex tool mode configuration (#2106)", () => { }); test("buildCatalogEntries with codexForwardNativeCapabilityAlias applies codexToolMode = shell", () => { - const { buildCatalogEntries, NATIVE_DAYBREAK_BLUE_MODEL, upstreamNativeEntry } = require("../src/codex/catalog"); - const { CODEX_CUSTOM_MODEL_CATALOG_KIND, findNativeTemplate } = require("../src/codex/catalog/parsing"); + const { buildCatalogEntries, NATIVE_DAYBREAK_BLUE_MODEL, upstreamNativeEntry } = require("../../src/codex/catalog"); + const { CODEX_CUSTOM_MODEL_CATALOG_KIND, findNativeTemplate } = require("../../src/codex/catalog/parsing"); const nativeTemplate = () => findNativeTemplate({ models: [upstreamNativeEntry("gpt-5.6-sol")!] }); const models = [{ id: NATIVE_DAYBREAK_BLUE_MODEL, @@ -210,7 +210,7 @@ describe("Codex tool mode configuration (#2106)", () => { describe("#2503 combo derivation preserves a member's verbosity opt-out", () => { - const { deriveComboCatalogModel } = require("../src/codex/catalog/aggregation"); + const { deriveComboCatalogModel } = require("../../src/codex/catalog/aggregation"); const combo = { name: "mixed-combo", targets: [ diff --git a/tests/codex-transition-state-adoption.test.ts b/tests/codex-integration/codex-transition-state-adoption.test.ts similarity index 90% rename from tests/codex-transition-state-adoption.test.ts rename to tests/codex-integration/codex-transition-state-adoption.test.ts index 9730d85c98..b025f12a7d 100644 --- a/tests/codex-transition-state-adoption.test.ts +++ b/tests/codex-integration/codex-transition-state-adoption.test.ts @@ -4,14 +4,15 @@ import { closeSync, existsSync, fsyncSync, mkdtempSync, openSync, realpathSync, import { tmpdir } from "node:os"; import { join } from "node:path"; -import { openCodexCoordinatorTransaction } from "../src/codex/transition-state"; +import { openCodexCoordinatorTransaction } from "../../src/codex/transition-state"; import { resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/user-identity"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { helperPath, repoRoot } from "../helpers/repo-root"; -const CHILD = join(import.meta.dir, "helpers", "codex-adoption-crash-child.ts"); +const CHILD = helperPath("codex-adoption-crash-child.ts"); let root = ""; let codexHome = ""; let opencodexHome = ""; @@ -39,7 +40,7 @@ afterEach(() => { for (const checkpoint of ["temp-created", "temp-committed", "published"] as const) { test(`a kill at ${checkpoint} leaves the home adoptable`, () => { const child = spawnSync(process.execPath, [CHILD], { - cwd: join(import.meta.dir, ".."), + cwd: repoRoot(), env: { ...process.env, CODEX_HOME: codexHome, diff --git a/tests/codex-transition-state-first-use-regression.test.ts b/tests/codex-integration/codex-transition-state-first-use-regression.test.ts similarity index 93% rename from tests/codex-transition-state-first-use-regression.test.ts rename to tests/codex-integration/codex-transition-state-first-use-regression.test.ts index 78e538540b..2c50d4d9de 100644 --- a/tests/codex-transition-state-first-use-regression.test.ts +++ b/tests/codex-integration/codex-transition-state-first-use-regression.test.ts @@ -5,12 +5,12 @@ import { tmpdir } from "node:os"; import { Database } from "bun:sqlite"; -import { beginCodexTransition } from "../src/codex/transition-state"; +import { beginCodexTransition } from "../../src/codex/transition-state"; import { resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/user-identity"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let codexHome = ""; let opencodexHome = ""; diff --git a/tests/codex-transition-state-race.test.ts b/tests/codex-integration/codex-transition-state-race.test.ts similarity index 97% rename from tests/codex-transition-state-race.test.ts rename to tests/codex-integration/codex-transition-state-race.test.ts index d8a06de4f7..31c87a194a 100644 --- a/tests/codex-transition-state-race.test.ts +++ b/tests/codex-integration/codex-transition-state-race.test.ts @@ -14,18 +14,19 @@ import { pathToFileURL } from "node:url"; import { Database } from "bun:sqlite"; -import { openCodexCoordinatorTransaction } from "../src/codex/transition-state"; +import { openCodexCoordinatorTransaction } from "../../src/codex/transition-state"; import { resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; +} from "../../src/codex/user-identity"; +import { repoPath } from "../helpers/repo-root"; const CHILD_TIMEOUT_MS = 10_000; const transitionStateModuleUrl = pathToFileURL( - join(import.meta.dir, "..", "src", "codex", "transition-state.ts"), + repoPath("src", "codex", "transition-state.ts"), ).href; const userIdentityModuleUrl = pathToFileURL( - join(import.meta.dir, "..", "src", "codex", "user-identity.ts"), + repoPath("src", "codex", "user-identity.ts"), ).href; const transitionProbe = ` diff --git a/tests/codex-transition-state.test.ts b/tests/codex-integration/codex-transition-state.test.ts similarity index 98% rename from tests/codex-transition-state.test.ts rename to tests/codex-integration/codex-transition-state.test.ts index 7877d1dd87..9032dfcbe4 100644 --- a/tests/codex-transition-state.test.ts +++ b/tests/codex-integration/codex-transition-state.test.ts @@ -10,14 +10,14 @@ import { openCodexCoordinatorTransaction, readCodexTransitionState, updateCodexHistoryTransition, -} from "../src/codex/transition-state"; -import { resolveCodexHistoryTransition } from "../src/codex/history-transition"; -import { historyBackupPathFor } from "../src/codex/history-provider"; +} from "../../src/codex/transition-state"; +import { resolveCodexHistoryTransition } from "../../src/codex/history-transition"; +import { historyBackupPathFor } from "../../src/codex/history-provider"; import { resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/user-identity"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let codexHome = ""; let opencodexHome = ""; diff --git a/tests/codex-user-identity.test.ts b/tests/codex-integration/codex-user-identity.test.ts similarity index 98% rename from tests/codex-user-identity.test.ts rename to tests/codex-integration/codex-user-identity.test.ts index c2d58b38b0..9635bdb526 100644 --- a/tests/codex-user-identity.test.ts +++ b/tests/codex-integration/codex-user-identity.test.ts @@ -12,15 +12,16 @@ import { resolveEffectiveUserRuntimeRoot, probeCodexCoordinatorNamespace, samePathIdentity, -} from "../src/codex/user-identity"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/user-identity"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath } from "../helpers/repo-root"; let codexHome = ""; let previousHome: string | undefined; const CHILD_TIMEOUT_MS = 10_000; const userIdentityModuleUrl = pathToFileURL( - join(import.meta.dir, "..", "src", "codex", "user-identity.ts"), + repoPath("src", "codex", "user-identity.ts"), ).href; const identityProbe = ` import { diff --git a/tests/codex-v2-gate.test.ts b/tests/codex-integration/codex-v2-gate.test.ts similarity index 99% rename from tests/codex-v2-gate.test.ts rename to tests/codex-integration/codex-v2-gate.test.ts index 7d813b5f09..8d3e2d9dc5 100644 --- a/tests/codex-v2-gate.test.ts +++ b/tests/codex-integration/codex-v2-gate.test.ts @@ -15,11 +15,11 @@ import { nativeEffortClamp, shouldApplyNativeEffortClamp, type MultiAgentMode, -} from "../src/codex/catalog"; +} from "../../src/codex/catalog"; import { buildCatalogEntriesFromObservedState, mergeCatalogEntriesFromObservedState, -} from "../src/codex/catalog/sync"; +} from "../../src/codex/catalog/sync"; import { getAgentsEnabled, getAgentsMaxDepth, @@ -42,11 +42,11 @@ import { transitionMultiAgentV2, v1ChildLimitToV2TotalLimit, v2TotalLimitToV1ChildLimit, -} from "../src/codex/features"; -import { resetCodexRuntimeResolveCacheForTests, setCodexRuntimeResolveCacheForTests } from "../src/codex/runtime"; -import { cmdV2, codexFeaturesInvocation, v2StatusLine, multiAgentModeLine } from "../src/cli/v2"; -import { handleManagementAPI } from "../src/server/management-api"; -import { catalogConvergenceFactory } from "./helpers/catalog-convergence"; +} from "../../src/codex/features"; +import { resetCodexRuntimeResolveCacheForTests, setCodexRuntimeResolveCacheForTests } from "../../src/codex/runtime"; +import { cmdV2, codexFeaturesInvocation, v2StatusLine, multiAgentModeLine } from "../../src/cli/v2"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { catalogConvergenceFactory } from "../helpers/catalog-convergence"; function template(): Record { return { @@ -994,7 +994,7 @@ describe("v1<->v2 root-slot translation", () => { describe("config-surface parity: agents.enabled, max_depth, subagent_developer_instructions", () => { test("opencodex mirrors exactly one upstream feature key", async () => { - const source = await Bun.file(new URL("../src/codex/features.ts", import.meta.url)).text(); + const source = await Bun.file(new URL("../../src/codex/features.ts", import.meta.url)).text(); // Upstream feature keys are snake_case, so the underscore requirement is the // discriminator: JS member accesses on locals named `features` (features.match, // features.slice, features.ts) are camelCase and never match, while a mirrored @@ -2014,4 +2014,4 @@ describe("3-state multi-agent mode", () => { expect(native.multi_agent_version).toBeUndefined(); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/codex-warmup.test.ts b/tests/codex-integration/codex-warmup.test.ts similarity index 99% rename from tests/codex-warmup.test.ts rename to tests/codex-integration/codex-warmup.test.ts index bfd4f4768f..14dd1455ff 100644 --- a/tests/codex-warmup.test.ts +++ b/tests/codex-integration/codex-warmup.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { CodexWarmupError, warmCodexAccount } from "../src/codex/warmup"; +import { CodexWarmupError, warmCodexAccount } from "../../src/codex/warmup"; const originalFetch = globalThis.fetch; diff --git a/tests/codex-websocket-registry.test.ts b/tests/codex-integration/codex-websocket-registry.test.ts similarity index 96% rename from tests/codex-websocket-registry.test.ts rename to tests/codex-integration/codex-websocket-registry.test.ts index 0fad252cb5..3a710ae015 100644 --- a/tests/codex-websocket-registry.test.ts +++ b/tests/codex-integration/codex-websocket-registry.test.ts @@ -7,9 +7,9 @@ import { registerCodexWebSocket, unregisterCodexWebSocket, updateCodexWebSocketAuthContext, -} from "../src/codex/websocket-registry"; -import { applyConfirmedMainCodexAccountTransition } from "../src/codex/account-lifecycle"; -import type { WsData } from "../src/server/ws-bridge"; +} from "../../src/codex/websocket-registry"; +import { applyConfirmedMainCodexAccountTransition } from "../../src/codex/account-lifecycle"; +import type { WsData } from "../../src/server/ws-bridge"; function mockWs(data: WsData): { ws: ServerWebSocket; diff --git a/tests/codex-write-lock.test.ts b/tests/codex-integration/codex-write-lock.test.ts similarity index 98% rename from tests/codex-write-lock.test.ts rename to tests/codex-integration/codex-write-lock.test.ts index e20fbd3ecc..e33163361d 100644 --- a/tests/codex-write-lock.test.ts +++ b/tests/codex-integration/codex-write-lock.test.ts @@ -13,7 +13,7 @@ import { mkdirSync, mkdtempSync, realpathSync, rmSync, symlinkSync, writeFileSyn import { resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; +} from "../../src/codex/user-identity"; import { tmpdir } from "node:os"; import { join } from "node:path"; @@ -21,9 +21,10 @@ import { CODEX_WRITE_LOCK_MAX_TIMEOUT_MS, canonicalizeCodexHome, withCodexWriteLock, -} from "../src/codex/codex-write-lock"; -import type { AdmissionSnapshot } from "../src/codex/convergence-types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/codex-write-lock"; +import type { AdmissionSnapshot } from "../../src/codex/convergence-types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { helperPath } from "../helpers/repo-root"; let root = ""; let codexHome = ""; @@ -280,7 +281,7 @@ describe("two real processes contend for one lock", () => { * like a race and was not one. So: a real child process, calling the * production module. */ - const childPath = join(import.meta.dir, "helpers", "codex-write-lock-child.ts"); + const childPath = helperPath("codex-write-lock-child.ts"); function spawnChild(payload: Record) { return Bun.spawn(["bun", childPath], { diff --git a/tests/combos.test.ts b/tests/codex-integration/combos.test.ts similarity index 98% rename from tests/combos.test.ts rename to tests/codex-integration/combos.test.ts index 51ae4fa1a9..a50385c54c 100644 --- a/tests/combos.test.ts +++ b/tests/codex-integration/combos.test.ts @@ -39,29 +39,29 @@ import { targetKey, tryPickComboModel, UnknownComboError, -} from "../src/combos"; +} from "../../src/combos"; import { comboFailureCooldownScope, comboFailureDecision, isTransientRequestRateLimit, -} from "../src/combos/failover"; -import { comboUnavailableResponse } from "../src/server/responses/core"; -import { getConfigPath, readConfigDiagnostics, saveConfig } from "../src/config"; -import { routeModel } from "../src/router"; -import { handleManagementAPI } from "../src/server/management-api"; -import { handleResponses } from "../src/server/responses"; -import type { OcxConfig } from "../src/types"; -import { syncCatalogModels } from "../src/codex/catalog"; -import { injectClaudeAgentDefs } from "../src/claude/agents-inject"; -import { reconcileComboRotationState } from "../src/combos/resolve"; +} from "../../src/combos/failover"; +import { comboUnavailableResponse } from "../../src/server/responses/core"; +import { getConfigPath, readConfigDiagnostics, saveConfig } from "../../src/config"; +import { routeModel } from "../../src/router"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { handleResponses } from "../../src/server/responses"; +import type { OcxConfig } from "../../src/types"; +import { syncCatalogModels } from "../../src/codex/catalog"; +import { injectClaudeAgentDefs } from "../../src/claude/agents-inject"; +import { reconcileComboRotationState } from "../../src/combos/resolve"; import { clearCachedProviderQuotas, getCachedProviderQuota, replaceCachedProviderQuotas, setCachedProviderQuotaForTests, -} from "../src/providers/quota-routing-cache"; -import { catalogConvergenceFactory } from "./helpers/catalog-convergence"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/quota-routing-cache"; +import { catalogConvergenceFactory } from "../helpers/catalog-convergence"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const VALID_COMBO = { targets: [{ provider: "a", model: "m1" }] }; diff --git a/tests/compatibility-manifest.test.ts b/tests/codex-integration/compatibility-manifest.test.ts similarity index 91% rename from tests/compatibility-manifest.test.ts rename to tests/codex-integration/compatibility-manifest.test.ts index ed74a5cfc9..8576136955 100644 --- a/tests/compatibility-manifest.test.ts +++ b/tests/codex-integration/compatibility-manifest.test.ts @@ -2,20 +2,21 @@ import { describe, expect, test } from "bun:test"; import { existsSync, readFileSync } from "node:fs"; import { dirname, join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; -import { createRegisteredAdapter, effectiveAdapterContract } from "../src/adapters/registry"; +import { createRegisteredAdapter, effectiveAdapterContract } from "../../src/adapters/registry"; import { COMPATIBILITY_MANIFESTS, OPENAI_CODEX_FORWARD_GPT56_SOL_MANIFEST, compatibilityManifestIssues, -} from "../src/compatibility"; -import { createTranslatorBudget } from "../src/lib/translator-budget"; -import { listScenarioIds } from "../src/lab/conformance/runner"; -import { providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { SUPPORTED_NATIVE_OPENAI_SLUGS } from "../src/codex/catalog/native-models"; -import { parseRequest } from "../src/responses/parser"; -import { resolveJsonPointer } from "../src/lab/conformance/json-pointer"; -import fixtureJson from "./fixtures/compatibility/openai-codex-forward-gpt56-sol-v1.json"; +} from "../../src/compatibility"; +import { createTranslatorBudget } from "../../src/lib/translator-budget"; +import { listScenarioIds } from "../../src/lab/conformance/runner"; +import { providerConfigSeed } from "../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; +import { SUPPORTED_NATIVE_OPENAI_SLUGS } from "../../src/codex/catalog/native-models"; +import { parseRequest } from "../../src/responses/parser"; +import { resolveJsonPointer } from "../../src/lab/conformance/json-pointer"; +import fixtureJson from "../fixtures/compatibility/openai-codex-forward-gpt56-sol-v1.json"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; type FixtureAssertion = { id: string; @@ -39,7 +40,7 @@ type CompatibilityFixture = { }; const fixture = fixtureJson as CompatibilityFixture; -const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); +const repoRoot = resolveRepoRoot(); const RUNTIME_IMPORT_RE = /^\s*import\s+(?!type\b)[^;]*?from\s+["']([^"']+)["']|^\s*import\s+["']([^"']+)["']|^\s*export\s+(?!type\b)[^;]*?from\s+["']([^"']+)["']|\bimport\s*\(\s*["']([^"']+)["']\s*\)/gm; function resolveRuntimeImport(specifier: string, fromFile: string): string | null { diff --git a/tests/custom-model-catalog-migration.test.ts b/tests/codex-integration/custom-model-catalog-migration.test.ts similarity index 97% rename from tests/custom-model-catalog-migration.test.ts rename to tests/codex-integration/custom-model-catalog-migration.test.ts index 4a8134b0a4..a39dcdb8d8 100644 --- a/tests/custom-model-catalog-migration.test.ts +++ b/tests/codex-integration/custom-model-catalog-migration.test.ts @@ -3,8 +3,8 @@ import { describe, expect, test } from "bun:test"; import { projectCustomModelCatalogMigration, legacyCustomModelCatalogSlugs, -} from "../src/codex/custom-model-catalog-migration"; -import type { OcxConfig, OcxCustomModel } from "../src/types"; +} from "../../src/codex/custom-model-catalog-migration"; +import type { OcxConfig, OcxCustomModel } from "../../src/types"; function config(customModels?: OcxCustomModel[]): OcxConfig { return { diff --git a/tests/doctor.test.ts b/tests/codex-integration/doctor.test.ts similarity index 99% rename from tests/doctor.test.ts rename to tests/codex-integration/doctor.test.ts index 6261b7c106..9fdb7ee30d 100644 --- a/tests/doctor.test.ts +++ b/tests/codex-integration/doctor.test.ts @@ -19,9 +19,9 @@ import { resolveCodexHomeDir, runDoctor, type ServiceMemoryData, -} from "../src/cli/doctor"; -import { collectOrcaCodexHomeDiagnostic } from "../src/codex/home"; -import { NativeProfileError } from "../src/codex/native-profile-types"; +} from "../../src/cli/doctor"; +import { collectOrcaCodexHomeDiagnostic } from "../../src/codex/home"; +import { NativeProfileError } from "../../src/codex/native-profile-types"; import { LOCAL_MANAGEMENT_CAPABILITY_HEADER, LOCAL_MANAGEMENT_CAPABILITY_EXPIRES_AT_HEADER, @@ -29,9 +29,9 @@ import { LOCAL_MANAGEMENT_NONCE_HEADER, LOCAL_MANAGEMENT_READ_PATHS, verifyLocalManagementReadCapability, -} from "../src/lib/local-management-capability"; -import { findDeadPid } from "./helpers/dead-pid"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/lib/local-management-capability"; +import { findDeadPid } from "../helpers/dead-pid"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-doctor-test"); const TEST_CODEX_HOME = join(TEST_DIR, "codex"); diff --git a/tests/effort-policy.test.ts b/tests/codex-integration/effort-policy.test.ts similarity index 97% rename from tests/effort-policy.test.ts rename to tests/codex-integration/effort-policy.test.ts index f704ee53a7..3f2262ade6 100644 --- a/tests/effort-policy.test.ts +++ b/tests/codex-integration/effort-policy.test.ts @@ -7,14 +7,14 @@ import { afterEach, describe, expect, test } from "bun:test"; import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { applyEffortCap, effortCapAppliesTo, effortCapFor, isThreadSpawnRequest, resolveCappedEffort, stripEmptyLadderEffort, supportedLadderFor } from "../src/server/effort-policy"; -import { collabSurface } from "../src/server/responses"; -import { handleManagementAPI } from "../src/server/management-api"; -import { NoEnabledOpenAiProviderError, routeModel } from "../src/router"; -import { mapReasoningEffort } from "../src/reasoning-effort"; -import { nativeEffortClamp } from "../src/codex/catalog"; -import type { OcxConfig, OcxParsedRequest } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { applyEffortCap, effortCapAppliesTo, effortCapFor, isThreadSpawnRequest, resolveCappedEffort, stripEmptyLadderEffort, supportedLadderFor } from "../../src/server/effort-policy"; +import { collabSurface } from "../../src/server/responses"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { NoEnabledOpenAiProviderError, routeModel } from "../../src/router"; +import { mapReasoningEffort } from "../../src/reasoning-effort"; +import { nativeEffortClamp } from "../../src/codex/catalog"; +import type { OcxConfig, OcxParsedRequest } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const savedHome = process.env.OPENCODEX_HOME; const savedCodexHome = process.env.CODEX_HOME; @@ -490,4 +490,4 @@ describe("/api/effort-caps", () => { expect(config.subagentEffortCap).toBe("low"); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/fast-row-listing.test.ts b/tests/codex-integration/fast-row-listing.test.ts similarity index 94% rename from tests/fast-row-listing.test.ts rename to tests/codex-integration/fast-row-listing.test.ts index 7d03834580..ccdd2b3881 100644 --- a/tests/fast-row-listing.test.ts +++ b/tests/codex-integration/fast-row-listing.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { AUTO_CONTEXT_OFF } from "../src/claude/context-windows"; -import { desktop3pAlias } from "../src/claude/desktop-3p"; -import { buildAnthropicModelInfos } from "../src/claude/model-info"; -import type { CatalogModel } from "../src/codex/catalog"; +import { AUTO_CONTEXT_OFF } from "../../src/claude/context-windows"; +import { desktop3pAlias } from "../../src/claude/desktop-3p"; +import { buildAnthropicModelInfos } from "../../src/claude/model-info"; +import type { CatalogModel } from "../../src/codex/catalog"; /** * Fast rows on Claude Code discovery (devlog 260904_external_fast_wire/020). diff --git a/tests/fast-row.test.ts b/tests/codex-integration/fast-row.test.ts similarity index 98% rename from tests/fast-row.test.ts rename to tests/codex-integration/fast-row.test.ts index d9c0005a20..6a0437b8af 100644 --- a/tests/fast-row.test.ts +++ b/tests/codex-integration/fast-row.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { clearModelCache, setCached } from "../src/codex/model-cache"; -import { knownEffortRowIds, parseEffortRowId, parseRequestEffortRowId } from "../src/server/effort-row"; +import { clearModelCache, setCached } from "../../src/codex/model-cache"; +import { knownEffortRowIds, parseEffortRowId, parseRequestEffortRowId } from "../../src/server/effort-row"; import { effortBaseCarriesFastMarker, expandFastRow, @@ -10,9 +10,9 @@ import { parseFastOnlyRowId, parseFastRowId, parseSyntheticRowId, -} from "../src/server/fast-row"; -import { isDeclaredReasoningEffort } from "../src/reasoning-effort"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +} from "../../src/server/fast-row"; +import { isDeclaredReasoningEffort } from "../../src/reasoning-effort"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; /** * Synthetic Fast selectors (devlog 260904_external_fast_wire/010). diff --git a/tests/gather-routed-models-single-flight.test.ts b/tests/codex-integration/gather-routed-models-single-flight.test.ts similarity index 97% rename from tests/gather-routed-models-single-flight.test.ts rename to tests/codex-integration/gather-routed-models-single-flight.test.ts index 40055d08c9..0957cf7d6b 100644 --- a/tests/gather-routed-models-single-flight.test.ts +++ b/tests/codex-integration/gather-routed-models-single-flight.test.ts @@ -5,11 +5,11 @@ import { gatherRoutedModels as gatherRoutedModelsDirect, resetCatalogRuntimeStateForTests, type ComboCatalogOmission, -} from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import type { OcxConfig } from "../src/types"; -import { CatalogGatherBusyError } from "../src/codex/catalog/provider-fetch"; +} from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import type { OcxConfig } from "../../src/types"; +import { CatalogGatherBusyError } from "../../src/codex/catalog/provider-fetch"; const originalFetch = globalThis.fetch; diff --git a/tests/history-migration-guardian.test.ts b/tests/codex-integration/history-migration-guardian.test.ts similarity index 98% rename from tests/history-migration-guardian.test.ts rename to tests/codex-integration/history-migration-guardian.test.ts index 65b90cc7ed..ad044cc98a 100644 --- a/tests/history-migration-guardian.test.ts +++ b/tests/codex-integration/history-migration-guardian.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { startHistoryMigrationGuardian } from "../src/codex/history-migration-guardian"; +import { startHistoryMigrationGuardian } from "../../src/codex/history-migration-guardian"; /** * Manual scheduler: collects scheduled callbacks so tests drive ticks diff --git a/tests/injection-model-api.test.ts b/tests/codex-integration/injection-model-api.test.ts similarity index 97% rename from tests/injection-model-api.test.ts rename to tests/codex-integration/injection-model-api.test.ts index 645584bfa0..71fa8c35be 100644 --- a/tests/injection-model-api.test.ts +++ b/tests/codex-integration/injection-model-api.test.ts @@ -7,12 +7,12 @@ import { afterEach, describe, expect, test } from "bun:test"; import { existsSync, mkdtempSync, readFileSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { getConfigPath, loadConfig } from "../src/config"; -import { refreshCodexModelCatalog } from "../src/codex/refresh"; -import { handleManagementAPI } from "../src/server/management-api"; -import { CODEX_REASONING_LEVELS } from "../src/reasoning-effort"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { getConfigPath, loadConfig } from "../../src/config"; +import { refreshCodexModelCatalog } from "../../src/codex/refresh"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { CODEX_REASONING_LEVELS } from "../../src/reasoning-effort"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const savedHome = process.env.OPENCODEX_HOME; let tempHome: string | null = null; @@ -413,4 +413,4 @@ describe("/api/injection-model guidance kill switch + partial update", () => { }); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/issue-452-empty-503.test.ts b/tests/codex-integration/issue-452-empty-503.test.ts similarity index 94% rename from tests/issue-452-empty-503.test.ts rename to tests/codex-integration/issue-452-empty-503.test.ts index 92e2328050..c04b6a8fdf 100644 --- a/tests/issue-452-empty-503.test.ts +++ b/tests/codex-integration/issue-452-empty-503.test.ts @@ -1,22 +1,22 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync} from "node:fs"; import { join } from "node:path"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { clearAccountNeedsReauth, clearAccountQuota, updateAccountQuota } from "../src/codex/auth-api"; -import { clearCodexUpstreamHealth, clearThreadAccountMap } from "../src/codex/routing"; -import { saveConfig } from "../src/config"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { BOUNDED_BODY_MAX_BYTES } from "../src/lib/bounded-body"; -import { getDebugLogEntries, resetDebugLogBufferForTests } from "../src/lib/debug-log-buffer"; -import { resetDebugSettingsForTests } from "../src/lib/debug-settings"; -import { setDraining } from "../src/server/lifecycle"; -import { startServer } from "../src/server"; -import { readDisplaySafeErrorText } from "../src/server/responses/core"; -import { formatPassthroughUpstreamError } from "../src/server/responses/passthrough-error"; -import type { OcxConfig, OcxParsedRequest } from "../src/types"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { SERVER_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { clearAccountNeedsReauth, clearAccountQuota, updateAccountQuota } from "../../src/codex/auth-api"; +import { clearCodexUpstreamHealth, clearThreadAccountMap } from "../../src/codex/routing"; +import { saveConfig } from "../../src/config"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { BOUNDED_BODY_MAX_BYTES } from "../../src/lib/bounded-body"; +import { getDebugLogEntries, resetDebugLogBufferForTests } from "../../src/lib/debug-log-buffer"; +import { resetDebugSettingsForTests } from "../../src/lib/debug-settings"; +import { setDraining } from "../../src/server/lifecycle"; +import { startServer } from "../../src/server"; +import { readDisplaySafeErrorText } from "../../src/server/responses/core"; +import { formatPassthroughUpstreamError } from "../../src/server/responses/passthrough-error"; +import type { OcxConfig, OcxParsedRequest } from "../../src/types"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { SERVER_BUDGET_MS } from "../helpers/test-budget"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const previousApiToken = process.env.OPENCODEX_API_AUTH_TOKEN; const previousOpencodexHome = process.env.OPENCODEX_HOME; diff --git a/tests/issue-702-expired-replay-state.test.ts b/tests/codex-integration/issue-702-expired-replay-state.test.ts similarity index 96% rename from tests/issue-702-expired-replay-state.test.ts rename to tests/codex-integration/issue-702-expired-replay-state.test.ts index 476e795306..b73439ecc9 100644 --- a/tests/issue-702-expired-replay-state.test.ts +++ b/tests/codex-integration/issue-702-expired-replay-state.test.ts @@ -2,11 +2,11 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync, readdirSync, unlinkSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; +import { saveConfig } from "../../src/config"; import { resetSubagentModelFallbackStateForTests, setSubagentQuotaPrimeForTests, -} from "../src/codex/subagent-model-fallback"; +} from "../../src/codex/subagent-model-fallback"; import { clearResponseStateForTests, clearResponseStateMemoryForTests, @@ -15,14 +15,14 @@ import { responseStateMetrics, setResponseStateByteCapForTests, type ResponseStateMetrics, -} from "../src/responses/state"; -import { responseSpillDirectory } from "../src/responses/spill-store"; -import { startServer } from "../src/server"; -import type { OcxConfig } from "../src/types"; -import { fakeChatGptJwt } from "./helpers/fake-chatgpt-jwt"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { SERVER_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/responses/state"; +import { responseSpillDirectory } from "../../src/responses/spill-store"; +import { startServer } from "../../src/server"; +import type { OcxConfig } from "../../src/types"; +import { fakeChatGptJwt } from "../helpers/fake-chatgpt-jwt"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { SERVER_BUDGET_MS } from "../helpers/test-budget"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const originalFetch = globalThis.fetch; const previousOpencodexHome = process.env.OPENCODEX_HOME; diff --git a/tests/issue-914-transport-attribution.test.ts b/tests/codex-integration/issue-914-transport-attribution.test.ts similarity index 93% rename from tests/issue-914-transport-attribution.test.ts rename to tests/codex-integration/issue-914-transport-attribution.test.ts index e2236a48d5..6823c7b6e3 100644 --- a/tests/issue-914-transport-attribution.test.ts +++ b/tests/codex-integration/issue-914-transport-attribution.test.ts @@ -8,20 +8,20 @@ import { isCodexAccountSoftAvoided, recordCodexUpstreamOutcome, resolveCodexAccountForThread, -} from "../src/codex/routing"; +} from "../../src/codex/routing"; import { clearUpstreamHostHealth, getUpstreamHostHealth, upstreamHostHealthKey, -} from "../src/codex/upstream-host-health"; -import { classifyTransportFailureKind } from "../src/lib/upstream-reachability"; -import { fetchWithResetRetry, fetchWithTransientRetry } from "../src/lib/upstream-retry"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { getConfigPath } from "../src/config"; -import type { OcxConfig } from "../src/types"; +} from "../../src/codex/upstream-host-health"; +import { classifyTransportFailureKind } from "../../src/lib/upstream-reachability"; +import { fetchWithResetRetry, fetchWithTransientRetry } from "../../src/lib/upstream-retry"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { getConfigPath } from "../../src/config"; +import type { OcxConfig } from "../../src/types"; import { existsSync, mkdirSync} from "node:fs"; import { join } from "node:path"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-issue-914-test"); let previousOpencodexHome: string | undefined; diff --git a/tests/model-cache-generation-tombstone.test.ts b/tests/codex-integration/model-cache-generation-tombstone.test.ts similarity index 98% rename from tests/model-cache-generation-tombstone.test.ts rename to tests/codex-integration/model-cache-generation-tombstone.test.ts index 1e2cc5b4b2..48d914a945 100644 --- a/tests/model-cache-generation-tombstone.test.ts +++ b/tests/codex-integration/model-cache-generation-tombstone.test.ts @@ -5,7 +5,7 @@ import { providerCacheGenerations, reconcileModelCacheProviders, setCached, -} from "../src/codex/model-cache"; +} from "../../src/codex/model-cache"; let reconciliationGeneration = Date.now(); diff --git a/tests/model-cache.test.ts b/tests/codex-integration/model-cache.test.ts similarity index 97% rename from tests/model-cache.test.ts rename to tests/codex-integration/model-cache.test.ts index d3b30f3720..58ab24eacf 100644 --- a/tests/model-cache.test.ts +++ b/tests/codex-integration/model-cache.test.ts @@ -5,7 +5,7 @@ import { getStaleCached, reconcileModelCacheProviders, setCached, -} from "../src/codex/model-cache"; +} from "../../src/codex/model-cache"; const provider = "removed-provider-generation"; diff --git a/tests/model-display-names-management-api.test.ts b/tests/codex-integration/model-display-names-management-api.test.ts similarity index 97% rename from tests/model-display-names-management-api.test.ts rename to tests/codex-integration/model-display-names-management-api.test.ts index 468584536e..ea11600e83 100644 --- a/tests/model-display-names-management-api.test.ts +++ b/tests/codex-integration/model-display-names-management-api.test.ts @@ -1,9 +1,9 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { clearModelCache, getFreshCached, setCached } from "../src/codex/model-cache"; -import type { CatalogDisposition } from "../src/codex/convergence-types"; -import { listManagementModelRows, toExportModel } from "../src/server/management/model-rows"; -import { handleModelRoutes } from "../src/server/management/model-routes"; -import type { OcxConfig } from "../src/types"; +import { clearModelCache, getFreshCached, setCached } from "../../src/codex/model-cache"; +import type { CatalogDisposition } from "../../src/codex/convergence-types"; +import { listManagementModelRows, toExportModel } from "../../src/server/management/model-rows"; +import { handleModelRoutes } from "../../src/server/management/model-routes"; +import type { OcxConfig } from "../../src/types"; const DISPLAY_PROVIDER = "display-test"; diff --git a/tests/model-metadata-sync.test.ts b/tests/codex-integration/model-metadata-sync.test.ts similarity index 86% rename from tests/model-metadata-sync.test.ts rename to tests/codex-integration/model-metadata-sync.test.ts index dfe5ae4370..47d7c5b895 100644 --- a/tests/model-metadata-sync.test.ts +++ b/tests/codex-integration/model-metadata-sync.test.ts @@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test"; import { existsSync, mkdtempSync, readFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; +import { repoPath, repoRoot } from "../helpers/repo-root"; /** * `src/generated/model-metadata.ts` is generated from the vendored snapshot @@ -15,10 +16,10 @@ import { join, resolve } from "node:path"; * everywhere, including CI. Refreshing the metadata is one deliberate commit: replace the * snapshot and rerun `bun run generate:model-metadata`. */ -const GENERATED = resolve(import.meta.dir, "../src/generated/model-metadata.ts"); +const GENERATED = repoPath("src/generated/model-metadata.ts"); // Mirror the generator's fixed source: the vendored snapshot next to the script, so the guard is // deterministic in worktrees and CI. -const SOURCE = resolve(import.meta.dir, "../scripts/model-metadata.source.json"); +const SOURCE = repoPath("scripts/model-metadata.source.json"); describe("generated model metadata stays in sync with its source", () => { test.skipIf(!existsSync(SOURCE))( @@ -28,9 +29,9 @@ describe("generated model metadata stays in sync with its source", () => { const outPath = join(outDir, "model-metadata.ts"); const proc = Bun.spawn( - ["bun", resolve(import.meta.dir, "../scripts/generate-model-metadata.ts")], + ["bun", repoPath("scripts/generate-model-metadata.ts")], { - cwd: resolve(import.meta.dir, ".."), + cwd: repoRoot(), env: { ...process.env, MODEL_METADATA_OUT: outPath }, stdout: "pipe", stderr: "pipe", diff --git a/tests/model-visibility-management-api.test.ts b/tests/codex-integration/model-visibility-management-api.test.ts similarity index 95% rename from tests/model-visibility-management-api.test.ts rename to tests/codex-integration/model-visibility-management-api.test.ts index 1737577935..6259818667 100644 --- a/tests/model-visibility-management-api.test.ts +++ b/tests/codex-integration/model-visibility-management-api.test.ts @@ -1,12 +1,12 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync} from "node:fs"; import { join } from "node:path"; -import { nativeModelRows } from "../src/codex/catalog"; -import { loadConfig, saveConfig } from "../src/config"; -import { handleManagementAPI } from "../src/server/management-api"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { catalogConvergenceFactory } from "./helpers/catalog-convergence"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { nativeModelRows } from "../../src/codex/catalog"; +import { loadConfig, saveConfig } from "../../src/config"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { catalogConvergenceFactory } from "../helpers/catalog-convergence"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, `.tmp-model-visibility-management-${process.pid}`); const previousOpencodexHome = process.env.OPENCODEX_HOME; @@ -65,10 +65,10 @@ async function put(body: unknown): Promise { describe("atomic model visibility management", () => { test("catalog busy maps management and v1 models to 503 startup to warn-skip and system-env to skip", async () => { - const management = await Bun.file(new URL("../src/server/management-api.ts", import.meta.url)).text(); - const server = await Bun.file(new URL("../src/server/index.ts", import.meta.url)).text(); - const prewarm = await Bun.file(new URL("../src/cli/catalog-prewarm.ts", import.meta.url)).text(); - const systemEnv = await Bun.file(new URL("../src/server/system-env.ts", import.meta.url)).text(); + const management = await Bun.file(new URL("../../src/server/management-api.ts", import.meta.url)).text(); + const server = await Bun.file(new URL("../../src/server/index.ts", import.meta.url)).text(); + const prewarm = await Bun.file(new URL("../../src/cli/catalog-prewarm.ts", import.meta.url)).text(); + const systemEnv = await Bun.file(new URL("../../src/server/system-env.ts", import.meta.url)).text(); for (const source of [management, server]) { expect(source).toContain("CatalogGatherBusyError"); expect(source).toContain('"catalog_busy"'); @@ -365,4 +365,4 @@ describe("atomic model visibility management", () => { expect(loadConfig()).toEqual(before); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/multi-agent-compat.test.ts b/tests/codex-integration/multi-agent-compat.test.ts similarity index 99% rename from tests/multi-agent-compat.test.ts rename to tests/codex-integration/multi-agent-compat.test.ts index c295a25e27..ac5956c5c7 100644 --- a/tests/multi-agent-compat.test.ts +++ b/tests/codex-integration/multi-agent-compat.test.ts @@ -7,18 +7,18 @@ import { afterAll, afterEach, beforeAll, describe, expect, test } from "bun:test import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { injectDeveloperMessage, multiAgentGuidanceText, sanitizeEncryptedContentInPlace } from "../src/server/responses"; -import { parseRequest } from "../src/responses/parser"; -import type { OcxParsedRequest } from "../src/types"; -import { CODEX_ACCOUNT_BOUND_CATALOG_KIND, effectiveSubagentRoster } from "../src/codex/catalog"; -import { collectCodexAppServerCatalogState, resetCodexAppServerCatalogStateCache } from "../src/codex/app-server-processes"; -import { setTrustedWindowsElevationExecutablesForTests } from "../src/lib/windows-elevation"; -import { createWindowsPowerShellFixture, type WindowsPowerShellFixture } from "./helpers/windows-power-shell-fixture"; -import { clearDebugSettings, setDebugSettings } from "../src/lib/debug-settings"; +import { injectDeveloperMessage, multiAgentGuidanceText, sanitizeEncryptedContentInPlace } from "../../src/server/responses"; +import { parseRequest } from "../../src/responses/parser"; +import type { OcxParsedRequest } from "../../src/types"; +import { CODEX_ACCOUNT_BOUND_CATALOG_KIND, effectiveSubagentRoster } from "../../src/codex/catalog"; +import { collectCodexAppServerCatalogState, resetCodexAppServerCatalogStateCache } from "../../src/codex/app-server-processes"; +import { setTrustedWindowsElevationExecutablesForTests } from "../../src/lib/windows-elevation"; +import { createWindowsPowerShellFixture, type WindowsPowerShellFixture } from "../helpers/windows-power-shell-fixture"; +import { clearDebugSettings, setDebugSettings } from "../../src/lib/debug-settings"; import { getInjectionDebugLogEntries, resetInjectionDebugLogBufferForTests, -} from "../src/lib/injection-debug-log"; +} from "../../src/lib/injection-debug-log"; const savedCodexHome = process.env.CODEX_HOME; const savedCatalogStateOverride = process.env.OPENCODEX_APP_SERVER_CATALOG_STATE_OVERRIDE; diff --git a/tests/multi-agent-keep-native-v1.test.ts b/tests/codex-integration/multi-agent-keep-native-v1.test.ts similarity index 96% rename from tests/multi-agent-keep-native-v1.test.ts rename to tests/codex-integration/multi-agent-keep-native-v1.test.ts index da951b5c4a..d774c6e8e7 100644 --- a/tests/multi-agent-keep-native-v1.test.ts +++ b/tests/codex-integration/multi-agent-keep-native-v1.test.ts @@ -6,15 +6,15 @@ import { applyMultiAgentMode, catalogEntryIsNativeChatGpt, type RawEntry, -} from "../src/codex/catalog/parsing"; -import { CODEX_NATIVE_ALIAS_CATALOG_KIND } from "../src/codex/catalog/kinds"; -import { buildCatalogEntriesFromObservedState } from "../src/codex/catalog/sync"; -import { cmdV2 } from "../src/cli/v2"; -import { loadConfig, saveConfig } from "../src/config"; -import { isMultiAgentV2Enabled } from "../src/codex/features"; -import { handleManagementAPI } from "../src/server/management-api"; -import { catalogConvergenceFactory } from "./helpers/catalog-convergence"; -import type { OcxConfig } from "../src/types"; +} from "../../src/codex/catalog/parsing"; +import { CODEX_NATIVE_ALIAS_CATALOG_KIND } from "../../src/codex/catalog/kinds"; +import { buildCatalogEntriesFromObservedState } from "../../src/codex/catalog/sync"; +import { cmdV2 } from "../../src/cli/v2"; +import { loadConfig, saveConfig } from "../../src/config"; +import { isMultiAgentV2Enabled } from "../../src/codex/features"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { catalogConvergenceFactory } from "../helpers/catalog-convergence"; +import type { OcxConfig } from "../../src/types"; describe("keepNativeChatGptOnV1", () => { test("v2 without the switch stamps every row v2", () => { diff --git a/tests/native-alias-maintainer-regressions.test.ts b/tests/codex-integration/native-alias-maintainer-regressions.test.ts similarity index 96% rename from tests/native-alias-maintainer-regressions.test.ts rename to tests/codex-integration/native-alias-maintainer-regressions.test.ts index f93edc500e..6426b712c9 100644 --- a/tests/native-alias-maintainer-regressions.test.ts +++ b/tests/codex-integration/native-alias-maintainer-regressions.test.ts @@ -3,13 +3,13 @@ import { catalogHasRoutedEntries, type CatalogModel, type RawEntry, -} from "../src/codex/catalog/parsing"; +} from "../../src/codex/catalog/parsing"; import { buildCatalogEntries, mergeCatalogEntriesForSync, mergeCatalogModelsWithNativeRecovery, -} from "../src/codex/catalog/sync"; -import { CODEX_NATIVE_ALIAS_CATALOG_KIND } from "../src/codex/catalog/kinds"; +} from "../../src/codex/catalog/sync"; +import { CODEX_NATIVE_ALIAS_CATALOG_KIND } from "../../src/codex/catalog/kinds"; function aliasModel(slug: string): CatalogModel { return { diff --git a/tests/native-claude-code-toggle.test.ts b/tests/codex-integration/native-claude-code-toggle.test.ts similarity index 98% rename from tests/native-claude-code-toggle.test.ts rename to tests/codex-integration/native-claude-code-toggle.test.ts index 59ad138bf2..e0ae5dffb3 100644 --- a/tests/native-claude-code-toggle.test.ts +++ b/tests/codex-integration/native-claude-code-toggle.test.ts @@ -1,6 +1,6 @@ import { expect, test } from "bun:test"; -import { handleManagementAPI } from "../src/server/management-api"; -import type { OcxConfig } from "../src/types"; +import { handleManagementAPI } from "../../src/server/management-api"; +import type { OcxConfig } from "../../src/types"; /** * Route contract for devlog/_fin/260803_integrations_toggle_all/011. diff --git a/tests/native-claude-desktop-toggle.test.ts b/tests/codex-integration/native-claude-desktop-toggle.test.ts similarity index 97% rename from tests/native-claude-desktop-toggle.test.ts rename to tests/codex-integration/native-claude-desktop-toggle.test.ts index 248f24d85a..8f843f7c51 100644 --- a/tests/native-claude-desktop-toggle.test.ts +++ b/tests/codex-integration/native-claude-desktop-toggle.test.ts @@ -2,12 +2,12 @@ import { afterEach, beforeEach, expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { handleManagementAPI } from "../src/server/management-api"; -import { setIntegrationEnabled } from "../src/codex/desired-state"; -import { MANAGEMENT_JSON_BODY_MAX_BYTES } from "../src/server/management/body"; -import type { ManagementApiDeps } from "../src/server/management/context"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { setIntegrationEnabled } from "../../src/codex/desired-state"; +import { MANAGEMENT_JSON_BODY_MAX_BYTES } from "../../src/server/management/body"; +import type { ManagementApiDeps } from "../../src/server/management/context"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let root = ""; let library = ""; diff --git a/tests/native-codex-toggle.test.ts b/tests/codex-integration/native-codex-toggle.test.ts similarity index 96% rename from tests/native-codex-toggle.test.ts rename to tests/codex-integration/native-codex-toggle.test.ts index bd15a3f2c5..d78e41c1d2 100644 --- a/tests/native-codex-toggle.test.ts +++ b/tests/codex-integration/native-codex-toggle.test.ts @@ -16,10 +16,10 @@ import { mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { homedir, tmpdir } from "node:os"; import { join } from "node:path"; -import { handleManagementAPI } from "../src/server/management-api"; -import type { ManagementApiDeps } from "../src/server/management/context"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { handleManagementAPI } from "../../src/server/management-api"; +import type { ManagementApiDeps } from "../../src/server/management/context"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let fixtureRoot = ""; let previousOpencodexHome: string | undefined; diff --git a/tests/native-grok-toggle.test.ts b/tests/codex-integration/native-grok-toggle.test.ts similarity index 95% rename from tests/native-grok-toggle.test.ts rename to tests/codex-integration/native-grok-toggle.test.ts index e73113eed2..d7c53f2224 100644 --- a/tests/native-grok-toggle.test.ts +++ b/tests/codex-integration/native-grok-toggle.test.ts @@ -2,12 +2,13 @@ import { afterEach, beforeEach, expect, test } from "bun:test"; import { mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { homedir, tmpdir } from "node:os"; import { join } from "node:path"; -import { handleManagementAPI } from "../src/server/management-api"; -import type { ManagementApiDeps } from "../src/server/management/context"; -import { syncGrokConfig } from "../src/grok/sync"; -import { injectGrokConfig, type GrokInjectModel } from "../src/grok/inject"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { handleManagementAPI } from "../../src/server/management-api"; +import type { ManagementApiDeps } from "../../src/server/management/context"; +import { syncGrokConfig } from "../../src/grok/sync"; +import { injectGrokConfig, type GrokInjectModel } from "../../src/grok/inject"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath } from "../helpers/repo-root"; /** * Route contract for devlog/_fin/260803_integrations_toggle_all/012 (Rev 3). @@ -334,14 +335,14 @@ test("a catalog failure refuses and writes nothing", async () => { }); test("the route never calls syncGrokConfig, and the inspector never re-implements the parser", () => { - const routeSource = readFileSync(join(import.meta.dir, "../src/server/management/native-integration-routes.ts"), "utf8"); + const routeSource = readFileSync(repoPath("src/server/management/native-integration-routes.ts"), "utf8"); // Comments may NAME the wrapper (they explain why it is bypassed); what must // not exist is an import of it or a call to it. expect(routeSource).not.toMatch(/import\s*\{[^}]*syncGrokConfig/); expect(routeSource).not.toMatch(/[^A-Za-z]syncGrokConfig\s*\(/); - const inspectSource = readFileSync(join(import.meta.dir, "../src/grok/inspect.ts"), "utf8"); + const inspectSource = readFileSync(repoPath("src/grok/inspect.ts"), "utf8"); expect(inspectSource).not.toContain("function findManagedRegion"); - const injectSource = readFileSync(join(import.meta.dir, "../src/grok/inject.ts"), "utf8"); + const injectSource = readFileSync(repoPath("src/grok/inject.ts"), "utf8"); expect(injectSource.match(/function findManagedRegion/g)).toHaveLength(1); }); @@ -499,12 +500,12 @@ test("a second concurrent PUT gets 409 config_busy and writes nothing", async () test("no journal row and no snapshot exist for this toggle", () => { // The module must not touch the file-client bookkeeping at all — a static // check that the imports were never widened (012 §OUT). - const routeSource = readFileSync(join(import.meta.dir, "../src/server/management/native-integration-routes.ts"), "utf8"); + const routeSource = readFileSync(repoPath("src/server/management/native-integration-routes.ts"), "utf8"); expect(routeSource).not.toMatch(/import[^;]*integrations\/(journal|store|writer)/); }); test("the ownership preflight itself is reachable, not declared", async () => { - const { assertNativeTeardownOwned } = await import("../src/integrations/native/ownership-preflight"); + const { assertNativeTeardownOwned } = await import("../../src/integrations/native/ownership-preflight"); // The beforeEach fixture already records the CURRENT homes under // OPENCODEX_HOME: owned. expect(assertNativeTeardownOwned().ok).toBe(true); diff --git a/tests/native-main-auth-temp.test.ts b/tests/codex-integration/native-main-auth-temp.test.ts similarity index 94% rename from tests/native-main-auth-temp.test.ts rename to tests/codex-integration/native-main-auth-temp.test.ts index 673b1e0eea..ab924f8e27 100644 --- a/tests/native-main-auth-temp.test.ts +++ b/tests/codex-integration/native-main-auth-temp.test.ts @@ -13,10 +13,10 @@ import { import { tmpdir } from "node:os"; import { join } from "node:path"; -import { scrubNativeMainAuthTempResidues } from "../src/codex/native-main-auth-temp"; -import { resolveNativeProfileContext } from "../src/codex/native-profile-store"; -import { NativeProfileError } from "../src/codex/native-profile-types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { scrubNativeMainAuthTempResidues } from "../../src/codex/native-main-auth-temp"; +import { resolveNativeProfileContext } from "../../src/codex/native-profile-store"; +import { NativeProfileError } from "../../src/codex/native-profile-types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/native-main-claim-cache.test.ts b/tests/codex-integration/native-main-claim-cache.test.ts similarity index 97% rename from tests/native-main-claim-cache.test.ts rename to tests/codex-integration/native-main-claim-cache.test.ts index b4adbf8a03..af19c6394d 100644 --- a/tests/native-main-claim-cache.test.ts +++ b/tests/codex-integration/native-main-claim-cache.test.ts @@ -4,7 +4,7 @@ import { hardenedIdentities, NATIVE_MAIN_HARDENED_IDENTITY_MAX_ENTRIES, rememberHardenedIdentity, -} from "../src/codex/native-main-claim"; +} from "../../src/codex/native-main-claim"; beforeEach(() => { hardenedIdentities.clear(); diff --git a/tests/native-main-claim.test.ts b/tests/codex-integration/native-main-claim.test.ts similarity index 95% rename from tests/native-main-claim.test.ts rename to tests/codex-integration/native-main-claim.test.ts index 05316650fd..f4754b550b 100644 --- a/tests/native-main-claim.test.ts +++ b/tests/codex-integration/native-main-claim.test.ts @@ -7,10 +7,11 @@ import { nativeMainClaimPath, withNativeMainExclusiveClaim, withNativeMainSharedClaim, -} from "../src/codex/native-main-claim"; -import { retainNativeMainOwner } from "../src/codex/native-main-owner"; -import type { NativeProfileContext } from "../src/codex/native-profile-store"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/native-main-claim"; +import { retainNativeMainOwner } from "../../src/codex/native-main-owner"; +import type { NativeProfileContext } from "../../src/codex/native-profile-store"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { helperPath, repoRoot } from "../helpers/repo-root"; const roots: string[] = []; const noHardening = async (): Promise => {}; @@ -118,9 +119,9 @@ describe("native-main shared and exclusive claims", () => { const child = Bun.spawn([ process.execPath, - join(import.meta.dir, "helpers", "native-main-claim-child.ts"), + helperPath("native-main-claim-child.ts"), context.codexHome, - ], { cwd: join(import.meta.dir, ".."), stdout: "pipe", stderr: "pipe" }); + ], { cwd: repoRoot(), stdout: "pipe", stderr: "pipe" }); const [exitCode, stdout, stderr] = await Promise.all([ child.exited, new Response(child.stdout).text(), diff --git a/tests/native-main-owner-lifetime.test.ts b/tests/codex-integration/native-main-owner-lifetime.test.ts similarity index 97% rename from tests/native-main-owner-lifetime.test.ts rename to tests/codex-integration/native-main-owner-lifetime.test.ts index b88a05f56e..49d42dcae6 100644 --- a/tests/native-main-owner-lifetime.test.ts +++ b/tests/codex-integration/native-main-owner-lifetime.test.ts @@ -11,21 +11,22 @@ import { } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; -import { watchdogMs } from "./helpers/ci-watchdog"; +import { watchdogMs } from "../helpers/ci-watchdog"; -import { saveConfig } from "../src/config"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/main-account"; +import { saveConfig } from "../../src/config"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/main-account"; import { NATIVE_MAIN_OWNER_DB, nativeMainOwnerFilesystemSupported, retainNativeMainOwner, withNativeMainOwnerOperation, -} from "../src/codex/native-main-owner"; -import { NativeProfileManager } from "../src/codex/native-profile-manager"; -import { probeNativeProfileRecoveryState } from "../src/codex/native-profile-store"; -import type { NativeProfileKey, NativeProfileKeyProvider } from "../src/codex/native-profile-types"; -import type { OcxConfig } from "../src/types"; +} from "../../src/codex/native-main-owner"; +import { NativeProfileManager } from "../../src/codex/native-profile-manager"; +import { probeNativeProfileRecoveryState } from "../../src/codex/native-profile-store"; +import type { NativeProfileKey, NativeProfileKeyProvider } from "../../src/codex/native-profile-types"; +import type { OcxConfig } from "../../src/types"; +import { helperPath, repoRoot } from "../helpers/repo-root"; const roots: string[] = []; const previousCodexHome = process.env.CODEX_HOME; @@ -165,8 +166,8 @@ class ChildHarness { private readonly waiters = new Set<() => void>(); constructor(f: Fixture, extraEnv: Record = {}) { - this.child = Bun.spawn([process.execPath, join(import.meta.dir, "helpers", "native-main-owner-child.ts")], { - cwd: join(import.meta.dir, ".."), + this.child = Bun.spawn([process.execPath, helperPath("native-main-owner-child.ts")], { + cwd: repoRoot(), env: { ...process.env, HOME: f.root, diff --git a/tests/native-model-toggle.test.ts b/tests/codex-integration/native-model-toggle.test.ts similarity index 98% rename from tests/native-model-toggle.test.ts rename to tests/codex-integration/native-model-toggle.test.ts index 60bc5e7ec2..52044cde5a 100644 --- a/tests/native-model-toggle.test.ts +++ b/tests/codex-integration/native-model-toggle.test.ts @@ -22,18 +22,18 @@ import { trustedAccountBoundNativeCatalogSlug, visibleCodexAccountSelectors, visibleNativeSlugs, -} from "../src/codex/catalog"; -import { handleManagementAPI } from "../src/server/management-api"; -import { applyMultiAgentMode, applyNativeOpenAiContextOverride } from "../src/codex/catalog/parsing"; -import { NATIVE_GPT56_CONTEXT_WINDOW, NATIVE_GPT56_OPT_IN_CONTEXT_WINDOW, nativeOpenAiContextTier, nativeOpenAiContextWindow } from "../src/codex/catalog"; -import type { OcxConfig } from "../src/types"; -import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../src/codex/catalog/native-models"; +} from "../../src/codex/catalog"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { applyMultiAgentMode, applyNativeOpenAiContextOverride } from "../../src/codex/catalog/parsing"; +import { NATIVE_GPT56_CONTEXT_WINDOW, NATIVE_GPT56_OPT_IN_CONTEXT_WINDOW, nativeOpenAiContextTier, nativeOpenAiContextWindow } from "../../src/codex/catalog"; +import type { OcxConfig } from "../../src/types"; +import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../../src/codex/catalog/native-models"; import { GATED_MODEL_CLIENT_VERSION_FLOOR, resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests, -} from "../src/codex/model-entitlements"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/model-entitlements"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; afterEach(() => resetCodexModelEntitlementCacheForTests()); @@ -835,7 +835,7 @@ describe("native GPT model toggles (bare slugs in disabledModels)", () => { } }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; describe("#2574 a stale on-disk row is what a subagent reads", () => { /** diff --git a/tests/native-profile-api.test.ts b/tests/codex-integration/native-profile-api.test.ts similarity index 98% rename from tests/native-profile-api.test.ts rename to tests/codex-integration/native-profile-api.test.ts index 89a3ff36ea..dafe059a6b 100644 --- a/tests/native-profile-api.test.ts +++ b/tests/codex-integration/native-profile-api.test.ts @@ -1,21 +1,21 @@ import { afterEach, describe, expect, test } from "bun:test"; import { join } from "node:path"; import { tmpdir, userInfo } from "node:os"; -import type { OcxConfig } from "../src/types"; -import { handleNativeProfileAPI } from "../src/codex/native-profile-api"; -import type { NativeProfileManager } from "../src/codex/native-profile-manager"; -import { NativeProfileError } from "../src/codex/native-profile-types"; +import type { OcxConfig } from "../../src/types"; +import { handleNativeProfileAPI } from "../../src/codex/native-profile-api"; +import type { NativeProfileManager } from "../../src/codex/native-profile-manager"; +import { NativeProfileError } from "../../src/codex/native-profile-types"; import { codexAccountSelectionForTurn, resetLifecycleDrainStateForTests, tryAdmitTurn, -} from "../src/server/lifecycle"; +} from "../../src/server/lifecycle"; import { blockNativeMainRecovery, completeNativeMainRecovery, initializeNativeMainStartupGate, nativeMainStartupGateSnapshot, -} from "../src/codex/native-profile-startup"; +} from "../../src/codex/native-profile-startup"; const originalCodexHome = process.env.CODEX_HOME; diff --git a/tests/native-profile-crash-boundaries.test.ts b/tests/codex-integration/native-profile-crash-boundaries.test.ts similarity index 95% rename from tests/native-profile-crash-boundaries.test.ts rename to tests/codex-integration/native-profile-crash-boundaries.test.ts index 48bd106b90..59624a379a 100644 --- a/tests/native-profile-crash-boundaries.test.ts +++ b/tests/codex-integration/native-profile-crash-boundaries.test.ts @@ -3,15 +3,16 @@ import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/main-account"; -import { NativeProfileManager, type NativeProfileSwitchBoundary } from "../src/codex/native-profile-manager"; -import { readNativeProfileJournal, readNativeProfileVault } from "../src/codex/native-profile-store"; -import type { NativeProfileKey, NativeProfileKeyProvider } from "../src/codex/native-profile-types"; -import type { OcxConfig } from "../src/types"; -import { INTERNAL_DEADLINE_MS } from "./helpers/test-budget"; -import { watchdogMs } from "./helpers/ci-watchdog"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { saveConfig } from "../../src/config"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/main-account"; +import { NativeProfileManager, type NativeProfileSwitchBoundary } from "../../src/codex/native-profile-manager"; +import { readNativeProfileJournal, readNativeProfileVault } from "../../src/codex/native-profile-store"; +import type { NativeProfileKey, NativeProfileKeyProvider } from "../../src/codex/native-profile-types"; +import type { OcxConfig } from "../../src/types"; +import { INTERNAL_DEADLINE_MS } from "../helpers/test-budget"; +import { watchdogMs } from "../helpers/ci-watchdog"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { helperPath, repoRoot } from "../helpers/repo-root"; /** * How long to wait for a spawned startup child to publish its port file. @@ -160,8 +161,8 @@ async function stopStartup( } function spawnSwitch(f: Awaited>, options: { boundary?: NativeProfileSwitchBoundary; marker?: string; release?: string; contention?: string; result: string }) { - return Bun.spawn([process.execPath, join(import.meta.dir, "helpers", "native-profile-switch-child.ts")], { - cwd: join(import.meta.dir, ".."), + return Bun.spawn([process.execPath, helperPath("native-profile-switch-child.ts")], { + cwd: repoRoot(), env: { ...process.env, HOME: f.home, @@ -190,8 +191,8 @@ function spawnStartup( p: ReturnType, extraEnv: Record = {}, ) { - return Bun.spawn([process.execPath, join(import.meta.dir, "helpers", "native-profile-startup-child.ts")], { - cwd: join(import.meta.dir, ".."), + return Bun.spawn([process.execPath, helperPath("native-profile-startup-child.ts")], { + cwd: repoRoot(), env: { ...process.env, HOME: f.home, USERPROFILE: f.home, CODEX_HOME: f.codexHome, OPENCODEX_HOME: f.configDir, OPENCODEX_ADMIN_AUTH_TOKEN: "crash-test-admin", diff --git a/tests/native-profile-drain-server.test.ts b/tests/codex-integration/native-profile-drain-server.test.ts similarity index 93% rename from tests/native-profile-drain-server.test.ts rename to tests/codex-integration/native-profile-drain-server.test.ts index 48ecbe9b60..34fc9f71c5 100644 --- a/tests/native-profile-drain-server.test.ts +++ b/tests/codex-integration/native-profile-drain-server.test.ts @@ -3,29 +3,29 @@ import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { request as httpRequest } from "node:http"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { resetMainCodexAccountIdentityTrackingForTests } from "../src/codex/account-lifecycle"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/account-id"; -import { clearMainAccountInfoCache } from "../src/codex/main-account-cache"; -import { clearAccountQuota, updateAccountQuota } from "../src/codex/quota"; -import { clearThreadAccountMap } from "../src/codex/routing"; -import { saveConfig } from "../src/config"; -import { handleNativeProfileAPI } from "../src/codex/native-profile-api"; -import { CODEX_MAIN_PROFILE_MAINTENANCE_MESSAGE } from "../src/codex/auth-context"; -import type { NativeProfileManager } from "../src/codex/native-profile-manager"; -import { waitForNativeMainStartupGate } from "../src/codex/native-profile-startup"; -import { startServer } from "../src/server"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { resetMainCodexAccountIdentityTrackingForTests } from "../../src/codex/account-lifecycle"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/account-id"; +import { clearMainAccountInfoCache } from "../../src/codex/main-account-cache"; +import { clearAccountQuota, updateAccountQuota } from "../../src/codex/quota"; +import { clearThreadAccountMap } from "../../src/codex/routing"; +import { saveConfig } from "../../src/config"; +import { handleNativeProfileAPI } from "../../src/codex/native-profile-api"; +import { CODEX_MAIN_PROFILE_MAINTENANCE_MESSAGE } from "../../src/codex/auth-context"; +import type { NativeProfileManager } from "../../src/codex/native-profile-manager"; +import { waitForNativeMainStartupGate } from "../../src/codex/native-profile-startup"; +import { startServer } from "../../src/server"; import { acquireNativeMainProfileDrain, getNativeMainProfileRequestCount, resetLifecycleDrainStateForTests, -} from "../src/server/lifecycle"; -import type { OcxConfig } from "../src/types"; -import { fakeChatGptJwt } from "./helpers/fake-chatgpt-jwt"; -import { ownedServiceHomeInspection } from "./helpers/owned-service-home-inspection"; +} from "../../src/server/lifecycle"; +import type { OcxConfig } from "../../src/types"; +import { fakeChatGptJwt } from "../helpers/fake-chatgpt-jwt"; +import { ownedServiceHomeInspection } from "../helpers/owned-service-home-inspection"; -import { watchdogMs } from "./helpers/ci-watchdog"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { watchdogMs } from "../helpers/ci-watchdog"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** These cases sandbox CODEX_HOME/OPENCODEX_HOME, so the installed service is not their evidence. */ const inspectNativeCodexOwnership = ownedServiceHomeInspection("native-profile drain server test"); diff --git a/tests/native-profile-manager.test.ts b/tests/codex-integration/native-profile-manager.test.ts similarity index 99% rename from tests/native-profile-manager.test.ts rename to tests/codex-integration/native-profile-manager.test.ts index 8e0d654796..5d7a29509f 100644 --- a/tests/native-profile-manager.test.ts +++ b/tests/codex-integration/native-profile-manager.test.ts @@ -2,7 +2,7 @@ import { afterEach, describe, expect, test } from "bun:test"; import { existsSync, linkSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; -import { NativeProfileManager } from "../src/codex/native-profile-manager"; +import { NativeProfileManager } from "../../src/codex/native-profile-manager"; import { decryptNativeEnvelope, MAX_NATIVE_PROFILE_JOURNAL_BYTES, @@ -12,10 +12,11 @@ import { probeNativeProfileRecoveryState, readNativeProfileVault, type NativeEnvelopeSnapshot, -} from "../src/codex/native-profile-store"; -import { NativeProfileError, type NativeProfileKey, type NativeProfileKeyProvider } from "../src/codex/native-profile-types"; -import { codexCredentialMutationEpoch } from "../src/codex/credential-mutation-epoch"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/native-profile-store"; +import { NativeProfileError, type NativeProfileKey, type NativeProfileKeyProvider } from "../../src/codex/native-profile-types"; +import { codexCredentialMutationEpoch } from "../../src/codex/credential-mutation-epoch"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { helperPath, repoRoot } from "../helpers/repo-root"; const roots: string[] = []; @@ -155,8 +156,8 @@ function spawnLockHolder( releasePath: string, options: { crash?: boolean; contention?: string } = {}, ): ReturnType { - return Bun.spawn([process.execPath, join(import.meta.dir, "helpers", "native-profile-lock-child.ts")], { - cwd: join(import.meta.dir, ".."), + return Bun.spawn([process.execPath, helperPath("native-profile-lock-child.ts")], { + cwd: repoRoot(), env: { ...process.env, NATIVE_PROFILE_TEST_CODEX_HOME: f.codexHome, @@ -176,8 +177,8 @@ function spawnLockProbe( f: ReturnType, resultPath: string, ): ReturnType { - return Bun.spawn([process.execPath, join(import.meta.dir, "helpers", "native-profile-lock-child.ts")], { - cwd: join(import.meta.dir, ".."), + return Bun.spawn([process.execPath, helperPath("native-profile-lock-child.ts")], { + cwd: repoRoot(), env: { ...process.env, NATIVE_PROFILE_TEST_CODEX_HOME: f.codexHome, diff --git a/tests/native-profile-processes.test.ts b/tests/codex-integration/native-profile-processes.test.ts similarity index 98% rename from tests/native-profile-processes.test.ts rename to tests/codex-integration/native-profile-processes.test.ts index 8427811676..0a5c449d12 100644 --- a/tests/native-profile-processes.test.ts +++ b/tests/codex-integration/native-profile-processes.test.ts @@ -6,9 +6,9 @@ import { executeNativeProcess, probeNativeCodexProcesses, type NativeProcessExecutor, -} from "../src/codex/native-profile-processes"; -import { setTrustedWindowsSystemDirectoryResolverForTests } from "../src/lib/windows-elevation"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/native-profile-processes"; +import { setTrustedWindowsSystemDirectoryResolverForTests } from "../../src/lib/windows-elevation"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; async function withTrustedWindowsPowerShell(run: (powershell: string) => Promise): Promise { const systemDirectory = mkdtempSync(join(tmpdir(), "ocx-system32-")); diff --git a/tests/native-profile-recovery.test.ts b/tests/codex-integration/native-profile-recovery.test.ts similarity index 98% rename from tests/native-profile-recovery.test.ts rename to tests/codex-integration/native-profile-recovery.test.ts index 4e7eb57f4e..b9cce8ed1c 100644 --- a/tests/native-profile-recovery.test.ts +++ b/tests/codex-integration/native-profile-recovery.test.ts @@ -4,7 +4,7 @@ import { decideNativeProfileRecovery, type NativeProfileAuthObservation, type NativeProfileJournalPhase, -} from "../src/codex/native-profile-recovery"; +} from "../../src/codex/native-profile-recovery"; const phases: NativeProfileJournalPhase[] = [ "prepared", diff --git a/tests/native-profile-route-security.test.ts b/tests/codex-integration/native-profile-route-security.test.ts similarity index 95% rename from tests/native-profile-route-security.test.ts rename to tests/codex-integration/native-profile-route-security.test.ts index 87075959ea..4185b2f19c 100644 --- a/tests/native-profile-route-security.test.ts +++ b/tests/codex-integration/native-profile-route-security.test.ts @@ -2,14 +2,14 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; -import type { NativeProfileManager } from "../src/codex/native-profile-manager"; -import { startServer } from "../src/server"; -import { initializeManagementAuthState, issueGuiSession, type ManagementAuthState } from "../src/server/management-auth"; -import { consumeGuiPairingGrant, createGuiPairingGrant } from "../src/server/gui-session"; -import type { OcxConfig } from "../src/types"; -import { SERVER_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { saveConfig } from "../../src/config"; +import type { NativeProfileManager } from "../../src/codex/native-profile-manager"; +import { startServer } from "../../src/server"; +import { initializeManagementAuthState, issueGuiSession, type ManagementAuthState } from "../../src/server/management-auth"; +import { consumeGuiPairingGrant, createGuiPairingGrant } from "../../src/server/gui-session"; +import type { OcxConfig } from "../../src/types"; +import { SERVER_BUDGET_MS } from "../helpers/test-budget"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const previousHome = process.env.HOME; const previousOpenCodexHome = process.env.OPENCODEX_HOME; diff --git a/tests/native-profile-stage-lifecycle.test.ts b/tests/codex-integration/native-profile-stage-lifecycle.test.ts similarity index 98% rename from tests/native-profile-stage-lifecycle.test.ts rename to tests/codex-integration/native-profile-stage-lifecycle.test.ts index dd521089eb..bc69711884 100644 --- a/tests/native-profile-stage-lifecycle.test.ts +++ b/tests/codex-integration/native-profile-stage-lifecycle.test.ts @@ -14,12 +14,12 @@ import { import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; -import { NativeProfileManager } from "../src/codex/native-profile-manager"; +import { NativeProfileManager } from "../../src/codex/native-profile-manager"; import { startNativeMainStartupLifecycle, type NativeMainStartupLifecycle, -} from "../src/codex/native-profile-startup"; -import { NativeProfileError, type NativeProfileKey, type NativeProfileKeyProvider } from "../src/codex/native-profile-types"; +} from "../../src/codex/native-profile-startup"; +import { NativeProfileError, type NativeProfileKey, type NativeProfileKeyProvider } from "../../src/codex/native-profile-types"; const roots: string[] = []; const lifecycles: NativeMainStartupLifecycle[] = []; diff --git a/tests/native-profile-startup.test.ts b/tests/codex-integration/native-profile-startup.test.ts similarity index 98% rename from tests/native-profile-startup.test.ts rename to tests/codex-integration/native-profile-startup.test.ts index d9e9123d13..ed0a622769 100644 --- a/tests/native-profile-startup.test.ts +++ b/tests/codex-integration/native-profile-startup.test.ts @@ -9,11 +9,11 @@ import { import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/main-account"; -import { NativeProfileManager } from "../src/codex/native-profile-manager"; -import { handleNativeProfileAPI } from "../src/codex/native-profile-api"; +import { saveConfig } from "../../src/config"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/main-account"; +import { NativeProfileManager } from "../../src/codex/native-profile-manager"; +import { handleNativeProfileAPI } from "../../src/codex/native-profile-api"; import { encryptNativeEnvelope, probeNativeProfileRecoveryState, @@ -21,13 +21,13 @@ import { readNativeProfileVault, inspectNativeProfileJournal, serializeNativeProfileJournal, -} from "../src/codex/native-profile-store"; +} from "../../src/codex/native-profile-store"; import type { NativeProfileKey, NativeProfileKeyProvider, NativeProfileSwitchJournalV1, -} from "../src/codex/native-profile-types"; -import type { OcxConfig } from "../src/types"; +} from "../../src/codex/native-profile-types"; +import type { OcxConfig } from "../../src/types"; import { bindNativeMainStartupLifecycle, blockNativeMainStartupForUnownedServiceHome, @@ -40,19 +40,20 @@ import { type NativeMainStartupLifecycle, waitForNativeMainStartupGate, __resetNativeMainOwnershipRetries, -} from "../src/codex/native-profile-startup"; -import type { NativeCodexOwnership } from "../src/integrations/native/ownership-preflight"; +} from "../../src/codex/native-profile-startup"; +import type { NativeCodexOwnership } from "../../src/integrations/native/ownership-preflight"; import { tryAcquireNativeMainProfileClaim, tryClaimNativeMainProfileForTurn, -} from "../src/codex/native-main-admission"; +} from "../../src/codex/native-main-admission"; import { getNativeMainProfileRequestCount, resetLifecycleDrainStateForTests, tryAdmitTurn, -} from "../src/server/lifecycle"; -import { startServer } from "../src/server"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/server/lifecycle"; +import { startServer } from "../../src/server"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { helperPath, repoRoot } from "../helpers/repo-root"; const roots: string[] = []; const previousOpencodexHome = process.env.OPENCODEX_HOME; @@ -262,8 +263,8 @@ function childPaths(f: Fixture) { } function spawnChild(f: Fixture, paths: ReturnType): ReturnType { - return Bun.spawn([process.execPath, join(import.meta.dir, "helpers", "native-profile-startup-child.ts")], { - cwd: join(import.meta.dir, ".."), + return Bun.spawn([process.execPath, helperPath("native-profile-startup-child.ts")], { + cwd: repoRoot(), env: { ...process.env, OPENCODEX_HOME: f.configDir, diff --git a/tests/native-profile-store.test.ts b/tests/codex-integration/native-profile-store.test.ts similarity index 98% rename from tests/native-profile-store.test.ts rename to tests/codex-integration/native-profile-store.test.ts index a133c91d03..13b26b5b42 100644 --- a/tests/native-profile-store.test.ts +++ b/tests/codex-integration/native-profile-store.test.ts @@ -15,15 +15,15 @@ import { resolveNativeProfileContext, serializeNativeProfileJournal, type NativeProfileContext, -} from "../src/codex/native-profile-store"; +} from "../../src/codex/native-profile-store"; import { NativeProfileError, type EncryptedNativeEnvelopeV1, type NativeMainProfileRecordV1, type NativeMainProfileVaultV1, type NativeProfileSwitchJournalV1, -} from "../src/codex/native-profile-types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/native-profile-types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; const HOME_ID = "a".repeat(64); @@ -391,7 +391,7 @@ describe("native-profile recovery journal storage", () => { const configDir = join(base, "opencodex"); mkdirSync(codexHome, { mode: 0o700 }); mkdirSync(configDir, { mode: 0o700 }); - const moduleUrl = new URL("../src/codex/native-profile-store.ts", import.meta.url).href; + const moduleUrl = new URL("../../src/codex/native-profile-store.ts", import.meta.url).href; const childSource = ` import { execFileSync } from "node:child_process"; import { lstatSync, mkdirSync, unlinkSync, writeFileSync } from "node:fs"; diff --git a/tests/parallel-tool-calls-optin.test.ts b/tests/codex-integration/parallel-tool-calls-optin.test.ts similarity index 97% rename from tests/parallel-tool-calls-optin.test.ts rename to tests/codex-integration/parallel-tool-calls-optin.test.ts index 5b154e6ba8..689fd207f8 100644 --- a/tests/parallel-tool-calls-optin.test.ts +++ b/tests/codex-integration/parallel-tool-calls-optin.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { applyProviderConfigHints, normalizeRoutedCatalogEntry } from "../src/codex/catalog"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxParsedRequest, OcxTool } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { applyProviderConfigHints, normalizeRoutedCatalogEntry } from "../../src/codex/catalog"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxParsedRequest, OcxTool } from "../../src/types"; const tools: OcxTool[] = [{ name: "shell", description: "run", parameters: { type: "object" } }]; diff --git a/tests/project-config-warnings.test.ts b/tests/codex-integration/project-config-warnings.test.ts similarity index 99% rename from tests/project-config-warnings.test.ts rename to tests/codex-integration/project-config-warnings.test.ts index f59f7ba99e..16f9dd258d 100644 --- a/tests/project-config-warnings.test.ts +++ b/tests/codex-integration/project-config-warnings.test.ts @@ -13,8 +13,8 @@ import { parseTrustedProjectPathsFromCodexConfig, relPath, resolveEffectiveProjectModelProvider, -} from "../src/codex/project-config-warnings"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/project-config-warnings"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; describe("relPath home containment (devlog 260715_cross_platform_audit/030)", () => { let savedUserProfile: string | undefined; diff --git a/tests/reasoning-effort.test.ts b/tests/codex-integration/reasoning-effort.test.ts similarity index 98% rename from tests/reasoning-effort.test.ts rename to tests/codex-integration/reasoning-effort.test.ts index cf34b8070b..a5d3cd1114 100644 --- a/tests/reasoning-effort.test.ts +++ b/tests/codex-integration/reasoning-effort.test.ts @@ -1,12 +1,12 @@ import { describe, expect, test } from "bun:test"; -import { buildCatalogEntries } from "../src/codex/catalog"; -import { createAnthropicAdapter } from "../src/adapters/anthropic"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import type { AdapterRequest } from "../src/adapters/base"; -import { configuredReasoningEfforts, mapReasoningEffort, sanitizeCodexReasoningEfforts } from "../src/reasoning-effort"; -import { routeModel } from "../src/router"; -import { resolveWireProtocolOverride } from "../src/server/adapter-resolve"; -import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { buildCatalogEntries } from "../../src/codex/catalog"; +import { createAnthropicAdapter } from "../../src/adapters/anthropic"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import type { AdapterRequest } from "../../src/adapters/base"; +import { configuredReasoningEfforts, mapReasoningEffort, sanitizeCodexReasoningEfforts } from "../../src/reasoning-effort"; +import { routeModel } from "../../src/router"; +import { resolveWireProtocolOverride } from "../../src/server/adapter-resolve"; +import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../../src/types"; function nativeTemplate(): Record { return { diff --git a/tests/selected-models.test.ts b/tests/codex-integration/selected-models.test.ts similarity index 98% rename from tests/selected-models.test.ts rename to tests/codex-integration/selected-models.test.ts index 755060410c..df6aa22586 100644 --- a/tests/selected-models.test.ts +++ b/tests/codex-integration/selected-models.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { filterCatalogVisibleModels, type CatalogModel } from "../src/codex/catalog"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { filterCatalogVisibleModels, type CatalogModel } from "../../src/codex/catalog"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; function m(provider: string, id: string): CatalogModel { return { provider, id, owned_by: provider }; diff --git a/tests/slug-codec.test.ts b/tests/codex-integration/slug-codec.test.ts similarity index 97% rename from tests/slug-codec.test.ts rename to tests/codex-integration/slug-codec.test.ts index 5482fcca17..611754ce18 100644 --- a/tests/slug-codec.test.ts +++ b/tests/codex-integration/slug-codec.test.ts @@ -14,13 +14,13 @@ import { slugEquals, slugEquivalenceKey, slugsEquivalent, -} from "../src/providers/slug-codec"; -import { knownModelIdsForProvider, routeModel } from "../src/router"; -import { buildCatalogEntries, resetCatalogRuntimeStateForTests } from "../src/codex/catalog"; -import { clearModelCache, setCached } from "../src/codex/model-cache"; -import { getModelMetadata } from "../src/generated/model-metadata"; -import type { RawEntry } from "../src/codex/catalog"; -import type { OcxConfig } from "../src/types"; +} from "../../src/providers/slug-codec"; +import { knownModelIdsForProvider, routeModel } from "../../src/router"; +import { buildCatalogEntries, resetCatalogRuntimeStateForTests } from "../../src/codex/catalog"; +import { clearModelCache, setCached } from "../../src/codex/model-cache"; +import { getModelMetadata } from "../../src/generated/model-metadata"; +import type { RawEntry } from "../../src/codex/catalog"; +import type { OcxConfig } from "../../src/types"; beforeEach(() => { clearModelCache(); diff --git a/tests/token-guardian.test.ts b/tests/codex-integration/token-guardian.test.ts similarity index 96% rename from tests/token-guardian.test.ts rename to tests/codex-integration/token-guardian.test.ts index d3bcf99ec7..7c8e09ec85 100644 --- a/tests/token-guardian.test.ts +++ b/tests/codex-integration/token-guardian.test.ts @@ -2,17 +2,17 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveCredential } from "../src/oauth/store"; -import { getConfigPath } from "../src/config"; -import { markCodexAccountValidated, readCodexAccountRecord, saveCodexAccountCredential } from "../src/codex/account-store"; -import { __resetGuardianState, guardianSweep } from "../src/oauth/token-guardian"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { saveCredential } from "../../src/oauth/store"; +import { getConfigPath } from "../../src/config"; +import { markCodexAccountValidated, readCodexAccountRecord, saveCodexAccountCredential } from "../../src/codex/account-store"; +import { __resetGuardianState, guardianSweep } from "../../src/oauth/token-guardian"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; import { acquireNativeMainProfileDrain, getNativeMainProfileRequestCount, resetLifecycleDrainStateForTests, -} from "../src/server/lifecycle"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/server/lifecycle"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const origHome = process.env.HOME; const origOcxHome = process.env.OPENCODEX_HOME; diff --git a/tests/ultrafast-tier-honesty.test.ts b/tests/codex-integration/ultrafast-tier-honesty.test.ts similarity index 97% rename from tests/ultrafast-tier-honesty.test.ts rename to tests/codex-integration/ultrafast-tier-honesty.test.ts index a1f97af6de..9ba3a77d87 100644 --- a/tests/ultrafast-tier-honesty.test.ts +++ b/tests/codex-integration/ultrafast-tier-honesty.test.ts @@ -12,9 +12,9 @@ * for nothing. These tests pin the corrected accounting. */ import { describe, expect, test } from "bun:test"; -import { canonicalFastTierMarker, createAdapterTierMetadata, decideTier, tierObservationContext } from "../src/providers/fastwire"; -import { requestLogSpeedLabel } from "../src/server/request-log"; -import { normalizeRoutedCatalogEntry } from "../src/codex/catalog/parsing"; +import { canonicalFastTierMarker, createAdapterTierMetadata, decideTier, tierObservationContext } from "../../src/providers/fastwire"; +import { requestLogSpeedLabel } from "../../src/server/request-log"; +import { normalizeRoutedCatalogEntry } from "../../src/codex/catalog/parsing"; describe("ultrafast intent is recognised, not mistaken for silence", () => { test("the caller marker folds ultrafast to its own canonical, not to priority", () => { diff --git a/tests/upstream-reachability.test.ts b/tests/codex-integration/upstream-reachability.test.ts similarity index 98% rename from tests/upstream-reachability.test.ts rename to tests/codex-integration/upstream-reachability.test.ts index 6c3a32a2d7..064131bec4 100644 --- a/tests/upstream-reachability.test.ts +++ b/tests/codex-integration/upstream-reachability.test.ts @@ -4,8 +4,8 @@ import { isPreConnectReachabilityError, transportErrorCode, MAX_REACHABILITY_CAUSE_DEPTH, -} from "../src/lib/upstream-reachability"; -import { UpstreamRetryEvidenceError } from "../src/lib/upstream-retry"; +} from "../../src/lib/upstream-reachability"; +import { UpstreamRetryEvidenceError } from "../../src/lib/upstream-retry"; import { UPSTREAM_HOST_CIRCUIT_COOLDOWN_MS, UPSTREAM_HOST_CIRCUIT_MAX_THRESHOLD, @@ -21,13 +21,13 @@ import { resetUpstreamHostHealth, upstreamHostHealthKey, type UpstreamHostAdmissionLease, -} from "../src/codex/upstream-host-health"; +} from "../../src/codex/upstream-host-health"; import { maybePrimeSubagentQuota, resetSubagentModelFallbackStateForTests, setSubagentQuotaPrimeForTests, -} from "../src/codex/subagent-model-fallback"; -import type { OcxConfig } from "../src/types"; +} from "../../src/codex/subagent-model-fallback"; +import type { OcxConfig } from "../../src/types"; beforeEach(() => { clearUpstreamHostHealth(); diff --git a/tests/warmup.test.ts b/tests/codex-integration/warmup.test.ts similarity index 99% rename from tests/warmup.test.ts rename to tests/codex-integration/warmup.test.ts index 5727627021..33fb3504a1 100644 --- a/tests/warmup.test.ts +++ b/tests/codex-integration/warmup.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect, mock, spyOn, test } from "bun:test"; -import { CodexWarmupError, codexWarmupFailureReason, warmCodexAccount } from "../src/codex/warmup"; +import { CodexWarmupError, codexWarmupFailureReason, warmCodexAccount } from "../../src/codex/warmup"; const originalFetch = globalThis.fetch; diff --git a/tests/helpers/repo-root.ts b/tests/helpers/repo-root.ts index 84850bdae9..7943005cc1 100644 --- a/tests/helpers/repo-root.ts +++ b/tests/helpers/repo-root.ts @@ -38,3 +38,8 @@ export function repoPath(...segments: string[]): string { export function helperPath(name: string): string { return join(repoRoot(), "tests", "helpers", name); } + +/** Absolute path of a file under tests/fixtures. */ +export function fixturePath(...segments: string[]): string { + return join(repoRoot(), "tests", "fixtures", ...segments); +} diff --git a/tests/lib/transient-budget-scope-source.test.ts b/tests/lib/transient-budget-scope-source.test.ts index 3c63b493df..e693deb0ff 100644 --- a/tests/lib/transient-budget-scope-source.test.ts +++ b/tests/lib/transient-budget-scope-source.test.ts @@ -16,7 +16,7 @@ const source = (relative: string): string => * The continuation leg shipped on the raw policy value instead, so a request that reached it * received a fresh full `attempts` allowance: with `attempts: 3` an initial send that had * already spent its budget could still emit three more upstream sends. Runtime coverage in - * `tests/upstream-transient-retry.test.ts` proves the helper reports and honors a remainder; + * `tests/providers/upstream-transient-retry.test.ts` proves the helper reports and honors a remainder; * it cannot prove that every call site asks for one, because a site that forgets simply * passes a larger number. This asserts the wiring at the source, which is the only place the * omission is visible. diff --git a/tests/alibaba-region-backup.test.ts b/tests/providers/alibaba-region-backup.test.ts similarity index 96% rename from tests/alibaba-region-backup.test.ts rename to tests/providers/alibaba-region-backup.test.ts index ff5ae930cc..6084c5c7b6 100644 --- a/tests/alibaba-region-backup.test.ts +++ b/tests/providers/alibaba-region-backup.test.ts @@ -5,8 +5,8 @@ import { join } from "node:path"; import { AlibabaBackupIntegrityError, backupConfigBeforeAlibabaRegionMigration, -} from "../src/providers/alibaba-region-backup"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/alibaba-region-backup"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; test("absent source produces no backup", () => { const dir = mkdtempSync(join(tmpdir(), "ocx-bak-")); diff --git a/tests/alibaba-region-migration.test.ts b/tests/providers/alibaba-region-migration.test.ts similarity index 95% rename from tests/alibaba-region-migration.test.ts rename to tests/providers/alibaba-region-migration.test.ts index e08a75bf66..0406fea22b 100644 --- a/tests/alibaba-region-migration.test.ts +++ b/tests/providers/alibaba-region-migration.test.ts @@ -2,11 +2,11 @@ import { expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { loadConfig, saveConfig } from "../src/config"; -import { projectAlibabaRegionMigration } from "../src/providers/alibaba-region-migration"; -import { routeModel } from "../src/router"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { loadConfig, saveConfig } from "../../src/config"; +import { projectAlibabaRegionMigration } from "../../src/providers/alibaba-region-migration"; +import { routeModel } from "../../src/router"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const INTL_URL = "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1"; diff --git a/tests/alibaba-region-startup.test.ts b/tests/providers/alibaba-region-startup.test.ts similarity index 91% rename from tests/alibaba-region-startup.test.ts rename to tests/providers/alibaba-region-startup.test.ts index eda003d503..ba578cb11b 100644 --- a/tests/alibaba-region-startup.test.ts +++ b/tests/providers/alibaba-region-startup.test.ts @@ -1,8 +1,8 @@ import { expect, test } from "bun:test"; -import { AlibabaBackupIntegrityError } from "../src/providers/alibaba-region-backup"; -import { projectAlibabaRegionMigration } from "../src/providers/alibaba-region-migration"; -import { runAlibabaRegionStartupMigration } from "../src/providers/alibaba-region-startup"; -import type { OcxConfig } from "../src/types"; +import { AlibabaBackupIntegrityError } from "../../src/providers/alibaba-region-backup"; +import { projectAlibabaRegionMigration } from "../../src/providers/alibaba-region-migration"; +import { runAlibabaRegionStartupMigration } from "../../src/providers/alibaba-region-startup"; +import type { OcxConfig } from "../../src/types"; const INTL_URL = "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1"; diff --git a/tests/aside-client.test.ts b/tests/providers/aside-client.test.ts similarity index 97% rename from tests/aside-client.test.ts rename to tests/providers/aside-client.test.ts index 6cb30bea50..abf4146ba8 100644 --- a/tests/aside-client.test.ts +++ b/tests/providers/aside-client.test.ts @@ -14,14 +14,14 @@ import { buildClientContribution, type ExportContext, type PiGeneratedConfig, -} from "../src/clients/config-export"; -import { INTEGRATION_CLIENTS, resolveIntegrationPaths, unresolvedPathHintFor } from "../src/integrations/registry"; -import { readIntegrationState } from "../src/integrations/state"; -import { createIntegrationStateStore } from "../src/integrations/store"; -import { defaultIntegrationIO } from "../src/integrations/config-io"; -import { applyIntegration } from "../src/integrations/writer"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/clients/config-export"; +import { INTEGRATION_CLIENTS, resolveIntegrationPaths, unresolvedPathHintFor } from "../../src/integrations/registry"; +import { readIntegrationState } from "../../src/integrations/state"; +import { createIntegrationStateStore } from "../../src/integrations/store"; +import { defaultIntegrationIO } from "../../src/integrations/config-io"; +import { applyIntegration } from "../../src/integrations/writer"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const CONFIG = { port: 10100, diff --git a/tests/auto-compact-budget.test.ts b/tests/providers/auto-compact-budget.test.ts similarity index 97% rename from tests/auto-compact-budget.test.ts rename to tests/providers/auto-compact-budget.test.ts index f7973d9247..7441757dbd 100644 --- a/tests/auto-compact-budget.test.ts +++ b/tests/providers/auto-compact-budget.test.ts @@ -3,7 +3,7 @@ import { describe, expect, test } from "bun:test"; import { clampAutoCompactTokenLimit, modelAutoCompactTokenLimitsConfigError, -} from "../src/providers/auto-compact-budget"; +} from "../../src/providers/auto-compact-budget"; describe("per-model auto-compaction budgets", () => { test("configuration only lowers the effective hard-limit envelope", () => { diff --git a/tests/azure-adapter.test.ts b/tests/providers/azure-adapter.test.ts similarity index 94% rename from tests/azure-adapter.test.ts rename to tests/providers/azure-adapter.test.ts index 9a68033917..f309734da9 100644 --- a/tests/azure-adapter.test.ts +++ b/tests/providers/azure-adapter.test.ts @@ -2,11 +2,11 @@ import { describe, expect, test } from "bun:test"; import { existsSync, mkdtempSync, readdirSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { createAzureAdapter as createAzureAdapterProduction } from "../src/adapters/azure"; -import { getConfigPath, loadConfig, readConfigDiagnostics } from "../src/config"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { createAzureAdapter as createAzureAdapterProduction } from "../../src/adapters/azure"; +import { getConfigPath, loadConfig, readConfigDiagnostics } from "../../src/config"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const createAzureAdapter = (...args: Parameters) => withTestTranslatorBudget(createAzureAdapterProduction(...args)); diff --git a/tests/azure-model-router-tool-schema.test.ts b/tests/providers/azure-model-router-tool-schema.test.ts similarity index 93% rename from tests/azure-model-router-tool-schema.test.ts rename to tests/providers/azure-model-router-tool-schema.test.ts index 352c000682..e1022e3c2d 100644 --- a/tests/azure-model-router-tool-schema.test.ts +++ b/tests/providers/azure-model-router-tool-schema.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../src/types"; const toolSchema = { oneOf: [ diff --git a/tests/baseten-provider.test.ts b/tests/providers/baseten-provider.test.ts similarity index 92% rename from tests/baseten-provider.test.ts rename to tests/providers/baseten-provider.test.ts index 70f168e9d4..8f3da5ed25 100644 --- a/tests/baseten-provider.test.ts +++ b/tests/providers/baseten-provider.test.ts @@ -1,24 +1,25 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; +} from "../../src/providers/derive"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; -const FIXTURE = readFileSync(join(import.meta.dir, "fixtures/baseten-models.json"), "utf8"); +const FIXTURE = readFileSync(fixturePath("baseten-models.json"), "utf8"); const originalFetch = globalThis.fetch; afterEach(() => { diff --git a/tests/chutes-provider.test.ts b/tests/providers/chutes-provider.test.ts similarity index 89% rename from tests/chutes-provider.test.ts rename to tests/providers/chutes-provider.test.ts index b7e945023e..3a49a5bdba 100644 --- a/tests/chutes-provider.test.ts +++ b/tests/providers/chutes-provider.test.ts @@ -1,25 +1,26 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { resolveProviderModelDiscovery } from "../src/providers/model-discovery"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; - -const CHUTES_FIXTURE = readFileSync(join(import.meta.dir, "fixtures/chutes-models.json"), "utf8"); +} from "../../src/providers/derive"; +import { resolveProviderModelDiscovery } from "../../src/providers/model-discovery"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; + +const CHUTES_FIXTURE = readFileSync(fixturePath("chutes-models.json"), "utf8"); const BASE_URL = "https://llm.chutes.ai/v1"; const MODELS_URL = `${BASE_URL}/models`; const TEST_KEY = "chutes-test-key"; diff --git a/tests/cline-pass-deepseek-v4-tool-replay.test.ts b/tests/providers/cline-pass-deepseek-v4-tool-replay.test.ts similarity index 92% rename from tests/cline-pass-deepseek-v4-tool-replay.test.ts rename to tests/providers/cline-pass-deepseek-v4-tool-replay.test.ts index 16ef1e2c78..0cba245597 100644 --- a/tests/cline-pass-deepseek-v4-tool-replay.test.ts +++ b/tests/providers/cline-pass-deepseek-v4-tool-replay.test.ts @@ -1,11 +1,11 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { createRegisteredAdapter } from "../src/adapters/registry"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { createRegisteredAdapter } from "../../src/adapters/registry"; import { stripClinePassDeepSeekV4ToolReplayNarration, -} from "../src/adapters/cline-pass-deepseek-v4-tool-replay"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../src/adapters/cline-pass-deepseek-v4-tool-replay"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../src/types"; +import { createTestTranslatorBudget } from "../helpers/translator-budget"; const TARGET_MODELS = [ "cline-pass/deepseek-v4-flash", diff --git a/tests/cline-pass-provider.test.ts b/tests/providers/cline-pass-provider.test.ts similarity index 96% rename from tests/cline-pass-provider.test.ts rename to tests/providers/cline-pass-provider.test.ts index c5e80cbecf..3db66eccd6 100644 --- a/tests/cline-pass-provider.test.ts +++ b/tests/providers/cline-pass-provider.test.ts @@ -1,11 +1,11 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { createTranslatorBudget } from "../src/lib/translator-budget"; -import { KEY_LOGIN_PROVIDERS } from "../src/oauth/key-providers"; -import { enrichProviderFromRegistry, providerConfigSeed } from "../src/providers/derive"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxParsedRequest } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { createTranslatorBudget } from "../../src/lib/translator-budget"; +import { KEY_LOGIN_PROVIDERS } from "../../src/oauth/key-providers"; +import { enrichProviderFromRegistry, providerConfigSeed } from "../../src/providers/derive"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxParsedRequest } from "../../src/types"; const OFFICIAL_CLINE_PASS_MODELS = [ "cline-pass/glm-5.3", diff --git a/tests/cline-pass-reasoning-efforts.test.ts b/tests/providers/cline-pass-reasoning-efforts.test.ts similarity index 95% rename from tests/cline-pass-reasoning-efforts.test.ts rename to tests/providers/cline-pass-reasoning-efforts.test.ts index 5b56b7b744..a0acff6078 100644 --- a/tests/cline-pass-reasoning-efforts.test.ts +++ b/tests/providers/cline-pass-reasoning-efforts.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxParsedRequest } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxParsedRequest } from "../../src/types"; const CLINE_PASS_MODELS = [ "cline-pass/glm-5.2", diff --git a/tests/cline-provider.test.ts b/tests/providers/cline-provider.test.ts similarity index 91% rename from tests/cline-provider.test.ts rename to tests/providers/cline-provider.test.ts index 3e912f98e1..4fee356379 100644 --- a/tests/cline-provider.test.ts +++ b/tests/providers/cline-provider.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { providerConfigSeed, deriveKeyLoginMap, deriveProviderPresets } from "../src/providers/derive"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { providerConfigSeed, deriveKeyLoginMap, deriveProviderPresets } from "../../src/providers/derive"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../src/types"; function minimalRequest(model: string): OcxParsedRequest { return { diff --git a/tests/command-code-error-finish.test.ts b/tests/providers/command-code-error-finish.test.ts similarity index 92% rename from tests/command-code-error-finish.test.ts rename to tests/providers/command-code-error-finish.test.ts index fc1ff3fcbc..44e969ca53 100644 --- a/tests/command-code-error-finish.test.ts +++ b/tests/providers/command-code-error-finish.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { createCommandCodeAdapter } from "../src/adapters/command-code"; -import { buildResponseJSON } from "../src/bridge"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import type { AdapterEvent, OcxProviderConfig } from "../src/types"; +import { createCommandCodeAdapter } from "../../src/adapters/command-code"; +import { buildResponseJSON } from "../../src/bridge"; +import { createTestTranslatorBudget } from "../helpers/translator-budget"; +import type { AdapterEvent, OcxProviderConfig } from "../../src/types"; const provider: OcxProviderConfig = { adapter: "command-code", diff --git a/tests/command-code-provider.test.ts b/tests/providers/command-code-provider.test.ts similarity index 98% rename from tests/command-code-provider.test.ts rename to tests/providers/command-code-provider.test.ts index 76aed55ccf..e4bb3c4d90 100644 --- a/tests/command-code-provider.test.ts +++ b/tests/providers/command-code-provider.test.ts @@ -1,15 +1,15 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { createCommandCodeAdapter } from "../src/adapters/command-code"; -import { loginCommandCode, parseCommandCodeCallback, shouldImportLocalCommandCodeAuth } from "../src/oauth/command-code"; -import { buildModelsRequest, OAUTH_PROVIDERS } from "../src/oauth"; +import { createCommandCodeAdapter } from "../../src/adapters/command-code"; +import { loginCommandCode, parseCommandCodeCallback, shouldImportLocalCommandCodeAuth } from "../../src/oauth/command-code"; +import { buildModelsRequest, OAUTH_PROVIDERS } from "../../src/oauth"; import { commandCodeReasoningEfforts, refreshCommandCodeReasoningEfforts, resetCommandCodeReasoningEffortsForTest, -} from "../src/providers/command-code-efforts"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../src/providers/command-code-efforts"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../src/types"; +import { createTestTranslatorBudget } from "../helpers/translator-budget"; const provider: OcxProviderConfig = { adapter: "command-code", diff --git a/tests/command-code-quota.test.ts b/tests/providers/command-code-quota.test.ts similarity index 98% rename from tests/command-code-quota.test.ts rename to tests/providers/command-code-quota.test.ts index 634adce216..32d607aa03 100644 --- a/tests/command-code-quota.test.ts +++ b/tests/providers/command-code-quota.test.ts @@ -2,10 +2,10 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveCredential } from "../src/oauth/store"; -import { clearProviderQuotaCache, fetchProviderQuotaReports } from "../src/providers/quota"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { saveCredential } from "../../src/oauth/store"; +import { clearProviderQuotaCache, fetchProviderQuotaReports } from "../../src/providers/quota"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const originalFetch = globalThis.fetch; const previousOpencodexHome = process.env.OPENCODEX_HOME; diff --git a/tests/command-code-workspace-cache.test.ts b/tests/providers/command-code-workspace-cache.test.ts similarity index 98% rename from tests/command-code-workspace-cache.test.ts rename to tests/providers/command-code-workspace-cache.test.ts index 6a8e6e536d..0b26a2521c 100644 --- a/tests/command-code-workspace-cache.test.ts +++ b/tests/providers/command-code-workspace-cache.test.ts @@ -3,7 +3,7 @@ import { workspaceMetadataCache, pruneWorkspaceMetadataCache, MAX_WORKSPACE_METADATA_ENTRIES, -} from "../src/adapters/command-code"; +} from "../../src/adapters/command-code"; beforeEach(() => { workspaceMetadataCache.clear(); diff --git a/tests/commandcode-provider.test.ts b/tests/providers/commandcode-provider.test.ts similarity index 91% rename from tests/commandcode-provider.test.ts rename to tests/providers/commandcode-provider.test.ts index b6d27a0366..e76355dc4f 100644 --- a/tests/commandcode-provider.test.ts +++ b/tests/providers/commandcode-provider.test.ts @@ -1,25 +1,26 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { providerModelDiscoverySpecError } from "../src/providers/model-discovery"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; - -const FIXTURE = readFileSync(join(import.meta.dir, "fixtures/commandcode-models.json"), "utf8"); +} from "../../src/providers/derive"; +import { providerModelDiscoverySpecError } from "../../src/providers/model-discovery"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; + +const FIXTURE = readFileSync(fixturePath("commandcode-models.json"), "utf8"); const originalFetch = globalThis.fetch; afterEach(() => { diff --git a/tests/context-cap-unknown-window.test.ts b/tests/providers/context-cap-unknown-window.test.ts similarity index 95% rename from tests/context-cap-unknown-window.test.ts rename to tests/providers/context-cap-unknown-window.test.ts index 79e46ff410..87ed6d2d30 100644 --- a/tests/context-cap-unknown-window.test.ts +++ b/tests/providers/context-cap-unknown-window.test.ts @@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test"; import { applyProviderContextCap, resolveUnknownRoutedContextWindow, -} from "../src/providers/context-cap"; +} from "../../src/providers/context-cap"; describe("unknown routed context windows", () => { test("an enabled cap fills a missing window instead of inventing 128k", () => { diff --git a/tests/cursor-adapter.test.ts b/tests/providers/cursor/cursor-adapter.test.ts similarity index 97% rename from tests/cursor-adapter.test.ts rename to tests/providers/cursor/cursor-adapter.test.ts index b891e06ba7..a86df7c243 100644 --- a/tests/cursor-adapter.test.ts +++ b/tests/providers/cursor/cursor-adapter.test.ts @@ -2,23 +2,23 @@ import { describe, expect, test } from "bun:test"; import { createCursorAdapter as createCursorAdapterProduction, cursorExecDeniedMessage, -} from "../src/adapters/cursor"; +} from "../../../src/adapters/cursor"; import { clearCursorThreadContinuityForTests, lookupCursorThreadConversation, -} from "../src/adapters/cursor/thread-continuity"; +} from "../../../src/adapters/cursor/thread-continuity"; import { clearCursorCheckpointsForTests, commitCursorCheckpoint, getCursorCheckpoint, -} from "../src/adapters/cursor/checkpoint-store"; +} from "../../../src/adapters/cursor/checkpoint-store"; import { create, toBinary } from "@bufbuild/protobuf"; -import { ConversationStateStructureSchema } from "../src/adapters/cursor/gen/agent_pb"; -import type { AdapterEvent, OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import type { CursorClientMessage, CursorRunRequest, CursorServerMessage } from "../src/adapters/cursor/types"; -import type { CursorTransportFactoryInput } from "../src/adapters/cursor/transport"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; -import { CursorRootEnvelopeLimitError } from "../src/adapters/cursor/cursor-errors"; +import { ConversationStateStructureSchema } from "../../../src/adapters/cursor/gen/agent_pb"; +import type { AdapterEvent, OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; +import type { CursorClientMessage, CursorRunRequest, CursorServerMessage } from "../../../src/adapters/cursor/types"; +import type { CursorTransportFactoryInput } from "../../../src/adapters/cursor/transport"; +import { withTestTranslatorBudget } from "../../helpers/translator-budget"; +import { CursorRootEnvelopeLimitError } from "../../../src/adapters/cursor/cursor-errors"; const createCursorAdapter = (...args: Parameters) => withTestTranslatorBudget(createCursorAdapterProduction(...args)); @@ -130,7 +130,7 @@ describe("Cursor adapter live transport", () => { // happens inside the live transport (`prepareCursorRunRequest` in live-transport.ts), which a // mock replaces, so a mocked run can never reach the guard itself. What is under test here is // the adapter's terminal catch, not the guard — the guard has its own tests in - // tests/cursor-blob.test.ts. + // tests/providers/cursor/cursor-blob.test.ts. const adapter = createCursorAdapter(provider, { createTransport: () => ({ async *run(): AsyncGenerator { diff --git a/tests/cursor-arg-normalize.test.ts b/tests/providers/cursor/cursor-arg-normalize.test.ts similarity index 97% rename from tests/cursor-arg-normalize.test.ts rename to tests/providers/cursor/cursor-arg-normalize.test.ts index fc16102f18..a56afa0a38 100644 --- a/tests/cursor-arg-normalize.test.ts +++ b/tests/providers/cursor/cursor-arg-normalize.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { normalizeArgKeys } from "../src/adapters/cursor/arg-normalize"; +import { normalizeArgKeys } from "../../../src/adapters/cursor/arg-normalize"; const schema = { type: "object", diff --git a/tests/cursor-blob-integrity.test.ts b/tests/providers/cursor/cursor-blob-integrity.test.ts similarity index 96% rename from tests/cursor-blob-integrity.test.ts rename to tests/providers/cursor/cursor-blob-integrity.test.ts index b97d2e537f..b2231d54b8 100644 --- a/tests/cursor-blob-integrity.test.ts +++ b/tests/providers/cursor/cursor-blob-integrity.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; import { createHash } from "node:crypto"; -import { cursorBlobServeIntegrityOk, storeCursorBlob } from "../src/adapters/cursor/native-exec"; +import { cursorBlobServeIntegrityOk, storeCursorBlob } from "../../../src/adapters/cursor/native-exec"; describe("cursor blob serve-time integrity (devlog 260826 080)", () => { test("content-addressed blob passes when bytes match the id", () => { diff --git a/tests/cursor-blob.test.ts b/tests/providers/cursor/cursor-blob.test.ts similarity index 99% rename from tests/cursor-blob.test.ts rename to tests/providers/cursor/cursor-blob.test.ts index de92758870..b173345d1d 100644 --- a/tests/cursor-blob.test.ts +++ b/tests/providers/cursor/cursor-blob.test.ts @@ -17,7 +17,7 @@ import { setCursorBlobLimitsForTests, storeCursorBlob, type CursorBlobRequestScopeToken, -} from "../src/adapters/cursor/native-exec"; +} from "../../../src/adapters/cursor/native-exec"; import { clearCursorCheckpointsForTests, commitCursorCheckpoint, @@ -25,13 +25,13 @@ import { cursorCheckpointStoreMetricsForTests, installCursorCheckpointClockForTests, invalidateCursorCheckpoint, -} from "../src/adapters/cursor/checkpoint-store"; +} from "../../../src/adapters/cursor/checkpoint-store"; import { configureAppOwnedMemoryBudget, registerRetainedStore, resetAppOwnedMemoryForTests, -} from "../src/lib/app-owned-memory"; -import { resetDebugSettingsForTests } from "../src/lib/debug-settings"; +} from "../../../src/lib/app-owned-memory"; +import { resetDebugSettingsForTests } from "../../../src/lib/debug-settings"; import { CURSOR_EXTERNAL_ROOT_BYTE_LIMIT, CURSOR_EXTERNAL_TOOL_CONTINUATION_TEXT, @@ -39,12 +39,12 @@ import { CURSOR_ROUTING_LEVEL_PARAMETER_ID, encodeCursorRunRequest, prepareCursorRunRequest, -} from "../src/adapters/cursor/protobuf-request"; -import { estimateTokens } from "../src/lib/token-estimate"; -import type { OcxAssistantContentPart } from "../src/types"; -import { CursorRootEnvelopeLimitError } from "../src/adapters/cursor/cursor-errors"; -import { isRetryableCursorError } from "../src/adapters/cursor/transport-retry"; -import { encodeCursorCallId, resetCursorCallIdProvenanceForTests } from "../src/adapters/cursor/call-id"; +} from "../../../src/adapters/cursor/protobuf-request"; +import { estimateTokens } from "../../../src/lib/token-estimate"; +import type { OcxAssistantContentPart } from "../../../src/types"; +import { CursorRootEnvelopeLimitError } from "../../../src/adapters/cursor/cursor-errors"; +import { isRetryableCursorError } from "../../../src/adapters/cursor/transport-retry"; +import { encodeCursorCallId, resetCursorCallIdProvenanceForTests } from "../../../src/adapters/cursor/call-id"; import { AgentClientMessageSchema, ConversationStepSchema, @@ -54,7 +54,7 @@ import { KvServerMessageSchema, SetBlobArgsSchema, UserMessageSchema, -} from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; beforeEach(() => { resetCursorBlobStateForTests(); diff --git a/tests/cursor-call-id.test.ts b/tests/providers/cursor/cursor-call-id.test.ts similarity index 94% rename from tests/cursor-call-id.test.ts rename to tests/providers/cursor/cursor-call-id.test.ts index eb500f520e..6405f5deb6 100644 --- a/tests/cursor-call-id.test.ts +++ b/tests/providers/cursor/cursor-call-id.test.ts @@ -3,10 +3,10 @@ import { decodeCursorCallId, encodeCursorCallId, resetCursorCallIdProvenanceForTests, -} from "../src/adapters/cursor/call-id"; -import { mapCursorServerMessage } from "../src/adapters/cursor/message-mapper"; -import type { CursorMessageMapperState } from "../src/adapters/cursor/message-mapper"; -import type { CursorKvStore } from "../src/adapters/cursor/kv-store"; +} from "../../../src/adapters/cursor/call-id"; +import { mapCursorServerMessage } from "../../../src/adapters/cursor/message-mapper"; +import type { CursorMessageMapperState } from "../../../src/adapters/cursor/message-mapper"; +import type { CursorKvStore } from "../../../src/adapters/cursor/kv-store"; const COMPOSITE = "call-9aee6d07-edc0-442f-8466-9d3924e16e03-0\nfc_5a1a53c6-32ce-9602-bc56-459030165589_0"; diff --git a/tests/cursor-cancel-provenance.test.ts b/tests/providers/cursor/cursor-cancel-provenance.test.ts similarity index 94% rename from tests/cursor-cancel-provenance.test.ts rename to tests/providers/cursor/cursor-cancel-provenance.test.ts index c954f64184..f4ab0a917b 100644 --- a/tests/cursor-cancel-provenance.test.ts +++ b/tests/providers/cursor/cursor-cancel-provenance.test.ts @@ -1,13 +1,13 @@ import { describe, expect, test } from "bun:test"; -import { createLiveCursorTransport } from "../src/adapters/cursor/live-transport"; +import { createLiveCursorTransport } from "../../../src/adapters/cursor/live-transport"; import { classifyCursorError, CursorUnexpectedCancelError, isCursorBenignCancelError, -} from "../src/adapters/cursor/cursor-errors"; -import { resetCursorBlobStateForTests } from "../src/adapters/cursor/native-exec"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import type { CursorServerMessage } from "../src/adapters/cursor/types"; +} from "../../../src/adapters/cursor/cursor-errors"; +import { resetCursorBlobStateForTests } from "../../../src/adapters/cursor/native-exec"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; +import type { CursorServerMessage } from "../../../src/adapters/cursor/types"; type OpenFn = ( encoded: Uint8Array, diff --git a/tests/cursor-catalog.test.ts b/tests/providers/cursor/cursor-catalog.test.ts similarity index 99% rename from tests/cursor-catalog.test.ts rename to tests/providers/cursor/cursor-catalog.test.ts index a5826fd151..4d8a79e352 100644 --- a/tests/cursor-catalog.test.ts +++ b/tests/providers/cursor/cursor-catalog.test.ts @@ -6,13 +6,13 @@ import { recordLiveCursorClaudeModels, resetLiveCursorClaudeWireIdentitiesForTests, resolveCursorSelection, -} from "../src/adapters/cursor/catalog"; +} from "../../../src/adapters/cursor/catalog"; import { cursorEffortSuffix, cursorModelHasEffortTiers, cursorRequestWireModelIdWithEffort, CURSOR_THINKING_MODEL_IDS, -} from "../src/adapters/cursor/effort-map"; +} from "../../../src/adapters/cursor/effort-map"; /** * The frozen legacy picker ids (discovery.ts static seed minus the 4 router diff --git a/tests/cursor-claude-id.test.ts b/tests/providers/cursor/cursor-claude-id.test.ts similarity index 98% rename from tests/cursor-claude-id.test.ts rename to tests/providers/cursor/cursor-claude-id.test.ts index 7c424d17bf..238cd1f4fe 100644 --- a/tests/cursor-claude-id.test.ts +++ b/tests/providers/cursor/cursor-claude-id.test.ts @@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test"; import { composeCursorClaudeWireId, normalizeCursorClaudeId, -} from "../src/adapters/cursor/claude-id"; +} from "../../../src/adapters/cursor/claude-id"; describe("Cursor Claude id normalization", () => { test("normalizes every observed Fable 5.1 spelling to one capability base", () => { diff --git a/tests/cursor-default-catalog-suppression.test.ts b/tests/providers/cursor/cursor-default-catalog-suppression.test.ts similarity index 91% rename from tests/cursor-default-catalog-suppression.test.ts rename to tests/providers/cursor/cursor-default-catalog-suppression.test.ts index 2d6871076d..6399f4cda5 100644 --- a/tests/cursor-default-catalog-suppression.test.ts +++ b/tests/providers/cursor/cursor-default-catalog-suppression.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { createCursorRequest } from "../src/adapters/cursor/request-builder"; -import type { OcxParsedRequest } from "../src/types/request"; +import { createCursorRequest } from "../../../src/adapters/cursor/request-builder"; +import type { OcxParsedRequest } from "../../../src/types/request"; function parsedRequest(overrides: Partial = {}): OcxParsedRequest { return { diff --git a/tests/cursor-desktop-exec.test.ts b/tests/providers/cursor/cursor-desktop-exec.test.ts similarity index 97% rename from tests/cursor-desktop-exec.test.ts rename to tests/providers/cursor/cursor-desktop-exec.test.ts index 5d6085b086..43023799ad 100644 --- a/tests/cursor-desktop-exec.test.ts +++ b/tests/providers/cursor/cursor-desktop-exec.test.ts @@ -5,10 +5,10 @@ import { ComputerUseArgsSchema, ExecServerMessageSchema, RecordScreenArgsSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import { handleCursorNativeExec } from "../src/adapters/cursor/native-exec"; -import { desktopDepsFromConfig } from "../src/adapters/cursor/native-exec-desktop"; -import { shellInvocation } from "../src/lib/win-exec"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { handleCursorNativeExec } from "../../../src/adapters/cursor/native-exec"; +import { desktopDepsFromConfig } from "../../../src/adapters/cursor/native-exec-desktop"; +import { shellInvocation } from "../../../src/lib/win-exec"; function execMessage(message: Parameters>[1]["message"]) { return create(ExecServerMessageSchema, { id: 3, execId: "exec-test", message }); diff --git a/tests/cursor-discovery.test.ts b/tests/providers/cursor/cursor-discovery.test.ts similarity index 99% rename from tests/cursor-discovery.test.ts rename to tests/providers/cursor/cursor-discovery.test.ts index 0087a2bb8e..32656dd12d 100644 --- a/tests/cursor-discovery.test.ts +++ b/tests/providers/cursor/cursor-discovery.test.ts @@ -20,7 +20,7 @@ import { isCursorNativeWireModel, cursorNeedsExternalToolContinuation, normalizeCursorModels, -} from "../src/adapters/cursor/discovery"; +} from "../../../src/adapters/cursor/discovery"; describe("Cursor discovery metadata", () => { test("no-vision list is a curated explicit subset of the static seed", () => { diff --git a/tests/cursor-display-names.test.ts b/tests/providers/cursor/cursor-display-names.test.ts similarity index 88% rename from tests/cursor-display-names.test.ts rename to tests/providers/cursor/cursor-display-names.test.ts index 8c36f13615..3751601445 100644 --- a/tests/cursor-display-names.test.ts +++ b/tests/providers/cursor/cursor-display-names.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from "bun:test"; -import { cursorModelDisplayNames, CURSOR_STATIC_MODELS, isCursorBrandedLabel } from "../src/adapters/cursor/discovery"; -import { cursorUmbrellaRows } from "../src/adapters/cursor/catalog"; -import { enrichProviderFromRegistry, providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { configuredModelDisplayName } from "../src/codex/catalog/provider-fetch"; -import type { OcxProviderConfig } from "../src/types"; +import { cursorModelDisplayNames, CURSOR_STATIC_MODELS, isCursorBrandedLabel } from "../../../src/adapters/cursor/discovery"; +import { cursorUmbrellaRows } from "../../../src/adapters/cursor/catalog"; +import { enrichProviderFromRegistry, providerConfigSeed } from "../../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../../src/providers/registry"; +import { configuredModelDisplayName } from "../../../src/codex/catalog/provider-fetch"; +import type { OcxProviderConfig } from "../../../src/types"; /** * `routedDisplayName` (codex/catalog/sync.ts) passes a routed slug through unchanged, so a diff --git a/tests/cursor-effort-rows.test.ts b/tests/providers/cursor/cursor-effort-rows.test.ts similarity index 93% rename from tests/cursor-effort-rows.test.ts rename to tests/providers/cursor/cursor-effort-rows.test.ts index 4929696af8..ea97860228 100644 --- a/tests/cursor-effort-rows.test.ts +++ b/tests/providers/cursor/cursor-effort-rows.test.ts @@ -3,25 +3,25 @@ import { mkdtempSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; +import { saveConfig } from "../../../src/config"; import { resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests, -} from "../src/codex/model-entitlements"; -import { buildCursorIntegrationStatus } from "../src/server/management/cursor-integration-routes"; -import { handleChatCompletions } from "../src/server/chat-completions"; -import { handleClaudeMessages } from "../src/server/claude-messages"; +} from "../../../src/codex/model-entitlements"; +import { buildCursorIntegrationStatus } from "../../../src/server/management/cursor-integration-routes"; +import { handleChatCompletions } from "../../../src/server/chat-completions"; +import { handleClaudeMessages } from "../../../src/server/claude-messages"; import { effortRowId, expandCursorEffortRow, parseEffortRowId, -} from "../src/server/effort-row"; -import { handleResponses } from "../src/server/responses"; -import { startServer } from "../src/server"; -import type { RequestLogContext } from "../src/server/request-log"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; -import { SERVER_BUDGET_MS } from "./helpers/test-budget"; +} from "../../../src/server/effort-row"; +import { handleResponses } from "../../../src/server/responses"; +import { startServer } from "../../../src/server"; +import type { RequestLogContext } from "../../../src/server/request-log"; +import type { OcxConfig } from "../../../src/types"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; +import { SERVER_BUDGET_MS } from "../../helpers/test-budget"; setDefaultTimeout(SERVER_BUDGET_MS); diff --git a/tests/cursor-effort-suffix.test.ts b/tests/providers/cursor/cursor-effort-suffix.test.ts similarity index 98% rename from tests/cursor-effort-suffix.test.ts rename to tests/providers/cursor/cursor-effort-suffix.test.ts index 917c2b1b2e..b0c314deeb 100644 --- a/tests/cursor-effort-suffix.test.ts +++ b/tests/providers/cursor/cursor-effort-suffix.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { createCursorRequest } from "../src/adapters/cursor/request-builder"; -import { CANONICAL_EFFORT_SUFFIXES, cursorEffortSuffix, cursorModelEffortLadder, cursorWireModelIdWithEffort, CURSOR_THINKING_MODEL_IDS } from "../src/adapters/cursor/effort-map"; -import { CURSOR_STATIC_MODELS, isCursorModelAvailableForAccount } from "../src/adapters/cursor/discovery"; -import type { OcxParsedRequest } from "../src/types"; +import { createCursorRequest } from "../../../src/adapters/cursor/request-builder"; +import { CANONICAL_EFFORT_SUFFIXES, cursorEffortSuffix, cursorModelEffortLadder, cursorWireModelIdWithEffort, CURSOR_THINKING_MODEL_IDS } from "../../../src/adapters/cursor/effort-map"; +import { CURSOR_STATIC_MODELS, isCursorModelAvailableForAccount } from "../../../src/adapters/cursor/discovery"; +import type { OcxParsedRequest } from "../../../src/types"; // Static fixture recorded from Cursor GetUsableModels on 2026-08-06. This pins the // exact wire ids observed during the incident; live availability normalization is diff --git a/tests/cursor-effort-table.test.ts b/tests/providers/cursor/cursor-effort-table.test.ts similarity index 93% rename from tests/cursor-effort-table.test.ts rename to tests/providers/cursor/cursor-effort-table.test.ts index f3f32fda58..973941d574 100644 --- a/tests/cursor-effort-table.test.ts +++ b/tests/providers/cursor/cursor-effort-table.test.ts @@ -7,11 +7,12 @@ import { resetCursorEffortTableCacheForTests, type CursorEffortTable, type CursorEffortTableDeps, -} from "../src/integrations/cursor-effort-table"; -import type { CursorInstall } from "../src/integrations/cursor-detect"; -import { predictCursorEffort } from "../src/server/models-capabilities"; +} from "../../../src/integrations/cursor-effort-table"; +import type { CursorInstall } from "../../../src/integrations/cursor-detect"; +import { predictCursorEffort } from "../../../src/server/models-capabilities"; +import { fixturePath } from "../../helpers/repo-root"; -const FIXTURE = readFileSync(join(import.meta.dir, "fixtures/cursor-agent-exec-effort-table.min.js"), "utf8"); +const FIXTURE = readFileSync(fixturePath("cursor-agent-exec-effort-table.min.js"), "utf8"); const INSTALL: CursorInstall = { build: "private-inference", path: "/Applications/Cursor Private Inference.app", version: "3.18.25" }; function parsedFixtureTable(): CursorEffortTable { diff --git a/tests/cursor-envelope-echo-retry.test.ts b/tests/providers/cursor/cursor-envelope-echo-retry.test.ts similarity index 98% rename from tests/cursor-envelope-echo-retry.test.ts rename to tests/providers/cursor/cursor-envelope-echo-retry.test.ts index e4f4e65ff1..0470eee8c6 100644 --- a/tests/cursor-envelope-echo-retry.test.ts +++ b/tests/providers/cursor/cursor-envelope-echo-retry.test.ts @@ -1,15 +1,15 @@ import { describe, expect, test } from "bun:test"; -import { createCursorAdapter as createCursorAdapterProduction } from "../src/adapters/cursor"; +import { createCursorAdapter as createCursorAdapterProduction } from "../../../src/adapters/cursor"; import { CURSOR_ECHO_RETRY_CONTINUATION_TEXT, CursorEnvelopeEchoSniffer, CursorMidstreamEchoObserver, CursorRoutingCommentarySniffer, MAX_MIDSTREAM_SCAN_LENGTH, -} from "../src/adapters/cursor/envelope-echo"; -import type { AdapterEvent, OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import type { CursorRunRequest, CursorServerMessage } from "../src/adapters/cursor/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../../src/adapters/cursor/envelope-echo"; +import type { AdapterEvent, OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; +import type { CursorRunRequest, CursorServerMessage } from "../../../src/adapters/cursor/types"; +import { withTestTranslatorBudget } from "../../helpers/translator-budget"; const createCursorAdapter = (...args: Parameters) => withTestTranslatorBudget(createCursorAdapterProduction(...args)); diff --git a/tests/cursor-eof-terminal.test.ts b/tests/providers/cursor/cursor-eof-terminal.test.ts similarity index 96% rename from tests/cursor-eof-terminal.test.ts rename to tests/providers/cursor/cursor-eof-terminal.test.ts index 614f04498b..d06651f5af 100644 --- a/tests/cursor-eof-terminal.test.ts +++ b/tests/providers/cursor/cursor-eof-terminal.test.ts @@ -10,11 +10,11 @@ import { ToolCallSchema, ToolCallStartedUpdateSchema, TurnEndedUpdateSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import { encodeConnectFrame } from "../src/adapters/cursor/framing"; -import { createLiveCursorTransport } from "../src/adapters/cursor/live-transport"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import type { CursorRunRequest, CursorServerMessage } from "../src/adapters/cursor/types"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { encodeConnectFrame } from "../../../src/adapters/cursor/framing"; +import { createLiveCursorTransport } from "../../../src/adapters/cursor/live-transport"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; +import type { CursorRunRequest, CursorServerMessage } from "../../../src/adapters/cursor/types"; const PROVIDER = "opencodex-responses"; diff --git a/tests/cursor-errors.test.ts b/tests/providers/cursor/cursor-errors.test.ts similarity index 98% rename from tests/cursor-errors.test.ts rename to tests/providers/cursor/cursor-errors.test.ts index a3307f982a..4d55bdd711 100644 --- a/tests/cursor-errors.test.ts +++ b/tests/providers/cursor/cursor-errors.test.ts @@ -4,8 +4,8 @@ import { isCursorBenignCancelError, isCursorInvalidArgumentError, safeCursorErrorMessage, -} from "../src/adapters/cursor/cursor-errors"; -import { inferHttpStatusFromAdapterMessage } from "../src/lib/errors"; +} from "../../../src/adapters/cursor/cursor-errors"; +import { inferHttpStatusFromAdapterMessage } from "../../../src/lib/errors"; describe("classifyCursorError", () => { test("rate limit and resource exhaustion stay distinct", () => { diff --git a/tests/cursor-exec-empty-result.test.ts b/tests/providers/cursor/cursor-exec-empty-result.test.ts similarity index 98% rename from tests/cursor-exec-empty-result.test.ts rename to tests/providers/cursor/cursor-exec-empty-result.test.ts index 57f42c0076..330390582c 100644 --- a/tests/cursor-exec-empty-result.test.ts +++ b/tests/providers/cursor/cursor-exec-empty-result.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { normalizeCursorToolResultText } from "../src/adapters/cursor/tool-result-normalize"; +import { normalizeCursorToolResultText } from "../../../src/adapters/cursor/tool-result-normalize"; describe("codex exec bridge empty-result normalization (devlog 260826 gap-7)", () => { test("empty exec cell output becomes explanatory text, not an error", () => { diff --git a/tests/cursor-fast-listing.test.ts b/tests/providers/cursor/cursor-fast-listing.test.ts similarity index 86% rename from tests/cursor-fast-listing.test.ts rename to tests/providers/cursor/cursor-fast-listing.test.ts index d764eb5799..8a67badf53 100644 --- a/tests/cursor-fast-listing.test.ts +++ b/tests/providers/cursor/cursor-fast-listing.test.ts @@ -1,13 +1,13 @@ import { describe, expect, test } from "bun:test"; -import { cursorFastCapableBases, cursorFastIdFor, resolveCursorSelection } from "../src/adapters/cursor/catalog"; -import { buildAnthropicModelInfos } from "../src/claude/model-info"; -import { AUTO_CONTEXT_OFF } from "../src/claude/context-windows"; -import { desktop3pAlias } from "../src/claude/desktop-3p"; -import { providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { decideTier } from "../src/providers/fastwire"; -import { fastPolicyForModel } from "../src/providers/service-tier"; -import type { CatalogModel } from "../src/codex/catalog"; +import { cursorFastCapableBases, cursorFastIdFor, resolveCursorSelection } from "../../../src/adapters/cursor/catalog"; +import { buildAnthropicModelInfos } from "../../../src/claude/model-info"; +import { AUTO_CONTEXT_OFF } from "../../../src/claude/context-windows"; +import { desktop3pAlias } from "../../../src/claude/desktop-3p"; +import { providerConfigSeed } from "../../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../../src/providers/registry"; +import { decideTier } from "../../../src/providers/fastwire"; +import { fastPolicyForModel } from "../../../src/providers/service-tier"; +import type { CatalogModel } from "../../../src/codex/catalog"; function cursorModel(id: string, contextWindow = 1_000_000): CatalogModel { return { provider: "cursor", id, contextWindow, reasoningEfforts: ["low", "high"] } as CatalogModel; diff --git a/tests/cursor-fast-tier.test.ts b/tests/providers/cursor/cursor-fast-tier.test.ts similarity index 91% rename from tests/cursor-fast-tier.test.ts rename to tests/providers/cursor/cursor-fast-tier.test.ts index 43ec6bd66b..bcdcc9c47f 100644 --- a/tests/cursor-fast-tier.test.ts +++ b/tests/providers/cursor/cursor-fast-tier.test.ts @@ -1,11 +1,11 @@ import { describe, expect, test } from "bun:test"; -import { cursorFastCapableBases, upgradeToFast } from "../src/adapters/cursor/catalog"; -import { createCursorRequest, cursorRequestEmitsFastVariant } from "../src/adapters/cursor/request-builder"; -import { providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { decideTier } from "../src/providers/fastwire"; -import { fastPolicyForModel, serviceTierSupportFromPolicy } from "../src/providers/service-tier"; -import type { OcxParsedRequest, TierDecision } from "../src/types"; +import { cursorFastCapableBases, upgradeToFast } from "../../../src/adapters/cursor/catalog"; +import { createCursorRequest, cursorRequestEmitsFastVariant } from "../../../src/adapters/cursor/request-builder"; +import { providerConfigSeed } from "../../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../../src/providers/registry"; +import { decideTier } from "../../../src/providers/fastwire"; +import { fastPolicyForModel, serviceTierSupportFromPolicy } from "../../../src/providers/service-tier"; +import type { OcxParsedRequest, TierDecision } from "../../../src/types"; const FAST_DECISION: TierDecision = { kind: "set", value: "fast" }; diff --git a/tests/cursor-framing.test.ts b/tests/providers/cursor/cursor-framing.test.ts similarity index 99% rename from tests/cursor-framing.test.ts rename to tests/providers/cursor/cursor-framing.test.ts index 7d4156f617..a6bb583a3a 100644 --- a/tests/cursor-framing.test.ts +++ b/tests/providers/cursor/cursor-framing.test.ts @@ -11,13 +11,13 @@ import { isConnectFrameCompressed, isConnectFrameEndStream, tryDecodeConnectFrame, -} from "../src/adapters/cursor/framing"; +} from "../../../src/adapters/cursor/framing"; import { CURSOR_MAX_CONNECT_FRAME_BYTES, CURSOR_MAX_EFFECTIVE_CONNECT_PAYLOAD_BYTES, CURSOR_MAX_PENDING_FRAMES, createTranslatorBudget, -} from "../src/lib/translator-budget"; +} from "../../../src/lib/translator-budget"; const bytes = (...values: number[]) => new Uint8Array(values); diff --git a/tests/cursor-h2-pool-shutdown.test.ts b/tests/providers/cursor/cursor-h2-pool-shutdown.test.ts similarity index 94% rename from tests/cursor-h2-pool-shutdown.test.ts rename to tests/providers/cursor/cursor-h2-pool-shutdown.test.ts index f832206f80..3efb7cc04a 100644 --- a/tests/cursor-h2-pool-shutdown.test.ts +++ b/tests/providers/cursor/cursor-h2-pool-shutdown.test.ts @@ -1,10 +1,10 @@ import http2 from "node:http2"; import { afterEach, describe, expect, test } from "bun:test"; -import { CursorH2SessionPool } from "../src/adapters/cursor/h2-pool"; +import { CursorH2SessionPool } from "../../../src/adapters/cursor/h2-pool"; import { resetOptionalShutdownHooksForTests, runOptionalShutdownHooks, -} from "../src/lib/optional-shutdown-hooks"; +} from "../../../src/lib/optional-shutdown-hooks"; afterEach(() => { resetOptionalShutdownHooksForTests(); diff --git a/tests/cursor-hardening.test.ts b/tests/providers/cursor/cursor-hardening.test.ts similarity index 98% rename from tests/cursor-hardening.test.ts rename to tests/providers/cursor/cursor-hardening.test.ts index 519f3ea7c4..0a8edc988b 100644 --- a/tests/cursor-hardening.test.ts +++ b/tests/providers/cursor/cursor-hardening.test.ts @@ -15,14 +15,14 @@ import { ToolCallSchema, ToolCallStartedUpdateSchema, InteractionUpdateSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import { CONNECT_FLAG_END_STREAM, encodeConnectFrame } from "../src/adapters/cursor/framing"; -import { fetchCursorUsableModels } from "../src/adapters/cursor/live-models"; -import { armTimeoutDestroyFallback, createLiveCursorTransport, createTerminalSettler } from "../src/adapters/cursor/live-transport"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache, getProviderDiscoveryStatus } from "../src/codex/model-cache"; -import { handleManagementAPI } from "../src/server/management-api"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { CONNECT_FLAG_END_STREAM, encodeConnectFrame } from "../../../src/adapters/cursor/framing"; +import { fetchCursorUsableModels } from "../../../src/adapters/cursor/live-models"; +import { armTimeoutDestroyFallback, createLiveCursorTransport, createTerminalSettler } from "../../../src/adapters/cursor/live-transport"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; +import { gatherRoutedModels } from "../../../src/codex/catalog"; +import { clearModelCache, getProviderDiscoveryStatus } from "../../../src/codex/model-cache"; +import { handleManagementAPI } from "../../../src/server/management-api"; async function withDiscoveryServer( handler: (stream: http2.ServerHttp2Stream, headers: http2.IncomingHttpHeaders) => void, @@ -1130,4 +1130,4 @@ describe("Cursor live transport incomplete-frame EOF", () => { }); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../../helpers/management-auth"; diff --git a/tests/cursor-http1-transport.test.ts b/tests/providers/cursor/cursor-http1-transport.test.ts similarity index 97% rename from tests/cursor-http1-transport.test.ts rename to tests/providers/cursor/cursor-http1-transport.test.ts index 9c57963fcf..7e60f1f593 100644 --- a/tests/cursor-http1-transport.test.ts +++ b/tests/providers/cursor/cursor-http1-transport.test.ts @@ -13,16 +13,16 @@ import { TextDeltaUpdateSchema, ToolCallSchema, ToolCallStartedUpdateSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import { decodeConnectFrame, encodeConnectFrame } from "../src/adapters/cursor/framing"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { decodeConnectFrame, encodeConnectFrame } from "../../../src/adapters/cursor/framing"; import { cursorBidiAppendRequestSize, encodeCursorBidiAppendRequest, -} from "../src/adapters/cursor/http1-bidi"; -import { createLiveCursorTransport } from "../src/adapters/cursor/live-transport"; -import type { CursorRunRequest, CursorServerMessage } from "../src/adapters/cursor/types"; -import type { OcxProviderConfig } from "../src/types"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../../src/adapters/cursor/http1-bidi"; +import { createLiveCursorTransport } from "../../../src/adapters/cursor/live-transport"; +import type { CursorRunRequest, CursorServerMessage } from "../../../src/adapters/cursor/types"; +import type { OcxProviderConfig } from "../../../src/types"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; interface DecodedAppend { data: string; diff --git a/tests/cursor-images.test.ts b/tests/providers/cursor/cursor-images.test.ts similarity index 97% rename from tests/cursor-images.test.ts rename to tests/providers/cursor/cursor-images.test.ts index 5083951562..515254af26 100644 --- a/tests/cursor-images.test.ts +++ b/tests/providers/cursor/cursor-images.test.ts @@ -20,18 +20,18 @@ import { resolveCursorImages, sniffCursorImageDimensions, sniffCursorImageFormat, -} from "../src/adapters/cursor/images"; +} from "../../../src/adapters/cursor/images"; import { handleCursorNativeKv, resetCursorBlobStateForTests, -} from "../src/adapters/cursor/native-exec"; -import { cursorRequestMessagesFromRaw } from "../src/adapters/cursor/request-builder"; -import { activePromptText, encodeCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; +} from "../../../src/adapters/cursor/native-exec"; +import { cursorRequestMessagesFromRaw } from "../../../src/adapters/cursor/request-builder"; +import { activePromptText, encodeCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; import { AgentClientMessageSchema, GetBlobArgsSchema, KvServerMessageSchema, -} from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; /** Minimal valid 1×1 PNG (real IHDR; not a signature-only stub). */ const PNG_BYTES = Uint8Array.from( @@ -43,7 +43,7 @@ const PNG_BYTES = Uint8Array.from( const PNG_DATA_URL = `data:image/png;base64,${Buffer.from(PNG_BYTES).toString("base64")}`; async function oversizedDecodablePng(): Promise { - const pngPath = new URL("./helpers/cursor-grumpy-fixture.png", import.meta.url); + const pngPath = new URL("../../helpers/cursor-grumpy-fixture.png", import.meta.url); const src = new Uint8Array(await Bun.file(pngPath).arrayBuffer()); return new Uint8Array(await new Bun.Image(src).resize(2400, 2400).png().bytes()); } @@ -243,7 +243,7 @@ describe("Cursor image resolver", () => { }); test("prepareCursorImageForWire re-encodes large PNG as JPEG under the soft cap", async () => { - const pngPath = new URL("./helpers/cursor-grumpy-fixture.png", import.meta.url); + const pngPath = new URL("../../helpers/cursor-grumpy-fixture.png", import.meta.url); const png = new Uint8Array(await Bun.file(pngPath).arrayBuffer()); expect(png.byteLength).toBeGreaterThan(CURSOR_VISION_SOFT_MAX_BYTES); @@ -262,7 +262,7 @@ describe("Cursor image resolver", () => { }); test("detail original/high uses a higher soft tier than auto", async () => { - const pngPath = new URL("./helpers/cursor-grumpy-fixture.png", import.meta.url); + const pngPath = new URL("../../helpers/cursor-grumpy-fixture.png", import.meta.url); const png = new Uint8Array(await Bun.file(pngPath).arrayBuffer()); const auto = await prepareCursorImageForWire({ data: png, @@ -310,7 +310,7 @@ describe("Cursor image resolver", () => { }); test("prepareCursorRawMessages JPEG-preps active-turn user data URLs", async () => { - const pngPath = new URL("./helpers/cursor-grumpy-fixture.png", import.meta.url); + const pngPath = new URL("../../helpers/cursor-grumpy-fixture.png", import.meta.url); const png = new Uint8Array(await Bun.file(pngPath).arrayBuffer()); const imageUrl = `data:image/png;base64,${Buffer.from(png).toString("base64")}`; const prepared = await prepareCursorRawMessages([ @@ -623,7 +623,7 @@ describe("Cursor image resolver", () => { }); test("prepareCursorImageForWire never returns ready JPEG above the detail soft cap", async () => { - const pngPath = new URL("./helpers/cursor-grumpy-fixture.png", import.meta.url); + const pngPath = new URL("../../helpers/cursor-grumpy-fixture.png", import.meta.url); const png = new Uint8Array(await Bun.file(pngPath).arrayBuffer()); const oversized = await oversizedDecodablePng(); for (const [label, input, detail, softMax] of [ @@ -644,7 +644,7 @@ describe("Cursor image resolver", () => { }); test("omits when shrink ladder best JPEG still exceeds soft cap", async () => { - const pngPath = new URL("./helpers/cursor-grumpy-fixture.png", import.meta.url); + const pngPath = new URL("../../helpers/cursor-grumpy-fixture.png", import.meta.url); const png = new Uint8Array(await Bun.file(pngPath).arrayBuffer()); const outcome = await prepareCursorImageForWire({ data: png, diff --git a/tests/cursor-integration-status.test.ts b/tests/providers/cursor/cursor-integration-status.test.ts similarity index 93% rename from tests/cursor-integration-status.test.ts rename to tests/providers/cursor/cursor-integration-status.test.ts index 35348dc933..6cb18458aa 100644 --- a/tests/cursor-integration-status.test.ts +++ b/tests/providers/cursor/cursor-integration-status.test.ts @@ -2,19 +2,20 @@ import { afterEach, beforeEach, describe, expect, setDefaultTimeout, test } from import { mkdtempSync, readFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; +import { saveConfig } from "../../../src/config"; import { resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests, -} from "../src/codex/model-entitlements"; -import { cursorProductJsonCandidates, detectCursorInstalls, type CursorDetectDeps } from "../src/integrations/cursor-detect"; -import { parseCursorEffortTable, type CursorEffortTable } from "../src/integrations/cursor-effort-table"; -import { cursorLastSeen, recordCursorSeen, resetCursorSeenForTests } from "../src/integrations/cursor-seen"; -import { cursorEffortFamily } from "../src/server/models-capabilities"; -import { startServer } from "../src/server"; -import type { OcxConfig } from "../src/types"; -import { SERVER_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/codex/model-entitlements"; +import { cursorProductJsonCandidates, detectCursorInstalls, type CursorDetectDeps } from "../../../src/integrations/cursor-detect"; +import { parseCursorEffortTable, type CursorEffortTable } from "../../../src/integrations/cursor-effort-table"; +import { cursorLastSeen, recordCursorSeen, resetCursorSeenForTests } from "../../../src/integrations/cursor-seen"; +import { cursorEffortFamily } from "../../../src/server/models-capabilities"; +import { startServer } from "../../../src/server"; +import type { OcxConfig } from "../../../src/types"; +import { SERVER_BUDGET_MS } from "../../helpers/test-budget"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; +import { fixturePath } from "../../helpers/repo-root"; setDefaultTimeout(SERVER_BUDGET_MS); @@ -94,7 +95,7 @@ describe("cursorEffortFamily", () => { const previousHome = process.env.OPENCODEX_HOME; let testHome = ""; -const CURSOR_EFFORT_FIXTURE = readFileSync(join(import.meta.dir, "fixtures/cursor-agent-exec-effort-table.min.js"), "utf8"); +const CURSOR_EFFORT_FIXTURE = readFileSync(fixturePath("cursor-agent-exec-effort-table.min.js"), "utf8"); const STATIC_CURSOR_EFFORT_DEPS = { managementApi: { loadCursorEffortTable: () => null } }; function fixtureEffortTable(): CursorEffortTable { diff --git a/tests/cursor-interaction-query.test.ts b/tests/providers/cursor/cursor-interaction-query.test.ts similarity index 90% rename from tests/cursor-interaction-query.test.ts rename to tests/providers/cursor/cursor-interaction-query.test.ts index 626da20fc6..4003dbb6a5 100644 --- a/tests/cursor-interaction-query.test.ts +++ b/tests/providers/cursor/cursor-interaction-query.test.ts @@ -18,8 +18,8 @@ import { ToolCallStartedUpdateSchema, WebSearchRequestQuerySchema, type InteractionQuery, -} from "../src/adapters/cursor/gen/agent_pb"; -import { isClientToolFrame, planInteractionQueryReply } from "../src/adapters/cursor/live-transport"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { isClientToolFrame, planInteractionQueryReply } from "../../../src/adapters/cursor/live-transport"; function query(id: number, q: InteractionQuery["query"]): InteractionQuery { return create(InteractionQuerySchema, { id, query: q }); @@ -147,8 +147,8 @@ describe("isClientToolFrame", () => { describe("partialUsageFromEventState", () => { test("reports checkpoint-derived cumulative usage on failure", async () => { - const { partialUsageFromEventState } = await import("../src/adapters/cursor/live-transport"); - const { createCursorProtobufEventState } = await import("../src/adapters/cursor/protobuf-events"); + const { partialUsageFromEventState } = await import("../../../src/adapters/cursor/live-transport"); + const { createCursorProtobufEventState } = await import("../../../src/adapters/cursor/protobuf-events"); const state = createCursorProtobufEventState(); state.usage.outputTokens = 42; state.contextTokens = 10_300; @@ -161,16 +161,16 @@ describe("partialUsageFromEventState", () => { }); test("reports output-only usage without a checkpoint", async () => { - const { partialUsageFromEventState } = await import("../src/adapters/cursor/live-transport"); - const { createCursorProtobufEventState } = await import("../src/adapters/cursor/protobuf-events"); + const { partialUsageFromEventState } = await import("../../../src/adapters/cursor/live-transport"); + const { createCursorProtobufEventState } = await import("../../../src/adapters/cursor/protobuf-events"); const state = createCursorProtobufEventState(); state.usage.outputTokens = 7; expect(partialUsageFromEventState(state)).toEqual({ inputTokens: 0, outputTokens: 7, estimated: true }); }); test("carries prior context usage on failure when the current turn had no checkpoint", async () => { - const { partialUsageFromEventState } = await import("../src/adapters/cursor/live-transport"); - const { createCursorContextUsageTracker, createCursorProtobufEventState } = await import("../src/adapters/cursor/protobuf-events"); + const { partialUsageFromEventState } = await import("../../../src/adapters/cursor/live-transport"); + const { createCursorContextUsageTracker, createCursorProtobufEventState } = await import("../../../src/adapters/cursor/protobuf-events"); const tracker = createCursorContextUsageTracker(); tracker.record("cursor_conv_1", 18_000); const state = createCursorProtobufEventState({ @@ -186,14 +186,14 @@ describe("partialUsageFromEventState", () => { }); test("returns undefined when the stream died before any token signal", async () => { - const { partialUsageFromEventState } = await import("../src/adapters/cursor/live-transport"); - const { createCursorProtobufEventState } = await import("../src/adapters/cursor/protobuf-events"); + const { partialUsageFromEventState } = await import("../../../src/adapters/cursor/live-transport"); + const { createCursorProtobufEventState } = await import("../../../src/adapters/cursor/protobuf-events"); expect(partialUsageFromEventState(createCursorProtobufEventState())).toBeUndefined(); }); test("does not report seeded carry when a fresh turn failed before any token signal", async () => { - const { partialUsageFromEventState } = await import("../src/adapters/cursor/live-transport"); - const { createCursorContextUsageTracker, createCursorProtobufEventState } = await import("../src/adapters/cursor/protobuf-events"); + const { partialUsageFromEventState } = await import("../../../src/adapters/cursor/live-transport"); + const { createCursorContextUsageTracker, createCursorProtobufEventState } = await import("../../../src/adapters/cursor/protobuf-events"); const tracker = createCursorContextUsageTracker(); tracker.record("cursor_conv_1", 18_000); diff --git a/tests/cursor-kv-store.test.ts b/tests/providers/cursor/cursor-kv-store.test.ts similarity index 86% rename from tests/cursor-kv-store.test.ts rename to tests/providers/cursor/cursor-kv-store.test.ts index 4162f025e6..eb4a782997 100644 --- a/tests/cursor-kv-store.test.ts +++ b/tests/providers/cursor/cursor-kv-store.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { createCursorKvStore } from "../src/adapters/cursor/kv-store"; -import { createTranslatorBudget } from "../src/lib/translator-budget"; +import { createCursorKvStore } from "../../../src/adapters/cursor/kv-store"; +import { createTranslatorBudget } from "../../../src/lib/translator-budget"; const bytes = (...values: number[]) => new Uint8Array(values); const store = (seed: Record = {}) => createCursorKvStore(seed, createTranslatorBudget()); diff --git a/tests/cursor-live-smoke-gate.test.ts b/tests/providers/cursor/cursor-live-smoke-gate.test.ts similarity index 97% rename from tests/cursor-live-smoke-gate.test.ts rename to tests/providers/cursor/cursor-live-smoke-gate.test.ts index d585fb78d0..b317fe75c5 100644 --- a/tests/cursor-live-smoke-gate.test.ts +++ b/tests/providers/cursor/cursor-live-smoke-gate.test.ts @@ -5,7 +5,7 @@ import { cursorLiveSmokeSkipMessage, getCursorLiveSmokeToken, readCursorLiveSmokeGate, -} from "../src/adapters/cursor/live-smoke-gate"; +} from "../../../src/adapters/cursor/live-smoke-gate"; const fakeSecret = "secret-cursor-token-123"; diff --git a/tests/cursor-live-transport.test.ts b/tests/providers/cursor/cursor-live-transport.test.ts similarity index 96% rename from tests/cursor-live-transport.test.ts rename to tests/providers/cursor/cursor-live-transport.test.ts index d2217fa000..082230eaa5 100644 --- a/tests/cursor-live-transport.test.ts +++ b/tests/providers/cursor/cursor-live-transport.test.ts @@ -3,22 +3,22 @@ import { PassThrough } from "node:stream"; import type { ChildProcessWithoutNullStreams } from "node:child_process"; import { create } from "@bufbuild/protobuf"; import { afterEach, describe, expect, test } from "bun:test"; -import { createLiveCursorTransport, CursorMissingCredentialError, parseConnectEndStreamError, resolveCursorToken } from "../src/adapters/cursor/live-transport"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import { prepareCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; +import { createLiveCursorTransport, CursorMissingCredentialError, parseConnectEndStreamError, resolveCursorToken } from "../../../src/adapters/cursor/live-transport"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; +import { prepareCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; import { CursorBlobAdmissionError, cursorBlobRetainedStoreSnapshot, resetCursorBlobStateForTests, setCursorBlobLimitsForTests, -} from "../src/adapters/cursor/native-exec"; +} from "../../../src/adapters/cursor/native-exec"; import { backgroundShellSpawnExec, resetBackgroundShellStateForTests, setBackgroundShellRuntimeForTests, -} from "../src/adapters/cursor/native-exec-shell"; -import { BackgroundShellSpawnArgsSchema, ExecServerMessageSchema } from "../src/adapters/cursor/gen/agent_pb"; -import type { CursorProtobufEventState } from "../src/adapters/cursor/protobuf-events"; +} from "../../../src/adapters/cursor/native-exec-shell"; +import { BackgroundShellSpawnArgsSchema, ExecServerMessageSchema } from "../../../src/adapters/cursor/gen/agent_pb"; +import type { CursorProtobufEventState } from "../../../src/adapters/cursor/protobuf-events"; class TransportFakeChild extends EventEmitter { readonly stdin = new PassThrough(); diff --git a/tests/cursor-local-models-schema.test.ts b/tests/providers/cursor/cursor-local-models-schema.test.ts similarity index 95% rename from tests/cursor-local-models-schema.test.ts rename to tests/providers/cursor/cursor-local-models-schema.test.ts index 2b0c9759c0..93c4be1840 100644 --- a/tests/cursor-local-models-schema.test.ts +++ b/tests/providers/cursor/cursor-local-models-schema.test.ts @@ -2,21 +2,21 @@ import { afterEach, beforeEach, describe, expect, setDefaultTimeout, test } from import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; -import { nativeOpenAiContextTier, nativeReasoningEfforts } from "../src/codex/catalog"; +import { saveConfig } from "../../../src/config"; +import { nativeOpenAiContextTier, nativeReasoningEfforts } from "../../../src/codex/catalog"; import { resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests, -} from "../src/codex/model-entitlements"; -import { startServer } from "../src/server"; +} from "../../../src/codex/model-entitlements"; +import { startServer } from "../../../src/server"; import { modelCapabilityFields, OPENAI_FAMILY_API_TYPES, OPENCODEX_MODEL_API_TYPES, -} from "../src/server/models-capabilities"; -import type { OcxConfig } from "../src/types"; -import { SERVER_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/server/models-capabilities"; +import type { OcxConfig } from "../../../src/types"; +import { SERVER_BUDGET_MS } from "../../helpers/test-budget"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; // Cursor's local-agent runtime ("Private Inference" build) only enables its reasoning-effort // control when a GET /v1/models row carries api_types (+ optional capabilities). These cases diff --git a/tests/cursor-mcp-manager.test.ts b/tests/providers/cursor/cursor-mcp-manager.test.ts similarity index 97% rename from tests/cursor-mcp-manager.test.ts rename to tests/providers/cursor/cursor-mcp-manager.test.ts index 1fcbc89b1d..f6b3d8ffbb 100644 --- a/tests/cursor-mcp-manager.test.ts +++ b/tests/providers/cursor/cursor-mcp-manager.test.ts @@ -11,12 +11,12 @@ import { McpArgsSchema, ReadMcpResourceExecArgsSchema, RequestContextArgsSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import { handleCursorNativeExec } from "../src/adapters/cursor/native-exec"; -import { resolveMcpServers } from "../src/adapters/cursor/mcp-config"; -import { CursorMcpManager, CursorMcpPayloadTooLargeError, McpCatalogLimitError } from "../src/adapters/cursor/mcp-manager"; -import { buildMcpToolDefinitions, mcpDepsFromManager } from "../src/adapters/cursor/native-exec-mcp"; -import type { OcxProviderConfig } from "../src/types"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { handleCursorNativeExec } from "../../../src/adapters/cursor/native-exec"; +import { resolveMcpServers } from "../../../src/adapters/cursor/mcp-config"; +import { CursorMcpManager, CursorMcpPayloadTooLargeError, McpCatalogLimitError } from "../../../src/adapters/cursor/mcp-manager"; +import { buildMcpToolDefinitions, mcpDepsFromManager } from "../../../src/adapters/cursor/native-exec-mcp"; +import type { OcxProviderConfig } from "../../../src/types"; const textEncoder = new TextEncoder(); // 1x1 transparent PNG, base64 — exercises real image-content fidelity (not a placeholder). diff --git a/tests/cursor-mcp-stdio.test.ts b/tests/providers/cursor/cursor-mcp-stdio.test.ts similarity index 93% rename from tests/cursor-mcp-stdio.test.ts rename to tests/providers/cursor/cursor-mcp-stdio.test.ts index c938c56b3e..73008ad99c 100644 --- a/tests/cursor-mcp-stdio.test.ts +++ b/tests/providers/cursor/cursor-mcp-stdio.test.ts @@ -2,7 +2,7 @@ import { fromBinary, create } from "@bufbuild/protobuf"; import { afterEach, beforeEach, describe, expect, setDefaultTimeout, test } from "bun:test"; import { mkdtempSync, writeFileSync } from "node:fs"; import { join } from "node:path"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; // Real child-process spawns resolve packages through bun's install cache; Windows CI runners // ("Slow filesystem detected") can take >5s for the first spawn. Explicit headroom. @@ -11,10 +11,10 @@ import { AgentClientMessageSchema, ExecServerMessageSchema, McpArgsSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import { handleCursorNativeExec } from "../src/adapters/cursor/native-exec"; -import { CursorMcpManager } from "../src/adapters/cursor/mcp-manager"; -import { buildMcpToolDefinitions, mcpDepsFromManager } from "../src/adapters/cursor/native-exec-mcp"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { handleCursorNativeExec } from "../../../src/adapters/cursor/native-exec"; +import { CursorMcpManager } from "../../../src/adapters/cursor/mcp-manager"; +import { buildMcpToolDefinitions, mcpDepsFromManager } from "../../../src/adapters/cursor/native-exec-mcp"; /** * Live stdio integration: spawns a REAL MCP server as a child process over actual stdio diff --git a/tests/cursor-message-mapper.test.ts b/tests/providers/cursor/cursor-message-mapper.test.ts similarity index 93% rename from tests/cursor-message-mapper.test.ts rename to tests/providers/cursor/cursor-message-mapper.test.ts index a404a6a436..7218887d92 100644 --- a/tests/cursor-message-mapper.test.ts +++ b/tests/providers/cursor/cursor-message-mapper.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { createCursorKvStore } from "../src/adapters/cursor/kv-store"; -import { mapCursorServerMessage } from "../src/adapters/cursor/message-mapper"; -import type { CursorClientMessage } from "../src/adapters/cursor/types"; -import { createTranslatorBudget } from "../src/lib/translator-budget"; +import { createCursorKvStore } from "../../../src/adapters/cursor/kv-store"; +import { mapCursorServerMessage } from "../../../src/adapters/cursor/message-mapper"; +import type { CursorClientMessage } from "../../../src/adapters/cursor/types"; +import { createTranslatorBudget } from "../../../src/lib/translator-budget"; const bytes = (...values: number[]) => new Uint8Array(values); const kvStore = (seed: Record = {}) => createCursorKvStore(seed, createTranslatorBudget()); diff --git a/tests/cursor-native-exec-common.test.ts b/tests/providers/cursor/cursor-native-exec-common.test.ts similarity index 95% rename from tests/cursor-native-exec-common.test.ts rename to tests/providers/cursor/cursor-native-exec-common.test.ts index dcc9cd4629..8518a9c00d 100644 --- a/tests/cursor-native-exec-common.test.ts +++ b/tests/providers/cursor/cursor-native-exec-common.test.ts @@ -1,6 +1,6 @@ import { create, fromBinary } from "@bufbuild/protobuf"; import { describe, expect, test } from "bun:test"; -import { execBytes } from "../src/adapters/cursor/native-exec-common"; +import { execBytes } from "../../../src/adapters/cursor/native-exec-common"; import { AgentClientMessageSchema, DiagnosticsErrorSchema, @@ -11,7 +11,7 @@ import { RequestContextSuccessSchema, RequestContextResultSchema, RequestContextSchema, -} from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; function execServerMessage(message: Parameters>[1]["message"]) { return create(ExecServerMessageSchema, { id: 7, execId: "exec-test", message }); diff --git a/tests/cursor-native-exec-policy.test.ts b/tests/providers/cursor/cursor-native-exec-policy.test.ts similarity index 96% rename from tests/cursor-native-exec-policy.test.ts rename to tests/providers/cursor/cursor-native-exec-policy.test.ts index 1cf33ba21b..24b63e28ea 100644 --- a/tests/cursor-native-exec-policy.test.ts +++ b/tests/providers/cursor/cursor-native-exec-policy.test.ts @@ -3,12 +3,12 @@ import { tmpdir } from "node:os"; import { join } from "node:path"; import { create, fromBinary } from "@bufbuild/protobuf"; import { afterEach, describe, expect, test } from "bun:test"; -import { createCursorAdapter } from "../src/adapters/cursor"; +import { createCursorAdapter } from "../../../src/adapters/cursor"; import { cursorRequestDeclaresFullAccess, effectiveCursorNativeExecAllow, resolveCursorNativeExecMode, -} from "../src/adapters/cursor/exec-policy"; +} from "../../../src/adapters/cursor/exec-policy"; import { AgentClientMessageSchema, BackgroundShellSpawnArgsSchema, @@ -16,15 +16,15 @@ import { FetchArgsSchema, ReadArgsSchema, ShellArgsSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import { handleCursorNativeExec } from "../src/adapters/cursor/native-exec"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { handleCursorNativeExec } from "../../../src/adapters/cursor/native-exec"; import { resetBackgroundShellStateForTests, setBackgroundShellRuntimeForTests, -} from "../src/adapters/cursor/native-exec-shell"; -import type { CursorTransportFactoryInput } from "../src/adapters/cursor/transport"; -import { parseRequest } from "../src/responses/parser"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +} from "../../../src/adapters/cursor/native-exec-shell"; +import type { CursorTransportFactoryInput } from "../../../src/adapters/cursor/transport"; +import { parseRequest } from "../../../src/responses/parser"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; const fullAccessDeclaration = "`sandbox_mode` is `danger-full-access`"; diff --git a/tests/cursor-native-exec-shell.test.ts b/tests/providers/cursor/cursor-native-exec-shell.test.ts similarity index 99% rename from tests/cursor-native-exec-shell.test.ts rename to tests/providers/cursor/cursor-native-exec-shell.test.ts index a5a8e96c64..bb0cdd9c75 100644 --- a/tests/cursor-native-exec-shell.test.ts +++ b/tests/providers/cursor/cursor-native-exec-shell.test.ts @@ -10,7 +10,7 @@ import { ShellArgsSchema, WriteShellStdinArgsSchema, type AgentClientMessage, -} from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; import { CURSOR_BACKGROUND_SHELL_ABSOLUTE_MS, CURSOR_BACKGROUND_SHELL_IDLE_MS, @@ -26,7 +26,7 @@ import { terminateAllBackgroundShells, terminateBackgroundShellsForSession, writeShellStdinExec, -} from "../src/adapters/cursor/native-exec-shell"; +} from "../../../src/adapters/cursor/native-exec-shell"; function decodeClient(bytes: Uint8Array): AgentClientMessage { return fromBinary(AgentClientMessageSchema, bytes); diff --git a/tests/cursor-native-exec.test.ts b/tests/providers/cursor/cursor-native-exec.test.ts similarity index 99% rename from tests/cursor-native-exec.test.ts rename to tests/providers/cursor/cursor-native-exec.test.ts index be1ac99c47..6fb24ff112 100644 --- a/tests/cursor-native-exec.test.ts +++ b/tests/providers/cursor/cursor-native-exec.test.ts @@ -3,12 +3,12 @@ import { tmpdir } from "node:os"; import { join } from "node:path"; import { create, fromBinary } from "@bufbuild/protobuf"; import { afterEach, describe, expect, test } from "bun:test"; -import { handleCursorNativeExec } from "../src/adapters/cursor/native-exec"; +import { handleCursorNativeExec } from "../../../src/adapters/cursor/native-exec"; import { backgroundShellAdmissionMetrics, resetBackgroundShellStateForTests, setBackgroundShellRuntimeForTests, -} from "../src/adapters/cursor/native-exec-shell"; +} from "../../../src/adapters/cursor/native-exec-shell"; import { AgentClientMessageSchema, BackgroundShellSpawnArgsSchema, @@ -33,7 +33,7 @@ import { ShellArgsSchema, WriteShellStdinArgsSchema, WriteArgsSchema, -} from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; function execMessage(message: Parameters>[1]["message"]) { return create(ExecServerMessageSchema, { diff --git a/tests/cursor-oauth-shell.test.ts b/tests/providers/cursor/cursor-oauth-shell.test.ts similarity index 83% rename from tests/cursor-oauth-shell.test.ts rename to tests/providers/cursor/cursor-oauth-shell.test.ts index 9b231d8492..2b422bbc10 100644 --- a/tests/cursor-oauth-shell.test.ts +++ b/tests/providers/cursor/cursor-oauth-shell.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from "bun:test"; -import { buildInitProviders } from "../src/cli/init"; -import { isOAuthProvider, listOAuthProviders } from "../src/oauth"; -import { deriveProviderPresets } from "../src/providers/derive"; +import { buildInitProviders } from "../../../src/cli/init"; +import { isOAuthProvider, listOAuthProviders } from "../../../src/oauth"; +import { deriveProviderPresets } from "../../../src/providers/derive"; // WP16 (devlog 350.100): the disabled OAuth shell was replaced by the real PKCE flow — the flow -// itself is covered by tests/cursor-oauth.test.ts. These tests cover cursor's provider-routing, +// itself is covered by tests/providers/cursor/cursor-oauth.test.ts. These tests cover cursor's provider-routing, // init/preset metadata, and the OAuth module's standalone property (no local fs/process/http2). describe("Cursor provider routing + standalone OAuth module", () => { // WP17 (devlog 350.101): cursor is now registered in OAUTH_PROVIDERS. diff --git a/tests/cursor-oauth.test.ts b/tests/providers/cursor/cursor-oauth.test.ts similarity index 99% rename from tests/cursor-oauth.test.ts rename to tests/providers/cursor/cursor-oauth.test.ts index c4f3b2651b..640301564d 100644 --- a/tests/cursor-oauth.test.ts +++ b/tests/providers/cursor/cursor-oauth.test.ts @@ -6,7 +6,7 @@ import { loginCursor, pollCursorAuth, refreshCursorToken, -} from "../src/oauth/cursor"; +} from "../../../src/oauth/cursor"; const realFetch = globalThis.fetch; afterEach(() => { diff --git a/tests/cursor-pool.test.ts b/tests/providers/cursor/cursor-pool.test.ts similarity index 96% rename from tests/cursor-pool.test.ts rename to tests/providers/cursor/cursor-pool.test.ts index 25881e8c48..a636b14e2a 100644 --- a/tests/cursor-pool.test.ts +++ b/tests/providers/cursor/cursor-pool.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { CursorCredentialRouter, NoAvailableCursorCredentialError } from "../src/providers/cursor-pool"; +import { CursorCredentialRouter, NoAvailableCursorCredentialError } from "../../../src/providers/cursor-pool"; describe("CursorCredentialRouter", () => { test("weighted round-robin distributes picks proportionally", () => { diff --git a/tests/cursor-protobuf-events.test.ts b/tests/providers/cursor/cursor-protobuf-events.test.ts similarity index 99% rename from tests/cursor-protobuf-events.test.ts rename to tests/providers/cursor/cursor-protobuf-events.test.ts index 8da5485215..53c198772b 100644 --- a/tests/cursor-protobuf-events.test.ts +++ b/tests/providers/cursor/cursor-protobuf-events.test.ts @@ -13,17 +13,17 @@ import { ToolCallCompletedUpdateSchema, ToolCallSchema, ToolCallStartedUpdateSchema, -} from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; import { createCursorContextUsageTracker, createCursorProtobufEventState, finalizeTurnEvents, mapCursorProtobufServerMessage, mapSyntheticMcpExecToToolEvents, -} from "../src/adapters/cursor/protobuf-events"; -import { createTranslatorBudget } from "../src/lib/translator-budget"; -import { observeEmptyCompletion } from "../src/server/responses/empty-completion-guard"; -import type { AdapterEvent } from "../src/types"; +} from "../../../src/adapters/cursor/protobuf-events"; +import { createTranslatorBudget } from "../../../src/lib/translator-budget"; +import { observeEmptyCompletion } from "../../../src/server/responses/empty-completion-guard"; +import type { AdapterEvent } from "../../../src/types"; const encoder = new TextEncoder(); diff --git a/tests/cursor-repetition-breaker.test.ts b/tests/providers/cursor/cursor-repetition-breaker.test.ts similarity index 96% rename from tests/cursor-repetition-breaker.test.ts rename to tests/providers/cursor/cursor-repetition-breaker.test.ts index bba00b39e9..48b9ca0ac2 100644 --- a/tests/cursor-repetition-breaker.test.ts +++ b/tests/providers/cursor/cursor-repetition-breaker.test.ts @@ -1,14 +1,14 @@ import { describe, expect, test } from "bun:test"; import { fromBinary } from "@bufbuild/protobuf"; -import { encodeCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; -import { handleCursorNativeKv } from "../src/adapters/cursor/native-exec"; +import { encodeCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; +import { handleCursorNativeKv } from "../../../src/adapters/cursor/native-exec"; import { create } from "@bufbuild/protobuf"; import { AgentClientMessageSchema, GetBlobArgsSchema, KvServerMessageSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import type { OcxMessage } from "../src/types"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import type { OcxMessage } from "../../../src/types"; function blobData(blobId: Uint8Array): Uint8Array { const reply = fromBinary(AgentClientMessageSchema, handleCursorNativeKv(create(KvServerMessageSchema, { diff --git a/tests/cursor-request-builder.test.ts b/tests/providers/cursor/cursor-request-builder.test.ts similarity index 99% rename from tests/cursor-request-builder.test.ts rename to tests/providers/cursor/cursor-request-builder.test.ts index 4ecd87993f..0e1b355b30 100644 --- a/tests/cursor-request-builder.test.ts +++ b/tests/providers/cursor/cursor-request-builder.test.ts @@ -1,13 +1,13 @@ import { describe, expect, test } from "bun:test"; import { create, toBinary } from "@bufbuild/protobuf"; -import { ConversationStateStructureSchema } from "../src/adapters/cursor/gen/agent_pb"; +import { ConversationStateStructureSchema } from "../../../src/adapters/cursor/gen/agent_pb"; import { clearCursorCheckpointsForTests, commitCursorCheckpoint, CURSOR_CHECKPOINT_TTL_MS, getCursorCheckpoint, installCursorCheckpointClockForTests, -} from "../src/adapters/cursor/checkpoint-store"; +} from "../../../src/adapters/cursor/checkpoint-store"; import { applyCursorToolBudget, createCursorRequest, @@ -15,12 +15,12 @@ import { cursorInstructionDigest, CURSOR_TOOL_BYTES_LIMIT, CURSOR_TOOL_COUNT_LIMIT, -} from "../src/adapters/cursor/request-builder"; -import { cursorCheckpointModelAffinityId } from "../src/adapters/cursor/discovery"; -import { cursorMcpToolsEncodedSize } from "../src/adapters/cursor/tool-definitions"; -import { encodeCursorCallId, resetCursorCallIdProvenanceForTests } from "../src/adapters/cursor/call-id"; -import { parseRequest } from "../src/responses/parser"; -import type { OcxParsedRequest } from "../src/types"; +} from "../../../src/adapters/cursor/request-builder"; +import { cursorCheckpointModelAffinityId } from "../../../src/adapters/cursor/discovery"; +import { cursorMcpToolsEncodedSize } from "../../../src/adapters/cursor/tool-definitions"; +import { encodeCursorCallId, resetCursorCallIdProvenanceForTests } from "../../../src/adapters/cursor/call-id"; +import { parseRequest } from "../../../src/responses/parser"; +import type { OcxParsedRequest } from "../../../src/types"; const base: OcxParsedRequest = { modelId: "cursor/auto", diff --git a/tests/cursor-silent-redirect.test.ts b/tests/providers/cursor/cursor-silent-redirect.test.ts similarity index 94% rename from tests/cursor-silent-redirect.test.ts rename to tests/providers/cursor/cursor-silent-redirect.test.ts index 8f63daf4b3..3699f21ab2 100644 --- a/tests/cursor-silent-redirect.test.ts +++ b/tests/providers/cursor/cursor-silent-redirect.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { nativeShellDisabledMessage } from "../src/adapters/cursor/native-exec-shell"; +import { nativeShellDisabledMessage } from "../../../src/adapters/cursor/native-exec-shell"; /** * Devlog 260826 gap-8: native-tool denial payloads must read as silent redirects. diff --git a/tests/cursor-static-catalog.test.ts b/tests/providers/cursor/cursor-static-catalog.test.ts similarity index 92% rename from tests/cursor-static-catalog.test.ts rename to tests/providers/cursor/cursor-static-catalog.test.ts index 87f73320b9..511cb8ac3f 100644 --- a/tests/cursor-static-catalog.test.ts +++ b/tests/providers/cursor/cursor-static-catalog.test.ts @@ -1,14 +1,14 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { buildCatalogEntries, gatherRoutedModels } from "../src/codex/catalog"; +import { buildCatalogEntries, gatherRoutedModels } from "../../../src/codex/catalog"; import { CURSOR_STATIC_MODELS, cursorModelContextWindows, cursorModelIds, cursorModelInputModalities, cursorModelReasoningEfforts, -} from "../src/adapters/cursor/discovery"; -import { cursorModelHasEffortTiers } from "../src/adapters/cursor/effort-map"; -import { clearModelCache } from "../src/codex/model-cache"; +} from "../../../src/adapters/cursor/discovery"; +import { cursorModelHasEffortTiers } from "../../../src/adapters/cursor/effort-map"; +import { clearModelCache } from "../../../src/codex/model-cache"; const originalFetch = globalThis.fetch; @@ -125,8 +125,8 @@ describe("Opus Fast catalog families (devlog 300, live-verified 260822)", () => // Umbrella merge (devlog 260828): the -fast rows folded into their bases. // The alias path still resolves them with the exact live-verified ladders. test("fast rows folded into bases; aliases keep resolving with tier semantics", async () => { - const { CURSOR_STATIC_MODELS } = await import("../src/adapters/cursor/discovery"); - const { resolveCursorSelection } = await import("../src/adapters/cursor/catalog"); + const { CURSOR_STATIC_MODELS } = await import("../../../src/adapters/cursor/discovery"); + const { resolveCursorSelection } = await import("../../../src/adapters/cursor/catalog"); for (const id of ["claude-opus-4-7-fast", "claude-opus-4-8-fast", "claude-opus-5-fast"]) { expect(CURSOR_STATIC_MODELS.some(model => model.id === id)).toBe(false); // Alias never sends a bare -fast id (not_found on the wire). @@ -136,14 +136,14 @@ describe("Opus Fast catalog families (devlog 300, live-verified 260822)", () => }); test("tier ladders match the 260822 GetUsableModels dump", async () => { - const { cursorModelEffortLadder } = await import("../src/adapters/cursor/effort-map"); + const { cursorModelEffortLadder } = await import("../../../src/adapters/cursor/effort-map"); expect(cursorModelEffortLadder("claude-opus-4-7-fast")).toEqual(["low", "medium", "high", "xhigh", "max"]); expect(cursorModelEffortLadder("claude-opus-4-8-fast")).toEqual(["low", "medium", "high", "xhigh", "max"]); expect(cursorModelEffortLadder("claude-opus-5-fast")).toEqual(["low", "medium", "high"]); }); test("wire-id derivation produces the live-verified suffixed forms and never a bare -fast id", async () => { - const { cursorWireModelIdWithEffort, cursorEffortSuffix } = await import("../src/adapters/cursor/effort-map"); + const { cursorWireModelIdWithEffort, cursorEffortSuffix } = await import("../../../src/adapters/cursor/effort-map"); expect(cursorWireModelIdWithEffort("claude-opus-4-8-fast", "high")).toBe("claude-opus-4-8-high-fast"); expect(cursorWireModelIdWithEffort("claude-opus-5-fast", "medium")).toBe("claude-opus-5-medium-fast"); expect(cursorWireModelIdWithEffort("claude-opus-4-7-fast", "max")).toBe("claude-opus-4-7-max-fast"); diff --git a/tests/cursor-stream-health.test.ts b/tests/providers/cursor/cursor-stream-health.test.ts similarity index 95% rename from tests/cursor-stream-health.test.ts rename to tests/providers/cursor/cursor-stream-health.test.ts index 3c8450b4ab..dc7b572bf1 100644 --- a/tests/cursor-stream-health.test.ts +++ b/tests/providers/cursor/cursor-stream-health.test.ts @@ -8,11 +8,11 @@ import { InteractionUpdateSchema, TextDeltaUpdateSchema, TurnEndedUpdateSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import { encodeConnectFrame } from "../src/adapters/cursor/framing"; -import { createLiveCursorTransport } from "../src/adapters/cursor/live-transport"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import type { CursorRunRequest, CursorServerMessage } from "../src/adapters/cursor/types"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { encodeConnectFrame } from "../../../src/adapters/cursor/framing"; +import { createLiveCursorTransport } from "../../../src/adapters/cursor/live-transport"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; +import type { CursorRunRequest, CursorServerMessage } from "../../../src/adapters/cursor/types"; /** * T04 (devlog 260822_senpi_cursor_transfer/110): inbound stream-health watchdog. diff --git a/tests/cursor-structured-edit.test.ts b/tests/providers/cursor/cursor-structured-edit.test.ts similarity index 99% rename from tests/cursor-structured-edit.test.ts rename to tests/providers/cursor/cursor-structured-edit.test.ts index 294dc394cd..b04e8ed124 100644 --- a/tests/cursor-structured-edit.test.ts +++ b/tests/providers/cursor/cursor-structured-edit.test.ts @@ -1,6 +1,6 @@ import { create } from "@bufbuild/protobuf"; import { describe, expect, test } from "bun:test"; -import type { OcxTool } from "../src/types"; +import type { OcxTool } from "../../../src/types"; import { AgentServerMessageSchema, ExecServerMessageSchema, @@ -11,7 +11,7 @@ import { ToolCallCompletedUpdateSchema, ToolCallSchema, ToolCallStartedUpdateSchema, -} from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; import { createCursorProtobufEventState, foldSequentialStructuredEdits, @@ -20,11 +20,11 @@ import { sanitizeCodexApplyPatch, sanitizeEmittedApplyPatchArgs, translateStructuredEditCall, -} from "../src/adapters/cursor/protobuf-events"; -import { planMcpArgsHandling } from "../src/adapters/cursor/live-transport"; +} from "../../../src/adapters/cursor/protobuf-events"; +import { planMcpArgsHandling } from "../../../src/adapters/cursor/live-transport"; import { applyCursorToolBudget, -} from "../src/adapters/cursor/request-builder"; +} from "../../../src/adapters/cursor/request-builder"; import { buildCursorToolGuidanceSystemNote, CURSOR_EDIT_FILE_INPUT_SCHEMA, @@ -34,7 +34,7 @@ import { cursorStructuredEditTools, cursorToolsForActivePrompt, isCursorSyntheticStructuredEditTool, -} from "../src/adapters/cursor/tool-definitions"; +} from "../../../src/adapters/cursor/tool-definitions"; const encoder = new TextEncoder(); diff --git a/tests/cursor-tool-arg-decoding.test.ts b/tests/providers/cursor/cursor-tool-arg-decoding.test.ts similarity index 99% rename from tests/cursor-tool-arg-decoding.test.ts rename to tests/providers/cursor/cursor-tool-arg-decoding.test.ts index 5980ad92e1..9bcdd47f60 100644 --- a/tests/cursor-tool-arg-decoding.test.ts +++ b/tests/providers/cursor/cursor-tool-arg-decoding.test.ts @@ -9,12 +9,12 @@ import { ToolCallStartedUpdateSchema, ToolCallCompletedUpdateSchema, ToolCallSchema, -} from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; import { createCursorProtobufEventState, mapCursorProtobufServerMessage, mapSyntheticMcpExecToToolEvents, -} from "../src/adapters/cursor/protobuf-events"; +} from "../../../src/adapters/cursor/protobuf-events"; const encoder = new TextEncoder(); diff --git a/tests/cursor-tool-choice.test.ts b/tests/providers/cursor/cursor-tool-choice.test.ts similarity index 94% rename from tests/cursor-tool-choice.test.ts rename to tests/providers/cursor/cursor-tool-choice.test.ts index fe6da06331..0a0861d0ab 100644 --- a/tests/cursor-tool-choice.test.ts +++ b/tests/providers/cursor/cursor-tool-choice.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { buildCursorToolDefinitions } from "../src/adapters/cursor/tool-definitions"; -import { createCursorRequest } from "../src/adapters/cursor/request-builder"; -import { parseRequest } from "../src/responses/parser"; -import type { OcxTool } from "../src/types"; +import { buildCursorToolDefinitions } from "../../../src/adapters/cursor/tool-definitions"; +import { createCursorRequest } from "../../../src/adapters/cursor/request-builder"; +import { parseRequest } from "../../../src/responses/parser"; +import type { OcxTool } from "../../../src/types"; const tools: OcxTool[] = [ { name: "read_file", namespace: "mcp__fs", description: "Read", parameters: {} }, diff --git a/tests/cursor-tool-continuation.test.ts b/tests/providers/cursor/cursor-tool-continuation.test.ts similarity index 96% rename from tests/cursor-tool-continuation.test.ts rename to tests/providers/cursor/cursor-tool-continuation.test.ts index 2772245035..6196af58da 100644 --- a/tests/cursor-tool-continuation.test.ts +++ b/tests/providers/cursor/cursor-tool-continuation.test.ts @@ -1,13 +1,13 @@ import { describe, expect, test } from "bun:test"; import { create, fromBinary } from "@bufbuild/protobuf"; -import { handleCursorNativeKv } from "../src/adapters/cursor/native-exec"; -import { encodeCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; +import { handleCursorNativeKv } from "../../../src/adapters/cursor/native-exec"; +import { encodeCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; import { AgentClientMessageSchema, GetBlobArgsSchema, KvServerMessageSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import type { OcxMessage } from "../src/types"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import type { OcxMessage } from "../../../src/types"; function blobData(blobId: Uint8Array): Uint8Array { const reply = fromBinary(AgentClientMessageSchema, handleCursorNativeKv(create(KvServerMessageSchema, { @@ -119,9 +119,9 @@ describe("363-B: tool result reaches the model via rootPromptMessagesJson", () = }); import { create as createPb } from "@bufbuild/protobuf"; -import { ExecServerMessageSchema, McpArgsSchema } from "../src/adapters/cursor/gen/agent_pb"; -import { createCursorContextUsageTracker, createCursorProtobufEventState } from "../src/adapters/cursor/protobuf-events"; -import { planMcpArgsHandling, finalizeAfterDrain } from "../src/adapters/cursor/live-transport"; +import { ExecServerMessageSchema, McpArgsSchema } from "../../../src/adapters/cursor/gen/agent_pb"; +import { createCursorContextUsageTracker, createCursorProtobufEventState } from "../../../src/adapters/cursor/protobuf-events"; +import { planMcpArgsHandling, finalizeAfterDrain } from "../../../src/adapters/cursor/live-transport"; function execMcpArgs(opts: { provider?: string; toolName?: string; toolCallId?: string; args?: Record }) { return createPb(ExecServerMessageSchema, { diff --git a/tests/cursor-tool-definitions.test.ts b/tests/providers/cursor/cursor-tool-definitions.test.ts similarity index 99% rename from tests/cursor-tool-definitions.test.ts rename to tests/providers/cursor/cursor-tool-definitions.test.ts index d87d77d067..f21ae2fb27 100644 --- a/tests/cursor-tool-definitions.test.ts +++ b/tests/providers/cursor/cursor-tool-definitions.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; import { fromBinary, toJson } from "@bufbuild/protobuf"; import { ValueSchema } from "@bufbuild/protobuf/wkt"; -import { normalizeArgKeys } from "../src/adapters/cursor/arg-normalize"; +import { normalizeArgKeys } from "../../../src/adapters/cursor/arg-normalize"; import { appendCursorGenericToolUseHint, buildCursorToolDefinitions, @@ -16,8 +16,8 @@ import { cursorToolWireName, isGenericToolUseCountDemoPrompt, nonEmptyShellBridgeCommandFromArgs, -} from "../src/adapters/cursor/tool-definitions"; -import type { OcxTool } from "../src/types"; +} from "../../../src/adapters/cursor/tool-definitions"; +import type { OcxTool } from "../../../src/types"; describe("Cursor tool definitions", () => { test("converts Responses tools to Cursor request context definitions", () => { diff --git a/tests/cursor-tool-finalize-race.test.ts b/tests/providers/cursor/cursor-tool-finalize-race.test.ts similarity index 96% rename from tests/cursor-tool-finalize-race.test.ts rename to tests/providers/cursor/cursor-tool-finalize-race.test.ts index 867d942561..e16a6c28f8 100644 --- a/tests/cursor-tool-finalize-race.test.ts +++ b/tests/providers/cursor/cursor-tool-finalize-race.test.ts @@ -1,9 +1,9 @@ import { describe, expect, test } from "bun:test"; import { create, toBinary } from "@bufbuild/protobuf"; -import { clientToolFinalizeGraceMsForRequest, createLiveCursorTransport } from "../src/adapters/cursor/live-transport"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import { createCursorProtobufEventState } from "../src/adapters/cursor/protobuf-events"; -import type { CursorRunRequest, CursorServerMessage } from "../src/adapters/cursor/types"; +import { clientToolFinalizeGraceMsForRequest, createLiveCursorTransport } from "../../../src/adapters/cursor/live-transport"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; +import { createCursorProtobufEventState } from "../../../src/adapters/cursor/protobuf-events"; +import type { CursorRunRequest, CursorServerMessage } from "../../../src/adapters/cursor/types"; import { AgentServerMessageSchema, ExecServerMessageSchema, @@ -13,7 +13,7 @@ import { ToolCallCompletedUpdateSchema, ToolCallStartedUpdateSchema, InteractionUpdateSchema, -} from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; const PROVIDER = "opencodex-responses"; diff --git a/tests/cursor-tool-result-image.test.ts b/tests/providers/cursor/cursor-tool-result-image.test.ts similarity index 98% rename from tests/cursor-tool-result-image.test.ts rename to tests/providers/cursor/cursor-tool-result-image.test.ts index 610c25e3c4..90c09ffaab 100644 --- a/tests/cursor-tool-result-image.test.ts +++ b/tests/providers/cursor/cursor-tool-result-image.test.ts @@ -1,15 +1,15 @@ import { describe, expect, test } from "bun:test"; import { create, fromBinary } from "@bufbuild/protobuf"; -import { handleCursorNativeKv, setCursorBlobLimitsForTests } from "../src/adapters/cursor/native-exec"; -import { encodeCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; +import { handleCursorNativeKv, setCursorBlobLimitsForTests } from "../../../src/adapters/cursor/native-exec"; +import { encodeCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; import { AgentClientMessageSchema, ConversationTurnStructureSchema, ConversationStepSchema, GetBlobArgsSchema, KvServerMessageSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import type { OcxMessage } from "../src/types"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import type { OcxMessage } from "../../../src/types"; const PNG_BYTES = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x01, 0x02, 0x03, 0x04]); const PNG_B64 = Buffer.from(PNG_BYTES).toString("base64"); diff --git a/tests/cursor-tool-result-invocation.test.ts b/tests/providers/cursor/cursor-tool-result-invocation.test.ts similarity index 99% rename from tests/cursor-tool-result-invocation.test.ts rename to tests/providers/cursor/cursor-tool-result-invocation.test.ts index 2c87fe0942..aa3b9d16d0 100644 --- a/tests/cursor-tool-result-invocation.test.ts +++ b/tests/providers/cursor/cursor-tool-result-invocation.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; import { create, fromBinary, toBinary } from "@bufbuild/protobuf"; -import { CURSOR_INVOCATION_ARGUMENTS_BYTE_LIMIT, encodeCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; -import { handleCursorNativeKv, storeCursorBlob } from "../src/adapters/cursor/native-exec"; +import { CURSOR_INVOCATION_ARGUMENTS_BYTE_LIMIT, encodeCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; +import { handleCursorNativeKv, storeCursorBlob } from "../../../src/adapters/cursor/native-exec"; import { AgentClientMessageSchema, ConversationStepSchema, @@ -9,8 +9,8 @@ import { ConversationTurnStructureSchema, GetBlobArgsSchema, KvServerMessageSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import type { OcxMessage } from "../src/types"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import type { OcxMessage } from "../../../src/types"; function blobData(blobId: Uint8Array): Uint8Array { const reply = fromBinary(AgentClientMessageSchema, handleCursorNativeKv(create(KvServerMessageSchema, { diff --git a/tests/cursor-tool-suspended-checkpoint.test.ts b/tests/providers/cursor/cursor-tool-suspended-checkpoint.test.ts similarity index 92% rename from tests/cursor-tool-suspended-checkpoint.test.ts rename to tests/providers/cursor/cursor-tool-suspended-checkpoint.test.ts index 6461d20a48..4ce1152173 100644 --- a/tests/cursor-tool-suspended-checkpoint.test.ts +++ b/tests/providers/cursor/cursor-tool-suspended-checkpoint.test.ts @@ -1,11 +1,11 @@ import { describe, expect, test } from "bun:test"; -import { createCursorAdapter as createCursorAdapterProduction } from "../src/adapters/cursor"; -import { clearCursorCheckpointsForTests, getCursorCheckpoint } from "../src/adapters/cursor/checkpoint-store"; +import { createCursorAdapter as createCursorAdapterProduction } from "../../../src/adapters/cursor"; +import { clearCursorCheckpointsForTests, getCursorCheckpoint } from "../../../src/adapters/cursor/checkpoint-store"; import { create, toBinary } from "@bufbuild/protobuf"; -import { ConversationStateStructureSchema } from "../src/adapters/cursor/gen/agent_pb"; -import type { AdapterEvent, OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import type { CursorServerMessage } from "../src/adapters/cursor/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { ConversationStateStructureSchema } from "../../../src/adapters/cursor/gen/agent_pb"; +import type { AdapterEvent, OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; +import type { CursorServerMessage } from "../../../src/adapters/cursor/types"; +import { withTestTranslatorBudget } from "../../helpers/translator-budget"; const createCursorAdapter = (...args: Parameters) => withTestTranslatorBudget(createCursorAdapterProduction(...args)); diff --git a/tests/cursor-toolresult-normalize.test.ts b/tests/providers/cursor/cursor-toolresult-normalize.test.ts similarity index 95% rename from tests/cursor-toolresult-normalize.test.ts rename to tests/providers/cursor/cursor-toolresult-normalize.test.ts index e4d5283544..c62ad8e27b 100644 --- a/tests/cursor-toolresult-normalize.test.ts +++ b/tests/providers/cursor/cursor-toolresult-normalize.test.ts @@ -1,16 +1,16 @@ import { describe, expect, test } from "bun:test"; import { create, fromBinary } from "@bufbuild/protobuf"; -import { handleCursorNativeKv } from "../src/adapters/cursor/native-exec"; -import { encodeCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; -import { normalizeCursorToolResultText } from "../src/adapters/cursor/tool-result-normalize"; +import { handleCursorNativeKv } from "../../../src/adapters/cursor/native-exec"; +import { encodeCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; +import { normalizeCursorToolResultText } from "../../../src/adapters/cursor/tool-result-normalize"; import { AgentClientMessageSchema, ConversationTurnStructureSchema, ConversationStepSchema, GetBlobArgsSchema, KvServerMessageSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import type { OcxMessage, OcxToolResultMessage } from "../src/types"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import type { OcxMessage, OcxToolResultMessage } from "../../../src/types"; function blobData(blobId: Uint8Array): Uint8Array { const reply = fromBinary(AgentClientMessageSchema, handleCursorNativeKv(create(KvServerMessageSchema, { diff --git a/tests/cursor-transport-retry.test.ts b/tests/providers/cursor/cursor-transport-retry.test.ts similarity index 98% rename from tests/cursor-transport-retry.test.ts rename to tests/providers/cursor/cursor-transport-retry.test.ts index 2c85c98518..fe55b0f825 100644 --- a/tests/cursor-transport-retry.test.ts +++ b/tests/providers/cursor/cursor-transport-retry.test.ts @@ -3,9 +3,9 @@ import { cursorRetryDelayMs, isRetryableCursorError, runCursorTurnWithRetry, -} from "../src/adapters/cursor/transport-retry"; -import type { CursorRunRequest, CursorServerMessage } from "../src/adapters/cursor/types"; -import type { CursorTransport } from "../src/adapters/cursor/transport"; +} from "../../../src/adapters/cursor/transport-retry"; +import type { CursorRunRequest, CursorServerMessage } from "../../../src/adapters/cursor/types"; +import type { CursorTransport } from "../../../src/adapters/cursor/transport"; const request = {} as CursorRunRequest; diff --git a/tests/cursor-ultra-mode.test.ts b/tests/providers/cursor/cursor-ultra-mode.test.ts similarity index 92% rename from tests/cursor-ultra-mode.test.ts rename to tests/providers/cursor/cursor-ultra-mode.test.ts index b45c70a91e..57587c290b 100644 --- a/tests/cursor-ultra-mode.test.ts +++ b/tests/providers/cursor/cursor-ultra-mode.test.ts @@ -4,12 +4,12 @@ import { CURSOR_ULTRA_1M_MODEL_IDS, cursorUltraBaseModelId, filterCursorConfiguredModelsByLiveDiscovery, -} from "../src/adapters/cursor/discovery"; -import { createCursorRequest } from "../src/adapters/cursor/request-builder"; -import { encodeCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; +} from "../../../src/adapters/cursor/discovery"; +import { createCursorRequest } from "../../../src/adapters/cursor/request-builder"; +import { encodeCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; import { fromBinary } from "@bufbuild/protobuf"; -import { AgentClientMessageSchema, type AgentRunRequest } from "../src/adapters/cursor/gen/agent_pb"; -import type { OcxParsedRequest } from "../src/types/request"; +import { AgentClientMessageSchema, type AgentRunRequest } from "../../../src/adapters/cursor/gen/agent_pb"; +import type { OcxParsedRequest } from "../../../src/types/request"; function decodeRunRequest(bytes: Uint8Array): AgentRunRequest { const msg = fromBinary(AgentClientMessageSchema, bytes); diff --git a/tests/cursor-umbrella-rows.test.ts b/tests/providers/cursor/cursor-umbrella-rows.test.ts similarity index 96% rename from tests/cursor-umbrella-rows.test.ts rename to tests/providers/cursor/cursor-umbrella-rows.test.ts index 7cb1bb1186..f616f7f505 100644 --- a/tests/cursor-umbrella-rows.test.ts +++ b/tests/providers/cursor/cursor-umbrella-rows.test.ts @@ -6,7 +6,7 @@ import { recordLiveCursorMaxModeModels, resetLiveCursorClaudeWireIdentitiesForTests, resolveCursorSelection, -} from "../src/adapters/cursor/catalog"; +} from "../../../src/adapters/cursor/catalog"; import { CURSOR_PRODUCT_MODELS, CURSOR_REAL_ID_EXCEPTIONS, @@ -14,9 +14,9 @@ import { CURSOR_STATIC_MODELS, cursorModelDisplayNames, cursorModelReasoningEfforts, -} from "../src/adapters/cursor/discovery"; -import { createCursorRequest } from "../src/adapters/cursor/request-builder"; -import type { OcxParsedRequest } from "../src/types"; +} from "../../../src/adapters/cursor/discovery"; +import { createCursorRequest } from "../../../src/adapters/cursor/request-builder"; +import type { OcxParsedRequest } from "../../../src/types"; function parsedFor(modelId: string, reasoning?: string): OcxParsedRequest { return { diff --git a/tests/cursor-uncallable-quarantine.test.ts b/tests/providers/cursor/cursor-uncallable-quarantine.test.ts similarity index 94% rename from tests/cursor-uncallable-quarantine.test.ts rename to tests/providers/cursor/cursor-uncallable-quarantine.test.ts index 64eb0b0b58..104a5bd3ba 100644 --- a/tests/cursor-uncallable-quarantine.test.ts +++ b/tests/providers/cursor/cursor-uncallable-quarantine.test.ts @@ -3,7 +3,7 @@ import { CURSOR_KNOWN_UNCALLABLE_MODEL_IDS, CURSOR_STATIC_MODELS, filterCursorConfiguredModelsByLiveDiscovery, -} from "../src/adapters/cursor/discovery"; +} from "../../../src/adapters/cursor/discovery"; describe("cursor uncallable-model quarantine (devlog 260826 060)", () => { // Umbrella merge (devlog 260828): the base row RETURNED to the seed because @@ -18,7 +18,7 @@ describe("cursor uncallable-model quarantine (devlog 260826 060)", () => { }); test("the quarantined REGULAR variant is never sent for the bare slug (resolver-level quarantine)", async () => { - const { resolveCursorSelection, CURSOR_CAPABILITIES } = await import("../src/adapters/cursor/catalog"); + const { resolveCursorSelection, CURSOR_CAPABILITIES } = await import("../../../src/adapters/cursor/catalog"); expect(CURSOR_CAPABILITIES["claude-opus-5"]!.variants.regular?.quarantined).toBe(true); // The bare slug routes the healthy thinking family, never claude-opus-5-. expect(resolveCursorSelection("claude-opus-5", "high").wireId).toBe("claude-opus-5-thinking-high"); diff --git a/tests/cursor-vision-wire-harness.test.ts b/tests/providers/cursor/cursor-vision-wire-harness.test.ts similarity index 93% rename from tests/cursor-vision-wire-harness.test.ts rename to tests/providers/cursor/cursor-vision-wire-harness.test.ts index 6b26c36931..35194f39ec 100644 --- a/tests/cursor-vision-wire-harness.test.ts +++ b/tests/providers/cursor/cursor-vision-wire-harness.test.ts @@ -1,14 +1,14 @@ import { describe, expect, test } from "bun:test"; import { fromBinary } from "@bufbuild/protobuf"; -import { encodeCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; -import { CURSOR_VISION_IMAGE_HISTORY_MARKER } from "../src/adapters/cursor/images"; +import { encodeCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; +import { CURSOR_VISION_IMAGE_HISTORY_MARKER } from "../../../src/adapters/cursor/images"; import { AgentClientMessageSchema, ConversationStepSchema, ConversationTurnStructureSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import { handleCursorNativeKv, resetCursorBlobStateForTests } from "../src/adapters/cursor/native-exec"; -import { GetBlobArgsSchema, KvServerMessageSchema } from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { handleCursorNativeKv, resetCursorBlobStateForTests } from "../../../src/adapters/cursor/native-exec"; +import { GetBlobArgsSchema, KvServerMessageSchema } from "../../../src/adapters/cursor/gen/agent_pb"; import { create } from "@bufbuild/protobuf"; function blobData(blobId: Uint8Array): Uint8Array { diff --git a/tests/cyber-policy-error-fidelity.test.ts b/tests/providers/cyber-policy-error-fidelity.test.ts similarity index 97% rename from tests/cyber-policy-error-fidelity.test.ts rename to tests/providers/cyber-policy-error-fidelity.test.ts index 86e6b61656..adcf36be01 100644 --- a/tests/cyber-policy-error-fidelity.test.ts +++ b/tests/providers/cyber-policy-error-fidelity.test.ts @@ -1,23 +1,23 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter as createOpenAIChatAdapterProduction } from "../src/adapters/openai-chat"; -import { bridgeToResponsesSSE, buildResponseJSON, formatErrorResponse } from "../src/bridge"; +import { createOpenAIChatAdapter as createOpenAIChatAdapterProduction } from "../../src/adapters/openai-chat"; +import { bridgeToResponsesSSE, buildResponseJSON, formatErrorResponse } from "../../src/bridge"; import { chatCompletionsErrorBody, chatCompletionsErrorResponse, responsesSseToChatCompletionsSse as responsesSseToChatCompletionsSseProduction, -} from "../src/chat/outbound"; -import { comboFailureDecision } from "../src/combos/failover"; +} from "../../src/chat/outbound"; +import { comboFailureDecision } from "../../src/combos/failover"; import { adapterFailureFromMessage, classifyError, CYBER_POLICY_ERROR_CODE, httpStatusFromTerminalError, -} from "../src/lib/errors"; -import { formatPassthroughUpstreamError } from "../src/server/responses/passthrough-error"; -import { consumeComboFailure } from "../src/server/responses/core"; -import { handleResponses } from "../src/server/responses"; -import type { AdapterEvent, OcxConfig } from "../src/types"; -import { createTestTranslatorBudget, withTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../src/lib/errors"; +import { formatPassthroughUpstreamError } from "../../src/server/responses/passthrough-error"; +import { consumeComboFailure } from "../../src/server/responses/core"; +import { handleResponses } from "../../src/server/responses"; +import type { AdapterEvent, OcxConfig } from "../../src/types"; +import { createTestTranslatorBudget, withTestTranslatorBudget } from "../helpers/translator-budget"; const createOpenAIChatAdapter = (...args: Parameters) => withTestTranslatorBudget(createOpenAIChatAdapterProduction(...args)); diff --git a/tests/deepinfra-provider.test.ts b/tests/providers/deepinfra-provider.test.ts similarity index 88% rename from tests/deepinfra-provider.test.ts rename to tests/providers/deepinfra-provider.test.ts index 39385652a8..f98f8151e1 100644 --- a/tests/deepinfra-provider.test.ts +++ b/tests/providers/deepinfra-provider.test.ts @@ -1,24 +1,25 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { PROVIDER_REGISTRY, type ProviderRegistryEntry } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; - -const FIXTURE = readFileSync(join(import.meta.dir, "fixtures/deepinfra-models.json"), "utf8"); +} from "../../src/providers/derive"; +import { PROVIDER_REGISTRY, type ProviderRegistryEntry } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; + +const FIXTURE = readFileSync(fixturePath("deepinfra-models.json"), "utf8"); const BASE_URL = "https://api.deepinfra.com/v1/openai"; const MODELS_URL = "https://api.deepinfra.com/v1/models"; const API_KEY = "di-test-key"; diff --git a/tests/deepseek-inbound-wire.test.ts b/tests/providers/deepseek-inbound-wire.test.ts similarity index 98% rename from tests/deepseek-inbound-wire.test.ts rename to tests/providers/deepseek-inbound-wire.test.ts index 1f298bacce..fa2b686a2d 100644 --- a/tests/deepseek-inbound-wire.test.ts +++ b/tests/providers/deepseek-inbound-wire.test.ts @@ -12,20 +12,20 @@ * assert the captured upstream URL, which is externally observable. */ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; -import { enrichProviderFromRegistry, providerConfigSeed } from "../src/providers/derive"; +import { enrichProviderFromRegistry, providerConfigSeed } from "../../src/providers/derive"; import { getProviderRegistryEntry, providerModelResponsesTerminalRepair, PROVIDER_REGISTRY, -} from "../src/providers/registry"; -import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../src/adapters/openai-responses"; -import { resolveWireProtocolOverride } from "../src/server/adapter-resolve"; -import { handleResponses } from "../src/server/responses/core"; -import { MAX_SYNTHESIZED_OUTPUT_ITEMS } from "../src/server/responses-json-events"; -import type { ResponsesTerminalRepairScheduler } from "../src/server/responses-terminal-repair"; -import { sendResponseToWebSocket } from "../src/server/ws-bridge"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../src/providers/registry"; +import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../../src/adapters/openai-responses"; +import { resolveWireProtocolOverride } from "../../src/server/adapter-resolve"; +import { handleResponses } from "../../src/server/responses/core"; +import { MAX_SYNTHESIZED_OUTPUT_ITEMS } from "../../src/server/responses-json-events"; +import type { ResponsesTerminalRepairScheduler } from "../../src/server/responses-terminal-repair"; +import { sendResponseToWebSocket } from "../../src/server/ws-bridge"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; const createResponsesPassthroughAdapter = (...args: Parameters) => withTestTranslatorBudget(createResponsesPassthroughAdapterProduction(...args)); diff --git a/tests/deepseek-reasoning-replay-gaps.test.ts b/tests/providers/deepseek-reasoning-replay-gaps.test.ts similarity index 98% rename from tests/deepseek-reasoning-replay-gaps.test.ts rename to tests/providers/deepseek-reasoning-replay-gaps.test.ts index bf1bd0248e..4e5c6ea3ca 100644 --- a/tests/deepseek-reasoning-replay-gaps.test.ts +++ b/tests/providers/deepseek-reasoning-replay-gaps.test.ts @@ -1,19 +1,19 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { buildResponseJSON } from "../src/bridge"; -import { parseRequest } from "../src/responses/parser"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { buildResponseJSON } from "../../src/bridge"; +import { parseRequest } from "../../src/responses/parser"; import { clearReasoningReplayCacheForTests, peekReasoningForCall as peekReasoningForCallRaw, rememberReasoningForCall as rememberReasoningForCallRaw, -} from "../src/responses/reasoning-replay-cache"; -import { routeModel } from "../src/router"; +} from "../../src/responses/reasoning-replay-cache"; +import { routeModel } from "../../src/router"; import type { AdapterEvent, OcxConfig, OcxParsedRequest, OcxReasoningReplayScopeRef, -} from "../src/types"; +} from "../../src/types"; /** * Regression coverage for opencodex issue #950: OpenCode Go DeepSeek V4 Flash diff --git a/tests/deepseek-reasoning-replay.test.ts b/tests/providers/deepseek-reasoning-replay.test.ts similarity index 94% rename from tests/deepseek-reasoning-replay.test.ts rename to tests/providers/deepseek-reasoning-replay.test.ts index b67b2c1798..37869afa17 100644 --- a/tests/deepseek-reasoning-replay.test.ts +++ b/tests/providers/deepseek-reasoning-replay.test.ts @@ -7,12 +7,12 @@ * still stripping proxy-minted `ocxr1` envelopes no upstream can decrypt. */ import { describe, expect, test } from "bun:test"; -import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction, sanitizeReasoningInputContent } from "../src/adapters/openai-responses"; -import { enrichProviderFromRegistry, providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { OCX_REASONING_PREFIX } from "../src/responses/reasoning-envelope"; -import type { OcxProviderConfig } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction, sanitizeReasoningInputContent } from "../../src/adapters/openai-responses"; +import { enrichProviderFromRegistry, providerConfigSeed } from "../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; +import { OCX_REASONING_PREFIX } from "../../src/responses/reasoning-envelope"; +import type { OcxProviderConfig } from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; const createResponsesPassthroughAdapter = (...args: Parameters) => withTestTranslatorBudget(createResponsesPassthroughAdapterProduction(...args)); diff --git a/tests/deepseek-responses-item-id-repair.test.ts b/tests/providers/deepseek-responses-item-id-repair.test.ts similarity index 96% rename from tests/deepseek-responses-item-id-repair.test.ts rename to tests/providers/deepseek-responses-item-id-repair.test.ts index 374e81a9a4..ed95f2394c 100644 --- a/tests/deepseek-responses-item-id-repair.test.ts +++ b/tests/providers/deepseek-responses-item-id-repair.test.ts @@ -1,14 +1,14 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { enrichProviderFromRegistry, providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; +import { enrichProviderFromRegistry, providerConfigSeed } from "../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; import { createResponsesItemIdPayloadRewrite, hasResponsesItemIdRepair, repairResponsesJsonItemIds, -} from "../src/server/responses-item-id-repair"; -import { handleResponses } from "../src/server/responses/core"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../src/server/responses-item-id-repair"; +import { handleResponses } from "../../src/server/responses/core"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { createTestTranslatorBudget } from "../helpers/translator-budget"; const UUID_MSG = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"; const UUID_RS = "1b9d6bcd-bbfd-4b2d-9b9d-5c0a2fb41a1b"; diff --git a/tests/digitalocean-scaleway-provider.test.ts b/tests/providers/digitalocean-scaleway-provider.test.ts similarity index 92% rename from tests/digitalocean-scaleway-provider.test.ts rename to tests/providers/digitalocean-scaleway-provider.test.ts index 7b84ef0544..34464c65aa 100644 --- a/tests/digitalocean-scaleway-provider.test.ts +++ b/tests/providers/digitalocean-scaleway-provider.test.ts @@ -1,26 +1,27 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { FREE_PROVIDER_DIRECTORY } from "../src/providers/free-directory"; -import { PROVIDER_REGISTRY, type ProviderRegistryEntry } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; +} from "../../src/providers/derive"; +import { FREE_PROVIDER_DIRECTORY } from "../../src/providers/free-directory"; +import { PROVIDER_REGISTRY, type ProviderRegistryEntry } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; -const DIGITALOCEAN_FIXTURE = readFileSync(join(import.meta.dir, "fixtures/digitalocean-models.json"), "utf8"); -const SCALEWAY_FIXTURE = readFileSync(join(import.meta.dir, "fixtures/scaleway-models.json"), "utf8"); +const DIGITALOCEAN_FIXTURE = readFileSync(fixturePath("digitalocean-models.json"), "utf8"); +const SCALEWAY_FIXTURE = readFileSync(fixturePath("scaleway-models.json"), "utf8"); const originalFetch = globalThis.fetch; type ProviderId = "digitalocean" | "scaleway"; diff --git a/tests/exa-web-search.test.ts b/tests/providers/exa-web-search.test.ts similarity index 95% rename from tests/exa-web-search.test.ts rename to tests/providers/exa-web-search.test.ts index f9202f768b..6422254573 100644 --- a/tests/exa-web-search.test.ts +++ b/tests/providers/exa-web-search.test.ts @@ -1,12 +1,12 @@ import { describe, expect, test } from "bun:test"; -import { mapExaSearchResponse, runExaWebSearch } from "../src/web-search/exa-executor"; -import { planWebSearch } from "../src/web-search"; -import { parseRequest } from "../src/responses/parser"; -import { runWithWebSearch, type WebSearchLoopDeps } from "../src/web-search/loop"; -import { MAX_SIDECAR_RESPONSE_BYTES } from "../src/web-search/parse"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import type { AdapterEvent, ProviderAdapter } from "../src/adapters/base"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { mapExaSearchResponse, runExaWebSearch } from "../../src/web-search/exa-executor"; +import { planWebSearch } from "../../src/web-search"; +import { parseRequest } from "../../src/responses/parser"; +import { runWithWebSearch, type WebSearchLoopDeps } from "../../src/web-search/loop"; +import { MAX_SIDECAR_RESPONSE_BYTES } from "../../src/web-search/parse"; +import { createTestTranslatorBudget } from "../helpers/translator-budget"; +import type { AdapterEvent, ProviderAdapter } from "../../src/adapters/base"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; const routed: OcxProviderConfig = { adapter: "openai-chat", baseUrl: "https://routed.test/v1", apiKey: "k" }; function config(overrides: Partial = {}): OcxConfig { diff --git a/tests/fast-row-ingress.test.ts b/tests/providers/fast-row-ingress.test.ts similarity index 92% rename from tests/fast-row-ingress.test.ts rename to tests/providers/fast-row-ingress.test.ts index ed3be17f11..46ce6b038c 100644 --- a/tests/fast-row-ingress.test.ts +++ b/tests/providers/fast-row-ingress.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from "bun:test"; -import { decideTier, tierValueAfterDecision } from "../src/providers/fastwire"; -import { providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { fastPolicyForModel } from "../src/providers/service-tier"; -import { parseFastOnlyRowId, parseSyntheticRowId } from "../src/server/fast-row"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { decideTier, tierValueAfterDecision } from "../../src/providers/fastwire"; +import { providerConfigSeed } from "../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; +import { fastPolicyForModel } from "../../src/providers/service-tier"; +import { parseFastOnlyRowId, parseSyntheticRowId } from "../../src/server/fast-row"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; /** * Ingress round-trip semantics for synthetic Fast selectors diff --git a/tests/featherless-provider.test.ts b/tests/providers/featherless-provider.test.ts similarity index 88% rename from tests/featherless-provider.test.ts rename to tests/providers/featherless-provider.test.ts index 7316f02f8d..b1b673943f 100644 --- a/tests/featherless-provider.test.ts +++ b/tests/providers/featherless-provider.test.ts @@ -1,26 +1,27 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { catalogHintsFromModelsApiItem } from "../src/codex/catalog/provider-fetch"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { catalogHintsFromModelsApiItem } from "../../src/codex/catalog/provider-fetch"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { resolveProviderModelDiscovery } from "../src/providers/model-discovery"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; - -const FEATHERLESS_FIXTURE = readFileSync(join(import.meta.dir, "fixtures/featherless-models.json"), "utf8"); +} from "../../src/providers/derive"; +import { resolveProviderModelDiscovery } from "../../src/providers/model-discovery"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; + +const FEATHERLESS_FIXTURE = readFileSync(fixturePath("featherless-models.json"), "utf8"); const BASE_URL = "https://api.featherless.ai/v1"; const TEST_KEY = "featherless-test-key"; const DISCOVERY_QUERY = { diff --git a/tests/forward-admission-separation.test.ts b/tests/providers/forward-admission-separation.test.ts similarity index 93% rename from tests/forward-admission-separation.test.ts rename to tests/providers/forward-admission-separation.test.ts index ad63317389..bb6d66a88e 100644 --- a/tests/forward-admission-separation.test.ts +++ b/tests/providers/forward-admission-separation.test.ts @@ -2,11 +2,11 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; -import { resolveFirstUsableOpenAiSidecar } from "../src/providers/openai-sidecar"; -import { startServer } from "../src/server"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { saveConfig } from "../../src/config"; +import { resolveFirstUsableOpenAiSidecar } from "../../src/providers/openai-sidecar"; +import { startServer } from "../../src/server"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const originalFetch = globalThis.fetch; const previousHome = process.env.OPENCODEX_HOME; diff --git a/tests/github-copilot-account-origin.test.ts b/tests/providers/github-copilot/github-copilot-account-origin.test.ts similarity index 96% rename from tests/github-copilot-account-origin.test.ts rename to tests/providers/github-copilot/github-copilot-account-origin.test.ts index f6ed6ad686..5f464a1d7e 100644 --- a/tests/github-copilot-account-origin.test.ts +++ b/tests/providers/github-copilot/github-copilot-account-origin.test.ts @@ -2,11 +2,11 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { clearGenericFailoverHealth } from "../src/oauth/generic-account-failover"; -import { getAccountSet, saveCredential, setActiveAccount } from "../src/oauth/store"; -import { handleResponses } from "../src/server/responses"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { clearGenericFailoverHealth } from "../../../src/oauth/generic-account-failover"; +import { getAccountSet, saveCredential, setActiveAccount } from "../../../src/oauth/store"; +import { handleResponses } from "../../../src/server/responses"; +import type { OcxConfig } from "../../../src/types"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const ACCOUNT_A_ORIGIN = "https://a.githubcopilot.com"; const ACCOUNT_B_ORIGIN = "https://b.githubcopilot.com"; diff --git a/tests/github-copilot-oauth.test.ts b/tests/providers/github-copilot/github-copilot-oauth.test.ts similarity index 97% rename from tests/github-copilot-oauth.test.ts rename to tests/providers/github-copilot/github-copilot-oauth.test.ts index 045b2f741a..9deaac3a9d 100644 --- a/tests/github-copilot-oauth.test.ts +++ b/tests/providers/github-copilot/github-copilot-oauth.test.ts @@ -7,8 +7,8 @@ import { refreshGithubCopilotToken, resolveCopilotApiBaseUrl, validateCopilotApiBaseUrl, -} from "../src/oauth/github-copilot"; -import type { OAuthController } from "../src/oauth/types"; +} from "../../../src/oauth/github-copilot"; +import type { OAuthController } from "../../../src/oauth/types"; const realFetch = globalThis.fetch; afterEach(() => { @@ -314,7 +314,7 @@ describe("github-copilot security repairs (absorb hardening)", () => { describe("github-copilot transport fail-closed host allowlist", () => { test("an OAuth credential without endpoints.api never sends the bearer to a foreign baseUrl", async () => { - const { resolveGithubCopilotTransport } = await import("../src/providers/github-copilot-transport"); + const { resolveGithubCopilotTransport } = await import("../../../src/providers/github-copilot-transport"); const resolved = resolveGithubCopilotTransport({ adapter: "openai-chat", authMode: "oauth", @@ -324,7 +324,7 @@ describe("github-copilot transport fail-closed host allowlist", () => { }); test("a valid credential apiBaseUrl still wins for OAuth transports", async () => { - const { resolveGithubCopilotTransport } = await import("../src/providers/github-copilot-transport"); + const { resolveGithubCopilotTransport } = await import("../../../src/providers/github-copilot-transport"); const resolved = resolveGithubCopilotTransport({ adapter: "openai-chat", authMode: "oauth", @@ -336,7 +336,7 @@ describe("github-copilot transport fail-closed host allowlist", () => { describe("copilot token redaction", () => { test("the Copilot tid= token grammar and GitHub token prefixes are fully redacted", async () => { - const { redactSecretString } = await import("../src/lib/redact"); + const { redactSecretString } = await import("../../../src/lib/redact"); const copilotish = "tid=abc-123;exp=1699999999;sku=copilot_pro;8kp=1:B64sig+value="; const redacted = redactSecretString(`upstream said: ${copilotish} and ${GH_ACCESS} plus body {"token":"${copilotish}"}`); expect(redacted).not.toContain("abc-123"); diff --git a/tests/github-copilot-sse-rewrite.test.ts b/tests/providers/github-copilot/github-copilot-sse-rewrite.test.ts similarity index 97% rename from tests/github-copilot-sse-rewrite.test.ts rename to tests/providers/github-copilot/github-copilot-sse-rewrite.test.ts index 80b7d3e6b7..7c8b562281 100644 --- a/tests/github-copilot-sse-rewrite.test.ts +++ b/tests/providers/github-copilot/github-copilot-sse-rewrite.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { createGithubCopilotResponsesBlockRewrite } from "../src/server/github-copilot-responses-repair"; -import { relaySseWithBlockRewrite } from "../src/server/sse-payload-rewrite"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; +import { createGithubCopilotResponsesBlockRewrite } from "../../../src/server/github-copilot-responses-repair"; +import { relaySseWithBlockRewrite } from "../../../src/server/sse-payload-rewrite"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; function streamFromChunks(...chunks: string[]): ReadableStream { const encoder = new TextEncoder(); diff --git a/tests/github-copilot-stream-contract.test.ts b/tests/providers/github-copilot/github-copilot-stream-contract.test.ts similarity index 96% rename from tests/github-copilot-stream-contract.test.ts rename to tests/providers/github-copilot/github-copilot-stream-contract.test.ts index 7843f914db..21ba36336e 100644 --- a/tests/github-copilot-stream-contract.test.ts +++ b/tests/providers/github-copilot/github-copilot-stream-contract.test.ts @@ -7,10 +7,10 @@ * The proxy must expose one internally consistent, plaintext Responses stream. */ import { afterEach, describe, expect, test } from "bun:test"; -import { providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { handleResponses } from "../src/server/responses/core"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { providerConfigSeed } from "../../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../../src/providers/registry"; +import { handleResponses } from "../../../src/server/responses/core"; +import type { OcxConfig, OcxProviderConfig } from "../../../src/types"; interface SseEvent { event?: string; diff --git a/tests/github-copilot-wire-defaults.test.ts b/tests/providers/github-copilot/github-copilot-wire-defaults.test.ts similarity index 92% rename from tests/github-copilot-wire-defaults.test.ts rename to tests/providers/github-copilot/github-copilot-wire-defaults.test.ts index a3bbc316f9..29af09048d 100644 --- a/tests/github-copilot-wire-defaults.test.ts +++ b/tests/providers/github-copilot/github-copilot-wire-defaults.test.ts @@ -6,14 +6,14 @@ * * The resolver-only cases would pass even if the handleResponses replay silently * flipped the wire back, so the end-to-end cases assert the captured upstream URL — - * the externally observable wire. Pattern mirrors tests/deepseek-inbound-wire.test.ts. + * the externally observable wire. Pattern mirrors tests/providers/deepseek-inbound-wire.test.ts. */ import { afterEach, describe, expect, test } from "bun:test"; -import { providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { resolveWireProtocolOverride } from "../src/server/adapter-resolve"; -import { handleResponses } from "../src/server/responses/core"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { providerConfigSeed } from "../../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../../src/providers/registry"; +import { resolveWireProtocolOverride } from "../../../src/server/adapter-resolve"; +import { handleResponses } from "../../../src/server/responses/core"; +import type { OcxConfig, OcxProviderConfig } from "../../../src/types"; const RESPONSES_ONLY = [ "gpt-5.3-codex", diff --git a/tests/hyperbolic-provider.test.ts b/tests/providers/hyperbolic-provider.test.ts similarity index 88% rename from tests/hyperbolic-provider.test.ts rename to tests/providers/hyperbolic-provider.test.ts index 7cdaf36efc..7ae77c7bf1 100644 --- a/tests/hyperbolic-provider.test.ts +++ b/tests/providers/hyperbolic-provider.test.ts @@ -1,24 +1,25 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { PROVIDER_REGISTRY, type ProviderRegistryEntry } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; - -const FIXTURE = readFileSync(join(import.meta.dir, "fixtures/hyperbolic-models.json"), "utf8"); +} from "../../src/providers/derive"; +import { PROVIDER_REGISTRY, type ProviderRegistryEntry } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; + +const FIXTURE = readFileSync(fixturePath("hyperbolic-models.json"), "utf8"); const BASE_URL = "https://api.hyperbolic.xyz/v1"; const API_KEY = "hyperbolic-test-key"; const originalFetch = globalThis.fetch; diff --git a/tests/kimi-oauth-identity.test.ts b/tests/providers/kimi-oauth-identity.test.ts similarity index 98% rename from tests/kimi-oauth-identity.test.ts rename to tests/providers/kimi-oauth-identity.test.ts index b48d4fa89c..f69a251a12 100644 --- a/tests/kimi-oauth-identity.test.ts +++ b/tests/providers/kimi-oauth-identity.test.ts @@ -1,9 +1,9 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync} from "node:fs"; import { join } from "node:path"; -import { identityFromKimiTokens, refreshKimiToken } from "../src/oauth/kimi"; -import { getCredential, listAccounts, saveCredential } from "../src/oauth/store"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { identityFromKimiTokens, refreshKimiToken } from "../../src/oauth/kimi"; +import { getCredential, listAccounts, saveCredential } from "../../src/oauth/store"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-kimi-oauth-identity-test"); let previousOpencodexHome: string | undefined; diff --git a/tests/kiro-account-quota.test.ts b/tests/providers/kiro/kiro-account-quota.test.ts similarity index 96% rename from tests/kiro-account-quota.test.ts rename to tests/providers/kiro/kiro-account-quota.test.ts index 2f0151c338..f5a869c20d 100644 --- a/tests/kiro-account-quota.test.ts +++ b/tests/providers/kiro/kiro-account-quota.test.ts @@ -2,16 +2,16 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveCredential } from "../src/oauth/store"; +import { saveCredential } from "../../../src/oauth/store"; import { clearAccountQuotaCache, clearProviderQuotaCache, fetchProviderAccountQuotas, getCachedProviderAccountQuota, supportsPerAccountQuota, -} from "../src/providers/quota"; -import { getKiroAccountExhaustion } from "../src/providers/kiro-usage"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/providers/quota"; +import { getKiroAccountExhaustion } from "../../../src/providers/kiro-usage"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const originalFetch = globalThis.fetch; const previousOpencodexHome = process.env.OPENCODEX_HOME; diff --git a/tests/kiro-adapter.test.ts b/tests/providers/kiro/kiro-adapter.test.ts similarity index 99% rename from tests/kiro-adapter.test.ts rename to tests/providers/kiro/kiro-adapter.test.ts index 4731bc6d69..cb530a8d51 100644 --- a/tests/kiro-adapter.test.ts +++ b/tests/providers/kiro/kiro-adapter.test.ts @@ -3,7 +3,7 @@ import { Database } from "bun:sqlite"; import { mkdirSync, mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { createKiroAdapter } from "../src/adapters/kiro"; +import { createKiroAdapter } from "../../../src/adapters/kiro"; import { KIRO_ANSWER_DELIVERED_MESSAGE, KIRO_COMPLETION_INSTRUCTIONS, @@ -12,18 +12,18 @@ import { KIRO_CONTINUATION_MESSAGE, KIRO_EMPTY_TOOL_RESULT_MESSAGE, KIRO_TOOL_RESULT_CARRIER_MESSAGE, -} from "../src/adapters/kiro-constants"; -import { EMPTY_EXEC_OUTPUT_MESSAGE, FAILED_EXEC_OUTPUT_MESSAGE } from "../src/adapters/exec-tool-result-normalize"; -import { MAX_KIRO_TOOL_CATALOG_BYTES, MAX_KIRO_TOOL_COUNT } from "../src/adapters/kiro-tools"; -import { applyProviderConfigHints, buildCatalogEntries } from "../src/codex/catalog"; -import { getValidAccessTokenSnapshot } from "../src/oauth"; -import { saveCredential } from "../src/oauth/store"; -import { normalizeKiroModelId } from "../src/providers/kiro-models"; -import { configuredReasoningEfforts, mapReasoningEffort } from "../src/reasoning-effort"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { parseRequest } from "../src/responses/parser"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/adapters/kiro-constants"; +import { EMPTY_EXEC_OUTPUT_MESSAGE, FAILED_EXEC_OUTPUT_MESSAGE } from "../../../src/adapters/exec-tool-result-normalize"; +import { MAX_KIRO_TOOL_CATALOG_BYTES, MAX_KIRO_TOOL_COUNT } from "../../../src/adapters/kiro-tools"; +import { applyProviderConfigHints, buildCatalogEntries } from "../../../src/codex/catalog"; +import { getValidAccessTokenSnapshot } from "../../../src/oauth"; +import { saveCredential } from "../../../src/oauth/store"; +import { normalizeKiroModelId } from "../../../src/providers/kiro-models"; +import { configuredReasoningEfforts, mapReasoningEffort } from "../../../src/reasoning-effort"; +import { PROVIDER_REGISTRY } from "../../../src/providers/registry"; +import { parseRequest } from "../../../src/responses/parser"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const origHome = process.env.HOME; const origLocalAppData = process.env.LOCALAPPDATA; @@ -1517,8 +1517,8 @@ describe("the completion contract survives a hostile tool catalog intact", () => describe("boundedInjectedInstruction surrogate safety", () => { test("a budget cut never ends on a lone high surrogate", async () => { - const { boundedInjectedInstructionForTests } = await import("../src/adapters/kiro"); - const { MAX_KIRO_INJECTED_INSTRUCTION_CHARS } = await import("../src/adapters/kiro-constants"); + const { boundedInjectedInstructionForTests } = await import("../../../src/adapters/kiro"); + const { MAX_KIRO_INJECTED_INSTRUCTION_CHARS } = await import("../../../src/adapters/kiro-constants"); // Place an astral character exactly at the budget boundary. const prefix = "가".repeat(MAX_KIRO_INJECTED_INSTRUCTION_CHARS - 1); const text = `${prefix}🎆tail`; diff --git a/tests/kiro-builder-id-profile.test.ts b/tests/providers/kiro/kiro-builder-id-profile.test.ts similarity index 95% rename from tests/kiro-builder-id-profile.test.ts rename to tests/providers/kiro/kiro-builder-id-profile.test.ts index 7d0632e3c6..800ca83a34 100644 --- a/tests/kiro-builder-id-profile.test.ts +++ b/tests/providers/kiro/kiro-builder-id-profile.test.ts @@ -3,11 +3,11 @@ import { Database } from "bun:sqlite"; import { existsSync, mkdirSync, mkdtempSync, readFileSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { createKiroAdapter } from "../src/adapters/kiro"; -import { KIRO_BUILDER_ID_SERVICE_PROFILE_ARN } from "../src/adapters/kiro-constants"; -import { getValidAccessTokenSnapshot } from "../src/oauth"; -import { resolveKiroApiRegion, resolveKiroProfileArn, resolveKiroRequestProfileArn } from "../src/oauth/kiro"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { createKiroAdapter } from "../../../src/adapters/kiro"; +import { KIRO_BUILDER_ID_SERVICE_PROFILE_ARN } from "../../../src/adapters/kiro-constants"; +import { getValidAccessTokenSnapshot } from "../../../src/oauth"; +import { resolveKiroApiRegion, resolveKiroProfileArn, resolveKiroRequestProfileArn } from "../../../src/oauth/kiro"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; /** Mirrors resolveKiroCliNativeSessionEntries so an accountless request reads a real local import. */ function seedKiroCliBuilderIdSession(): void { @@ -32,8 +32,8 @@ function seedKiroCliBuilderIdSession(): void { ]); db.close(); } -import { saveCredential } from "../src/oauth/store"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { saveCredential } from "../../../src/oauth/store"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; /** * Issue #993 follow-up: an AWS Builder ID account authenticates through SSO OIDC and never receives diff --git a/tests/kiro-calibration.test.ts b/tests/providers/kiro/kiro-calibration.test.ts similarity index 99% rename from tests/kiro-calibration.test.ts rename to tests/providers/kiro/kiro-calibration.test.ts index 7a9c116226..8743be7634 100644 --- a/tests/kiro-calibration.test.ts +++ b/tests/providers/kiro/kiro-calibration.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, test } from "bun:test"; -import { calibrateKiroEstimate, recordKiroCalibration, rekeyKiroCalibration, resetKiroCalibration } from "../src/adapters/kiro-calibration"; +import { calibrateKiroEstimate, recordKiroCalibration, rekeyKiroCalibration, resetKiroCalibration } from "../../../src/adapters/kiro-calibration"; beforeEach(() => resetKiroCalibration()); diff --git a/tests/kiro-images.test.ts b/tests/providers/kiro/kiro-images.test.ts similarity index 96% rename from tests/kiro-images.test.ts rename to tests/providers/kiro/kiro-images.test.ts index b614bb5d61..414a355864 100644 --- a/tests/kiro-images.test.ts +++ b/tests/providers/kiro/kiro-images.test.ts @@ -2,12 +2,12 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { createKiroAdapter } from "../src/adapters/kiro"; -import { normalizeKiroImages, KIRO_IMAGE_BASE64_BUDGET, KIRO_MAX_IMAGES_PER_MESSAGE, type KiroImage } from "../src/adapters/kiro-images"; -import { resetNormalizeStateForTests, TIER_SPECS, type EncodeFn } from "../src/adapters/anthropic-image-normalize"; -import { sniffImageDimensions } from "../src/adapters/anthropic-image-guard"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { createKiroAdapter } from "../../../src/adapters/kiro"; +import { normalizeKiroImages, KIRO_IMAGE_BASE64_BUDGET, KIRO_MAX_IMAGES_PER_MESSAGE, type KiroImage } from "../../../src/adapters/kiro-images"; +import { resetNormalizeStateForTests, TIER_SPECS, type EncodeFn } from "../../../src/adapters/anthropic-image-normalize"; +import { sniffImageDimensions } from "../../../src/adapters/anthropic-image-guard"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const origHome = process.env.HOME; const origRegion = process.env.KIRO_REGION; diff --git a/tests/kiro-oauth.test.ts b/tests/providers/kiro/kiro-oauth.test.ts similarity index 99% rename from tests/kiro-oauth.test.ts rename to tests/providers/kiro/kiro-oauth.test.ts index e3c87839fe..cd2e689842 100644 --- a/tests/kiro-oauth.test.ts +++ b/tests/providers/kiro/kiro-oauth.test.ts @@ -3,9 +3,9 @@ import { Database } from "bun:sqlite"; import { existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { OAUTH_PROVIDERS, runLogin } from "../src/oauth"; -import { inspectKiroCliSqlite, kiroCliInstallGuidance, loginKiro, readKiroCliSqlite, refreshKiroToken, resolveKiroApiRegion, resolveKiroProfileArn, resolveKiroRegion, settleKiroLoginTransaction } from "../src/oauth/kiro"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { OAUTH_PROVIDERS, runLogin } from "../../../src/oauth"; +import { inspectKiroCliSqlite, kiroCliInstallGuidance, loginKiro, readKiroCliSqlite, refreshKiroToken, resolveKiroApiRegion, resolveKiroProfileArn, resolveKiroRegion, settleKiroLoginTransaction } from "../../../src/oauth/kiro"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; // Windows CI cold runners take 5-7s for the real SQLite create/inspect cycles here // (same flake class as 810fa115); the default 5s harness timeout is too tight. diff --git a/tests/kiro-pool-rank.test.ts b/tests/providers/kiro/kiro-pool-rank.test.ts similarity index 97% rename from tests/kiro-pool-rank.test.ts rename to tests/providers/kiro/kiro-pool-rank.test.ts index b66b917ed3..b42eb969d0 100644 --- a/tests/kiro-pool-rank.test.ts +++ b/tests/providers/kiro/kiro-pool-rank.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { exhaustedCooldownMs, rankAccountsByHeadroom } from "../src/oauth/account-quota-rank"; +import { exhaustedCooldownMs, rankAccountsByHeadroom } from "../../../src/oauth/account-quota-rank"; import { mkdtempSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; @@ -9,25 +9,25 @@ import { genericFailoverRetryAfterSeconds, preferredInitialAccount, rotateGenericOAuthAccountOn429, -} from "../src/oauth/generic-account-failover"; +} from "../../../src/oauth/generic-account-failover"; import { getAccountSet, markAccountNeedsReauth, removeAccount, saveCredential, setActiveAccount, -} from "../src/oauth/store"; -import { getValidAccessSnapshotForAccount } from "../src/oauth"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +} from "../../../src/oauth/store"; +import { getValidAccessSnapshotForAccount } from "../../../src/oauth"; +import type { OcxConfig, OcxProviderConfig } from "../../../src/types"; import { clearAccountQuotaCache, setCachedProviderAccountQuotaForTests, -} from "../src/providers/quota"; +} from "../../../src/providers/quota"; import { clearKiroAccountUsageState, commitKiroAccountUsageState, -} from "../src/providers/kiro-usage"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/providers/kiro-usage"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const realFetch = globalThis.fetch; diff --git a/tests/kiro-reasoning-roundtrip.test.ts b/tests/providers/kiro/kiro-reasoning-roundtrip.test.ts similarity index 94% rename from tests/kiro-reasoning-roundtrip.test.ts rename to tests/providers/kiro/kiro-reasoning-roundtrip.test.ts index a38121d59b..9cf598f372 100644 --- a/tests/kiro-reasoning-roundtrip.test.ts +++ b/tests/providers/kiro/kiro-reasoning-roundtrip.test.ts @@ -1,9 +1,9 @@ import { describe, expect, test } from "bun:test"; -import { bridgeToResponsesSSE, buildResponseJSON } from "../src/bridge"; -import { parseRequest } from "../src/responses/parser"; -import { decodeReasoningEnvelope } from "../src/responses/reasoning-envelope"; -import type { AdapterEvent } from "../src/types"; -import { createTranslatorBudget } from "../src/lib/translator-budget"; +import { bridgeToResponsesSSE, buildResponseJSON } from "../../../src/bridge"; +import { parseRequest } from "../../../src/responses/parser"; +import { decodeReasoningEnvelope } from "../../../src/responses/reasoning-envelope"; +import type { AdapterEvent } from "../../../src/types"; +import { createTranslatorBudget } from "../../../src/lib/translator-budget"; const BLOB = "LktUUn5+ZXlKbGJtTnllWEIwYVc5dVVtVm5hVzl1SWpvaQ=="; diff --git a/tests/kiro-retry.test.ts b/tests/providers/kiro/kiro-retry.test.ts similarity index 98% rename from tests/kiro-retry.test.ts rename to tests/providers/kiro/kiro-retry.test.ts index df4285546b..1ccc23d830 100644 --- a/tests/kiro-retry.test.ts +++ b/tests/providers/kiro/kiro-retry.test.ts @@ -1,10 +1,10 @@ import { afterEach, describe, expect, test } from "bun:test"; -import type { AdapterRequest } from "../src/adapters/base"; +import type { AdapterRequest } from "../../../src/adapters/base"; import { fetchKiroWithRetry, noteKiroTransientThrottle, resetKiroThrottleStateForTests, -} from "../src/adapters/kiro-retry"; +} from "../../../src/adapters/kiro-retry"; const realFetch = globalThis.fetch; @@ -369,7 +369,7 @@ describe("kiro retry fetch", () => { describe("kiro adapter error formatter", () => { test("is classified, redacted, and does not copy secret headers", async () => { - const { createKiroAdapter } = await import("../src/adapters/kiro"); + const { createKiroAdapter } = await import("../../../src/adapters/kiro"); const adapter = createKiroAdapter({ adapter: "kiro", apiKey: "unused" } as never); const text = adapter.formatErrorBody!(403, new Headers({ authorization: "Bearer header-secret", diff --git a/tests/kiro-review-regressions.test.ts b/tests/providers/kiro/kiro-review-regressions.test.ts similarity index 97% rename from tests/kiro-review-regressions.test.ts rename to tests/providers/kiro/kiro-review-regressions.test.ts index b5efece4f5..3c1b212bee 100644 --- a/tests/kiro-review-regressions.test.ts +++ b/tests/providers/kiro/kiro-review-regressions.test.ts @@ -3,18 +3,18 @@ import { Database } from "bun:sqlite"; import { existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { getValidAccessTokenSnapshot, OAUTH_PROVIDERS, runLogin } from "../src/oauth"; -import { loginKiro, refreshKiroToken } from "../src/oauth/kiro"; +import { getValidAccessTokenSnapshot, OAUTH_PROVIDERS, runLogin } from "../../../src/oauth"; +import { loginKiro, refreshKiroToken } from "../../../src/oauth/kiro"; import { inspectKiroCliSessionSnapshot, persistKiroCliSessionRecovery, readKiroCliSqliteCredential, restoreStaleKiroCliSessionRecovery, -} from "../src/oauth/kiro-credentials"; -import { getAccountCredential, getAccountSet, saveCredential, setActiveAccount } from "../src/oauth/store"; -import type { OAuthController, OAuthCredentials } from "../src/oauth/types"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/oauth/kiro-credentials"; +import { getAccountCredential, getAccountSet, saveCredential, setActiveAccount } from "../../../src/oauth/store"; +import type { OAuthController, OAuthCredentials } from "../../../src/oauth/types"; +import type { OcxConfig } from "../../../src/types"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const ENV_KEYS = [ "HOME", diff --git a/tests/kiro-stream.test.ts b/tests/providers/kiro/kiro-stream.test.ts similarity index 99% rename from tests/kiro-stream.test.ts rename to tests/providers/kiro/kiro-stream.test.ts index db1098b4b4..acecd471ec 100644 --- a/tests/kiro-stream.test.ts +++ b/tests/providers/kiro/kiro-stream.test.ts @@ -6,22 +6,22 @@ import { createKiroAdapter as createKiroAdapterProduction, isRetryableKiroStreamCatchError, parseKiroStream, -} from "../src/adapters/kiro"; +} from "../../../src/adapters/kiro"; import { KIRO_COMPLETION_RETRY_MESSAGE, KIRO_COMPLETION_TOOL_NAME, KIRO_TOOL_RESULT_CARRIER_MESSAGE, -} from "../src/adapters/kiro-constants"; -import { parseKiroEvent } from "../src/adapters/kiro-events"; -import { resetKiroThrottleStateForTests } from "../src/adapters/kiro-retry"; -import { resetKiroCalibration } from "../src/adapters/kiro-calibration"; -import { buildResponseJSON } from "../src/bridge"; -import { encodeMessage } from "../src/lib/eventstream-decoder"; -import { estimateTokens } from "../src/lib/token-estimate"; -import { createTranslatorBudget } from "../src/lib/translator-budget"; -import type { OcxParsedRequest, OcxProviderConfig, OcxUsage } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/adapters/kiro-constants"; +import { parseKiroEvent } from "../../../src/adapters/kiro-events"; +import { resetKiroThrottleStateForTests } from "../../../src/adapters/kiro-retry"; +import { resetKiroCalibration } from "../../../src/adapters/kiro-calibration"; +import { buildResponseJSON } from "../../../src/bridge"; +import { encodeMessage } from "../../../src/lib/eventstream-decoder"; +import { estimateTokens } from "../../../src/lib/token-estimate"; +import { createTranslatorBudget } from "../../../src/lib/translator-budget"; +import type { OcxParsedRequest, OcxProviderConfig, OcxUsage } from "../../../src/types"; +import { withTestTranslatorBudget } from "../../helpers/translator-budget"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; function createKiroAdapter(...args: Parameters) { return withTestTranslatorBudget(createKiroAdapterProduction(...args)); @@ -88,8 +88,8 @@ function streamOf(...frames: Uint8Array[]): ReadableStream { }); } -async function collectAdapterEvents(events: AsyncGenerator) { - const out: import("../src/types").AdapterEvent[] = []; +async function collectAdapterEvents(events: AsyncGenerator) { + const out: import("../../../src/types").AdapterEvent[] = []; for await (const event of events) out.push(event); return out; } @@ -2164,7 +2164,7 @@ describe("kiro adapter — non-streaming parseResponse", () => { describe("surrogate safety at kiro boundaries", () => { test("the reasoning carry never emits a delta ending on a lone high surrogate", async () => { - const { KiroThinkingParser } = await import("../src/adapters/kiro-thinking"); + const { KiroThinkingParser } = await import("../../../src/adapters/kiro-thinking"); const parser = new KiroThinkingParser(); // An astral char exactly at the carry/send boundary. const events = parser.feed("🎆aaaaaaaaaaa"); @@ -2179,7 +2179,7 @@ describe("surrogate safety at kiro boundaries", () => { }); test("a truncated tool description never ends on a lone high surrogate", async () => { - const { truncateDescriptionForTests } = await import("../src/adapters/kiro-tools"); + const { truncateDescriptionForTests } = await import("../../../src/adapters/kiro-tools"); const description = "a".repeat(1022) + "🎆cd"; const out = truncateDescriptionForTests(description, 1024); expect(out.endsWith("…")).toBe(true); diff --git a/tests/kiro-usage-quota.test.ts b/tests/providers/kiro/kiro-usage-quota.test.ts similarity index 99% rename from tests/kiro-usage-quota.test.ts rename to tests/providers/kiro/kiro-usage-quota.test.ts index f5221a1f9a..8dcb42f347 100644 --- a/tests/kiro-usage-quota.test.ts +++ b/tests/providers/kiro/kiro-usage-quota.test.ts @@ -6,7 +6,7 @@ import { getKiroAccountExhaustion, kiroUsageManagementUrl, reconcileKiroAccountUsageState, -} from "../src/providers/kiro-usage"; +} from "../../../src/providers/kiro-usage"; const realFetch = globalThis.fetch; diff --git a/tests/kiro-windows-cli-db-path.test.ts b/tests/providers/kiro/kiro-windows-cli-db-path.test.ts similarity index 97% rename from tests/kiro-windows-cli-db-path.test.ts rename to tests/providers/kiro/kiro-windows-cli-db-path.test.ts index 132360b2ac..d94e166954 100644 --- a/tests/kiro-windows-cli-db-path.test.ts +++ b/tests/providers/kiro/kiro-windows-cli-db-path.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; -import { resolveKiroCliNativeSessionEntries } from "../src/oauth/kiro-credentials"; +import { resolveKiroCliNativeSessionEntries } from "../../../src/oauth/kiro-credentials"; /** * Issue #710: `ocx login kiro` could not import an existing Windows Kiro CLI session because the @@ -101,7 +101,7 @@ describe("kiro-cli native session store resolution", () => { // observable by reading which joiner the source uses, so that is what this checks. test("darwin and linux branches pin posix.join so a Windows host cannot flip the separator", () => { const source = readFileSync( - new URL("../src/oauth/kiro-credentials.ts", import.meta.url), + new URL("../../../src/oauth/kiro-credentials.ts", import.meta.url), "utf-8", ); const resolver = source.slice(source.indexOf("export function resolveKiroCliNativeSessionEntries")); diff --git a/tests/kiro-windows-cli-executable-path.test.ts b/tests/providers/kiro/kiro-windows-cli-executable-path.test.ts similarity index 98% rename from tests/kiro-windows-cli-executable-path.test.ts rename to tests/providers/kiro/kiro-windows-cli-executable-path.test.ts index 8dc2620962..73a4d28bd7 100644 --- a/tests/kiro-windows-cli-executable-path.test.ts +++ b/tests/providers/kiro/kiro-windows-cli-executable-path.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { resolveKiroCliExecutable } from "../src/oauth/kiro-credentials"; +import { resolveKiroCliExecutable } from "../../../src/oauth/kiro-credentials"; /** * Forced/add-account Kiro login still shells out to the local CLI. After #710 fixed Windows diff --git a/tests/meta-model-api-provider.test.ts b/tests/providers/meta-model-api-provider.test.ts similarity index 95% rename from tests/meta-model-api-provider.test.ts rename to tests/providers/meta-model-api-provider.test.ts index deb462874b..cb487ea2f5 100644 --- a/tests/meta-model-api-provider.test.ts +++ b/tests/providers/meta-model-api-provider.test.ts @@ -13,12 +13,12 @@ * - the note carrying the billing disclosure had no regression at all. */ import { describe, expect, test } from "bun:test"; -import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../src/adapters/openai-responses"; -import { enrichProviderFromRegistry, providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../../src/adapters/openai-responses"; +import { enrichProviderFromRegistry, providerConfigSeed } from "../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; const createResponsesPassthroughAdapter = (...args: Parameters) => withTestTranslatorBudget(createResponsesPassthroughAdapterProduction(...args)); diff --git a/tests/meta-muse-oauth.test.ts b/tests/providers/meta-muse-oauth.test.ts similarity index 97% rename from tests/meta-muse-oauth.test.ts rename to tests/providers/meta-muse-oauth.test.ts index 7ea46c7d90..08f824fc53 100644 --- a/tests/meta-muse-oauth.test.ts +++ b/tests/providers/meta-muse-oauth.test.ts @@ -9,12 +9,12 @@ * reaches a message or a status object. */ import { describe, expect, test } from "bun:test"; -import { OAUTH_PROVIDERS } from "../src/oauth"; -import { loginMetaMuse, refreshMetaMuseToken } from "../src/oauth/meta-muse"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { supportsPerAccountQuota } from "../src/providers/quota"; -import { routeModel } from "../src/router"; -import type { OcxConfig } from "../src/types"; +import { OAUTH_PROVIDERS } from "../../src/oauth"; +import { loginMetaMuse, refreshMetaMuseToken } from "../../src/oauth/meta-muse"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; +import { supportsPerAccountQuota } from "../../src/providers/quota"; +import { routeModel } from "../../src/router"; +import type { OcxConfig } from "../../src/types"; const MODELS = ["muse-spark-1.3", "muse-spark-1.3-contributor"] as const; diff --git a/tests/mimo-effort.test.ts b/tests/providers/mimo-effort.test.ts similarity index 92% rename from tests/mimo-effort.test.ts rename to tests/providers/mimo-effort.test.ts index 0f9b2c7712..bf095f3b4a 100644 --- a/tests/mimo-effort.test.ts +++ b/tests/providers/mimo-effort.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; const entry = PROVIDER_REGISTRY.find(provider => provider.id === "mimo-free")!; diff --git a/tests/mimo-free-provider.test.ts b/tests/providers/mimo-free-provider.test.ts similarity index 97% rename from tests/mimo-free-provider.test.ts rename to tests/providers/mimo-free-provider.test.ts index cc9477c712..04cd2c908e 100644 --- a/tests/mimo-free-provider.test.ts +++ b/tests/providers/mimo-free-provider.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test, mock, beforeEach } from "bun:test"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { providerConfigSeed, deriveKeyLoginMap, deriveFeaturedProviderIds } from "../src/providers/derive"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { providerConfigSeed, deriveKeyLoginMap, deriveFeaturedProviderIds } from "../../src/providers/derive"; import { getMimoClientId, resetMimoClientIdCache, @@ -10,8 +10,8 @@ import { MIMO_SYSTEM_MARKER, MIMO_CHAT_URL, createMimoFreeAdapter, -} from "../src/adapters/mimo-free"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +} from "../../src/adapters/mimo-free"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../src/types"; function minimalRequest(model = "mimo-auto"): OcxParsedRequest { return { @@ -349,7 +349,7 @@ describe("mimo-free adapter request building", () => { describe("mimo-free GUI preset", () => { test("deriveProviderPresets exposes keyOptional for picker", () => { - const { deriveProviderPresets } = require("../src/providers/derive"); + const { deriveProviderPresets } = require("../../src/providers/derive"); const presets = deriveProviderPresets(); const preset = presets.find((p: { id: string }) => p.id === "mimo-free"); expect(preset).toBeDefined(); diff --git a/tests/mimo-token-plan-provider.test.ts b/tests/providers/mimo-token-plan-provider.test.ts similarity index 94% rename from tests/mimo-token-plan-provider.test.ts rename to tests/providers/mimo-token-plan-provider.test.ts index bf282ac89a..6092452034 100644 --- a/tests/mimo-token-plan-provider.test.ts +++ b/tests/providers/mimo-token-plan-provider.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from "bun:test"; -import { applyProviderConfigHints } from "../src/codex/catalog"; -import { KEY_LOGIN_PROVIDERS } from "../src/oauth/key-providers"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { mapReasoningEffort } from "../src/reasoning-effort"; -import { routeModel } from "../src/router"; -import type { OcxConfig } from "../src/types"; +import { applyProviderConfigHints } from "../../src/codex/catalog"; +import { KEY_LOGIN_PROVIDERS } from "../../src/oauth/key-providers"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { mapReasoningEffort } from "../../src/reasoning-effort"; +import { routeModel } from "../../src/router"; +import type { OcxConfig } from "../../src/types"; describe("Xiaomi MiMo public OpenAI Chat endpoint (#1483)", () => { const baseUrl = "https://api.xiaomimimo.com/v1"; @@ -123,7 +123,7 @@ describe("Xiaomi MiMo token plan (#1158)", () => { // than an oversight: `healMappedTiers` treats a wire map as authoritative evidence of the // tiers the upstream can emit and merges its Codex values into the ladder, which is what lets // a stale persisted ladder recover a newly documented tier without rewriting user config - // (see "stale reasoning-ladder self-heal" in tests/reasoning-effort.test.ts). + // (see "stale reasoning-ladder self-heal" in tests/codex-integration/reasoning-effort.test.ts). // // So the registry clamp protects the DEFAULT route, not a user who has deliberately written a // conflicting map. This test records that boundary so the next reader does not mistake the diff --git a/tests/minimax-clients.test.ts b/tests/providers/minimax-clients.test.ts similarity index 98% rename from tests/minimax-clients.test.ts rename to tests/providers/minimax-clients.test.ts index c95c0d6722..651e6c9669 100644 --- a/tests/minimax-clients.test.ts +++ b/tests/providers/minimax-clients.test.ts @@ -13,7 +13,7 @@ import { mcodeHomeDir, type ExportContext, type McodeGeneratedConfig, -} from "../src/clients/config-export"; +} from "../../src/clients/config-export"; import { buildMmxEnv, finishMmxClientCleanup, @@ -25,8 +25,9 @@ import { isStandaloneInformationalInvocation, startMmxTextBridge, usableMinimaxLiveProxy, -} from "../src/cli/minimax"; -import type { OcxConfig } from "../src/types"; +} from "../../src/cli/minimax"; +import type { OcxConfig } from "../../src/types"; +import { fixturePath } from "../helpers/repo-root"; const CONFIG = { port: 10100, @@ -162,7 +163,7 @@ describe("MiniMax CLI wrapper", () => { }); await new Promise((resolve, reject) => reservation.close(error => error ? reject(error) : resolve())); - const child = Bun.spawn([process.execPath, join(import.meta.dir, "fixtures/minimax-bridge-direct.ts")], { + const child = Bun.spawn([process.execPath, fixturePath("minimax-bridge-direct.ts")], { env: { ...process.env, HTTP_PROXY: `http://127.0.0.1:${proxyPort}`, diff --git a/tests/minimax-reasoning-split.test.ts b/tests/providers/minimax-reasoning-split.test.ts similarity index 97% rename from tests/minimax-reasoning-split.test.ts rename to tests/providers/minimax-reasoning-split.test.ts index ad2b44d57e..4d21ff08f1 100644 --- a/tests/minimax-reasoning-split.test.ts +++ b/tests/providers/minimax-reasoning-split.test.ts @@ -1,9 +1,9 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { createTranslatorBudget } from "../src/lib/translator-budget"; -import { enrichProviderFromRegistry } from "../src/providers/derive"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { createTranslatorBudget } from "../../src/lib/translator-budget"; +import { enrichProviderFromRegistry } from "../../src/providers/derive"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../../src/types"; type ReasoningEffort = OcxParsedRequest["options"]["reasoning"]; diff --git a/tests/model-presets.test.ts b/tests/providers/model-presets.test.ts similarity index 97% rename from tests/model-presets.test.ts rename to tests/providers/model-presets.test.ts index 7af8fe9aed..8fcbb44dc2 100644 --- a/tests/model-presets.test.ts +++ b/tests/providers/model-presets.test.ts @@ -5,8 +5,8 @@ import { materializeModelPreset, modelPresetFor, MODEL_PRESETS, -} from "../src/providers/model-presets"; -import type { OcxProviderConfig } from "../src/types"; +} from "../../src/providers/model-presets"; +import type { OcxProviderConfig } from "../../src/types"; describe("#2465 model presets", () => { test("rules match vendor snapshot suffixes, not just bare ids", () => { diff --git a/tests/model-rename-migration.test.ts b/tests/providers/model-rename-migration.test.ts similarity index 97% rename from tests/model-rename-migration.test.ts rename to tests/providers/model-rename-migration.test.ts index 61796018ce..40803a4ed1 100644 --- a/tests/model-rename-migration.test.ts +++ b/tests/providers/model-rename-migration.test.ts @@ -3,9 +3,9 @@ import { MODEL_RENAMES, projectModelRenames, type ModelRename, -} from "../src/providers/model-rename-migration"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import type { OcxConfig } from "../src/types"; +} from "../../src/providers/model-rename-migration"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import type { OcxConfig } from "../../src/types"; const INTL_BASE_URL = "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1"; diff --git a/tests/moonshot-endpoints.test.ts b/tests/providers/moonshot-endpoints.test.ts similarity index 89% rename from tests/moonshot-endpoints.test.ts rename to tests/providers/moonshot-endpoints.test.ts index 3898bd1390..107a9771b9 100644 --- a/tests/moonshot-endpoints.test.ts +++ b/tests/providers/moonshot-endpoints.test.ts @@ -4,9 +4,9 @@ import { MOONSHOT_CN_BASE_URL, MOONSHOT_INTL_BASE_URL, matchBaseUrlChoice, -} from "../src/providers/base-url-choices"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { deriveProviderPresets } from "../src/providers/derive"; +} from "../../src/providers/base-url-choices"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { deriveProviderPresets } from "../../src/providers/derive"; describe("moonshot endpoint choices", () => { test("registry defaults to international and exposes china + custom choices", () => { diff --git a/tests/moonshot-tool-schema.test.ts b/tests/providers/moonshot-tool-schema.test.ts similarity index 99% rename from tests/moonshot-tool-schema.test.ts rename to tests/providers/moonshot-tool-schema.test.ts index 6628984340..ed1626927a 100644 --- a/tests/moonshot-tool-schema.test.ts +++ b/tests/providers/moonshot-tool-schema.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter as createOpenAIChatAdapterProduction } from "../src/adapters/openai-chat"; -import type { OcxParsedRequest, OcxTool } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { createOpenAIChatAdapter as createOpenAIChatAdapterProduction } from "../../src/adapters/openai-chat"; +import type { OcxParsedRequest, OcxTool } from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; const createOpenAIChatAdapter = ( ...args: Parameters diff --git a/tests/muse-passive-quota-cache.test.ts b/tests/providers/muse-passive-quota-cache.test.ts similarity index 94% rename from tests/muse-passive-quota-cache.test.ts rename to tests/providers/muse-passive-quota-cache.test.ts index cf144dbca5..48433851f7 100644 --- a/tests/muse-passive-quota-cache.test.ts +++ b/tests/providers/muse-passive-quota-cache.test.ts @@ -2,7 +2,7 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { getAccountSet, saveCredential } from "../src/oauth/store"; +import { getAccountSet, saveCredential } from "../../src/oauth/store"; import { clearAccountQuotaCache, getCachedProviderAccountQuota, @@ -12,11 +12,11 @@ import { resetProviderQuotaReconcileStateForTests, setCachedProviderAccountQuotaForTests, supportsPerAccountQuota, -} from "../src/providers/quota"; -import { hasHeadroomEvidence, rankAccountsByHeadroom } from "../src/oauth/account-quota-rank"; -import { captureConfigGeneration } from "../src/lib/state-store-sweeper"; -import type { ProviderQuota } from "../src/providers/quota-types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/quota"; +import { hasHeadroomEvidence, rankAccountsByHeadroom } from "../../src/oauth/account-quota-rank"; +import { captureConfigGeneration } from "../../src/lib/state-store-sweeper"; +import type { ProviderQuota } from "../../src/providers/quota-types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const previousOpencodexHome = process.env.OPENCODEX_HOME; let opencodexHome: string; @@ -95,7 +95,7 @@ describe("passive Muse quota cache", () => { test("discards a write whose config generation has been superseded", () => { // Generation 0 predates any reconciliation; a stale writer must not commit. - const { reconcileStateGeneration } = require("../src/lib/state-store-sweeper"); + const { reconcileStateGeneration } = require("../../src/lib/state-store-sweeper"); reconcileStateGeneration({ generation: 0, oauthAccountKeys: new Set(), providerNames: new Set() }); recordPassiveAccountQuota("meta-muse", FIRST.accountId, quotaAt(42), -1); expect(getCachedProviderAccountQuota("meta-muse", FIRST.accountId)).toBeNull(); @@ -198,7 +198,7 @@ describe("passive quota and routing headroom", () => { expect(hasHeadroomEvidence("anthropic", [FIRST.accountId])).toBe(true); }); }); -import { readPersistedAccountQuotas } from "../src/providers/account-quota-disk"; +import { readPersistedAccountQuotas } from "../../src/providers/account-quota-disk"; /** PERSIST_DEBOUNCE_MS is 250ms in account-quota-disk.ts; wait past it. */ const PERSIST_SETTLE_MS = 400; diff --git a/tests/muse-passive-quota-observation.test.ts b/tests/providers/muse-passive-quota-observation.test.ts similarity index 96% rename from tests/muse-passive-quota-observation.test.ts rename to tests/providers/muse-passive-quota-observation.test.ts index ed48130d29..56d7d74b43 100644 --- a/tests/muse-passive-quota-observation.test.ts +++ b/tests/providers/muse-passive-quota-observation.test.ts @@ -10,8 +10,8 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { createSseInspector } from "../src/server/relay"; -import { handleOauthAccountRoutes } from "../src/server/management/oauth-account-routes"; +import { createSseInspector } from "../../src/server/relay"; +import { handleOauthAccountRoutes } from "../../src/server/management/oauth-account-routes"; import { clearAccountQuotaCache, clearProviderQuotaCache, @@ -19,15 +19,15 @@ import { getCachedProviderAccountQuota, recordPassiveAccountQuota, resetProviderQuotaReconcileStateForTests, -} from "../src/providers/quota"; +} from "../../src/providers/quota"; import { isMuseSubscriptionUsagePayload, MUSE_SUBSCRIPTION_USAGE_TYPE, parseMuseSubscriptionUsage, -} from "../src/providers/muse-subscription-usage"; -import { captureConfigGeneration } from "../src/lib/state-store-sweeper"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/muse-subscription-usage"; +import { captureConfigGeneration } from "../../src/lib/state-store-sweeper"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const previousHome = process.env.OPENCODEX_HOME; let testDir = ""; diff --git a/tests/muse-spark-web-search-compat.test.ts b/tests/providers/muse-spark-web-search-compat.test.ts similarity index 96% rename from tests/muse-spark-web-search-compat.test.ts rename to tests/providers/muse-spark-web-search-compat.test.ts index 04e0f56a73..ed22b4e036 100644 --- a/tests/muse-spark-web-search-compat.test.ts +++ b/tests/providers/muse-spark-web-search-compat.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../src/adapters/openai-responses"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import type { OcxProviderConfig } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../../src/adapters/openai-responses"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; +import type { OcxProviderConfig } from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; const createResponsesPassthroughAdapter = (...args: Parameters) => withTestTranslatorBudget(createResponsesPassthroughAdapterProduction(...args)); diff --git a/tests/muse-subscription-usage.test.ts b/tests/providers/muse-subscription-usage.test.ts similarity index 98% rename from tests/muse-subscription-usage.test.ts rename to tests/providers/muse-subscription-usage.test.ts index 2b8b2ed86b..154b6ac509 100644 --- a/tests/muse-subscription-usage.test.ts +++ b/tests/providers/muse-subscription-usage.test.ts @@ -3,7 +3,7 @@ import { isMuseSubscriptionUsagePayload, MUSE_SUBSCRIPTION_USAGE_TYPE, parseMuseSubscriptionUsage, -} from "../src/providers/muse-subscription-usage"; +} from "../../src/providers/muse-subscription-usage"; /** The payload measured against the live endpoint on 2026-09-03 (003 §E). */ function measuredPayload(): unknown { diff --git a/tests/new-model-policy.test.ts b/tests/providers/new-model-policy.test.ts similarity index 98% rename from tests/new-model-policy.test.ts rename to tests/providers/new-model-policy.test.ts index be6656dada..dbf591bec3 100644 --- a/tests/new-model-policy.test.ts +++ b/tests/providers/new-model-policy.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { applyNewModelPolicy, reconcileSuccessfulModelDiscoveries } from "../src/providers/new-model-policy"; +import { applyNewModelPolicy, reconcileSuccessfulModelDiscoveries } from "../../src/providers/new-model-policy"; const now = "2026-08-24T02:11:00Z"; diff --git a/tests/nous-oauth-live.test.ts b/tests/providers/nous-oauth-live.test.ts similarity index 95% rename from tests/nous-oauth-live.test.ts rename to tests/providers/nous-oauth-live.test.ts index 83204a84af..51e4ad47b1 100644 --- a/tests/nous-oauth-live.test.ts +++ b/tests/providers/nous-oauth-live.test.ts @@ -21,10 +21,10 @@ * accepting either an OpenAI-style `{ data: [...] }` body or a bare array. */ import { describe, expect, test } from "bun:test"; -import { getAccountCredential, getAccountSet, getCredential } from "../src/oauth/store"; -import { NOUS_INFERENCE_BASE_URL, refreshNousToken } from "../src/oauth/nous"; -import { refreshGenericAccountWithLock } from "../src/oauth/index"; -import type { OAuthCredentials } from "../src/oauth/types"; +import { getAccountCredential, getAccountSet, getCredential } from "../../src/oauth/store"; +import { NOUS_INFERENCE_BASE_URL, refreshNousToken } from "../../src/oauth/nous"; +import { refreshGenericAccountWithLock } from "../../src/oauth/index"; +import type { OAuthCredentials } from "../../src/oauth/types"; const LIVE = process.env.NOUS_LIVE_TEST === "1"; diff --git a/tests/nous-oauth.test.ts b/tests/providers/nous-oauth.test.ts similarity index 99% rename from tests/nous-oauth.test.ts rename to tests/providers/nous-oauth.test.ts index e6fc200020..c1294cfc5f 100644 --- a/tests/nous-oauth.test.ts +++ b/tests/providers/nous-oauth.test.ts @@ -2,12 +2,12 @@ import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test"; import { createHash } from "node:crypto"; import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { join } from "node:path"; -import { clearNousRefreshIntent, identityFromNousTokens, loginNous, nousRefreshIntentBlocksReplay, refreshNousToken, RefreshIntentIOError } from "../src/oauth/nous"; -import { getCredential, listAccounts, saveCredential } from "../src/oauth/store"; -import type { OAuthController } from "../src/oauth/types"; -import * as configModule from "../src/config"; -import { BOUNDED_BODY_MAX_BYTES } from "../src/lib/bounded-body"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { clearNousRefreshIntent, identityFromNousTokens, loginNous, nousRefreshIntentBlocksReplay, refreshNousToken, RefreshIntentIOError } from "../../src/oauth/nous"; +import { getCredential, listAccounts, saveCredential } from "../../src/oauth/store"; +import type { OAuthController } from "../../src/oauth/types"; +import * as configModule from "../../src/config"; +import { BOUNDED_BODY_MAX_BYTES } from "../../src/lib/bounded-body"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-nous-oauth-test"); const TEST_PORTAL = "https://portal.test"; diff --git a/tests/novita-provider.test.ts b/tests/providers/novita-provider.test.ts similarity index 88% rename from tests/novita-provider.test.ts rename to tests/providers/novita-provider.test.ts index 1b8320dece..d1c6ba2ff5 100644 --- a/tests/novita-provider.test.ts +++ b/tests/providers/novita-provider.test.ts @@ -1,25 +1,26 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { resolveProviderModelDiscovery } from "../src/providers/model-discovery"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; - -const NOVITA_FIXTURE = readFileSync(join(import.meta.dir, "fixtures/novita-models.json"), "utf8"); +} from "../../src/providers/derive"; +import { resolveProviderModelDiscovery } from "../../src/providers/model-discovery"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; + +const NOVITA_FIXTURE = readFileSync(fixturePath("novita-models.json"), "utf8"); const BASE_URL = "https://api.novita.ai/openai/v1"; const MODELS_URL = `${BASE_URL}/models`; const TEST_KEY = "novita-test-key"; diff --git a/tests/nscale-vultr-provider.test.ts b/tests/providers/nscale-vultr-provider.test.ts similarity index 90% rename from tests/nscale-vultr-provider.test.ts rename to tests/providers/nscale-vultr-provider.test.ts index 37042629d9..0a78785647 100644 --- a/tests/nscale-vultr-provider.test.ts +++ b/tests/providers/nscale-vultr-provider.test.ts @@ -1,22 +1,23 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; +} from "../../src/providers/derive"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; const NSCALE_BASE_URL = "https://inference.api.nscale.com/v1"; const VULTR_BASE_URL = "https://api.vultrinference.com/v1"; @@ -24,8 +25,8 @@ const NSCALE_MODEL = "meta-llama/Llama-3.1-8B-Instruct"; const VULTR_MODEL = "kimi-k2-instruct"; const API_KEY = "provider-test-key"; const fixtures = { - nscale: readFileSync(join(import.meta.dir, "fixtures/nscale-models.json"), "utf8"), - vultr: readFileSync(join(import.meta.dir, "fixtures/vultr-models.json"), "utf8"), + nscale: readFileSync(fixturePath("nscale-models.json"), "utf8"), + vultr: readFileSync(fixturePath("vultr-models.json"), "utf8"), }; const originalFetch = globalThis.fetch; diff --git a/tests/nvidia-nim-hardening.test.ts b/tests/providers/nvidia-nim-hardening.test.ts similarity index 97% rename from tests/nvidia-nim-hardening.test.ts rename to tests/providers/nvidia-nim-hardening.test.ts index 7a1c0b397f..17d553c3f1 100644 --- a/tests/nvidia-nim-hardening.test.ts +++ b/tests/providers/nvidia-nim-hardening.test.ts @@ -5,13 +5,13 @@ // natively image-capable models do not. Plan/evidence: // devlog/_fin/260804_stack7_service_vision (010 design, 011 per-id audit). import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter, formatOpenAIChatErrorBody } from "../src/adapters/openai-chat"; -import { applyProviderConfigHints, normalizeRoutedCatalogEntry } from "../src/codex/catalog"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { parseRequest } from "../src/responses/parser"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxParsedRequest, OcxTool } from "../src/types"; -import { planVisionSidecar } from "../src/vision"; +import { createOpenAIChatAdapter, formatOpenAIChatErrorBody } from "../../src/adapters/openai-chat"; +import { applyProviderConfigHints, normalizeRoutedCatalogEntry } from "../../src/codex/catalog"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { parseRequest } from "../../src/responses/parser"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxParsedRequest, OcxTool } from "../../src/types"; +import { planVisionSidecar } from "../../src/vision"; const tools: OcxTool[] = [{ name: "shell", description: "run", parameters: { type: "object" } }]; diff --git a/tests/ollama-native-parser.test.ts b/tests/providers/ollama/ollama-native-parser.test.ts similarity index 98% rename from tests/ollama-native-parser.test.ts rename to tests/providers/ollama/ollama-native-parser.test.ts index 589d84e3fc..71bfad723a 100644 --- a/tests/ollama-native-parser.test.ts +++ b/tests/providers/ollama/ollama-native-parser.test.ts @@ -1,9 +1,9 @@ import { describe, expect, test } from "bun:test"; -import { createOllamaNativeAdapter } from "../src/adapters/ollama-native"; -import { ollamaNativeChatUrl } from "../src/adapters/ollama-native-url"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import type { AdapterEvent } from "../src/types"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { createOllamaNativeAdapter } from "../../../src/adapters/ollama-native"; +import { ollamaNativeChatUrl } from "../../../src/adapters/ollama-native-url"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; +import type { AdapterEvent } from "../../../src/types"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; /** * Parser/request contract tests for the native Ollama transport. @@ -49,7 +49,7 @@ async function collect(adapter: ReturnType, re describe("ollama-native — observer-free streaming", () => { test("no structural-receipt machinery exists in the module surface", async () => { - const mod = await import("../src/adapters/ollama-native") as unknown as Record; + const mod = await import("../../../src/adapters/ollama-native") as unknown as Record; for (const name of [ "setOllamaNativeObservationSink", "createOllamaNativeObservationBuffer", diff --git a/tests/ollama-native-reasoning-wire.test.ts b/tests/providers/ollama/ollama-native-reasoning-wire.test.ts similarity index 94% rename from tests/ollama-native-reasoning-wire.test.ts rename to tests/providers/ollama/ollama-native-reasoning-wire.test.ts index fc84e37cf3..c1fe09dcaf 100644 --- a/tests/ollama-native-reasoning-wire.test.ts +++ b/tests/providers/ollama/ollama-native-reasoning-wire.test.ts @@ -1,9 +1,9 @@ import { describe, expect, test } from "bun:test"; -import { createOllamaNativeAdapter } from "../src/adapters/ollama-native"; -import { buildCatalogEntries, gatherRoutedModels as gatherRoutedModelsDirect } from "../src/codex/catalog"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import { REASONING_EFFORT_OMIT_SENTINEL } from "../src/reasoning-effort"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { createOllamaNativeAdapter } from "../../../src/adapters/ollama-native"; +import { buildCatalogEntries, gatherRoutedModels as gatherRoutedModelsDirect } from "../../../src/codex/catalog"; +import { withStubbedProviderFetch } from "../../helpers/catalog-provider-fetch"; +import { REASONING_EFFORT_OMIT_SENTINEL } from "../../../src/reasoning-effort"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; const gatherRoutedModels: typeof gatherRoutedModelsDirect = (config, options) => gatherRoutedModelsDirect(withStubbedProviderFetch(config), options); diff --git a/tests/ollama-native-structured-output.test.ts b/tests/providers/ollama/ollama-native-structured-output.test.ts similarity index 97% rename from tests/ollama-native-structured-output.test.ts rename to tests/providers/ollama/ollama-native-structured-output.test.ts index 4e2bcfa001..ed2df67380 100644 --- a/tests/ollama-native-structured-output.test.ts +++ b/tests/providers/ollama/ollama-native-structured-output.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { createOllamaNativeAdapter } from "../src/adapters/ollama-native"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { createOllamaNativeAdapter } from "../../../src/adapters/ollama-native"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; /** * Structured output is a capability boundary, not a formatting preference. diff --git a/tests/ollama-native-v4.test.ts b/tests/providers/ollama/ollama-native-v4.test.ts similarity index 93% rename from tests/ollama-native-v4.test.ts rename to tests/providers/ollama/ollama-native-v4.test.ts index 4da76379d0..13fa0269a5 100644 --- a/tests/ollama-native-v4.test.ts +++ b/tests/providers/ollama/ollama-native-v4.test.ts @@ -1,9 +1,9 @@ import { describe, expect, test } from "bun:test"; -import { createOllamaNativeAdapter } from "../src/adapters/ollama-native"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import { REASONING_EFFORT_OMIT_SENTINEL } from "../src/reasoning-effort"; -import type { AdapterEvent } from "../src/types"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { createOllamaNativeAdapter } from "../../../src/adapters/ollama-native"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; +import { REASONING_EFFORT_OMIT_SENTINEL } from "../../../src/reasoning-effort"; +import type { AdapterEvent } from "../../../src/types"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; function provider(overrides: Partial = {}): OcxProviderConfig { return { diff --git a/tests/ollama-native.test.ts b/tests/providers/ollama/ollama-native.test.ts similarity index 96% rename from tests/ollama-native.test.ts rename to tests/providers/ollama/ollama-native.test.ts index 65c90c5848..d22cdc1ce4 100644 --- a/tests/ollama-native.test.ts +++ b/tests/providers/ollama/ollama-native.test.ts @@ -1,13 +1,13 @@ import { describe, expect, test } from "bun:test"; -import { createOllamaNativeAdapter } from "../src/adapters/ollama-native"; +import { createOllamaNativeAdapter } from "../../../src/adapters/ollama-native"; import { ollamaNativeChatUrl, ollamaNativeEndpointKind, -} from "../src/adapters/ollama-native-url"; -import { buildCatalogEntries, gatherRoutedModels as gatherRoutedModelsDirect, upstreamNativeEntry } from "../src/codex/catalog"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +} from "../../../src/adapters/ollama-native-url"; +import { buildCatalogEntries, gatherRoutedModels as gatherRoutedModelsDirect, upstreamNativeEntry } from "../../../src/codex/catalog"; +import { getProviderRegistryEntry } from "../../../src/providers/registry"; +import { withStubbedProviderFetch } from "../../helpers/catalog-provider-fetch"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; const gatherRoutedModels: typeof gatherRoutedModelsDirect = (config, options) => gatherRoutedModelsDirect(withStubbedProviderFetch(config), options); diff --git a/tests/ollama-show-enrichment-v7.test.ts b/tests/providers/ollama/ollama-show-enrichment-v7.test.ts similarity index 97% rename from tests/ollama-show-enrichment-v7.test.ts rename to tests/providers/ollama/ollama-show-enrichment-v7.test.ts index a82f8a336d..9595db263a 100644 --- a/tests/ollama-show-enrichment-v7.test.ts +++ b/tests/providers/ollama/ollama-show-enrichment-v7.test.ts @@ -1,6 +1,6 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { gatherRoutedModels, resetCatalogRuntimeStateForTests, resetOpenAiApiCatalogWarningStateForTests } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; +import { gatherRoutedModels, resetCatalogRuntimeStateForTests, resetOpenAiApiCatalogWarningStateForTests } from "../../../src/codex/catalog"; +import { clearModelCache } from "../../../src/codex/model-cache"; afterEach(() => { // The provider-model cache is keyed by provider name; without this, one test's gather would @@ -12,9 +12,9 @@ afterEach(() => { }); const originalFetch = globalThis.fetch; -import { fetchOllamaShowEnrichment, ollamaShowMetadataFromPayload, showHeadersFromCaptured } from "../src/providers/ollama-show"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import type { OcxConfig } from "../src/types"; +import { fetchOllamaShowEnrichment, ollamaShowMetadataFromPayload, showHeadersFromCaptured } from "../../../src/providers/ollama-show"; +import { withStubbedProviderFetch } from "../../helpers/catalog-provider-fetch"; +import type { OcxConfig } from "../../../src/types"; /** * V7: auth/outbound-policy integration, aggregate fan-out bounds, and models-API precedence. @@ -368,8 +368,8 @@ describe("ollama /api/show — payload extraction contract (input not mutated)", }); // The adapter-level third surface is exercised directly below via the real adapter factory, // which is what the native /api/chat route uses. -import { createOllamaNativeAdapter } from "../src/adapters/ollama-native"; -import type { OcxParsedRequest } from "../src/types"; +import { createOllamaNativeAdapter } from "../../../src/adapters/ollama-native"; +import type { OcxParsedRequest } from "../../../src/types"; function nativeParsed(modelId = "glm-5.3-flash"): OcxParsedRequest { return { modelId, stream: true, options: {}, context: { messages: [{ role: "user", content: "hi" }] } } as unknown as OcxParsedRequest; diff --git a/tests/ollama-show-enrichment.test.ts b/tests/providers/ollama/ollama-show-enrichment.test.ts similarity index 97% rename from tests/ollama-show-enrichment.test.ts rename to tests/providers/ollama/ollama-show-enrichment.test.ts index 240a2665d6..8517913a77 100644 --- a/tests/ollama-show-enrichment.test.ts +++ b/tests/providers/ollama/ollama-show-enrichment.test.ts @@ -1,6 +1,6 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { gatherRoutedModels, resetCatalogRuntimeStateForTests, resetOpenAiApiCatalogWarningStateForTests } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; +import { gatherRoutedModels, resetCatalogRuntimeStateForTests, resetOpenAiApiCatalogWarningStateForTests } from "../../../src/codex/catalog"; +import { clearModelCache } from "../../../src/codex/model-cache"; afterEach(() => { // The provider-model cache is keyed by provider name; without this, one test's gather would @@ -12,9 +12,9 @@ afterEach(() => { }); const originalFetch = globalThis.fetch; -import { ollamaShowMetadataFromPayload } from "../src/providers/ollama-show"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import type { OcxConfig } from "../src/types"; +import { ollamaShowMetadataFromPayload } from "../../../src/providers/ollama-show"; +import { withStubbedProviderFetch } from "../../helpers/catalog-provider-fetch"; +import type { OcxConfig } from "../../../src/types"; /** * Bounded /api/show metadata enrichment for Ollama Cloud live discovery. diff --git a/tests/ollama-show-ignore-abort.test.ts b/tests/providers/ollama/ollama-show-ignore-abort.test.ts similarity index 98% rename from tests/ollama-show-ignore-abort.test.ts rename to tests/providers/ollama/ollama-show-ignore-abort.test.ts index 0a87075d59..327524ce71 100644 --- a/tests/ollama-show-ignore-abort.test.ts +++ b/tests/providers/ollama/ollama-show-ignore-abort.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { fetchOllamaShowEnrichment } from "../src/providers/ollama-show"; +import { fetchOllamaShowEnrichment } from "../../../src/providers/ollama-show"; /** * V10: the aggregate deadline TIMER ITSELF is the return bound. diff --git a/tests/opencode-cli.test.ts b/tests/providers/opencode-cli.test.ts similarity index 98% rename from tests/opencode-cli.test.ts rename to tests/providers/opencode-cli.test.ts index 1b8cce02d7..e1aed8a045 100644 --- a/tests/opencode-cli.test.ts +++ b/tests/providers/opencode-cli.test.ts @@ -2,8 +2,8 @@ import { describe, expect, test } from "bun:test"; import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { clearModelCache } from "../src/codex/model-cache"; -import { loadServiceTokenFromFile, serviceApiTokenFilePath } from "../src/lib/service-secrets"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { loadServiceTokenFromFile, serviceApiTokenFilePath } from "../../src/lib/service-secrets"; import { OPENCODE_API_KEY_ENV, OPENCODE_API_KEY_ENV_REF, @@ -31,8 +31,8 @@ import { parseJsonc, projectConfigOverridesProvider, serializeOpencodeRuntimeConfig, -} from "../src/cli/opencode"; -import type { OcxConfig } from "../src/types"; +} from "../../src/cli/opencode"; +import type { OcxConfig } from "../../src/types"; function cfg(extra?: Partial): OcxConfig { return { @@ -273,7 +273,7 @@ describe("ocx opencode proxy model catalog", () => { delete process.env[ENV_KEY]; clearModelCache(PROVIDER); try { - const { fetchAllModels } = await import("../src/server/management/shared"); + const { fetchAllModels } = await import("../../src/server/management/shared"); const cliModels = await fetchAllModels(config); const cliIds = cliModels.filter(m => m.provider === PROVIDER).map(m => m.id).sort(); expect(cliIds).toEqual(["static-fallback"]); @@ -283,7 +283,7 @@ describe("ocx opencode proxy model catalog", () => { clearModelCache(PROVIDER); requestedAuth = undefined; - const { handleManagementAPI } = await import("../src/server/management-api"); + const { handleManagementAPI } = await import("../../src/server/management-api"); const modelsRes = await handleManagementAPI( new Request("http://localhost/api/models"), new URL("http://localhost/api/models"), @@ -668,4 +668,4 @@ describe("ocx opencode not-found hint", () => { expect(opencodeNotFoundHint(0, null, "win32")).toBeNull(); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/opencode-free-provider.test.ts b/tests/providers/opencode-free-provider.test.ts similarity index 95% rename from tests/opencode-free-provider.test.ts rename to tests/providers/opencode-free-provider.test.ts index 0db4aafb3e..c468af2cc0 100644 --- a/tests/opencode-free-provider.test.ts +++ b/tests/providers/opencode-free-provider.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from "bun:test"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { providerConfigSeed, deriveKeyLoginMap, deriveFeaturedProviderIds } from "../src/providers/derive"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { routedProviderConfig } from "../src/router"; -import { buildModelsRequest } from "../src/oauth"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { providerConfigSeed, deriveKeyLoginMap, deriveFeaturedProviderIds } from "../../src/providers/derive"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { routedProviderConfig } from "../../src/router"; +import { buildModelsRequest } from "../../src/oauth"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../src/types"; function minimalRequest(model = "kimi-k2.7-code"): OcxParsedRequest { return { @@ -208,7 +208,7 @@ describe("opencode-free provider", () => { }); test("deriveProviderPresets exposes keyOptional for GUI picker", () => { - const { deriveProviderPresets } = require("../src/providers/derive"); + const { deriveProviderPresets } = require("../../src/providers/derive"); const presets = deriveProviderPresets(); const preset = presets.find((p: { id: string }) => p.id === "opencode-free"); expect(preset).toBeDefined(); diff --git a/tests/opencode-go-deepseek.test.ts b/tests/providers/opencode-go-deepseek.test.ts similarity index 96% rename from tests/opencode-go-deepseek.test.ts rename to tests/providers/opencode-go-deepseek.test.ts index dd972e36b1..edf42a4815 100644 --- a/tests/opencode-go-deepseek.test.ts +++ b/tests/providers/opencode-go-deepseek.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { routeModel } from "../src/router"; -import type { OcxConfig } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { routeModel } from "../../src/router"; +import type { OcxConfig } from "../../src/types"; function configFor(modelId: string): OcxConfig { return { diff --git a/tests/opencode-go-grok46-responses.test.ts b/tests/providers/opencode-go-grok46-responses.test.ts similarity index 91% rename from tests/opencode-go-grok46-responses.test.ts rename to tests/providers/opencode-go-grok46-responses.test.ts index 175e29c313..19c2addd46 100644 --- a/tests/opencode-go-grok46-responses.test.ts +++ b/tests/providers/opencode-go-grok46-responses.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from "bun:test"; -import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../src/adapters/openai-responses"; -import { providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { resolveWireProtocolOverride } from "../src/server/adapter-resolve"; -import type { OcxProviderConfig } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../../src/adapters/openai-responses"; +import { providerConfigSeed } from "../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; +import { resolveWireProtocolOverride } from "../../src/server/adapter-resolve"; +import type { OcxProviderConfig } from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; const createResponsesPassthroughAdapter = (...args: Parameters) => withTestTranslatorBudget(createResponsesPassthroughAdapterProduction(...args)); diff --git a/tests/opencode-go-luna-wire.test.ts b/tests/providers/opencode-go-luna-wire.test.ts similarity index 90% rename from tests/opencode-go-luna-wire.test.ts rename to tests/providers/opencode-go-luna-wire.test.ts index 72e383abdf..152783b9bd 100644 --- a/tests/opencode-go-luna-wire.test.ts +++ b/tests/providers/opencode-go-luna-wire.test.ts @@ -5,11 +5,11 @@ * boundary that lets operators opt out if the upstream changes. */ import { afterEach, describe, expect, test } from "bun:test"; -import { providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { resolveWireProtocolOverride } from "../src/server/adapter-resolve"; -import { handleResponses } from "../src/server/responses/core"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { providerConfigSeed } from "../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; +import { resolveWireProtocolOverride } from "../../src/server/adapter-resolve"; +import { handleResponses } from "../../src/server/responses/core"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; const MODEL = "gpt-5.6-luna"; diff --git a/tests/opencode-go-muse-context.test.ts b/tests/providers/opencode-go-muse-context.test.ts similarity index 92% rename from tests/opencode-go-muse-context.test.ts rename to tests/providers/opencode-go-muse-context.test.ts index 56bdc9dcc2..26c1e5444a 100644 --- a/tests/opencode-go-muse-context.test.ts +++ b/tests/providers/opencode-go-muse-context.test.ts @@ -8,10 +8,10 @@ * in and prove the catalog advertises the full 1M window for Muse. */ import { describe, expect, test } from "bun:test"; -import { applyProviderConfigHints } from "../src/codex/catalog"; -import { getProviderRegistryEntry, PROVIDER_REGISTRY } from "../src/providers/registry"; -import { providerConfigSeed } from "../src/providers/derive"; -import type { OcxProviderConfig } from "../src/types"; +import { applyProviderConfigHints } from "../../src/codex/catalog"; +import { getProviderRegistryEntry, PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { providerConfigSeed } from "../../src/providers/derive"; +import type { OcxProviderConfig } from "../../src/types"; const MUSE_MODEL = "muse-spark-1.2-contributor"; const MUSE_13_MODEL = "muse-spark-1.3-contributor"; diff --git a/tests/opencode-go-muse-vision.test.ts b/tests/providers/opencode-go-muse-vision.test.ts similarity index 95% rename from tests/opencode-go-muse-vision.test.ts rename to tests/providers/opencode-go-muse-vision.test.ts index b8eca82a6c..0a39bdb92a 100644 --- a/tests/opencode-go-muse-vision.test.ts +++ b/tests/providers/opencode-go-muse-vision.test.ts @@ -9,10 +9,10 @@ * and prove the catalog advertises image input for Muse. */ import { describe, expect, test } from "bun:test"; -import { applyProviderConfigHints } from "../src/codex/catalog"; -import { getProviderRegistryEntry, PROVIDER_REGISTRY } from "../src/providers/registry"; -import { providerConfigSeed } from "../src/providers/derive"; -import type { OcxProviderConfig } from "../src/types"; +import { applyProviderConfigHints } from "../../src/codex/catalog"; +import { getProviderRegistryEntry, PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { providerConfigSeed } from "../../src/providers/derive"; +import type { OcxProviderConfig } from "../../src/types"; const MUSE_MODEL = "muse-spark-1.2-contributor"; const MUSE_13_MODEL = "muse-spark-1.3-contributor"; diff --git a/tests/opencode-go-quota.test.ts b/tests/providers/opencode-go-quota.test.ts similarity index 98% rename from tests/opencode-go-quota.test.ts rename to tests/providers/opencode-go-quota.test.ts index df2bb52525..26d9463ee1 100644 --- a/tests/opencode-go-quota.test.ts +++ b/tests/providers/opencode-go-quota.test.ts @@ -1,6 +1,6 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; -import { clearProviderQuotaCache, fetchProviderQuotaReports } from "../src/providers/quota"; -import type { OcxConfig } from "../src/types"; +import { clearProviderQuotaCache, fetchProviderQuotaReports } from "../../src/providers/quota"; +import type { OcxConfig } from "../../src/types"; const originalFetch = globalThis.fetch; diff --git a/tests/opencode-go-session-header.test.ts b/tests/providers/opencode-go-session-header.test.ts similarity index 93% rename from tests/opencode-go-session-header.test.ts rename to tests/providers/opencode-go-session-header.test.ts index 2a4de51b6c..00684f065b 100644 --- a/tests/opencode-go-session-header.test.ts +++ b/tests/providers/opencode-go-session-header.test.ts @@ -1,9 +1,9 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { providerConfigSeed } from "../src/providers/derive"; -import { resolveOpenCodeGoTransport } from "../src/providers/opencode-go-transport"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { handleResponses } from "../src/server/responses/core"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { providerConfigSeed } from "../../src/providers/derive"; +import { resolveOpenCodeGoTransport } from "../../src/providers/opencode-go-transport"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; +import { handleResponses } from "../../src/server/responses/core"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; const MUSE_MODEL = "muse-spark-1.3-contributor"; const CHAT_MODEL = "glm-5.2"; diff --git a/tests/opencode-zen-deepseek-reasoning.test.ts b/tests/providers/opencode-zen-deepseek-reasoning.test.ts similarity index 95% rename from tests/opencode-zen-deepseek-reasoning.test.ts rename to tests/providers/opencode-zen-deepseek-reasoning.test.ts index 4c29e34ed7..5074a510f1 100644 --- a/tests/opencode-zen-deepseek-reasoning.test.ts +++ b/tests/providers/opencode-zen-deepseek-reasoning.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { routeModel } from "../src/router"; -import type { OcxConfig } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { routeModel } from "../../src/router"; +import type { OcxConfig } from "../../src/types"; function configFor(modelId: string): OcxConfig { return { diff --git a/tests/opencode-zen-rate-limit.test.ts b/tests/providers/opencode-zen-rate-limit.test.ts similarity index 94% rename from tests/opencode-zen-rate-limit.test.ts rename to tests/providers/opencode-zen-rate-limit.test.ts index ae56694c56..5678a35b77 100644 --- a/tests/opencode-zen-rate-limit.test.ts +++ b/tests/providers/opencode-zen-rate-limit.test.ts @@ -1,14 +1,14 @@ import { describe, expect, test } from "bun:test"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; import { OPENCODE_ZEN_OBSERVED_RPM_HINT, OPENCODE_ZEN_SYNTHETIC_RETRY_AFTER_SEC, enrichOpenCodeZenRateLimitMessage, isOpenCodeZenRateLimitProvider, -} from "../src/providers/opencode-zen-rate-limit"; -import { resolveClientRetryAfter } from "../src/lib/retry-after"; -import { safeConfigDTO } from "../src/server/auth-cors"; -import type { OcxConfig } from "../src/types"; +} from "../../src/providers/opencode-zen-rate-limit"; +import { resolveClientRetryAfter } from "../../src/lib/retry-after"; +import { safeConfigDTO } from "../../src/server/auth-cors"; +import type { OcxConfig } from "../../src/types"; describe("opencode-zen rate-limit guidance (#1145)", () => { test("registry note documents the observed short-window RPM", () => { diff --git a/tests/openrouter-provider-routing.test.ts b/tests/providers/openrouter-provider-routing.test.ts similarity index 97% rename from tests/openrouter-provider-routing.test.ts rename to tests/providers/openrouter-provider-routing.test.ts index 7a833a5b7a..8211c8f008 100644 --- a/tests/openrouter-provider-routing.test.ts +++ b/tests/providers/openrouter-provider-routing.test.ts @@ -2,17 +2,17 @@ import { describe, expect, test } from "bun:test"; import { mkdtempSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { buildOpenAIChatPassthroughRequest, createOpenAIChatAdapter } from "../src/adapters/openai-chat"; +import { buildOpenAIChatPassthroughRequest, createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; import { openRouterRoutingConfigError, openRouterProviderPayload, -} from "../src/providers/openrouter-routing"; -import { fastPolicyForModel } from "../src/providers/service-tier"; -import { clearKeyCooldowns, rotateProviderTransportOn429 } from "../src/providers/key-failover"; -import { routeModel } from "../src/router"; -import { providerManagementConfigError, safeConfigDTO } from "../src/server/auth-cors"; -import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/openrouter-routing"; +import { fastPolicyForModel } from "../../src/providers/service-tier"; +import { clearKeyCooldowns, rotateProviderTransportOn429 } from "../../src/providers/key-failover"; +import { routeModel } from "../../src/router"; +import { providerManagementConfigError, safeConfigDTO } from "../../src/server/auth-cors"; +import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; function provider(baseUrl: string, overrides: Partial = {}): OcxProviderConfig { return { adapter: "openai-chat", baseUrl, apiKey: "test-key", ...overrides }; diff --git a/tests/provider-account-quota-persistence.test.ts b/tests/providers/provider-account-quota-persistence.test.ts similarity index 94% rename from tests/provider-account-quota-persistence.test.ts rename to tests/providers/provider-account-quota-persistence.test.ts index 672ad73966..d9a8f05ef4 100644 --- a/tests/provider-account-quota-persistence.test.ts +++ b/tests/providers/provider-account-quota-persistence.test.ts @@ -6,9 +6,9 @@ import { cancelPendingAccountQuotaPersist, readPersistedAccountQuotas, schedulePersistAccountQuotas, -} from "../src/providers/account-quota-disk"; -import type { ProviderQuota } from "../src/providers/quota-types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/account-quota-disk"; +import type { ProviderQuota } from "../../src/providers/quota-types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const previousHome = process.env.OPENCODEX_HOME; let home: string; diff --git a/tests/provider-account-quota.test.ts b/tests/providers/provider-account-quota.test.ts similarity index 97% rename from tests/provider-account-quota.test.ts rename to tests/providers/provider-account-quota.test.ts index 11b3d69489..ccebd5c032 100644 --- a/tests/provider-account-quota.test.ts +++ b/tests/providers/provider-account-quota.test.ts @@ -2,8 +2,8 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveCredential } from "../src/oauth/store"; -import type { OcxConfig } from "../src/types"; +import { saveCredential } from "../../src/oauth/store"; +import type { OcxConfig } from "../../src/types"; import { clearAccountQuotaCache, clearProviderQuotaCache, @@ -13,8 +13,8 @@ import { reconcileProviderAccountQuotaRows, resetProviderQuotaReconcileStateForTests, supportsPerAccountQuota, -} from "../src/providers/quota"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/quota"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const originalFetch = globalThis.fetch; const previousOpencodexHome = process.env.OPENCODEX_HOME; @@ -171,7 +171,7 @@ describe("fetchProviderAccountQuotas", () => { access: "token-bg", refresh: "refresh-bg", expires, accountId: "acct-bg", email: "bg@example.com", source: "local-cli", }); - const { getAccountSet, setActiveAccount } = await import("../src/oauth/store"); + const { getAccountSet, setActiveAccount } = await import("../../src/oauth/store"); const set = getAccountSet("anthropic"); const active = set?.accounts.find(a => a.credential.email === "active@example.com"); const background = set?.accounts.find(a => a.credential.email === "bg@example.com"); @@ -223,7 +223,7 @@ describe("fetchProviderAccountQuotas", () => { test("provider-report probe seeds the active account cache for per-account reads", async () => { await seedTwoAccounts(); - const { getAccountSet, setActiveAccount } = await import("../src/oauth/store"); + const { getAccountSet, setActiveAccount } = await import("../../src/oauth/store"); const set = getAccountSet("anthropic"); const first = set?.accounts.find(a => a.credential.email === "first@example.com"); expect(first).toBeTruthy(); @@ -277,7 +277,7 @@ describe("fetchProviderAccountQuotas", () => { access: "token-bg", refresh: "refresh-bg", expires, accountId: "acct-bg", email: "bg@example.com", source: "oauth", }); - const { getAccountSet, setActiveAccount } = await import("../src/oauth/store"); + const { getAccountSet, setActiveAccount } = await import("../../src/oauth/store"); const set = getAccountSet("anthropic"); const active = set?.accounts.find(a => a.credential.email === "active@example.com"); const background = set?.accounts.find(a => a.credential.email === "bg@example.com"); @@ -327,7 +327,7 @@ describe("fetchProviderAccountQuotas", () => { test("provider-report seeding binds to the probed account across an active switch", async () => { await seedTwoAccounts(); - const { getAccountSet, setActiveAccount } = await import("../src/oauth/store"); + const { getAccountSet, setActiveAccount } = await import("../../src/oauth/store"); const set = getAccountSet("anthropic"); const first = set?.accounts.find(a => a.credential.email === "first@example.com"); const second = set?.accounts.find(a => a.credential.email === "second@example.com"); @@ -384,7 +384,7 @@ describe("fetchProviderAccountQuotas", () => { test("provider removal during an Anthropic report probe cannot recreate its account quota row", async () => { await seedTwoAccounts(); - const { getAccountSet, setActiveAccount } = await import("../src/oauth/store"); + const { getAccountSet, setActiveAccount } = await import("../../src/oauth/store"); const first = getAccountSet("anthropic")?.accounts.find(account => account.credential.email === FIRST.email); expect(first).toBeTruthy(); await setActiveAccount("anthropic", first!.id); @@ -425,8 +425,8 @@ describe("fetchProviderAccountQuotas", () => { }); describe("google-antigravity per-account quota (#1082)", () => { - const { setAntigravityAccountQuotaTransportForTests } = require("../src/providers/quota") as typeof import("../src/providers/quota"); - const { getAccountSet } = require("../src/oauth/store") as typeof import("../src/oauth/store"); + const { setAntigravityAccountQuotaTransportForTests } = require("../../src/providers/quota") as typeof import("../../src/providers/quota"); + const { getAccountSet } = require("../../src/oauth/store") as typeof import("../../src/oauth/store"); const idFor = (email: string) => getAccountSet("google-antigravity")!.accounts.find(a => a.credential.email === email)!.id; function antigravityBody(gemRemaining: number, claRemaining: number): string { diff --git a/tests/provider-api-keys.test.ts b/tests/providers/provider-api-keys.test.ts similarity index 94% rename from tests/provider-api-keys.test.ts rename to tests/providers/provider-api-keys.test.ts index 10ff2f4bb5..88bb2393b7 100644 --- a/tests/provider-api-keys.test.ts +++ b/tests/providers/provider-api-keys.test.ts @@ -1,13 +1,13 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; -import { managementFetch as fetch } from "./helpers/management-auth"; +import { managementFetch as fetch } from "../helpers/management-auth"; import { mkdtempSync, readFileSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; -import { startServer } from "../src/server"; -import type { OcxConfig } from "../src/types"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { saveConfig } from "../../src/config"; +import { startServer } from "../../src/server"; +import type { OcxConfig } from "../../src/types"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testDir = ""; let previousHome: string | undefined; diff --git a/tests/provider-capacity.test.ts b/tests/providers/provider-capacity.test.ts similarity index 99% rename from tests/provider-capacity.test.ts rename to tests/providers/provider-capacity.test.ts index 978cb39bc8..5c3f9bf918 100644 --- a/tests/provider-capacity.test.ts +++ b/tests/providers/provider-capacity.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { aggregateCodexPoolCapacity, CODEX_CAPACITY_MAX_QUOTA_AGE_MS, type CodexCapacityAccount } from "../src/providers/codex-capacity"; +import { aggregateCodexPoolCapacity, CODEX_CAPACITY_MAX_QUOTA_AGE_MS, type CodexCapacityAccount } from "../../src/providers/codex-capacity"; const NOW = 1_800_000_000_000; const account = ( diff --git a/tests/provider-config-batch-management.test.ts b/tests/providers/provider-config-batch-management.test.ts similarity index 95% rename from tests/provider-config-batch-management.test.ts rename to tests/providers/provider-config-batch-management.test.ts index 250c1e5afd..ae3af067f5 100644 --- a/tests/provider-config-batch-management.test.ts +++ b/tests/providers/provider-config-batch-management.test.ts @@ -2,16 +2,16 @@ import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test"; import { mkdirSync, mkdtempSync, readFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import * as configModule from "../src/config"; -import { getConfigPath, loadConfig, saveConfig } from "../src/config"; -import * as destinationPolicy from "../src/lib/destination-policy"; -import { safeConfigDTO } from "../src/server/auth-cors"; -import { handleManagementAPI } from "../src/server/management-api"; -import type { OcxConfig } from "../src/types"; -import { catalogConvergenceFactory } from "./helpers/catalog-convergence"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { ManagementRequest as Request } from "./helpers/management-auth"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import * as configModule from "../../src/config"; +import { getConfigPath, loadConfig, saveConfig } from "../../src/config"; +import * as destinationPolicy from "../../src/lib/destination-policy"; +import { safeConfigDTO } from "../../src/server/auth-cors"; +import { handleManagementAPI } from "../../src/server/management-api"; +import type { OcxConfig } from "../../src/types"; +import { catalogConvergenceFactory } from "../helpers/catalog-convergence"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { ManagementRequest as Request } from "../helpers/management-auth"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; type EditorConfig = { defaultProvider: string; diff --git a/tests/provider-config-validation.test.ts b/tests/providers/provider-config-validation.test.ts similarity index 99% rename from tests/provider-config-validation.test.ts rename to tests/providers/provider-config-validation.test.ts index 73238884e4..fc3a2808ca 100644 --- a/tests/provider-config-validation.test.ts +++ b/tests/providers/provider-config-validation.test.ts @@ -12,7 +12,7 @@ import { providerHeadersConfigError, reasoningSummaryDeliveryRecordConfigError, upstreamHttpVersionConfigError, -} from "../src/config/provider-validation"; +} from "../../src/config/provider-validation"; describe("provider config validation leaf", () => { test("accepts only credential-free HTTP(S) base URLs", () => { diff --git a/tests/provider-connection-test.test.ts b/tests/providers/provider-connection-test.test.ts similarity index 96% rename from tests/provider-connection-test.test.ts rename to tests/providers/provider-connection-test.test.ts index 892b45bef4..aefcad49c9 100644 --- a/tests/provider-connection-test.test.ts +++ b/tests/providers/provider-connection-test.test.ts @@ -2,15 +2,15 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync} from "node:fs"; import { join } from "node:path"; import { tmpdir } from "node:os"; -import { setFetchCursorUsableModelsForTests } from "../src/adapters/cursor/live-models"; -import { handleManagementAPI } from "../src/server/management-api"; -import { saveConfig } from "../src/config"; -import { OAUTH_PROVIDERS } from "../src/oauth"; -import { saveCredential } from "../src/oauth/store"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import type { OcxConfig } from "../src/types"; -import { withRegistryDiscovery } from "./helpers/provider-registry-discovery"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { setFetchCursorUsableModelsForTests } from "../../src/adapters/cursor/live-models"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { saveConfig } from "../../src/config"; +import { OAUTH_PROVIDERS } from "../../src/oauth"; +import { saveCredential } from "../../src/oauth/store"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import type { OcxConfig } from "../../src/types"; +import { withRegistryDiscovery } from "../helpers/provider-registry-discovery"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(tmpdir(), "ocx-conn-test"); const previousHome = process.env.OPENCODEX_HOME; @@ -411,4 +411,4 @@ describe("POST /api/oauth/login/cancel (WP040)", () => { expect(ok.body).toEqual({ ok: true, cancelled: false }); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/provider-cost-overlay-config.test.ts b/tests/providers/provider-cost-overlay-config.test.ts similarity index 98% rename from tests/provider-cost-overlay-config.test.ts rename to tests/providers/provider-cost-overlay-config.test.ts index eb721ee07f..011e74c014 100644 --- a/tests/provider-cost-overlay-config.test.ts +++ b/tests/providers/provider-cost-overlay-config.test.ts @@ -8,11 +8,11 @@ import { providerModelCostsConfigError, saveConfig, validateConfigCandidate, -} from "../src/config"; -import { providerManagementConfigError, safeConfigDTO } from "../src/server/auth-cors"; -import { activeUserCostOverlays, refreshUserCostOverlays, userCostOverlayVersion } from "../src/usage/user-cost-overlays"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/config"; +import { providerManagementConfigError, safeConfigDTO } from "../../src/server/auth-cors"; +import { activeUserCostOverlays, refreshUserCostOverlays, userCostOverlayVersion } from "../../src/usage/user-cost-overlays"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const VALID_COSTS = { "deepseek-v4-flash": { input: 0.14, output: 0.28, cacheRead: 0.0028, cacheWrite: 0 }, diff --git a/tests/provider-discovery-log-suppression.test.ts b/tests/providers/provider-discovery-log-suppression.test.ts similarity index 98% rename from tests/provider-discovery-log-suppression.test.ts rename to tests/providers/provider-discovery-log-suppression.test.ts index ad803a4a34..b9d69729e3 100644 --- a/tests/provider-discovery-log-suppression.test.ts +++ b/tests/providers/provider-discovery-log-suppression.test.ts @@ -4,7 +4,7 @@ import { markProviderDiscoveryFailed, markProviderDiscoveryOk, shouldLogDiscoveryFailure, -} from "../src/codex/model-cache"; +} from "../../src/codex/model-cache"; const P = "azure-foundry-anthropic"; diff --git a/tests/provider-id-rewrite.test.ts b/tests/providers/provider-id-rewrite.test.ts similarity index 97% rename from tests/provider-id-rewrite.test.ts rename to tests/providers/provider-id-rewrite.test.ts index 5c6fc5a8b0..1df8753b82 100644 --- a/tests/provider-id-rewrite.test.ts +++ b/tests/providers/provider-id-rewrite.test.ts @@ -1,8 +1,8 @@ import { expect, test } from "bun:test"; -import { comboConfigError } from "../src/combos"; -import { providerContextCap } from "../src/providers/context-cap"; -import { dropProviderCustomModels, rewriteProviderReferences } from "../src/providers/provider-id-rewrite"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { comboConfigError } from "../../src/combos"; +import { providerContextCap } from "../../src/providers/context-cap"; +import { dropProviderCustomModels, rewriteProviderReferences } from "../../src/providers/provider-id-rewrite"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; const FROM = "alibaba-token-plan"; const TO = "alibaba-token-plan-intl"; diff --git a/tests/provider-key-store.test.ts b/tests/providers/provider-key-store.test.ts similarity index 94% rename from tests/provider-key-store.test.ts rename to tests/providers/provider-key-store.test.ts index 94fe8e313f..645920e32c 100644 --- a/tests/provider-key-store.test.ts +++ b/tests/providers/provider-key-store.test.ts @@ -2,8 +2,8 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync, readFileSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { loadConfig, saveConfig } from "../src/config"; -import { maskApiKey } from "../src/providers/api-keys"; +import { loadConfig, saveConfig } from "../../src/config"; +import { maskApiKey } from "../../src/providers/api-keys"; import { PROVIDER_KEYCHAIN_SERVICE, probeProviderKeychain, @@ -13,13 +13,13 @@ import { setProviderKeychainEntryFactoryForTests, storeProviderKeyInKeychain, type ProviderKeychainEntry, -} from "../src/providers/key-store"; -import { routedProviderConfig } from "../src/router"; -import { managementFetch as fetch } from "./helpers/management-auth"; -import { startServer } from "../src/server"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/key-store"; +import { routedProviderConfig } from "../../src/router"; +import { managementFetch as fetch } from "../helpers/management-auth"; +import { startServer } from "../../src/server"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** In-memory keychain: service/account → secret, with optional fault injection. */ function fakeKeychain(options: { unavailable?: boolean; readBackMismatch?: boolean } = {}) { diff --git a/tests/provider-live-models.test.ts b/tests/providers/provider-live-models.test.ts similarity index 98% rename from tests/provider-live-models.test.ts rename to tests/providers/provider-live-models.test.ts index d3958e8606..ea7b8249a0 100644 --- a/tests/provider-live-models.test.ts +++ b/tests/providers/provider-live-models.test.ts @@ -1,7 +1,7 @@ import { afterEach, describe, expect, spyOn, test } from "bun:test"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; // Phase 2 of devlog/model_update/260709_model_refresh: live /models discovery is the // authoritative lineup; static config lists are the fallback seed. These tests pin the diff --git a/tests/provider-model-aliases.test.ts b/tests/providers/provider-model-aliases.test.ts similarity index 94% rename from tests/provider-model-aliases.test.ts rename to tests/providers/provider-model-aliases.test.ts index dda94842a8..4ecc4198e1 100644 --- a/tests/provider-model-aliases.test.ts +++ b/tests/providers/provider-model-aliases.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { effectiveModelAliases } from "../src/providers/default-aliases"; -import { routeModel } from "../src/router"; -import type { OcxConfig } from "../src/types"; +import { effectiveModelAliases } from "../../src/providers/default-aliases"; +import { routeModel } from "../../src/router"; +import type { OcxConfig } from "../../src/types"; function config(): OcxConfig { return { diff --git a/tests/provider-model-discovery-contract.test.ts b/tests/providers/provider-model-discovery-contract.test.ts similarity index 96% rename from tests/provider-model-discovery-contract.test.ts rename to tests/providers/provider-model-discovery-contract.test.ts index a78977d161..a4a5d6ec43 100644 --- a/tests/provider-model-discovery-contract.test.ts +++ b/tests/providers/provider-model-discovery-contract.test.ts @@ -1,30 +1,31 @@ import { afterEach, describe, expect, spyOn, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { catalogHintsFromModelsApiItem } from "../src/codex/catalog/provider-fetch"; -import { clearModelCache, getFreshCached, setCached } from "../src/codex/model-cache"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; -import { deriveKeyLoginMap, providerConfigSeed } from "../src/providers/derive"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { catalogHintsFromModelsApiItem } from "../../src/codex/catalog/provider-fetch"; +import { clearModelCache, getFreshCached, setCached } from "../../src/codex/model-cache"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; +import { deriveKeyLoginMap, providerConfigSeed } from "../../src/providers/derive"; import { extractProviderModelItems, providerModelDiscoverySpecError, readBoundedDiscoveryJson, resolveProviderModelDiscovery, resolveProviderModelDiscoveryUrl, -} from "../src/providers/model-discovery"; +} from "../../src/providers/model-discovery"; import { PROVIDER_REGISTRY, registryEntryForProviderDestination, type ProviderModelDiscoverySpec, -} from "../src/providers/registry"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import { withRegistryDiscovery } from "./helpers/provider-registry-discovery"; - -const FIXTURE = readFileSync(join(import.meta.dir, "fixtures/provider-model-discovery.json"), "utf8"); +} from "../../src/providers/registry"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { withRegistryDiscovery } from "../helpers/provider-registry-discovery"; +import { fixturePath } from "../helpers/repo-root"; + +const FIXTURE = readFileSync(fixturePath("provider-model-discovery.json"), "utf8"); const originalFetch = globalThis.fetch; afterEach(() => { diff --git a/tests/provider-outbound-private-network.test.ts b/tests/providers/provider-outbound-private-network.test.ts similarity index 97% rename from tests/provider-outbound-private-network.test.ts rename to tests/providers/provider-outbound-private-network.test.ts index 3c17d307b3..54e3f46eaf 100644 --- a/tests/provider-outbound-private-network.test.ts +++ b/tests/providers/provider-outbound-private-network.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { providerOutboundGet, ProviderOutboundPolicyError } from "../src/lib/provider-outbound"; -import { resolvePublicAddresses } from "../src/lib/destination-policy"; +import { providerOutboundGet, ProviderOutboundPolicyError } from "../../src/lib/provider-outbound"; +import { resolvePublicAddresses } from "../../src/lib/destination-policy"; /** * #758: a stock Ollama provider passed config validation -- which consults the registry's diff --git a/tests/provider-outbound.test.ts b/tests/providers/provider-outbound.test.ts similarity index 94% rename from tests/provider-outbound.test.ts rename to tests/providers/provider-outbound.test.ts index d7d9bd1631..5cf7d60039 100644 --- a/tests/provider-outbound.test.ts +++ b/tests/providers/provider-outbound.test.ts @@ -2,9 +2,9 @@ import { afterEach, describe, expect, mock, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import type { ProviderOutboundDependencies } from "../src/lib/provider-outbound"; -import { PROXY_ENV_KEYS } from "../src/lib/proxy-env"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import type { ProviderOutboundDependencies } from "../../src/lib/provider-outbound"; +import { PROXY_ENV_KEYS } from "../../src/lib/proxy-env"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const proxyKeys = PROXY_ENV_KEYS.flatMap(key => [key, key.toLowerCase()]); const originalProxyEnv = Object.fromEntries(proxyKeys.map(key => [key, process.env[key]])); @@ -54,7 +54,7 @@ function directDependencies( describe("provider outbound GET transport", () => { test("direct HTTPS connects only to the validated address with TLS verification", async () => { for (const key of proxyKeys) delete process.env[key]; - const { providerOutboundGet } = await import("../src/lib/provider-outbound"); + const { providerOutboundGet } = await import("../../src/lib/provider-outbound"); const { dependencies, captured } = directDependencies(new Response('{"data":[]}', { status: 200, headers: { "content-type": "application/json" }, @@ -82,7 +82,7 @@ describe("provider outbound GET transport", () => { process.env.https_proxy = proxyUrl; process.env.NO_PROXY = "localhost,127.0.0.1,::1,[::1]"; process.env.no_proxy = "localhost,127.0.0.1,::1,[::1]"; - const { providerOutboundGet } = await import("../src/lib/provider-outbound"); + const { providerOutboundGet } = await import("../../src/lib/provider-outbound"); const { dependencies, captured } = directDependencies(new Response(null, { status: 200 }), { privateNetwork: true, address: "192.168.1.50", @@ -115,7 +115,7 @@ describe("provider outbound GET transport", () => { }) as typeof fetch; globalThis.fetch = fetchMock; try { - const { providerOutboundGet } = await import("../src/lib/provider-outbound"); + const { providerOutboundGet } = await import("../../src/lib/provider-outbound"); const resolveOptions: { allowBenchmarkAddresses?: boolean }[] = []; const { dependencies, captured } = directDependencies(new Response(null, { status: 500 })); const innerResolve = dependencies.resolveAddresses!; @@ -151,7 +151,7 @@ describe("provider outbound GET transport", () => { test("Clash fake-IP without a configured proxy is not granted the benchmark opt-in (#1748)", async () => { for (const key of proxyKeys) delete process.env[key]; - const { providerOutboundGet } = await import("../src/lib/provider-outbound"); + const { providerOutboundGet } = await import("../../src/lib/provider-outbound"); const resolveOptions: { allowBenchmarkAddresses?: boolean }[] = []; const { dependencies, captured } = directDependencies(new Response(null, { status: 500 })); dependencies.resolveAddresses = mock(async (_url: string, options?: { allowBenchmarkAddresses?: boolean }) => { @@ -181,7 +181,7 @@ describe("provider outbound GET transport", () => { const fetchMock = mock(async () => new Response("unexpected", { status: 500 })) as typeof fetch; globalThis.fetch = fetchMock; try { - const { providerOutboundGet } = await import("../src/lib/provider-outbound"); + const { providerOutboundGet } = await import("../../src/lib/provider-outbound"); const resolveOptions: { allowBenchmarkAddresses?: boolean }[] = []; const { dependencies, captured } = directDependencies(new Response(null, { status: 500 })); dependencies.resolveAddresses = mock(async (_url: string, options?: { allowBenchmarkAddresses?: boolean }) => { @@ -207,7 +207,7 @@ describe("provider outbound GET transport", () => { test("built-in ollama admits loopback discovery without an explicit allowPrivateNetwork flag (#758)", async () => { for (const key of proxyKeys) delete process.env[key]; - const { providerOutboundGet } = await import("../src/lib/provider-outbound"); + const { providerOutboundGet } = await import("../../src/lib/provider-outbound"); let sawAllowPrivate: boolean | undefined; const dependencies: ProviderOutboundDependencies = { resolveAddresses: mock(async (_url, options) => { @@ -240,7 +240,7 @@ describe("provider outbound GET transport", () => { const redirectTarget = new URL("https://final.example/v1/models?token=secret#fragment"); redirectTarget.username = "user"; redirectTarget.password = "password"; - const { providerOutboundGet, providerRedirectError } = await import("../src/lib/provider-outbound"); + const { providerOutboundGet, providerRedirectError } = await import("../../src/lib/provider-outbound"); const { dependencies } = directDependencies(new Response(null, { status: 302, headers: { location: redirectTarget.toString() }, @@ -275,7 +275,7 @@ describe("provider outbound GET transport", () => { baseUrl: "https://override.example/v1", fetch: override, } as { baseUrl: string; fetch: typeof fetch }; - const { providerOutboundGet } = await import("../src/lib/provider-outbound"); + const { providerOutboundGet } = await import("../../src/lib/provider-outbound"); const response = await providerOutboundGet( "override", @@ -357,7 +357,7 @@ describe("provider outbound GET transport", () => { describe("provider outbound POST transport", () => { test("direct HTTPS posts only to the validated address with its credential and body", async () => { for (const key of proxyKeys) delete process.env[key]; - const { providerOutboundPost } = await import("../src/lib/provider-outbound"); + const { providerOutboundPost } = await import("../../src/lib/provider-outbound"); const { dependencies, captured } = directDependencies(new Response('{"models":{}}', { status: 200, headers: { "content-type": "application/json" }, @@ -382,7 +382,7 @@ describe("provider outbound POST transport", () => { }); test("blocks an unsafe POST destination before invoking a caller-owned executor", async () => { - const { providerOutboundPost, ProviderOutboundPolicyError } = await import("../src/lib/provider-outbound"); + const { providerOutboundPost, ProviderOutboundPolicyError } = await import("../../src/lib/provider-outbound"); let calls = 0; const provider = { baseUrl: "https://provider.example", @@ -402,7 +402,7 @@ describe("provider outbound POST transport", () => { }); test("requires HTTPS before invoking a caller-owned executor", async () => { - const { providerOutboundPost, ProviderOutboundPolicyError } = await import("../src/lib/provider-outbound"); + const { providerOutboundPost, ProviderOutboundPolicyError } = await import("../../src/lib/provider-outbound"); let calls = 0; const provider = { baseUrl: "https://provider.example", diff --git a/tests/provider-quota-observed-marker.test.ts b/tests/providers/provider-quota-observed-marker.test.ts similarity index 93% rename from tests/provider-quota-observed-marker.test.ts rename to tests/providers/provider-quota-observed-marker.test.ts index 4925acfebf..d9c36bedf8 100644 --- a/tests/provider-quota-observed-marker.test.ts +++ b/tests/providers/provider-quota-observed-marker.test.ts @@ -12,16 +12,16 @@ import { afterEach, beforeEach, expect, test } from "bun:test"; import { mkdtempSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveCredential } from "../src/oauth/store"; +import { saveCredential } from "../../src/oauth/store"; import { clearAccountQuotaCache, clearProviderQuotaCache, fetchProviderQuotaReports, recordPassiveAccountQuota, -} from "../src/providers/quota"; -import { captureConfigGeneration } from "../src/lib/state-store-sweeper"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; -import type { OcxConfig } from "../src/types"; +} from "../../src/providers/quota"; +import { captureConfigGeneration } from "../../src/lib/state-store-sweeper"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import type { OcxConfig } from "../../src/types"; const originalHome = process.env.OPENCODEX_HOME; const originalFetch = globalThis.fetch; @@ -71,7 +71,7 @@ async function seedObservation(ageMs: number): Promise { accountId: "muse-account", email: "muse@example.test", }); - const { getAccountSet } = await import("../src/oauth/store"); + const { getAccountSet } = await import("../../src/oauth/store"); const accountId = getAccountSet("meta-muse")!.accounts[0]!.id; recordPassiveAccountQuota("meta-muse", accountId, { fiveHourPercent: 1, diff --git a/tests/provider-quota.test.ts b/tests/providers/provider-quota.test.ts similarity index 99% rename from tests/provider-quota.test.ts rename to tests/providers/provider-quota.test.ts index 4c659df5b8..582b03b457 100644 --- a/tests/provider-quota.test.ts +++ b/tests/providers/provider-quota.test.ts @@ -1,15 +1,15 @@ import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test"; import { existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import * as authApi from "../src/codex/auth-api"; -import { clearAccountNeedsReauth, markAccountNeedsReauth } from "../src/codex/account-runtime-state"; -import { clearMainAccountInfoCache } from "../src/codex/main-account-cache"; -import { clearAccountQuota, updateAccountQuota } from "../src/codex/quota"; -import { clearCodexUpstreamHealth } from "../src/codex/routing"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { saveCredential } from "../src/oauth/store"; +import * as authApi from "../../src/codex/auth-api"; +import { clearAccountNeedsReauth, markAccountNeedsReauth } from "../../src/codex/account-runtime-state"; +import { clearMainAccountInfoCache } from "../../src/codex/main-account-cache"; +import { clearAccountQuota, updateAccountQuota } from "../../src/codex/quota"; +import { clearCodexUpstreamHealth } from "../../src/codex/routing"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { saveCredential } from "../../src/oauth/store"; import { clearProviderQuotaCache, fetchProviderQuotaReports, @@ -17,8 +17,9 @@ import { QUOTA_RESPONSE_MAX_BYTES, readProviderQuotaJsonForTests, setProviderQuotaBeforePublishForTests, -} from "../src/providers/quota"; -import type { OcxConfig } from "../src/types"; +} from "../../src/providers/quota"; +import type { OcxConfig } from "../../src/types"; +import { repoPath } from "../helpers/repo-root"; const originalFetch = globalThis.fetch; const previousOpencodexHome = process.env.OPENCODEX_HOME; const previousCodexHome = process.env.CODEX_HOME; @@ -101,7 +102,7 @@ afterEach(() => { describe("fetchProviderQuotaReports", () => { test("provider quota probes have no direct Response.json calls", () => { - const source = readFileSync(join(import.meta.dir, "../src/providers/quota.ts"), "utf8"); + const source = readFileSync(repoPath("src/providers/quota.ts"), "utf8"); expect(source).not.toMatch(/\.\s*json\s*\(/); }); diff --git a/tests/provider-registry-parity.test.ts b/tests/providers/provider-registry-parity.test.ts similarity index 98% rename from tests/provider-registry-parity.test.ts rename to tests/providers/provider-registry-parity.test.ts index 2ed9856cd6..ecfb66e88e 100644 --- a/tests/provider-registry-parity.test.ts +++ b/tests/providers/provider-registry-parity.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from "bun:test"; -import { buildCatalogEntries } from "../src/codex/catalog"; -import { CURSOR_NO_VISION_MODELS } from "../src/adapters/cursor/discovery"; -import { getModelMetadata, resolveMetadataProvider } from "../src/generated/model-metadata"; -import { buildInitProviders } from "../src/cli/init"; -import { OAUTH_PROVIDERS } from "../src/oauth"; -import { enrichProviderFromCatalog, KEY_LOGIN_PROVIDERS } from "../src/oauth/key-providers"; +import { buildCatalogEntries } from "../../src/codex/catalog"; +import { CURSOR_NO_VISION_MODELS } from "../../src/adapters/cursor/discovery"; +import { getModelMetadata, resolveMetadataProvider } from "../../src/generated/model-metadata"; +import { buildInitProviders } from "../../src/cli/init"; +import { OAUTH_PROVIDERS } from "../../src/oauth"; +import { enrichProviderFromCatalog, KEY_LOGIN_PROVIDERS } from "../../src/oauth/key-providers"; import { deriveFeaturedProviderIds, deriveInitProviders, @@ -12,13 +12,13 @@ import { deriveKeyLoginMap, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { FREE_PROVIDER_DIRECTORY } from "../src/providers/free-directory"; -import { applyProviderConfigHints } from "../src/codex/catalog"; -import { routeModel } from "../src/router"; -import { resolveAdapter } from "../src/server"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +} from "../../src/providers/derive"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { FREE_PROVIDER_DIRECTORY } from "../../src/providers/free-directory"; +import { applyProviderConfigHints } from "../../src/codex/catalog"; +import { routeModel } from "../../src/router"; +import { resolveAdapter } from "../../src/server"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; function nativeTemplate(): Record { return { @@ -603,7 +603,7 @@ describe("provider registry parity", () => { }); test("freeTier propagates through config seed, enrich backfill, and presets without overwriting user config", async () => { - const { enrichProviderFromRegistry } = await import("../src/providers/derive"); + const { enrichProviderFromRegistry } = await import("../../src/providers/derive"); const nvidia = PROVIDER_REGISTRY.find(entry => entry.id === "nvidia")!; // Seed propagation. diff --git a/tests/provider-static-model-discovery.test.ts b/tests/providers/provider-static-model-discovery.test.ts similarity index 94% rename from tests/provider-static-model-discovery.test.ts rename to tests/providers/provider-static-model-discovery.test.ts index 01cc31b883..88006aaf3e 100644 --- a/tests/provider-static-model-discovery.test.ts +++ b/tests/providers/provider-static-model-discovery.test.ts @@ -1,14 +1,14 @@ import { describe, expect, test } from "bun:test"; -import { createMimoFreeAdapter, MIMO_CHAT_URL } from "../src/adapters/mimo-free"; -import { enrichProviderFromRegistry, providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; +import { createMimoFreeAdapter, MIMO_CHAT_URL } from "../../src/adapters/mimo-free"; +import { enrichProviderFromRegistry, providerConfigSeed } from "../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; import { providerMatchesRegistryTransportWithStaticGuards, providerSupportsLiveModelDiscovery, registryEntrySupportsLiveModelDiscovery, -} from "../src/providers/static-model-discovery"; -import { routedProviderConfig } from "../src/router"; -import type { OcxProviderConfig } from "../src/types"; +} from "../../src/providers/static-model-discovery"; +import { routedProviderConfig } from "../../src/router"; +import type { OcxProviderConfig } from "../../src/types"; function provider(overrides: Partial): OcxProviderConfig { return { diff --git a/tests/qwen38-preserve-reasoning.test.ts b/tests/providers/qwen38-preserve-reasoning.test.ts similarity index 94% rename from tests/qwen38-preserve-reasoning.test.ts rename to tests/providers/qwen38-preserve-reasoning.test.ts index a14d1d7513..237e681cd6 100644 --- a/tests/qwen38-preserve-reasoning.test.ts +++ b/tests/providers/qwen38-preserve-reasoning.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../src/types"; function provider(overrides: Partial = {}): OcxProviderConfig { return { @@ -103,7 +103,7 @@ describe("Qwen 3.8 reasoning_content preservation", () => { }); test("registry includes qwen3.8-max in alibaba-token-plan preserveReasoningContentModels", async () => { - const { PROVIDER_REGISTRY } = await import("../src/providers/registry"); + const { PROVIDER_REGISTRY } = await import("../../src/providers/registry"); const alibaba = PROVIDER_REGISTRY.find(e => e.id === "alibaba-token-plan"); expect(alibaba).toBeDefined(); expect(alibaba!.preserveReasoningContentModels).toContain("qwen3.8-max"); diff --git a/tests/rate-limit-retry.test.ts b/tests/providers/rate-limit-retry.test.ts similarity index 98% rename from tests/rate-limit-retry.test.ts rename to tests/providers/rate-limit-retry.test.ts index 244d244f17..709ccdae12 100644 --- a/tests/rate-limit-retry.test.ts +++ b/tests/providers/rate-limit-retry.test.ts @@ -2,9 +2,9 @@ import { afterEach, describe, expect, test } from "bun:test"; import { rateLimitRetryDelayMs, rateLimitRetryPolicyFor, -} from "../src/providers/key-failover"; -import { handleResponses } from "../src/server/responses"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +} from "../../src/providers/key-failover"; +import { handleResponses } from "../../src/server/responses"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; describe("rateLimitRetryPolicyFor", () => { test("null when absent or explicitly disabled", () => { diff --git a/tests/sambanova-nebius-provider.test.ts b/tests/providers/sambanova-nebius-provider.test.ts similarity index 92% rename from tests/sambanova-nebius-provider.test.ts rename to tests/providers/sambanova-nebius-provider.test.ts index 9313daf9e5..2aa3892d76 100644 --- a/tests/sambanova-nebius-provider.test.ts +++ b/tests/providers/sambanova-nebius-provider.test.ts @@ -1,27 +1,28 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { FREE_PROVIDER_DIRECTORY } from "../src/providers/free-directory"; -import { resolveProviderModelDiscovery } from "../src/providers/model-discovery"; -import { PROVIDER_REGISTRY, type ProviderRegistryEntry } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; +} from "../../src/providers/derive"; +import { FREE_PROVIDER_DIRECTORY } from "../../src/providers/free-directory"; +import { resolveProviderModelDiscovery } from "../../src/providers/model-discovery"; +import { PROVIDER_REGISTRY, type ProviderRegistryEntry } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; -const SAMBANOVA_FIXTURE = readFileSync(join(import.meta.dir, "fixtures/sambanova-models.json"), "utf8"); -const NEBIUS_FIXTURE = readFileSync(join(import.meta.dir, "fixtures/nebius-models.json"), "utf8"); +const SAMBANOVA_FIXTURE = readFileSync(fixturePath("sambanova-models.json"), "utf8"); +const NEBIUS_FIXTURE = readFileSync(fixturePath("nebius-models.json"), "utf8"); const originalFetch = globalThis.fetch; type ProviderId = "sambanova" | "nebius"; diff --git a/tests/umans-provider.test.ts b/tests/providers/umans-provider.test.ts similarity index 97% rename from tests/umans-provider.test.ts rename to tests/providers/umans-provider.test.ts index 3654177d75..755b50570a 100644 --- a/tests/umans-provider.test.ts +++ b/tests/providers/umans-provider.test.ts @@ -1,9 +1,9 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { createAnthropicAdapter as createAnthropicAdapterProduction } from "../src/adapters/anthropic"; -import { providerConfigFromKeyLoginProvider } from "../src/oauth/login-cli"; -import { enrichProviderFromCatalog, KEY_LOGIN_PROVIDERS, validateApiKey, type KeyLoginProvider } from "../src/oauth/key-providers"; -import type { AdapterEvent, OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { createAnthropicAdapter as createAnthropicAdapterProduction } from "../../src/adapters/anthropic"; +import { providerConfigFromKeyLoginProvider } from "../../src/oauth/login-cli"; +import { enrichProviderFromCatalog, KEY_LOGIN_PROVIDERS, validateApiKey, type KeyLoginProvider } from "../../src/oauth/key-providers"; +import type { AdapterEvent, OcxParsedRequest, OcxProviderConfig } from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; const createAnthropicAdapter = (...args: Parameters) => withTestTranslatorBudget(createAnthropicAdapterProduction(...args)); diff --git a/tests/upstream-transient-retry.test.ts b/tests/providers/upstream-transient-retry.test.ts similarity index 98% rename from tests/upstream-transient-retry.test.ts rename to tests/providers/upstream-transient-retry.test.ts index 420060b02e..58199ac55a 100644 --- a/tests/upstream-transient-retry.test.ts +++ b/tests/providers/upstream-transient-retry.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { fetchWithTransientRetry, isTransientUpstreamStatus } from "../src/lib/upstream-retry"; -import { transientRetryPolicyFor } from "../src/providers/key-failover"; -import type { OcxProviderConfig } from "../src/types"; +import { fetchWithTransientRetry, isTransientUpstreamStatus } from "../../src/lib/upstream-retry"; +import { transientRetryPolicyFor } from "../../src/providers/key-failover"; +import type { OcxProviderConfig } from "../../src/types"; function bodyResponse(status: number, headers?: Record): Response { // ReadableStream body so cancel() is observable. diff --git a/tests/vercel-gateway-provider-routing.test.ts b/tests/providers/vercel-gateway-provider-routing.test.ts similarity index 96% rename from tests/vercel-gateway-provider-routing.test.ts rename to tests/providers/vercel-gateway-provider-routing.test.ts index d031ba61c9..dbe11aad67 100644 --- a/tests/vercel-gateway-provider-routing.test.ts +++ b/tests/providers/vercel-gateway-provider-routing.test.ts @@ -1,13 +1,13 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter, buildOpenAIChatPassthroughRequest } from "../src/adapters/openai-chat"; +import { createOpenAIChatAdapter, buildOpenAIChatPassthroughRequest } from "../../src/adapters/openai-chat"; import { vercelGatewayRoutingConfigError, vercelGatewayProviderPayload, -} from "../src/providers/vercel-gateway-routing"; -import { fastPolicyForModel } from "../src/providers/service-tier"; -import { routeModel } from "../src/router"; -import { safeConfigDTO, providerManagementConfigError } from "../src/server/auth-cors"; -import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../src/types"; +} from "../../src/providers/vercel-gateway-routing"; +import { fastPolicyForModel } from "../../src/providers/service-tier"; +import { routeModel } from "../../src/router"; +import { safeConfigDTO, providerManagementConfigError } from "../../src/server/auth-cors"; +import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../../src/types"; function provider(baseUrl: string, overrides: Partial = {}): OcxProviderConfig { return { adapter: "openai-chat", baseUrl, apiKey: "test-key", ...overrides }; diff --git a/tests/volcengine-ark-assistant-content.test.ts b/tests/providers/volcengine-ark-assistant-content.test.ts similarity index 98% rename from tests/volcengine-ark-assistant-content.test.ts rename to tests/providers/volcengine-ark-assistant-content.test.ts index 992bb5f35c..cb48dc2a19 100644 --- a/tests/volcengine-ark-assistant-content.test.ts +++ b/tests/providers/volcengine-ark-assistant-content.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import type { OcxMessage, OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import type { OcxMessage, OcxParsedRequest, OcxProviderConfig } from "../../src/types"; /** * #796: Volcengine Ark validates an assistant message's text as a REQUIRED parameter and treats diff --git a/tests/grok-attribution.test.ts b/tests/providers/xai/grok-attribution.test.ts similarity index 88% rename from tests/grok-attribution.test.ts rename to tests/providers/xai/grok-attribution.test.ts index 29281fc59f..25c43a4e1a 100644 --- a/tests/grok-attribution.test.ts +++ b/tests/providers/xai/grok-attribution.test.ts @@ -2,11 +2,11 @@ import { expect, test } from "bun:test"; import { mkdirSync, mkdtempSync, readFileSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { buildGrokManagedBlock, injectGrokConfig } from "../src/grok/inject"; -import { handleChatCompletions } from "../src/server/chat-completions"; -import type { RequestLogContext } from "../src/server/request-log"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { buildGrokManagedBlock, injectGrokConfig } from "../../../src/grok/inject"; +import { handleChatCompletions } from "../../../src/server/chat-completions"; +import type { RequestLogContext } from "../../../src/server/request-log"; +import type { OcxConfig } from "../../../src/types"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; /** * D3 activation evidence: the fence stamps `x-opencodex-grok` on every registered diff --git a/tests/grok-config-inject.test.ts b/tests/providers/xai/grok-config-inject.test.ts similarity index 99% rename from tests/grok-config-inject.test.ts rename to tests/providers/xai/grok-config-inject.test.ts index a5f08c66d0..9c6b0d02de 100644 --- a/tests/grok-config-inject.test.ts +++ b/tests/providers/xai/grok-config-inject.test.ts @@ -2,8 +2,8 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { buildGrokManagedBlock, injectGrokConfig, stripGrokConfig } from "../src/grok/inject"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { buildGrokManagedBlock, injectGrokConfig, stripGrokConfig } from "../../../src/grok/inject"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const BEGIN_MARKER = "# >>> opencodex managed block — do not edit (removed by `ocx stop`) >>>"; const END_MARKER = "# <<< opencodex managed block <<<"; diff --git a/tests/grok-effort-inject.test.ts b/tests/providers/xai/grok-effort-inject.test.ts similarity index 96% rename from tests/grok-effort-inject.test.ts rename to tests/providers/xai/grok-effort-inject.test.ts index 680e1fe268..179bfc5dae 100644 --- a/tests/grok-effort-inject.test.ts +++ b/tests/providers/xai/grok-effort-inject.test.ts @@ -6,19 +6,19 @@ import { nativeDefaultReasoningEffort, nativeReasoningEfforts, type CatalogModel, -} from "../src/codex/catalog"; +} from "../../../src/codex/catalog"; import { resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests, -} from "../src/codex/model-entitlements"; -import { buildGrokManagedBlock, injectGrokConfig, type GrokInjectModel } from "../src/grok/inject"; -import { grokDefaultReasoningEffort, sanitizeGrokReasoningEfforts } from "../src/grok/effort"; -import { buildGrokInjectModels } from "../src/grok/models"; -import { syncGrokConfig } from "../src/grok/sync"; -import { handleManagementAPI } from "../src/server/management-api"; -import type { ManagementApiDeps } from "../src/server/management/context"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/codex/model-entitlements"; +import { buildGrokManagedBlock, injectGrokConfig, type GrokInjectModel } from "../../../src/grok/inject"; +import { grokDefaultReasoningEffort, sanitizeGrokReasoningEfforts } from "../../../src/grok/effort"; +import { buildGrokInjectModels } from "../../../src/grok/models"; +import { syncGrokConfig } from "../../../src/grok/sync"; +import { handleManagementAPI } from "../../../src/server/management-api"; +import type { ManagementApiDeps } from "../../../src/server/management/context"; +import type { OcxConfig } from "../../../src/types"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const NATIVE_SOL = "gpt-5.6-sol"; const ROUTED_WITH_LADDER: CatalogModel = { diff --git a/tests/grok-lifecycle.test.ts b/tests/providers/xai/grok-lifecycle.test.ts similarity index 94% rename from tests/grok-lifecycle.test.ts rename to tests/providers/xai/grok-lifecycle.test.ts index 7166a99dfc..4ae5564cde 100644 --- a/tests/grok-lifecycle.test.ts +++ b/tests/providers/xai/grok-lifecycle.test.ts @@ -1,14 +1,15 @@ import { describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { classifyWindowsServiceStop, installedServiceRespawnRisk, isServiceOwnershipError, ServiceOwnershipError } from "../src/service"; +import { classifyWindowsServiceStop, installedServiceRespawnRisk, isServiceOwnershipError, ServiceOwnershipError } from "../../../src/service"; +import { repoPath } from "../../helpers/repo-root"; -const CLI_SOURCE = readFileSync(join(import.meta.dir, "..", "src", "cli", "index.ts"), "utf8"); -const ENSURE_SOURCE = readFileSync(join(import.meta.dir, "..", "src", "cli", "ensure-desired-integrations.ts"), "utf8"); -const DISPATCH_SOURCE = readFileSync(join(import.meta.dir, "..", "src", "cli", "dispatch.ts"), "utf8"); -const SERVICE_SOURCE = readFileSync(join(import.meta.dir, "..", "src", "service.ts"), "utf8"); -const MANAGEMENT_SOURCE = readFileSync(join(import.meta.dir, "..", "src", "server", "management-api.ts"), "utf8"); -const PROCESS_CONTROL_SOURCE = readFileSync(join(import.meta.dir, "..", "src", "lib", "process-control.ts"), "utf8"); +const CLI_SOURCE = readFileSync(repoPath("src", "cli", "index.ts"), "utf8"); +const ENSURE_SOURCE = readFileSync(repoPath("src", "cli", "ensure-desired-integrations.ts"), "utf8"); +const DISPATCH_SOURCE = readFileSync(repoPath("src", "cli", "dispatch.ts"), "utf8"); +const SERVICE_SOURCE = readFileSync(repoPath("src", "service.ts"), "utf8"); +const MANAGEMENT_SOURCE = readFileSync(repoPath("src", "server", "management-api.ts"), "utf8"); +const PROCESS_CONTROL_SOURCE = readFileSync(repoPath("src", "lib", "process-control.ts"), "utf8"); function sliceFn(source: string, start: string, end: string): string { const from = source.indexOf(start); @@ -175,7 +176,7 @@ describe("Grok fence lifecycle wiring", () => { test("only Task Scheduler earns the respawn wait", () => { const stopFn = sliceFn(CLI_SOURCE, "async function handleStop(", "async function handleUninstall("); - const serviceSource = readFileSync(join(import.meta.dir, "..", "src", "service.ts"), "utf8"); + const serviceSource = readFileSync(repoPath("src", "service.ts"), "utf8"); // schtasks /end leaves the `cmd :loop` wrapper alive to respawn its child (#764). // launchd, systemd and WinSW are down when they report stopped, so charging them a // seven-second poll on every ocx stop would be a regression in ordinary use. @@ -188,8 +189,8 @@ describe("Grok fence lifecycle wiring", () => { test("ocx stop defers shared teardown so a respawn survivor keeps its config", () => { const stopFn = sliceFn(CLI_SOURCE, "async function handleStop(", "async function handleUninstall("); - const apiSource = readFileSync(join(import.meta.dir, "..", "src", "server", "management-api.ts"), "utf8"); - const controlSource = readFileSync(join(import.meta.dir, "..", "src", "lib", "process-control.ts"), "utf8"); + const apiSource = readFileSync(repoPath("src", "server", "management-api.ts"), "utf8"); + const controlSource = readFileSync(repoPath("src", "lib", "process-control.ts"), "utf8"); // POST /api/stop normally restores native Codex and strips the Grok fence itself. If // ocx stop let it, a scheduler wrapper that respawns seconds later would already have // lost its client config, and the parent ownershipBlocked guard could only prevent a @@ -285,9 +286,9 @@ describe("Grok fence lifecycle wiring", () => { // After a parent crashed mid-deferral the service, pid and runtime records can all be // absent while shared client config still points at a proxy that is gone. Installing // over that skips the recovery the receipt exists to trigger (#3008). - const updateSource = readFileSync(join(import.meta.dir, "..", "src", "update", "index.ts"), "utf8"); + const updateSource = readFileSync(repoPath("src", "update", "index.ts"), "utf8"); expect(updateSource).toContain("readPid() || readRuntimePort() || pendingTeardownOutstanding()"); - const launcherSource = readFileSync(join(import.meta.dir, "..", "bin", "ocx.mjs"), "utf8"); + const launcherSource = readFileSync(repoPath("bin", "ocx.mjs"), "utf8"); // The launcher runs under plain Node, so it shares the naming rule as ESM rather than // spelling it out — which is how it ended up watching the retired singleton filename // after receipts moved to one file per claim, silently seeing none of them. @@ -297,11 +298,11 @@ describe("Grok fence lifecycle wiring", () => { // Checked AFTER the stop too: a quarantined receipt lets the stop succeed, so a // pre-stop check alone let the retry install over a teardown that never ran. expect(launcherSource).toContain("teardownOutstanding: hasPendingTeardownIn(readdirSync, configDir())"); - const updateSource2 = readFileSync(join(import.meta.dir, "..", "src", "update", "index.ts"), "utf8"); + const updateSource2 = readFileSync(repoPath("src", "update", "index.ts"), "utf8"); expect(updateSource2).toContain("teardownOutstanding: pendingTeardownOutstanding()"); - const decisionSource = readFileSync(join(import.meta.dir, "..", "src", "update", "stop-decision.mjs"), "utf8"); + const decisionSource = readFileSync(repoPath("src", "update", "stop-decision.mjs"), "utf8"); expect(decisionSource).toContain('if (teardownOutstanding) return { proceed: false, reason: "teardown-outstanding" };'); - const receiptSource = readFileSync(join(import.meta.dir, "..", "src", "config", "pending-teardown.ts"), "utf8"); + const receiptSource = readFileSync(repoPath("src", "config", "pending-teardown.ts"), "utf8"); expect(receiptSource).toContain('from "./pending-teardown-names.mjs"'); expect(receiptSource).toContain("isPendingTeardownFileName(name)"); }); @@ -384,13 +385,13 @@ describe("POST /api/stop teardown", () => { // the route still delegates to it rather than growing a second copy. const handler = sliceFn(MANAGEMENT_SOURCE, '"/api/stop"', "/api/codex-auth/"); expect(handler).toContain("performStopTeardown(url, { ownsReceipt: deferralMatchesReceipt })"); - const teardownSource = readFileSync(join(import.meta.dir, "..", "src", "server", "stop-teardown.ts"), "utf8"); + const teardownSource = readFileSync(repoPath("src", "server", "stop-teardown.ts"), "utf8"); expect(teardownSource).toContain('await import("../grok/inject")'); expect(teardownSource).toContain("stripGrokConfig()"); }); test("an unreadable scheduler state gets the same diagnosis from the CLI and the API", () => { - const serviceSource = readFileSync(join(import.meta.dir, "..", "src", "service.ts"), "utf8"); + const serviceSource = readFileSync(repoPath("src", "service.ts"), "utf8"); // A manager that refused to stop and a query that could not answer are different // problems: reporting the second as "did not stop" sends the operator looking for the // wrong thing, and `ocx stop` was the command the API told them to run (#3008). @@ -483,7 +484,7 @@ describe("POST /api/stop teardown", () => { }); test("direct service stop and uninstall fail when a shared teardown half fails", () => { - const serviceSource = readFileSync(join(import.meta.dir, "..", "src", "service.ts"), "utf8"); + const serviceSource = readFileSync(repoPath("src", "service.ts"), "utf8"); // These paths logged the failure and exited 0, so a script could not tell a complete // teardown from one that left Grok aimed at a stopped proxy. const stopCase = serviceSource.slice( diff --git a/tests/grok-management-api.test.ts b/tests/providers/xai/grok-management-api.test.ts similarity index 95% rename from tests/grok-management-api.test.ts rename to tests/providers/xai/grok-management-api.test.ts index d8038f9cf0..5afe23efc1 100644 --- a/tests/grok-management-api.test.ts +++ b/tests/providers/xai/grok-management-api.test.ts @@ -1,14 +1,14 @@ import { afterEach, beforeEach, expect, setDefaultTimeout, test } from "bun:test"; -import { managementFetch as fetch } from "./helpers/management-auth"; +import { managementFetch as fetch } from "../../helpers/management-auth"; import { mkdirSync, mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { loadConfig, saveConfig } from "../src/config"; -import { startServer } from "../src/server"; -import type { OcxConfig } from "../src/types"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { GROK_APPLY_TERMINAL_MS, runGrokApplyFlightForTests, setGrokApplyFlightTestHooks } from "../src/server/management/agent-settings-routes"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { loadConfig, saveConfig } from "../../../src/config"; +import { startServer } from "../../../src/server"; +import type { OcxConfig } from "../../../src/types"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../../helpers/isolated-codex-home"; +import { GROK_APPLY_TERMINAL_MS, runGrokApplyFlightForTests, setGrokApplyFlightTestHooks } from "../../../src/server/management/agent-settings-routes"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; // Full-suite Windows load: startServer + management flows often exceed bun's default // 5s per-test budget (same flake class as claude-management-api.test.ts). diff --git a/tests/grok-models-effort-list.test.ts b/tests/providers/xai/grok-models-effort-list.test.ts similarity index 95% rename from tests/grok-models-effort-list.test.ts rename to tests/providers/xai/grok-models-effort-list.test.ts index c64964cef7..65fb31e932 100644 --- a/tests/grok-models-effort-list.test.ts +++ b/tests/providers/xai/grok-models-effort-list.test.ts @@ -2,15 +2,15 @@ import { afterEach, beforeEach, describe, expect, setDefaultTimeout, test } from import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; +import { saveConfig } from "../../../src/config"; import { resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests, -} from "../src/codex/model-entitlements"; -import { startServer } from "../src/server"; -import type { OcxConfig } from "../src/types"; -import { SERVER_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/codex/model-entitlements"; +import { startServer } from "../../../src/server"; +import type { OcxConfig } from "../../../src/types"; +import { SERVER_BUDGET_MS } from "../../helpers/test-budget"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; // These cases start a real server and hit /v1/models. Keep the budget at the // server class so a slow runner does not turn a discovery probe into a flake. diff --git a/tests/grok-orphan-adoption.test.ts b/tests/providers/xai/grok-orphan-adoption.test.ts similarity index 99% rename from tests/grok-orphan-adoption.test.ts rename to tests/providers/xai/grok-orphan-adoption.test.ts index c844f007ec..5017ec3888 100644 --- a/tests/grok-orphan-adoption.test.ts +++ b/tests/providers/xai/grok-orphan-adoption.test.ts @@ -2,8 +2,8 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { injectGrokConfig, stripGrokConfig } from "../src/grok/inject"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { injectGrokConfig, stripGrokConfig } from "../../../src/grok/inject"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; /** * #511 — Grok Build reported 200k for every model. diff --git a/tests/grok-selection.test.ts b/tests/providers/xai/grok-selection.test.ts similarity index 94% rename from tests/grok-selection.test.ts rename to tests/providers/xai/grok-selection.test.ts index 6911c54ae6..b0385aab9f 100644 --- a/tests/grok-selection.test.ts +++ b/tests/providers/xai/grok-selection.test.ts @@ -2,12 +2,12 @@ import { expect, test } from "bun:test"; import { mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { buildGrokManagedBlock, injectGrokConfig } from "../src/grok/inject"; -import { syncGrokConfig } from "../src/grok/sync"; -import { nativeOpenAiContextWindow, visibleNativeSlugs } from "../src/codex/catalog"; -import type { CatalogModel } from "../src/codex/catalog"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { buildGrokManagedBlock, injectGrokConfig } from "../../../src/grok/inject"; +import { syncGrokConfig } from "../../../src/grok/sync"; +import { nativeOpenAiContextWindow, visibleNativeSlugs } from "../../../src/codex/catalog"; +import type { CatalogModel } from "../../../src/codex/catalog"; +import type { OcxConfig } from "../../../src/types"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; /** * Alias-stable exclusion (WP3, audit blocker 3): aliases are allocated over the diff --git a/tests/grok-status.test.ts b/tests/providers/xai/grok-status.test.ts similarity index 96% rename from tests/grok-status.test.ts rename to tests/providers/xai/grok-status.test.ts index 34a039e65c..355472798d 100644 --- a/tests/grok-status.test.ts +++ b/tests/providers/xai/grok-status.test.ts @@ -2,9 +2,9 @@ import { describe, expect, test } from "bun:test"; import { mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { injectGrokConfig } from "../src/grok/inject"; -import { grokFenceEndpointDrift, readGrokStatus } from "../src/grok/status"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { injectGrokConfig } from "../../../src/grok/inject"; +import { grokFenceEndpointDrift, readGrokStatus } from "../../../src/grok/status"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; function tempGrokHome(): { root: string; grokHome: string } { const root = mkdtempSync(join(tmpdir(), "ocx-grok-status-")); diff --git a/tests/grok-sync.test.ts b/tests/providers/xai/grok-sync.test.ts similarity index 96% rename from tests/grok-sync.test.ts rename to tests/providers/xai/grok-sync.test.ts index 0b6fadd2af..af67b4dff6 100644 --- a/tests/grok-sync.test.ts +++ b/tests/providers/xai/grok-sync.test.ts @@ -2,16 +2,16 @@ import { afterEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { injectGrokConfig, type GrokInjectModel } from "../src/grok/inject"; -import { syncGrokConfig } from "../src/grok/sync"; -import { nativeOpenAiContextWindow, nativeOpenAiSlugs, visibleNativeSlugs } from "../src/codex/catalog"; -import type { CatalogModel } from "../src/codex/catalog"; +import { injectGrokConfig, type GrokInjectModel } from "../../../src/grok/inject"; +import { syncGrokConfig } from "../../../src/grok/sync"; +import { nativeOpenAiContextWindow, nativeOpenAiSlugs, visibleNativeSlugs } from "../../../src/codex/catalog"; +import type { CatalogModel } from "../../../src/codex/catalog"; import { resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests, -} from "../src/codex/model-entitlements"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/codex/model-entitlements"; +import type { OcxConfig } from "../../../src/types"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const baseConfig = { port: 10100, defaultProvider: "openai", providers: {} } as unknown as OcxConfig; diff --git a/tests/grok-writer-boundary.test.ts b/tests/providers/xai/grok-writer-boundary.test.ts similarity index 96% rename from tests/grok-writer-boundary.test.ts rename to tests/providers/xai/grok-writer-boundary.test.ts index ad70d210ca..ad1ce21a5b 100644 --- a/tests/grok-writer-boundary.test.ts +++ b/tests/providers/xai/grok-writer-boundary.test.ts @@ -21,7 +21,7 @@ function* walk(dir: string): Generator { // fileURLToPath, not .pathname: on Windows .pathname keeps a leading slash before the // drive letter (\D:\a\...), which breaks fs calls on CI. -const SRC = fileURLToPath(new URL("../src", import.meta.url)); +const SRC = fileURLToPath(new URL("../../../src", import.meta.url)); test("only src/grok/inject.ts writes a grok config.toml", () => { const writers: string[] = []; diff --git a/tests/xai-oauth-retry.test.ts b/tests/providers/xai/xai-oauth-retry.test.ts similarity index 96% rename from tests/xai-oauth-retry.test.ts rename to tests/providers/xai/xai-oauth-retry.test.ts index 05f4e335a3..542b594a3c 100644 --- a/tests/xai-oauth-retry.test.ts +++ b/tests/providers/xai/xai-oauth-retry.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { postXaiToken, XaiTokenRequestError } from "../src/oauth/xai"; +import { postXaiToken, XaiTokenRequestError } from "../../../src/oauth/xai"; const original=globalThis.fetch; afterEach(()=>{globalThis.fetch=original;}); function queue(items:Array){let n=0;globalThis.fetch=(async()=>{const x=items[n++]!;if(x instanceof Error)throw x;return x;}) as typeof fetch;return()=>n;} const body={grant_type:"refresh_token",client_id:"client",refresh_token:"secret"}; const ok=()=>new Response(JSON.stringify({access_token:"a",refresh_token:"r",expires_in:3600})); diff --git a/tests/xai-refresh-lock.test.ts b/tests/providers/xai/xai-refresh-lock.test.ts similarity index 96% rename from tests/xai-refresh-lock.test.ts rename to tests/providers/xai/xai-refresh-lock.test.ts index 4b526e62fb..26144dbf84 100644 --- a/tests/xai-refresh-lock.test.ts +++ b/tests/providers/xai/xai-refresh-lock.test.ts @@ -1,8 +1,8 @@ import { afterEach,beforeEach,describe,expect,test } from "bun:test"; import { mkdirSync,readFileSync,utimesSync,writeFileSync } from "node:fs";import{tmpdir}from"node:os";import{join}from"node:path"; -import { OAUTH_PROVIDERS,OAuthLoginRequiredError,refreshXaiAccountWithLock } from "../src/oauth";import{XaiTokenRequestError}from"../src/oauth/xai"; -import{createOAuthFileLock,createOAuthRefreshIntentLock,getAccountCredential,getAccountSet,getAuthRefreshIntentLockPath,OAuthFileLockError,saveCredential}from"../src/oauth/store"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { OAUTH_PROVIDERS,OAuthLoginRequiredError,refreshXaiAccountWithLock } from "../../../src/oauth";import{XaiTokenRequestError}from"../../../src/oauth/xai"; +import{createOAuthFileLock,createOAuthRefreshIntentLock,getAccountCredential,getAccountSet,getAuthRefreshIntentLockPath,OAuthFileLockError,saveCredential}from"../../../src/oauth/store"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const oldHome=process.env.HOME,oldOcx=process.env.OPENCODEX_HOME;let root:string;beforeEach(()=>{root=join(tmpdir(),`xai-lock-${crypto.randomUUID()}`);process.env.HOME=root;process.env.OPENCODEX_HOME=join(root,"ocx");mkdirSync(process.env.OPENCODEX_HOME,{recursive:true});});afterEach(()=>{if(oldHome===undefined)delete process.env.HOME;else process.env.HOME=oldHome;if(oldOcx===undefined)delete process.env.OPENCODEX_HOME;else process.env.OPENCODEX_HOME=oldOcx;removeTreeWithRetry(root);}); async function seed(){await saveCredential("xai",{access:"old",refresh:"rotating",expires:1,accountId:"acct"});return getAccountSet("xai")!.activeAccountId;}function def(c:{n:number},gate?:Promise){return{...OAUTH_PROVIDERS.xai!,refresh:async()=>{c.n++;if(gate)await gate;return{access:"fresh",refresh:"next",expires:Date.now()+3600000}}};} describe("two-lock xAI refresh",()=>{ diff --git a/tests/xai-tool-schema.test.ts b/tests/providers/xai/xai-tool-schema.test.ts similarity index 98% rename from tests/xai-tool-schema.test.ts rename to tests/providers/xai/xai-tool-schema.test.ts index 0937137b75..67edf07154 100644 --- a/tests/xai-tool-schema.test.ts +++ b/tests/providers/xai/xai-tool-schema.test.ts @@ -1,12 +1,12 @@ import { describe, expect, test } from "bun:test"; import { createOpenAIChatAdapter as createOpenAIChatAdapterProduction, -} from "../src/adapters/openai-chat"; +} from "../../../src/adapters/openai-chat"; import type { OcxParsedRequest, OcxTool, -} from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../../src/types"; +import { withTestTranslatorBudget } from "../../helpers/translator-budget"; const createOpenAIChatAdapter = ( ...args: Parameters diff --git a/tests/xai-transport.test.ts b/tests/providers/xai/xai-transport.test.ts similarity index 98% rename from tests/xai-transport.test.ts rename to tests/providers/xai/xai-transport.test.ts index 0de3b6ba68..5b87d9bad6 100644 --- a/tests/xai-transport.test.ts +++ b/tests/providers/xai/xai-transport.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { parseRequest } from "../src/responses/parser"; -import { buildModelsRequest } from "../src/oauth"; +import { createOpenAIChatAdapter } from "../../../src/adapters/openai-chat"; +import { parseRequest } from "../../../src/responses/parser"; +import { buildModelsRequest } from "../../../src/oauth"; import { isXaiResponsesDestination, resolveProviderTransport, @@ -9,11 +9,11 @@ import { XAI_CONV_ID_HEADER, XAI_GROK_CLI_BASE_URL, XAI_GROK_CLIENT_VERSION, -} from "../src/providers/xai-transport"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { XAI_RESPONSES_OPT_IN_MODELS } from "../src/providers/xai-responses-opt-in"; -import { resolveWireProtocolOverride } from "../src/server/adapter-resolve"; -import type { OcxAssistantMessage, OcxParsedRequest, OcxProviderConfig } from "../src/types"; +} from "../../../src/providers/xai-transport"; +import { getProviderRegistryEntry } from "../../../src/providers/registry"; +import { XAI_RESPONSES_OPT_IN_MODELS } from "../../../src/providers/xai-responses-opt-in"; +import { resolveWireProtocolOverride } from "../../../src/server/adapter-resolve"; +import type { OcxAssistantMessage, OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; const UUID_V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; const OMITTED = [ diff --git a/tests/xai-web-search-compat.test.ts b/tests/providers/xai/xai-web-search-compat.test.ts similarity index 96% rename from tests/xai-web-search-compat.test.ts rename to tests/providers/xai/xai-web-search-compat.test.ts index 6230264a23..67faa1c3f9 100644 --- a/tests/xai-web-search-compat.test.ts +++ b/tests/providers/xai/xai-web-search-compat.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { createResponsesPassthroughAdapter as createProductionAdapter } from "../src/adapters/openai-responses"; -import { normalizeXaiResponsesWebSearch } from "../src/adapters/xai-web-search"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { createResponsesPassthroughAdapter as createProductionAdapter } from "../../../src/adapters/openai-responses"; +import { normalizeXaiResponsesWebSearch } from "../../../src/adapters/xai-web-search"; +import { withTestTranslatorBudget } from "../../helpers/translator-budget"; function createXaiAdapter() { return withTestTranslatorBudget(createProductionAdapter({ diff --git a/tests/xai-web-search.test.ts b/tests/providers/xai/xai-web-search.test.ts similarity index 92% rename from tests/xai-web-search.test.ts rename to tests/providers/xai/xai-web-search.test.ts index 41e4a42c90..b755481a93 100644 --- a/tests/xai-web-search.test.ts +++ b/tests/providers/xai/xai-web-search.test.ts @@ -1,22 +1,22 @@ import { afterEach, describe, expect, mock, test } from "bun:test"; -import * as storeModule from "../src/oauth/store"; +import * as storeModule from "../../../src/oauth/store"; let accountSets: Record; activeAccountId?: string }> = {}; -mock.module("../src/oauth/store", () => ({ +mock.module("../../../src/oauth/store", () => ({ ...storeModule, getAccountSet: (provider: string) => accountSets[provider] ?? null, })); -import * as oauthModule from "../src/oauth"; -mock.module("../src/oauth", () => ({ +import * as oauthModule from "../../../src/oauth"; +mock.module("../../../src/oauth", () => ({ ...oauthModule, getValidAccessToken: async () => "test-token-xyz", })); -import { parseXaiResponsesSSE, validateXaiSearchOptions } from "../src/web-search/xai-executor"; -import { findXaiSidecarProvider, planWebSearch, xaiSearchOptionsFromConfig } from "../src/web-search"; -import { MAX_SIDECAR_RESPONSE_BYTES } from "../src/web-search/parse"; -import { parseRequest } from "../src/responses/parser"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { parseXaiResponsesSSE, validateXaiSearchOptions } from "../../../src/web-search/xai-executor"; +import { findXaiSidecarProvider, planWebSearch, xaiSearchOptionsFromConfig } from "../../../src/web-search"; +import { MAX_SIDECAR_RESPONSE_BYTES } from "../../../src/web-search/parse"; +import { parseRequest } from "../../../src/responses/parser"; +import type { OcxConfig, OcxProviderConfig } from "../../../src/types"; const routed: OcxProviderConfig = { adapter: "openai-chat", baseUrl: "https://routed.test/v1", apiKey: "k" }; const xaiProvider: OcxProviderConfig = { adapter: "openai-chat", baseUrl: "https://api.x.ai/v1", authMode: "oauth" }; @@ -148,7 +148,7 @@ describe("credential pinning + loop fail-closed (review blockers)", () => { }) as typeof fetch; try { const evil: OcxProviderConfig = { adapter: "openai-chat", baseUrl: "https://api.x.ai.evil/v1", authMode: "oauth" }; - const { runXaiWebSearch } = await import("../src/web-search/xai-executor"); + const { runXaiWebSearch } = await import("../../../src/web-search/xai-executor"); const out = await runXaiWebSearch("q", "xai", evil, { model: "grok-4.6", reasoning: "low", timeoutMs: 5000, describeImages: false }, {}); expect(captured.length).toBeGreaterThanOrEqual(1); for (const url of captured) expect(new URL(url).origin).toBe("https://api.x.ai"); @@ -159,9 +159,9 @@ describe("credential pinning + loop fail-closed (review blockers)", () => { }); }); -import { runWithWebSearch, type WebSearchLoopDeps } from "../src/web-search/loop"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import type { AdapterEvent, ProviderAdapter } from "../src/adapters/base"; +import { runWithWebSearch, type WebSearchLoopDeps } from "../../../src/web-search/loop"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; +import type { AdapterEvent, ProviderAdapter } from "../../../src/adapters/base"; describe("loop dispatch: xai arm fails closed without a sidecar (review blocker)", () => { test("missing xaiSidecar yields the invariant error tool-result; forward executor and pool recorder untouched", async () => { diff --git a/tests/zcode-client.test.ts b/tests/providers/zcode-client.test.ts similarity index 97% rename from tests/zcode-client.test.ts rename to tests/providers/zcode-client.test.ts index c287f6b41b..a8586babb7 100644 --- a/tests/zcode-client.test.ts +++ b/tests/providers/zcode-client.test.ts @@ -11,9 +11,9 @@ import { zcodeHomeDir, type ExportContext, type ZcodeGeneratedConfig, -} from "../src/clients/config-export"; -import type { OcxConfig } from "../src/types"; -import { handleZcodeCommand } from "../src/cli/integrations"; +} from "../../src/clients/config-export"; +import type { OcxConfig } from "../../src/types"; +import { handleZcodeCommand } from "../../src/cli/integrations"; const CONFIG = { port: 10100, diff --git a/tests/zhipu-bigmodel-provider.test.ts b/tests/providers/zhipu-bigmodel-provider.test.ts similarity index 92% rename from tests/zhipu-bigmodel-provider.test.ts rename to tests/providers/zhipu-bigmodel-provider.test.ts index 5cef6dfbbe..889cf6997d 100644 --- a/tests/zhipu-bigmodel-provider.test.ts +++ b/tests/providers/zhipu-bigmodel-provider.test.ts @@ -1,11 +1,11 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { KEY_LOGIN_PROVIDERS } from "../src/oauth/key-providers"; -import { deriveJawcodeAliases, deriveProviderPresets } from "../src/providers/derive"; -import { FREE_PROVIDER_DIRECTORY } from "../src/providers/free-directory"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { routeModel } from "../src/router"; -import type { OcxConfig } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { KEY_LOGIN_PROVIDERS } from "../../src/oauth/key-providers"; +import { deriveJawcodeAliases, deriveProviderPresets } from "../../src/providers/derive"; +import { FREE_PROVIDER_DIRECTORY } from "../../src/providers/free-directory"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { routeModel } from "../../src/router"; +import type { OcxConfig } from "../../src/types"; const BASE_URL = "https://open.bigmodel.cn/api/paas/v4"; diff --git a/tests/responses/responses-inbound-store-default.test.ts b/tests/responses/responses-inbound-store-default.test.ts index 0289e5b510..23bcc6aee1 100644 --- a/tests/responses/responses-inbound-store-default.test.ts +++ b/tests/responses/responses-inbound-store-default.test.ts @@ -12,7 +12,7 @@ * * End-to-end cases assert the captured upstream request body — the externally * observable payload. Pattern mirrors tests/responses/responses-compaction-routing.test.ts - * and tests/github-copilot-wire-defaults.test.ts. + * and tests/providers/github-copilot/github-copilot-wire-defaults.test.ts. */ import { afterEach, describe, expect, test } from "bun:test"; import { CODEX_FORWARD_BASE_URL } from "../../src/providers/openai-tiers"; diff --git a/tests/responses/responses-undeclared-tool-guard.test.ts b/tests/responses/responses-undeclared-tool-guard.test.ts index d9b2b8dc9f..41d8383a6c 100644 --- a/tests/responses/responses-undeclared-tool-guard.test.ts +++ b/tests/responses/responses-undeclared-tool-guard.test.ts @@ -917,7 +917,7 @@ describe("empty and absent tool catalogs", () => { ); // A passthrough request may omit `tools` entirely and still receive a tool call the client - // understands — the Copilot contract in tests/github-copilot-stream-contract.test.ts does + // understands — the Copilot contract in tests/providers/github-copilot/github-copilot-stream-contract.test.ts does // exactly that with `apply_patch`. With no catalog the proxy has no authorization boundary to // enforce, so the call remains untouched on both transports. test("non-streaming, no tools field — relayed, not refused", async () => { diff --git a/tests/server-auth.test.ts b/tests/server-auth.test.ts index 37db545e46..6fd98e29c8 100644 --- a/tests/server-auth.test.ts +++ b/tests/server-auth.test.ts @@ -3435,7 +3435,7 @@ describe("server local API auth", () => { // attacker-controlled bytes back to the client is precisely what #2398 stopped, so the // caller now gets #452's bounded status-only JSON instead of the original prefix // (pinned from the other side by "oversized passthrough errors become bounded - // status-only JSON" in tests/issue-452-empty-503.test.ts). + // status-only JSON" in tests/codex-integration/issue-452-empty-503.test.ts). // // The upstream's own headers still survive, which is what keeps pool-retry diagnostics // honest — that part is still checked below. diff --git a/tests/server-management-auth.test.ts b/tests/server-management-auth.test.ts index c256dede2a..9b8e4046ab 100644 --- a/tests/server-management-auth.test.ts +++ b/tests/server-management-auth.test.ts @@ -1581,7 +1581,7 @@ describe("management and data-plane credential separation", () => { describe("codex app-server restart routes ride the management gate", () => { // The service itself is unit-tested with injected seams - // (tests/codex-app-server-restart-service.test.ts). These cases exist for one + // (tests/codex-integration/codex-app-server-restart-service.test.ts). These cases exist for one // reason: the route terminates the user's Codex app-servers, so it must be // unreachable without management credentials and from a foreign origin. test("both routes reject an unauthenticated caller and a cross-origin caller", async () => { diff --git a/tests/service/stop-deferred-teardown.test.ts b/tests/service/stop-deferred-teardown.test.ts index 14ba8987d5..61eadbdc93 100644 --- a/tests/service/stop-deferred-teardown.test.ts +++ b/tests/service/stop-deferred-teardown.test.ts @@ -10,7 +10,7 @@ import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * Behavioural cover for the deferred shared teardown (#3008). * - * The wiring assertions in tests/grok-lifecycle.test.ts read source text, which cannot + * The wiring assertions in tests/providers/xai/grok-lifecycle.test.ts read source text, which cannot * tell a working deferral from a plausible-looking one. These tests call the real * functions: the graceful-stop client that builds the URL, the teardown decision the * route delegates to, and the on-disk receipts that decide whether a deferral is an owned diff --git a/tests/test-layout-tooling.test.ts b/tests/test-layout-tooling.test.ts index acffde0624..dc3ee6bf31 100644 --- a/tests/test-layout-tooling.test.ts +++ b/tests/test-layout-tooling.test.ts @@ -82,11 +82,15 @@ describe("scanEscapes", () => { 'const c = copyFileSync(join(import.meta.dir, "helpers", "child.ts"), out);', 'const d = join(import.meta.dir, "..");', 'const e = fileURLToPath(new URL("../", import.meta.url));', + 'const f = readFileSync(join(import.meta.dir, "fixtures/x.json"), "utf8");', + 'const g = join(import.meta.dir, "helpers/child.ts");', 'const local = join(import.meta.dir, ".tmp-x");', ].join("\n"); const { source, rewrites } = rewriteMetaDirEscapes(src, 1); - expect(rewrites).toBe(5); - expect(source).toContain('import { helperPath, repoPath, repoRoot } from "../helpers/repo-root";'); + expect(rewrites).toBe(7); + expect(source).toContain('import { fixturePath, helperPath, repoPath, repoRoot } from "../helpers/repo-root";'); + expect(source).toContain('readFileSync(fixturePath("x.json"), "utf8")'); + expect(source).toContain('const g = helperPath("child.ts");'); expect(source).toContain('readFileSync(repoPath("src", "cli", "index.ts"), "utf8")'); expect(source).toContain('repoPath("src/lib/winsw.ts")'); expect(source).toContain('copyFileSync(helperPath("child.ts"), out)'); @@ -124,6 +128,20 @@ describe("scanEscapes", () => { expect(out.source).toContain('readFileSync(join(repoRoot, rel), "utf8")'); expect(scanEscapes(out.source)).toEqual([]); + // A second escape in the same file must call the alias, never the local string; and a + // dynamic import() deep in the file must not drag the helper import to the bottom. + const two = 'import { join } from "node:path";\nconst repoRoot = join(import.meta.dir, "..");\nasync function f() {\n const m = await import("../src/x");\n return { cwd: join(import.meta.dir, "..") };\n}\n'; + const outTwo = rewriteMetaDirEscapes(two, 1); + expect(outTwo.source.split("\n")[1]).toBe('import { repoRoot as resolveRepoRoot } from "../helpers/repo-root";'); + expect(outTwo.source).toContain("return { cwd: resolveRepoRoot() };"); + expect(outTwo.source).not.toContain("repoRoot()"); + + // A file whose last line is a stray import still gets the helper in the leading block. + const trailing = 'import { join } from "node:path";\n\nconst r = join(import.meta.dir, "..");\nimport { X } from "../helpers/x";\n'; + const outTrailing = rewriteMetaDirEscapes(trailing, 1).source.split("\n"); + expect(outTrailing[1]).toBe('import { repoRoot } from "../helpers/repo-root";'); + expect(outTrailing[outTrailing.length - 2]).toBe('import { X } from "../helpers/x";'); + const url = 'import { join } from "node:path";\nconst root = new URL("../../", import.meta.url);\nconst t = await Bun.file(new URL(p, root)).text();\n'; const outUrl = rewriteMetaDirEscapes(url, 2); expect(outUrl.source).toContain('const root = pathToFileURL(repoRoot() + "/");'); diff --git a/tests/windows/windows-tray.test.ts b/tests/windows/windows-tray.test.ts index 4867834db7..60cfd9f323 100644 --- a/tests/windows/windows-tray.test.ts +++ b/tests/windows/windows-tray.test.ts @@ -9,6 +9,7 @@ import { writeFileSync, } from "node:fs"; import { tmpdir } from "node:os"; +import { helperPath, repoPath, repoRoot } from "../helpers/repo-root"; import { join } from "node:path"; import { buildWindowsTrayLauncherScript, @@ -557,4 +558,3 @@ describe("Windows tray packaging and command safety", () => { }); }); import { ManagementRequest as Request } from "../helpers/management-auth"; -import { helperPath, repoPath, repoRoot } from "../helpers/repo-root"; From 03433b1cf654ae3640a7fb87416e178560826d28 Mon Sep 17 00:00:00 2001 From: jun Date: Sat, 5 Sep 2026 04:40:13 +0900 Subject: [PATCH 2/3] test(layout): declare rootCall before the rewrite rules use it --- scripts/test-layout/schema.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/test-layout/schema.ts b/scripts/test-layout/schema.ts index f5cbb2a4ed..50a97031e5 100644 --- a/scripts/test-layout/schema.ts +++ b/scripts/test-layout/schema.ts @@ -178,11 +178,14 @@ export function rewriteMetaDirEscapes(source: string, depth: number): { source: const rebindsRoot = localRoot.test(view); const otherLocals = new RegExp(`\\b(?:const|let|var|function)\\s+(?:${HELPER_NAMES.filter(n => !(rebindsRoot && n === "repoRoot")).join("|")})\\b`); if (otherLocals.test(code)) return { source, rewrites: 0 }; + // When the file keeps a local string named repoRoot, the other rules must not emit a call + // to repoRoot() (that would call the string); they use the alias the rebind imports. + const rootCall = rebindsRoot ? "resolveRepoRoot()" : "repoRoot()"; const rules: Array<[RegExp, (m: RegExpMatchArray) => string]> = [ [new RegExp(localRoot.source, "g"), () => "const repoRoot = resolveRepoRoot();"], // `const root = new URL("../../", import.meta.url)` -> a file URL of the repository root. - [/\bconst\s+root\s*=\s*new\s+URL\(\s*"(?:\.\.\/)+"\s*,\s*import\.meta\.url\s*\)\s*;/g, () => 'const root = pathToFileURL(repoRoot() + "/");'], - [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\."\s*\)/g, () => "repoRoot()"], + [/\bconst\s+root\s*=\s*new\s+URL\(\s*"(?:\.\.\/)+"\s*,\s*import\.meta\.url\s*\)\s*;/g, () => `const root = pathToFileURL(${rootCall} + "/");`], + [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\."\s*\)/g, () => rootCall], [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\."\s*,\s*/g, () => "repoPath("], [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\.\/([^"]+)"/g, m => `repoPath("${m[1]}"`], [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"helpers"\s*,\s*/g, () => "helperPath("], @@ -320,4 +323,3 @@ export function layoutDir(): string { return dirname(LAYOUT_PATH); } - From a6d6e138c5ddc460ec90af37ce7c91230ea8636c Mon Sep 17 00:00:00 2001 From: jun Date: Sat, 5 Sep 2026 05:55:05 +0900 Subject: [PATCH 3/3] test(layout): honour #3523 placement of anthropic-quorum-cache; map docs-429-failover-claims --- scripts/test-layout/layout.json | 3 +- scripts/test-layout/move.ts | 18 ++- scripts/test-layout/schema.ts | 11 +- .../anthropic/anthropic-quorum-cache.test.ts | 146 ------------------ tests/fixtures/test-layout-expected.json | 3 +- tests/test-layout-tooling.test.ts | 11 +- 6 files changed, 33 insertions(+), 159 deletions(-) delete mode 100644 tests/adapters/anthropic/anthropic-quorum-cache.test.ts diff --git a/scripts/test-layout/layout.json b/scripts/test-layout/layout.json index a019b79878..ab49a9ddfd 100644 --- a/scripts/test-layout/layout.json +++ b/scripts/test-layout/layout.json @@ -201,7 +201,7 @@ "anthropic-image-retry-e2e.test.ts": "adapters/anthropic", "anthropic-image-retry.test.ts": "adapters/anthropic", "anthropic-pool-toggle-copy.test.ts": "adapters/anthropic", - "anthropic-quorum-cache.test.ts": "adapters/anthropic", + "anthropic-quorum-cache.test.ts": "routing", "anthropic-reasoning.test.ts": "adapters/anthropic", "anthropic-stream-hardening.test.ts": "adapters/anthropic", "anthropic-tail-guard.test.ts": "adapters/anthropic", @@ -576,6 +576,7 @@ "desktop-profile.test.ts": "clients", "destination-policy-resolved.test.ts": "routing", "digitalocean-scaleway-provider.test.ts": "providers", + "docs-429-failover-claims.test.ts": "ci-workflows", "docs-bun-source-requirement.test.ts": "ci-workflows", "doctor-codex-envkey-readiness.test.ts": "service", "doctor-oauth.test.ts": "service", diff --git a/scripts/test-layout/move.ts b/scripts/test-layout/move.ts index 51e9d3678e..5a930cff27 100644 --- a/scripts/test-layout/move.ts +++ b/scripts/test-layout/move.ts @@ -141,12 +141,18 @@ export function runMove(options: MoveOptions): MoveReport { const path = join(root, byFrom.get(file) ?? file); let text = readFileSync(path, "utf8"); const original = text; - for (const [from, to] of byFrom) { - text = text.split(from).join(to); - if (file === SERIAL_LANE_SOURCE && serial.has(basename(from))) { - const rel = from.slice("tests/".length); - text = text.split(`"${rel}"`).join(`"${to.slice("tests/".length)}"`); - } + for (const [from, to] of byFrom) text = text.split(from).join(to); + if (file === SERIAL_LANE_SOURCE) { + // Only the SERIAL_FULL_SUITE_FILES array holds tests/-relative paths; the timeout table + // next to it is keyed by basename and must not change. + text = text.replace(/SERIAL_FULL_SUITE_FILES = \[([\s\S]*?)\]/, (whole, body: string) => { + let next = body; + for (const [from, to] of byFrom) { + if (!serial.has(basename(from))) continue; + next = next.split(`"${from.slice("tests/".length)}"`).join(`"${to.slice("tests/".length)}"`); + } + return whole.replace(body, next); + }); } if (text !== original) { writeFileSync(path, text); diff --git a/scripts/test-layout/schema.ts b/scripts/test-layout/schema.ts index 50a97031e5..de75004d00 100644 --- a/scripts/test-layout/schema.ts +++ b/scripts/test-layout/schema.ts @@ -42,6 +42,8 @@ export function loadLayout(path: string = LAYOUT_PATH): Layout { * Explicit entries win, then child regexes, then domain regexes; first match wins. */ export function resolveTarget(layout: Layout, basename: string): string | null { + // A keep-at-root file never resolves to a domain, whatever the seeds say about its name. + if (layout.keepAtRoot.includes(basename)) return null; const explicit = layout.explicit[basename]; if (explicit !== undefined) return explicit; for (const [domain, spec] of Object.entries(layout.domains)) { @@ -174,7 +176,7 @@ export function rewriteMetaDirEscapes(source: string, depth: number): { source: // `const repoRoot = join(import.meta.dir, "..")` is the commonest escape of all: rebind the // local through an aliased import instead of refusing the file. Any other local named like a // helper (or a function) still stops the rewrite so nothing gets shadowed. - const localRoot = /\bconst\s+repoRoot\s*=\s*(?:(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\."\s*\)|fileURLToPath\(\s*new\s+URL\(\s*"(?:\.\.\/)+"\s*,\s*import\.meta\.url\s*\)\s*\)|resolve\(\s*dirname\(\s*fileURLToPath\(\s*import\.meta\.url\s*\)\s*\)\s*,\s*"\.\."\s*\))\s*;/; + const localRoot = /\bconst\s+repoRoot\s*=\s*(?:(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\."\s*\)|fileURLToPath\(\s*new\s+URL\(\s*"(?:\.\.\/)*\.\.\/?"\s*,\s*import\.meta\.url\s*\)\s*\)|resolve\(\s*dirname\(\s*fileURLToPath\(\s*import\.meta\.url\s*\)\s*\)\s*,\s*"\.\."\s*\))\s*;/; const rebindsRoot = localRoot.test(view); const otherLocals = new RegExp(`\\b(?:const|let|var|function)\\s+(?:${HELPER_NAMES.filter(n => !(rebindsRoot && n === "repoRoot")).join("|")})\\b`); if (otherLocals.test(code)) return { source, rewrites: 0 }; @@ -192,7 +194,9 @@ export function rewriteMetaDirEscapes(source: string, depth: number): { source: [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"helpers\/([^"]+)"/g, m => `helperPath("${m[1]}"`], [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"fixtures"\s*,\s*/g, () => "fixturePath("], [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"fixtures\/([^"]+)"/g, m => `fixturePath("${m[1]}"`], - [/\bfileURLToPath\(\s*new\s+URL\(\s*"\.\.\/"\s*,\s*import\.meta\.url\s*\)\s*\)/g, () => rootCall], + [/\bfileURLToPath\(\s*new\s+URL\(\s*"\.\.\/?"\s*,\s*import\.meta\.url\s*\)\s*\)/g, () => rootCall], + // `new URL("..", import.meta.url).href` as a root URL string. + [/\bnew\s+URL\(\s*"\.\.\/?"\s*,\s*import\.meta\.url\s*\)\.href/g, () => `pathToFileURL(${rootCall} + "/").href`], [/\bresolve\(\s*dirname\(\s*fileURLToPath\(\s*import\.meta\.url\s*\)\s*\)\s*,\s*"\.\."\s*\)/g, () => rootCall], ]; const edits: Array<{ start: number; end: number; text: string }> = []; @@ -266,7 +270,7 @@ export function insertAfterImports(source: string, line: string): string { /** A string argument that leaves the file's directory toward the repo or the tests/ siblings. */ const ESCAPE_ARG = /^["'](?:\.\.(?:["'\/])|helpers\b|fixtures\b|src\/|gui\/|scripts\/|tests\/)/; /** `new URL("../", import.meta.url)`: a URL used as a directory root, not a re-anchored specifier. */ -const URL_ROOT = /new\s+URL\s*\(\s*(["'])(?:\.\.\/)+\1\s*,\s*import\.meta\.url/; +const URL_ROOT = /new\s+URL\s*\(\s*(["'])(?:\.\.\/)*\.\.\/?\1\s*,\s*import\.meta\.url/; export interface EscapeHit { line: number; @@ -322,4 +326,3 @@ export function scanEscapes(source: string): EscapeHit[] { export function layoutDir(): string { return dirname(LAYOUT_PATH); } - diff --git a/tests/adapters/anthropic/anthropic-quorum-cache.test.ts b/tests/adapters/anthropic/anthropic-quorum-cache.test.ts deleted file mode 100644 index 6aaad77aa8..0000000000 --- a/tests/adapters/anthropic/anthropic-quorum-cache.test.ts +++ /dev/null @@ -1,146 +0,0 @@ -/** - * The quorum predicate must not read the auth store on every request. - * - * `hasAnthropicFailoverQuorum` decides whether an Anthropic request records the account that - * served it, so it runs on the INITIAL resolution of ordinary traffic -- not only after a 429. - * `getAccountSet` goes through `loadAuthStore`, which has no cache: it chmods the config dir, - * chmods the secret, reads the whole file and normalizes it on every call. An uncached predicate - * therefore puts a synchronous file read in front of every Anthropic turn. - * - * The generic module already solved this with a TTL-bounded count cache. These tests pin the same - * three properties for the Anthropic twin: the read is shared inside the window, a fresh login is - * still visible once it expires, and a rotation invalidates immediately rather than answering the - * next question from a pre-failure count. - */ -import { afterEach, beforeEach, describe, expect, test } from "bun:test"; -import { mkdtempSync, statSync, utimesSync } from "node:fs"; -import { tmpdir } from "node:os"; -import { join } from "node:path"; -import { - clearAnthropicAccountPoolState, - clearAnthropicSessionAffinityForAccount, - forgetAnthropicFailoverQuorum, - hasAnthropicFailoverQuorum, - resetAnthropicRoutingForManualSelection, - rotateAnthropicAccountOn429, -} from "../../../src/oauth/anthropic-routing"; -import { getAccountSet, saveCredential } from "../../../src/oauth/store"; -import { removeTreeWithRetry } from "../../helpers/remove-tree"; - -const originalHome = process.env.OPENCODEX_HOME; -let home: string; - -beforeEach(() => { - home = mkdtempSync(join(tmpdir(), "ocx-quorum-cache-")); - process.env.OPENCODEX_HOME = home; - clearAnthropicAccountPoolState(); - forgetAnthropicFailoverQuorum(); -}); - -afterEach(() => { - clearAnthropicAccountPoolState(); - forgetAnthropicFailoverQuorum(); - if (originalHome === undefined) delete process.env.OPENCODEX_HOME; - else process.env.OPENCODEX_HOME = originalHome; - removeTreeWithRetry(home); -}); - -async function seed(count: number, offset = 0): Promise { - for (let i = offset; i < offset + count; i++) { - await saveCredential("anthropic", { - access: `access-${i}`, - refresh: `refresh-${i}`, - expires: Date.now() + 3_600_000, - accountId: `uuid-${i}`, - email: `user${i}@example.test`, - } as never); - } - return getAccountSet("anthropic")?.accounts.map(a => a.id) ?? []; -} - -/** - * Observe the store read without stubbing the module: `loadAuthStore` calls `readFileSync`, - * which updates atime. Pinning atime into the past and checking whether it moved is a direct - * observation of the syscall this cache exists to avoid. - */ -function storePath(): string { - return join(home, "auth.json"); -} - -function markStoreUnread(): void { - const stats = statSync(storePath()); - utimesSync(storePath(), new Date(Date.now() - 60_000), stats.mtime); -} - -function storeWasRead(): boolean { - return statSync(storePath()).atimeMs > Date.now() - 30_000; -} - -describe("Anthropic failover quorum cache", () => { - test("a burst of requests inside the TTL window shares one store read", async () => { - const start = Date.now(); - await seed(2); - // Prime the cache, then prove the next calls do not touch the file at all. - expect(hasAnthropicFailoverQuorum(start)).toBe(true); - markStoreUnread(); - for (let i = 0; i < 25; i++) expect(hasAnthropicFailoverQuorum(start + i)).toBe(true); - expect(storeWasRead()).toBe(false); - }); - - test("a fresh login is visible once the window expires", async () => { - // The cache must not be able to strand an operator who just logged a second account in: - // a stale false would keep failover off for exactly the traffic that needs it. - const start = Date.now(); - await seed(1); - expect(hasAnthropicFailoverQuorum(start)).toBe(false); - await seed(1, 1); - // Same instant: still the memoized answer. - expect(hasAnthropicFailoverQuorum(start)).toBe(false); - // Past the window: seen without any explicit invalidation call. - expect(hasAnthropicFailoverQuorum(start + 2_001)).toBe(true); - }); - - test("a rotation invalidates immediately rather than waiting out the TTL", async () => { - const start = Date.now(); - const ids = await seed(2); - expect(hasAnthropicFailoverQuorum(start)).toBe(true); - expect(rotateAnthropicAccountOn429({ providers: {} } as never, ids[0]!, null, null, start)).toBe(ids[1]); - // The roster in use just changed, so the next question re-reads instead of answering from - // the count taken before the failure. - markStoreUnread(); - hasAnthropicFailoverQuorum(start + 1); - expect(storeWasRead()).toBe(true); - }); - - test("the cache holds no credential material", async () => { - // A boolean derived from a count. If this ever became an id or a token the cache would - // outlive the store's own hardening, which is the thing loadAuthStore re-applies per read. - await seed(2); - expect(typeof hasAnthropicFailoverQuorum()).toBe("boolean"); - }); - - test("removing an account invalidates immediately, not after the TTL", async () => { - // The management DELETE route calls clearAnthropicSessionAffinityForAccount for Anthropic. - // Without invalidation there, deleting the second account would leave quorum true for up to - // 2s -- long enough for a request to record an id whose credential is already gone. - const start = Date.now(); - const ids = await seed(2); - expect(hasAnthropicFailoverQuorum(start)).toBe(true); - clearAnthropicSessionAffinityForAccount(ids[1]!); - markStoreUnread(); - hasAnthropicFailoverQuorum(start + 1); - expect(storeWasRead()).toBe(true); - }); - - test("a manual account selection invalidates immediately", async () => { - // An operator picking an account is a statement about the roster, so the next activation - // question must not be answered from a count read before it. - const start = Date.now(); - const ids = await seed(2); - expect(hasAnthropicFailoverQuorum(start)).toBe(true); - resetAnthropicRoutingForManualSelection(ids[0]!); - markStoreUnread(); - hasAnthropicFailoverQuorum(start + 1); - expect(storeWasRead()).toBe(true); - }); -}); diff --git a/tests/fixtures/test-layout-expected.json b/tests/fixtures/test-layout-expected.json index 802cb98a8d..9a84ed2131 100644 --- a/tests/fixtures/test-layout-expected.json +++ b/tests/fixtures/test-layout-expected.json @@ -38,7 +38,7 @@ "anthropic-image-retry-e2e.test.ts": "adapters/anthropic", "anthropic-image-retry.test.ts": "adapters/anthropic", "anthropic-pool-toggle-copy.test.ts": "adapters/anthropic", - "anthropic-quorum-cache.test.ts": "adapters/anthropic", + "anthropic-quorum-cache.test.ts": "routing", "anthropic-reasoning.test.ts": "adapters/anthropic", "anthropic-stream-hardening.test.ts": "adapters/anthropic", "anthropic-tail-guard.test.ts": "adapters/anthropic", @@ -413,6 +413,7 @@ "desktop-profile.test.ts": "clients", "destination-policy-resolved.test.ts": "routing", "digitalocean-scaleway-provider.test.ts": "providers", + "docs-429-failover-claims.test.ts": "ci-workflows", "docs-bun-source-requirement.test.ts": "ci-workflows", "doctor-codex-envkey-readiness.test.ts": "service", "doctor-oauth.test.ts": "service", diff --git a/tests/test-layout-tooling.test.ts b/tests/test-layout-tooling.test.ts index dc3ee6bf31..6a9066aa29 100644 --- a/tests/test-layout-tooling.test.ts +++ b/tests/test-layout-tooling.test.ts @@ -202,6 +202,9 @@ describe("scanEscapes", () => { // A rewritten URL specifier is what a correct move looks like; a bare "../" root URL is not. expect(scanEscapes('const u = new URL("../../package.json", import.meta.url);')).toEqual([]); expect(scanEscapes('const root = fileURLToPath(new URL("../", import.meta.url));')).toHaveLength(1); + expect(scanEscapes('const root = fileURLToPath(new URL("..", import.meta.url));')).toHaveLength(1); + expect(rewriteMetaDirEscapes('const R = fileURLToPath(new URL("..", import.meta.url));\nconst U = new URL("..", import.meta.url).href;\n', 1).source) + .toContain('const R = repoRoot();\nconst U = pathToFileURL(repoRoot() + "/").href;'); expect(scanEscapes('const c = join(import.meta.dir, "helpers", "child.ts");')).toHaveLength(1); expect(scanEscapes('const r = resolve(\n import.meta.dir,\n "..",\n);')).toHaveLength(1); expect(scanEscapes('const t = `${import.meta.dir}/../src/x.ts`;')).toHaveLength(1); @@ -225,6 +228,7 @@ describe("resolver", () => { }; test("explicit beats child regex beats domain regex; unknown is null", () => { + expect(resolveTarget({ ...layout, keepAtRoot: ["server-kept.test.ts"] }, "server-kept.test.ts")).toBeNull(); expect(resolveTarget(layout, "cursor-odd.test.ts")).toBe("server"); expect(resolveTarget(layout, "cursor-adapter.test.ts")).toBe("providers/cursor"); expect(resolveTarget(layout, "provider-x.test.ts")).toBe("providers"); @@ -280,7 +284,12 @@ describe("membership oracle", () => { // (the 001 §2 "9 disagreeing files" whose name says one thing and whose imports say another). // Anything else is a seed pointing at the wrong domain, which would place a brand-new file // incorrectly on the day it is added. - const pinnedOverrides = new Set(["openai-responses-passthrough.test.ts"]); + const pinnedOverrides = new Set([ + "openai-responses-passthrough.test.ts", + // Placed under routing/ by its author in #3523 (it exercises the oauth routing quorum, + // not the Anthropic adapter); the anthropic- seed would say otherwise. + "anthropic-quorum-cache.test.ts", + ]); const mismatches: string[] = []; let resolved = 0; for (const [name, target] of Object.entries(layout.explicit)) {