From 1b0232315e244b69bf2999fa84e31b0e65f3afa1 Mon Sep 17 00:00:00 2001 From: jun Date: Sat, 5 Sep 2026 04:13:15 +0900 Subject: [PATCH] test(layout): move lib, config, clients, usage, vision, web-search into tests// (#3497) --- .../2026-07-26-oauth-reliability-integrity.md | 10 +-- .../2026-08-09-routed-computer-use-browser.md | 2 +- ...-26-discovered-model-display-names-core.md | 20 +++--- scripts/OCX-RUN.md | 2 +- scripts/test-layout/layout.json | 6 ++ scripts/test-layout/schema.ts | 5 +- scripts/test-layout/tokens.ts | 4 +- src/integrations/journal.ts | 2 +- src/server/management/config-routes.ts | 2 +- structure/04_transports-and-sidecars.md | 2 +- tests/cli-export-command.test.ts | 2 +- tests/{ => clients}/client-connect.test.ts | 8 +-- .../client-export-modality-enum.test.ts | 4 +- .../{ => clients}/client-fingerprint.test.ts | 6 +- tests/{ => clients}/client-hub-relay.test.ts | 2 +- .../client-machine-listener.test.ts | 13 ++-- tests/{ => clients}/desktop-3p-guard.test.ts | 8 +-- .../{ => clients}/desktop-3p-removal.test.ts | 2 +- tests/{ => clients}/desktop-3p.test.ts | 8 +-- .../{ => clients}/desktop-app-restart.test.ts | 4 +- tests/{ => clients}/desktop-profile.test.ts | 2 +- .../integrations-journal.test.ts | 15 +++-- .../integrations-serialize.test.ts | 2 +- .../{ => clients}/integrations-state.test.ts | 18 +++--- .../{ => clients}/integrations-writer.test.ts | 20 +++--- tests/{ => clients}/omp-path-contract.test.ts | 4 +- .../omp-yaml-source-inline-comments.test.ts | 2 +- tests/{ => clients}/pi-path-contract.test.ts | 6 +- tests/{ => clients}/prime-client.test.ts | 6 +- tests/{ => clients}/remote-catalog.test.ts | 2 +- .../sync-client-integrations.test.ts | 26 ++++---- .../client-config-export-new-clients.test.ts | 4 +- .../{ => config}/client-config-export.test.ts | 8 +-- .../client-config-new-clients.test.ts | 6 +- .../{ => config}/config-load-degrade.test.ts | 4 +- .../{ => config}/config-mutation-lock.test.ts | 25 ++++---- .../config-ownership-uninstall.test.ts | 6 +- .../config-rebase-provenance-writers.test.ts | 5 +- .../{ => config}/config-save-boundary.test.ts | 3 +- tests/{ => config}/config-user-edits.test.ts | 14 ++-- tests/{ => config}/expand-user-path.test.ts | 2 +- .../settings-oauth-open-browser.test.ts | 12 ++-- .../settings-startup-health-seam.test.ts | 8 +-- .../{ => config}/settings-stream-mode.test.ts | 26 ++++---- .../types-barrel-identity.test.ts | 6 +- tests/{ => config}/url-normalization.test.ts | 0 .../{ => config}/yaml-fragment-source.test.ts | 2 +- tests/integrations-invariants.test.ts | 2 +- tests/{ => lib}/abort-idle-deadline.test.ts | 2 +- .../acl-error-classification.test.ts | 2 +- tests/{ => lib}/bun-stream-caps.test.ts | 2 +- tests/{ => lib}/clearable-deadline.test.ts | 2 +- .../credential-redirect-guard.test.ts | 19 +++--- tests/{ => lib}/debug.test.ts | 12 ++-- .../{ => lib}/optional-shutdown-hooks.test.ts | 4 +- tests/{ => lib}/pinned-http.test.ts | 2 +- tests/{ => lib}/privacy-mask-account.test.ts | 2 +- .../process-control-graceful.test.ts | 2 +- tests/{ => lib}/process-control.test.ts | 2 +- .../reasoning-replay-scope-source.test.ts | 3 +- tests/{ => lib}/redact.test.ts | 2 +- tests/{ => lib}/remove-tree-helper.test.ts | 2 +- tests/{ => lib}/self-launch-argv.test.ts | 2 +- tests/{ => lib}/stall-timeout.test.ts | 2 +- tests/{ => lib}/strict-semver.test.ts | 2 +- .../system-restart-contract-security.test.ts | 2 +- tests/{ => lib}/token-estimate.test.ts | 2 +- .../transient-budget-scope-source.test.ts | 3 +- tests/{ => lib}/upstream-retry.test.ts | 2 +- tests/test-layout-tooling.test.ts | 2 + .../cost-cap-unknown-evidence.test.ts | 16 ++--- tests/{ => usage}/cost-scoring.test.ts | 8 +-- .../quota-401-recovery-runtime.test.ts | 64 +++++++++---------- tests/{ => usage}/quota-401-recovery.test.ts | 4 +- tests/{ => usage}/quota-scoring.test.ts | 18 +++--- tests/{ => usage}/request-decompress.test.ts | 8 +-- tests/{ => usage}/request-evidence.test.ts | 2 +- .../{ => usage}/request-history-index.test.ts | 24 +++---- .../request-log-conversation.test.ts | 6 +- .../request-log-estimate-cap.test.ts | 2 +- tests/{ => usage}/request-log.test.ts | 14 ++-- tests/{ => usage}/request-pacing.test.ts | 10 +-- .../{ => usage}/usage-aggregate-cache.test.ts | 14 ++-- tests/{ => usage}/usage-cost.test.ts | 10 +-- tests/{ => usage}/usage-debug.test.ts | 4 +- .../usage-failure-persistence.test.ts | 6 +- .../{ => usage}/usage-ledger-scanner.test.ts | 4 +- tests/{ => usage}/usage-log.test.ts | 6 +- .../{ => usage}/usage-provider-label.test.ts | 2 +- .../usage-shape-extraction.test.ts | 4 +- tests/{ => usage}/usage-summary.test.ts | 6 +- tests/{ => usage}/usage-surfaces.test.ts | 8 +-- ...ost-overlay-coderabbit-regressions.test.ts | 12 ++-- .../user-cost-overlay-live-reconcile.test.ts | 15 +++-- .../user-cost-overlay-provider-delete.test.ts | 12 ++-- tests/{ => vision}/sidecar-abort.test.ts | 16 ++--- tests/{ => vision}/sidecar-auth.test.ts | 18 +++--- tests/{ => vision}/sidecar-candidates.test.ts | 22 +++---- .../sidecar-settings-vision-controls.test.ts | 10 +-- .../sidecar-settings-vision-filter.test.ts | 16 ++--- .../sidecar-settings-web-search-gate.test.ts | 24 +++---- ...sidecar-settings-web-search-stream.test.ts | 10 +-- tests/{ => vision}/sidecar-tracker.test.ts | 2 +- tests/{ => vision}/vision-anthropic.test.ts | 18 +++--- .../{ => vision}/vision-backend-union.test.ts | 26 ++++---- tests/{ => vision}/vision-cache.test.ts | 10 +-- tests/{ => vision}/vision-eligibility.test.ts | 8 +-- tests/{ => vision}/vision-fail-closed.test.ts | 4 +- .../vision-reasoning-contract.test.ts | 16 ++--- tests/{ => vision}/vision-routed.test.ts | 14 ++-- tests/{ => vision}/vision-sidecar-e2e.test.ts | 18 +++--- .../vision-text-only-predicate.test.ts | 4 +- tests/{ => web-search}/format-result.test.ts | 2 +- .../web-search-anthropic.test.ts | 14 ++-- .../web-search-backend-union.test.ts | 12 ++-- .../web-search-candidates.test.ts | 24 +++---- .../{ => web-search}/web-search-parse.test.ts | 2 +- .../web-search-progress-stream.test.ts | 6 +- .../web-search-sources.test.ts | 2 +- .../web-search-timeout-contract.test.ts | 12 ++-- .../web-search-timeout-plan.test.ts | 6 +- tests/{ => web-search}/web-search.test.ts | 30 ++++----- 122 files changed, 535 insertions(+), 513 deletions(-) rename tests/{ => clients}/client-connect.test.ts (99%) rename tests/{ => clients}/client-export-modality-enum.test.ts (98%) rename tests/{ => clients}/client-fingerprint.test.ts (97%) rename tests/{ => clients}/client-hub-relay.test.ts (99%) rename tests/{ => clients}/client-machine-listener.test.ts (94%) rename tests/{ => clients}/desktop-3p-guard.test.ts (93%) rename tests/{ => clients}/desktop-3p-removal.test.ts (99%) rename tests/{ => clients}/desktop-3p.test.ts (98%) rename tests/{ => clients}/desktop-app-restart.test.ts (99%) rename tests/{ => clients}/desktop-profile.test.ts (99%) rename tests/{ => clients}/integrations-journal.test.ts (97%) rename tests/{ => clients}/integrations-serialize.test.ts (99%) rename tests/{ => clients}/integrations-state.test.ts (98%) rename tests/{ => clients}/integrations-writer.test.ts (98%) rename tests/{ => clients}/omp-path-contract.test.ts (89%) rename tests/{ => clients}/omp-yaml-source-inline-comments.test.ts (93%) rename tests/{ => clients}/pi-path-contract.test.ts (94%) rename tests/{ => clients}/prime-client.test.ts (96%) rename tests/{ => clients}/remote-catalog.test.ts (98%) rename tests/{ => clients}/sync-client-integrations.test.ts (94%) rename tests/{ => config}/client-config-export-new-clients.test.ts (99%) rename tests/{ => config}/client-config-export.test.ts (99%) rename tests/{ => config}/client-config-new-clients.test.ts (98%) rename tests/{ => config}/config-load-degrade.test.ts (97%) rename tests/{ => config}/config-mutation-lock.test.ts (89%) rename tests/{ => config}/config-ownership-uninstall.test.ts (98%) rename tests/{ => config}/config-rebase-provenance-writers.test.ts (92%) rename tests/{ => config}/config-save-boundary.test.ts (97%) rename tests/{ => config}/config-user-edits.test.ts (98%) rename tests/{ => config}/expand-user-path.test.ts (95%) rename tests/{ => config}/settings-oauth-open-browser.test.ts (91%) rename tests/{ => config}/settings-startup-health-seam.test.ts (85%) rename tests/{ => config}/settings-stream-mode.test.ts (96%) rename tests/{ => config}/types-barrel-identity.test.ts (95%) rename tests/{ => config}/url-normalization.test.ts (100%) rename tests/{ => config}/yaml-fragment-source.test.ts (98%) rename tests/{ => lib}/abort-idle-deadline.test.ts (97%) rename tests/{ => lib}/acl-error-classification.test.ts (97%) rename tests/{ => lib}/bun-stream-caps.test.ts (99%) rename tests/{ => lib}/clearable-deadline.test.ts (96%) rename tests/{ => lib}/credential-redirect-guard.test.ts (81%) rename tests/{ => lib}/debug.test.ts (96%) rename tests/{ => lib}/optional-shutdown-hooks.test.ts (98%) rename tests/{ => lib}/pinned-http.test.ts (97%) rename tests/{ => lib}/privacy-mask-account.test.ts (93%) rename tests/{ => lib}/process-control-graceful.test.ts (97%) rename tests/{ => lib}/process-control.test.ts (84%) rename tests/{ => lib}/reasoning-replay-scope-source.test.ts (95%) rename tests/{ => lib}/redact.test.ts (99%) rename tests/{ => lib}/remove-tree-helper.test.ts (95%) rename tests/{ => lib}/self-launch-argv.test.ts (91%) rename tests/{ => lib}/stall-timeout.test.ts (96%) rename tests/{ => lib}/strict-semver.test.ts (98%) rename tests/{ => lib}/system-restart-contract-security.test.ts (97%) rename tests/{ => lib}/token-estimate.test.ts (99%) rename tests/{ => lib}/transient-budget-scope-source.test.ts (96%) rename tests/{ => lib}/upstream-retry.test.ts (99%) rename tests/{ => usage}/cost-cap-unknown-evidence.test.ts (96%) rename tests/{ => usage}/cost-scoring.test.ts (97%) rename tests/{ => usage}/quota-401-recovery-runtime.test.ts (87%) rename tests/{ => usage}/quota-401-recovery.test.ts (98%) rename tests/{ => usage}/quota-scoring.test.ts (95%) rename tests/{ => usage}/request-decompress.test.ts (98%) rename tests/{ => usage}/request-evidence.test.ts (95%) rename tests/{ => usage}/request-history-index.test.ts (95%) rename tests/{ => usage}/request-log-conversation.test.ts (97%) rename tests/{ => usage}/request-log-estimate-cap.test.ts (99%) rename tests/{ => usage}/request-log.test.ts (99%) rename tests/{ => usage}/request-pacing.test.ts (97%) rename tests/{ => usage}/usage-aggregate-cache.test.ts (96%) rename tests/{ => usage}/usage-cost.test.ts (99%) rename tests/{ => usage}/usage-debug.test.ts (98%) rename tests/{ => usage}/usage-failure-persistence.test.ts (92%) rename tests/{ => usage}/usage-ledger-scanner.test.ts (99%) rename tests/{ => usage}/usage-log.test.ts (99%) rename tests/{ => usage}/usage-provider-label.test.ts (97%) rename tests/{ => usage}/usage-shape-extraction.test.ts (97%) rename tests/{ => usage}/usage-summary.test.ts (99%) rename tests/{ => usage}/usage-surfaces.test.ts (91%) rename tests/{ => usage}/user-cost-overlay-coderabbit-regressions.test.ts (94%) rename tests/{ => usage}/user-cost-overlay-live-reconcile.test.ts (98%) rename tests/{ => usage}/user-cost-overlay-provider-delete.test.ts (94%) rename tests/{ => vision}/sidecar-abort.test.ts (97%) rename tests/{ => vision}/sidecar-auth.test.ts (90%) rename tests/{ => vision}/sidecar-candidates.test.ts (89%) rename tests/{ => vision}/sidecar-settings-vision-controls.test.ts (96%) rename tests/{ => vision}/sidecar-settings-vision-filter.test.ts (96%) rename tests/{ => vision}/sidecar-settings-web-search-gate.test.ts (95%) rename tests/{ => vision}/sidecar-settings-web-search-stream.test.ts (93%) rename tests/{ => vision}/sidecar-tracker.test.ts (96%) rename tests/{ => vision}/vision-anthropic.test.ts (97%) rename tests/{ => vision}/vision-backend-union.test.ts (90%) rename tests/{ => vision}/vision-cache.test.ts (98%) rename tests/{ => vision}/vision-eligibility.test.ts (97%) rename tests/{ => vision}/vision-fail-closed.test.ts (92%) rename tests/{ => vision}/vision-reasoning-contract.test.ts (94%) rename tests/{ => vision}/vision-routed.test.ts (97%) rename tests/{ => vision}/vision-sidecar-e2e.test.ts (97%) rename tests/{ => vision}/vision-text-only-predicate.test.ts (94%) rename tests/{ => web-search}/format-result.test.ts (98%) rename tests/{ => web-search}/web-search-anthropic.test.ts (97%) rename tests/{ => web-search}/web-search-backend-union.test.ts (92%) rename tests/{ => web-search}/web-search-candidates.test.ts (87%) rename tests/{ => web-search}/web-search-parse.test.ts (99%) rename tests/{ => web-search}/web-search-progress-stream.test.ts (99%) rename tests/{ => web-search}/web-search-sources.test.ts (98%) rename tests/{ => web-search}/web-search-timeout-contract.test.ts (97%) rename tests/{ => web-search}/web-search-timeout-plan.test.ts (95%) rename tests/{ => web-search}/web-search.test.ts (99%) 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 2d573a50375..8a0bd1cf730 100644 --- a/docs/superpowers/plans/2026-07-26-oauth-reliability-integrity.md +++ b/docs/superpowers/plans/2026-07-26-oauth-reliability-integrity.md @@ -47,7 +47,7 @@ **Files:** - Modify: `src/lib/privacy.ts` -- Test: `tests/privacy-mask-account.test.ts` +- Test: `tests/lib/privacy-mask-account.test.ts` - Modify (if CLI already prints raw IDs in oauth summary paths later): none in this task beyond helper **Interfaces:** @@ -78,7 +78,7 @@ describe("maskAccountId", () => { - [ ] **Step 2: Run test to verify it fails** -Run: `bun test tests/privacy-mask-account.test.ts` +Run: `bun test tests/lib/privacy-mask-account.test.ts` Expected: FAIL — `maskAccountId` is not exported @@ -98,14 +98,14 @@ export function maskAccountId(value: string | null | undefined): string | null { - [ ] **Step 4: Run test to verify it passes** -Run: `bun test tests/privacy-mask-account.test.ts` +Run: `bun test tests/lib/privacy-mask-account.test.ts` Expected: PASS - [ ] **Step 5: Commit** ```bash -git add src/lib/privacy.ts tests/privacy-mask-account.test.ts +git add src/lib/privacy.ts tests/lib/privacy-mask-account.test.ts git commit -m "$(cat <<'EOF' feat(privacy): add maskAccountId for OAuth diagnostics @@ -713,7 +713,7 @@ EOF - [ ] **Step 1: Run verification commands** ```bash -bun test tests/privacy-mask-account.test.ts tests/oauth-log.test.ts tests/oauth-refresh-generic-lock.test.ts tests/oauth-health.test.ts tests/cli-status-oauth-health.test.ts tests/service/doctor-oauth.test.ts tests/oauth-accounts-api.test.ts tests/codex-metadata-integrity.test.ts +bun test tests/lib/privacy-mask-account.test.ts tests/oauth-log.test.ts tests/oauth-refresh-generic-lock.test.ts tests/oauth-health.test.ts tests/cli-status-oauth-health.test.ts tests/service/doctor-oauth.test.ts tests/oauth-accounts-api.test.ts tests/codex-metadata-integrity.test.ts bun test tests/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 run test bun run typecheck 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 e265c04b903..19c0f348421 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 @@ -249,7 +249,7 @@ Expected: progressive deltas, strict terminal repair, item IDs, and cancellation Run: ```bash -bun test tests/vision-sidecar-e2e.test.ts tests/vision-anthropic.test.ts tests/vision-cache.test.ts tests/vision-fail-closed.test.ts tests/catalog-vision-sidecar-modalities.test.ts tests/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/catalog-vision-sidecar-modalities.test.ts tests/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-26-discovered-model-display-names-core.md b/docs/superpowers/plans/2026-08-26-discovered-model-display-names-core.md index 35ca7d61da7..6d7c1776db5 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 @@ -34,8 +34,8 @@ - `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/config-load-degrade.test.ts`: covers safe hand edited config loading. -- `tests/config-user-edits.test.ts`: covers persistence and concurrent unrelated map edits. +- `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. - `docs-site/src/content/docs/reference/configuration/providers.md`: documents the field and exact key rules. @@ -51,7 +51,7 @@ - Modify: `src/config/provider-validation.ts` - Modify: `src/config.ts` - Test: `tests/provider-config-validation.test.ts` -- Test: `tests/config-load-degrade.test.ts` +- Test: `tests/config/config-load-degrade.test.ts` **Interfaces:** - Produces: `OcxProviderConfig.modelDisplayNames?: Record` @@ -126,7 +126,7 @@ Write a real config file fixture containing one valid and one invalid label. Ass Run: ```text -bun test tests/config-load-degrade.test.ts tests/provider-config-validation.test.ts +bun test tests/config/config-load-degrade.test.ts tests/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-load-degrade.test.ts tests/provider-config-validation.test.ts +bun test tests/config/config-load-degrade.test.ts tests/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-load-degrade.test.ts +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 commit -m "feat(config): add discovered model display names" ``` @@ -352,14 +352,14 @@ Expected: all API tests pass. - [ ] **Step 9: Add concurrent config merge regression** -In `tests/config-user-edits.test.ts`, start with two labels. Change one label in the live config, change the other on disk, call `saveConfigPreservingClaudeCode`, and assert both changes survive. Add a second test where the live writer removes one label while the disk writer adds a different label. +In `tests/config/config-user-edits.test.ts`, start with two labels. Change one label in the live config, change the other on disk, call `saveConfigPreservingClaudeCode`, and assert both changes survive. Add a second test where the live writer removes one label while the disk writer adds a different label. - [ ] **Step 10: Run persistence tests and confirm RED or existing support** Run: ```text -bun test tests/config-user-edits.test.ts +bun test tests/config/config-user-edits.test.ts ``` If the first run passes, record that the existing recursive provider merge already satisfies the contract and do not add production merge code. If it fails, make the smallest generic merge correction in `src/config.ts`, then rerun until green. @@ -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-user-edits.test.ts src/config.ts +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 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-load-degrade.test.ts tests/config-user-edits.test.ts tests/codex-catalog.test.ts tests/model-display-names-management-api.test.ts +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 ``` Expected: all pass. diff --git a/scripts/OCX-RUN.md b/scripts/OCX-RUN.md index 33c7ce63ecf..cdcdf304773 100644 --- a/scripts/OCX-RUN.md +++ b/scripts/OCX-RUN.md @@ -22,7 +22,7 @@ ssh 'ls -l ~/bin/ocx-run' || { ## Why On 2026-08-14 two `bun test` runs sat on `lidge` for **3h12m**. Both had stopped -producing output after ~4 minutes, both were wedged inside `tests/request-log.test.ts`, +producing output after ~4 minutes, both were wedged inside `tests/usage/request-log.test.ts`, and neither would ever write its `.exit` file — so every poller read them as "still running". A second run had also been started against the same 16 CPUs, so even healthy work crawled. Three independent failures, three guards: diff --git a/scripts/test-layout/layout.json b/scripts/test-layout/layout.json index c7bf18de0aa..29b264ddaf1 100644 --- a/scripts/test-layout/layout.json +++ b/scripts/test-layout/layout.json @@ -1227,8 +1227,14 @@ "zz-pr-coderabbit-readiness-revalidation.test.ts": "ci-workflows" }, "migrated": [ + "clients", + "config", + "lib", "service", "update", + "usage", + "vision", + "web-search", "windows" ] } diff --git a/scripts/test-layout/schema.ts b/scripts/test-layout/schema.ts index ffdd3e63b6f..04d33f48c14 100644 --- a/scripts/test-layout/schema.ts +++ b/scripts/test-layout/schema.ts @@ -280,7 +280,10 @@ export function scanEscapes(source: string): EscapeHit[] { const strings = stringTokens.filter(t => t.start >= back && t.end <= end).map(t => source.slice(t.start, t.end)); const urlSpec = /new\s+URL\s*\(\s*(["'][^"']*["'])\s*,\s*import\.meta\.url/.exec(stmt)?.[1]; const escapes = strings.some(str => str !== urlSpec && ESCAPE_ARG.test(str)); - if (escapes || URL_ROOT.test(stmt)) report(at, end); + // new URL(, import.meta.url): the specifier lives somewhere the rewriter cannot + // see, so a human has to look. + const variableUrl = /new\s+URL\s*\(\s*[A-Za-z_$][\w$.]*\s*,\s*import\.meta\.url/.test(stmt); + if (escapes || variableUrl || URL_ROOT.test(stmt)) report(at, end); } for (const t of tokens) { if (t.kind !== "template") continue; diff --git a/scripts/test-layout/tokens.ts b/scripts/test-layout/tokens.ts index 87808f558a1..d0ff238f01d 100644 --- a/scripts/test-layout/tokens.ts +++ b/scripts/test-layout/tokens.ts @@ -133,7 +133,9 @@ export interface SpecifierSite { quote: string; } -const SPECIFIER_LEAD = /(?:\bfrom|\bimport|\bimport\s*\(|\brequire\s*\(|\bimport\.meta\.resolve\s*\(|\bnew\s+URL\s*\()\s*$/; +// `mock.module("x", ...)` (bun:test) names a module the same way an import does: the string must +// re-anchor with the file or the mock silently stops intercepting. +const SPECIFIER_LEAD = /(?:\bfrom|\bimport|\bimport\s*\(|\brequire\s*\(|\bimport\.meta\.resolve\s*\(|\bnew\s+URL\s*\(|\bmock\.module\s*\()\s*$/; /** String tokens that sit in a module-specifier position. */ export function specifierSites(source: string, tokens: Token[] = tokenize(source)): SpecifierSite[] { diff --git a/src/integrations/journal.ts b/src/integrations/journal.ts index 1507276cd90..c23a2932116 100644 --- a/src/integrations/journal.ts +++ b/src/integrations/journal.ts @@ -26,7 +26,7 @@ import { isIntegrationClientId, type IntegrationClientId } from "./registry"; * * This union is re-declared, not imported, in two other places -- the management * route envelope and the GUI adapter -- because neither imports across that - * boundary. `tests/integrations-journal.test.ts` asserts the three agree, since + * boundary. `tests/clients/integrations-journal.test.ts` asserts the three agree, since * nothing else can: a kind persisted here and missing there renders as a raw * key with no type error anywhere. */ diff --git a/src/server/management/config-routes.ts b/src/server/management/config-routes.ts index 2cd99beb692..20dda304f05 100644 --- a/src/server/management/config-routes.ts +++ b/src/server/management/config-routes.ts @@ -696,7 +696,7 @@ export async function handleConfigRoutes(ctx: ManagementContext): Promise { // cannot show it in a checkout with no GUI build. Reading the file keeps the // assertion honest in both cases. const source = readFileSync( - join(import.meta.dir, "..", "src", "client", "machine-listener.ts"), + repoPath("src", "client", "machine-listener.ts"), "utf8", ); const call = /serveGuiFile\(([^)]*)\)/.exec(source); diff --git a/tests/desktop-3p-guard.test.ts b/tests/clients/desktop-3p-guard.test.ts similarity index 93% rename from tests/desktop-3p-guard.test.ts rename to tests/clients/desktop-3p-guard.test.ts index 2aa8902e742..8f8092dc626 100644 --- a/tests/desktop-3p-guard.test.ts +++ b/tests/clients/desktop-3p-guard.test.ts @@ -2,10 +2,10 @@ import { expect, test } from "bun:test"; import { mkdtempSync, readFileSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { assertDesktop3pModelsValid } from "../src/claude/desktop-3p-guard"; -import { generateDesktop3pModels, writeDesktop3pConfig } from "../src/claude/desktop-3p"; -import type { Desktop3pModelEntry } from "../src/claude/desktop-3p"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { assertDesktop3pModelsValid } from "../../src/claude/desktop-3p-guard"; +import { generateDesktop3pModels, writeDesktop3pConfig } from "../../src/claude/desktop-3p"; +import type { Desktop3pModelEntry } from "../../src/claude/desktop-3p"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * D2: the Desktop 3P output guard. The name was never the leak (non-Anthropic names diff --git a/tests/desktop-3p-removal.test.ts b/tests/clients/desktop-3p-removal.test.ts similarity index 99% rename from tests/desktop-3p-removal.test.ts rename to tests/clients/desktop-3p-removal.test.ts index ecbc34a4171..d06b2b74b87 100644 --- a/tests/desktop-3p-removal.test.ts +++ b/tests/clients/desktop-3p-removal.test.ts @@ -7,7 +7,7 @@ import { tmpdir } from "node:os"; import { inspectDesktop3pConfigLibrary, removeDesktop3pStandardPivot, -} from "../src/claude/desktop-3p"; +} from "../../src/claude/desktop-3p"; function envFor(path: string): NodeJS.ProcessEnv { return { ...process.env, OPENCODEX_CLAUDE_DESKTOP_CONFIG_DIR: path }; diff --git a/tests/desktop-3p.test.ts b/tests/clients/desktop-3p.test.ts similarity index 98% rename from tests/desktop-3p.test.ts rename to tests/clients/desktop-3p.test.ts index b8ac46b51a5..6b1857ff9f1 100644 --- a/tests/desktop-3p.test.ts +++ b/tests/clients/desktop-3p.test.ts @@ -14,10 +14,10 @@ import { resolveDesktop3pConfigLibraryPath, resolveDesktop3pAlias, writeDesktop3pConfig, -} from "../src/claude/desktop-3p"; -import { moveDesktopRoute, reconcileDesktopProfile, setDesktopFamilyDefault } from "../src/claude/desktop-profile"; -import { resolveInboundModel } from "../src/claude/inbound"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/claude/desktop-3p"; +import { moveDesktopRoute, reconcileDesktopProfile, setDesktopFamilyDefault } from "../../src/claude/desktop-profile"; +import { resolveInboundModel } from "../../src/claude/inbound"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; describe("Claude Desktop 3P models", () => { test("resolves the actual cross-platform Claude Desktop config library (#539)", () => { diff --git a/tests/desktop-app-restart.test.ts b/tests/clients/desktop-app-restart.test.ts similarity index 99% rename from tests/desktop-app-restart.test.ts rename to tests/clients/desktop-app-restart.test.ts index 95194f17e7b..632d88acaed 100644 --- a/tests/desktop-app-restart.test.ts +++ b/tests/clients/desktop-app-restart.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { restartCodexDesktopApp, type DesktopAppRestartIo } from "../src/codex/desktop-app-restart"; -import { setTrustedWindowsElevationExecutablesForTests } from "../src/lib/windows-elevation"; +import { restartCodexDesktopApp, type DesktopAppRestartIo } from "../../src/codex/desktop-app-restart"; +import { setTrustedWindowsElevationExecutablesForTests } from "../../src/lib/windows-elevation"; /** * #2292: the desktop restart is the one path in the CLI that terminates a user's diff --git a/tests/desktop-profile.test.ts b/tests/clients/desktop-profile.test.ts similarity index 99% rename from tests/desktop-profile.test.ts rename to tests/clients/desktop-profile.test.ts index 9fb97551748..f0021838506 100644 --- a/tests/desktop-profile.test.ts +++ b/tests/clients/desktop-profile.test.ts @@ -8,7 +8,7 @@ import { renderDesktopProfile, setDesktopFamilyDefault, type DesktopProfileModel, -} from "../src/claude/desktop-profile"; +} from "../../src/claude/desktop-profile"; const models: DesktopProfileModel[] = [ { route: "native/gpt-5.6-sol", label: "GPT 5.6 Sol", contextWindow: 1_000_000 }, diff --git a/tests/integrations-journal.test.ts b/tests/clients/integrations-journal.test.ts similarity index 97% rename from tests/integrations-journal.test.ts rename to tests/clients/integrations-journal.test.ts index 1ae86ebda4d..07010fc0318 100644 --- a/tests/integrations-journal.test.ts +++ b/tests/clients/integrations-journal.test.ts @@ -2,11 +2,12 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { appendFileSync, chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { getConfigDir } from "../src/config"; -import { SNAPSHOT_RETENTION, type JournalEntry } from "../src/integrations/journal"; -import type { OwnershipRecord } from "../src/integrations/ownership"; -import { createIntegrationStateStore, type IntegrationStateStore } from "../src/integrations/store"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { getConfigDir } from "../../src/config"; +import { SNAPSHOT_RETENTION, type JournalEntry } from "../../src/integrations/journal"; +import type { OwnershipRecord } from "../../src/integrations/ownership"; +import { createIntegrationStateStore, type IntegrationStateStore } from "../../src/integrations/store"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath } from "../helpers/repo-root"; /** Activation coverage for devlog/_fin/260802_client_toggle_api/021 §6. */ let root: string; @@ -357,7 +358,7 @@ describe("the operation-kind union agrees across the three trees that redeclare const UNION = /"apply"\s*\|\s*"disable"\s*\|\s*"refresh"\s*\|\s*"restore"[^;]*/; function kindsIn(relPath: string, anchor: RegExp): string[] { - const source = readFileSync(join(import.meta.dir, "..", relPath), "utf8"); + const source = readFileSync(repoPath(relPath), "utf8"); const declaration = source.match(anchor); if (!declaration) throw new Error(`no operation-kind union found in ${relPath}`); const union = declaration[0].match(UNION); @@ -382,7 +383,7 @@ describe("the operation-kind union agrees across the three trees that redeclare * is exhaustive over the GUI's own union, so a kind missing from BOTH the * GUI union and the map type-checks clean and renders the raw key. */ - const map = readFileSync(join(import.meta.dir, "..", "gui/src/pages/integrations/overview-clients.ts"), "utf8"); + const map = readFileSync(repoPath("gui/src/pages/integrations/overview-clients.ts"), "utf8"); const block = map.match(/JOURNAL_KIND_KEY[^}]*}/); if (!block) throw new Error("JOURNAL_KIND_KEY is gone from overview-clients.ts"); for (const kind of kindsIn("src/integrations/journal.ts", /export type OperationKind =[^;]*/)) { diff --git a/tests/integrations-serialize.test.ts b/tests/clients/integrations-serialize.test.ts similarity index 99% rename from tests/integrations-serialize.test.ts rename to tests/clients/integrations-serialize.test.ts index 10f4ceef823..b290b2cfdda 100644 --- a/tests/integrations-serialize.test.ts +++ b/tests/clients/integrations-serialize.test.ts @@ -7,7 +7,7 @@ import { renderYaml, serializeDocument, tomlString, -} from "../src/integrations/serialize"; +} from "../../src/integrations/serialize"; /** * Activation coverage for devlog/_fin/260802_client_toggle_api/011 §1. diff --git a/tests/integrations-state.test.ts b/tests/clients/integrations-state.test.ts similarity index 98% rename from tests/integrations-state.test.ts rename to tests/clients/integrations-state.test.ts index 3ba927f766d..54ab80de121 100644 --- a/tests/integrations-state.test.ts +++ b/tests/clients/integrations-state.test.ts @@ -2,21 +2,21 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { chmodSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { EXPORT_CLIENTS, type ExportModel } from "../src/clients/config-export"; -import { PARSE_FAILED, fileIO, loadTarget, parseConfig } from "../src/integrations/config-io"; -import { serializeDocument } from "../src/integrations/serialize"; +import { EXPORT_CLIENTS, type ExportModel } from "../../src/clients/config-export"; +import { PARSE_FAILED, fileIO, loadTarget, parseConfig } from "../../src/integrations/config-io"; +import { serializeDocument } from "../../src/integrations/serialize"; import { canonicalContribution, semanticContribution, fingerprint, writeRecord, type OwnershipRecord, -} from "../src/integrations/ownership"; -import { INTEGRATION_CLIENT_IDS, isLoopbackOnly } from "../src/integrations/registry"; -import { classifyIntegration, readIntegrationState } from "../src/integrations/state"; -import { createIntegrationStateStore } from "../src/integrations/store"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/integrations/ownership"; +import { INTEGRATION_CLIENT_IDS, isLoopbackOnly } from "../../src/integrations/registry"; +import { classifyIntegration, readIntegrationState } from "../../src/integrations/state"; +import { createIntegrationStateStore } from "../../src/integrations/store"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * Activation coverage for devlog/_fin/260802_client_toggle_api/021 §6. diff --git a/tests/integrations-writer.test.ts b/tests/clients/integrations-writer.test.ts similarity index 98% rename from tests/integrations-writer.test.ts rename to tests/clients/integrations-writer.test.ts index 54c64875ace..0bf81fdb546 100644 --- a/tests/integrations-writer.test.ts +++ b/tests/clients/integrations-writer.test.ts @@ -2,22 +2,22 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdirSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; -import { buildClientContribution, type ExportModel } from "../src/clients/config-export"; -import { fileIO, type IntegrationIO } from "../src/integrations/config-io"; -import { canonicalContribution, fingerprint } from "../src/integrations/ownership"; -import { protectedContributionFingerprint } from "../src/integrations/ownership-policy"; -import { INTEGRATION_CLIENTS } from "../src/integrations/registry"; -import { createIntegrationStateStore, type IntegrationStateStore } from "../src/integrations/store"; -import { exportContextOf, readIntegrationState } from "../src/integrations/state"; +import { buildClientContribution, type ExportModel } from "../../src/clients/config-export"; +import { fileIO, type IntegrationIO } from "../../src/integrations/config-io"; +import { canonicalContribution, fingerprint } from "../../src/integrations/ownership"; +import { protectedContributionFingerprint } from "../../src/integrations/ownership-policy"; +import { INTEGRATION_CLIENTS } from "../../src/integrations/registry"; +import { createIntegrationStateStore, type IntegrationStateStore } from "../../src/integrations/store"; +import { exportContextOf, readIntegrationState } from "../../src/integrations/state"; import { applyIntegration, disableIntegration, overwriteIntegration, restoreIntegration, type IntegrationWriteInput, -} from "../src/integrations/writer"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/integrations/writer"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * Activation coverage for devlog/_fin/260802_client_toggle_api/031 §6. diff --git a/tests/omp-path-contract.test.ts b/tests/clients/omp-path-contract.test.ts similarity index 89% rename from tests/omp-path-contract.test.ts rename to tests/clients/omp-path-contract.test.ts index 295e9115e44..5928ae946b2 100644 --- a/tests/omp-path-contract.test.ts +++ b/tests/clients/omp-path-contract.test.ts @@ -2,8 +2,8 @@ import { describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { ompModelsConfigPath } from "../src/clients/config-export"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { ompModelsConfigPath } from "../../src/clients/config-export"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; function withTempHome(run: (home: string) => void): void { const home = mkdtempSync(join(tmpdir(), "opencodex-omp-home-")); diff --git a/tests/omp-yaml-source-inline-comments.test.ts b/tests/clients/omp-yaml-source-inline-comments.test.ts similarity index 93% rename from tests/omp-yaml-source-inline-comments.test.ts rename to tests/clients/omp-yaml-source-inline-comments.test.ts index 9405f86089c..276c0a77710 100644 --- a/tests/omp-yaml-source-inline-comments.test.ts +++ b/tests/clients/omp-yaml-source-inline-comments.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { patchOmpYamlSource } from "../src/integrations/omp-yaml-source"; +import { patchOmpYamlSource } from "../../src/integrations/omp-yaml-source"; const SOURCE_WITH_NESTED_INLINE_COMMENT = [ "providers:", diff --git a/tests/pi-path-contract.test.ts b/tests/clients/pi-path-contract.test.ts similarity index 94% rename from tests/pi-path-contract.test.ts rename to tests/clients/pi-path-contract.test.ts index 998bb27bd3f..8ffc94fe053 100644 --- a/tests/pi-path-contract.test.ts +++ b/tests/clients/pi-path-contract.test.ts @@ -8,9 +8,9 @@ import { ompModelsConfigPath, piAgentDir, piConfigPath, -} from "../src/clients/config-export"; -import { INTEGRATION_CLIENTS } from "../src/integrations/registry"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/clients/config-export"; +import { INTEGRATION_CLIENTS } from "../../src/integrations/registry"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; function withTempHome(run: (home: string) => void): void { const home = mkdtempSync(join(tmpdir(), "opencodex-pi-home-")); diff --git a/tests/prime-client.test.ts b/tests/clients/prime-client.test.ts similarity index 96% rename from tests/prime-client.test.ts rename to tests/clients/prime-client.test.ts index 2ddb42cf0c9..c88c77508af 100644 --- a/tests/prime-client.test.ts +++ b/tests/clients/prime-client.test.ts @@ -12,9 +12,9 @@ import { primeConfigPath, type ExportContext, type PiGeneratedConfig, -} from "../src/clients/config-export"; -import { INTEGRATION_CLIENTS } from "../src/integrations/registry"; -import type { OcxConfig } from "../src/types"; +} from "../../src/clients/config-export"; +import { INTEGRATION_CLIENTS } from "../../src/integrations/registry"; +import type { OcxConfig } from "../../src/types"; const CONFIG = { port: 10100, diff --git a/tests/remote-catalog.test.ts b/tests/clients/remote-catalog.test.ts similarity index 98% rename from tests/remote-catalog.test.ts rename to tests/clients/remote-catalog.test.ts index 3ac893a4572..b38e0c4587a 100644 --- a/tests/remote-catalog.test.ts +++ b/tests/clients/remote-catalog.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { downloadClientCatalog, HubClientError } from "../src/client/hub-client"; +import { downloadClientCatalog, HubClientError } from "../../src/client/hub-client"; const JSON_HEADERS = { "Content-Type": "application/json", ETag: '"catalog-v1"' }; diff --git a/tests/sync-client-integrations.test.ts b/tests/clients/sync-client-integrations.test.ts similarity index 94% rename from tests/sync-client-integrations.test.ts rename to tests/clients/sync-client-integrations.test.ts index 31d1d952f77..e02d50af8be 100644 --- a/tests/sync-client-integrations.test.ts +++ b/tests/clients/sync-client-integrations.test.ts @@ -2,16 +2,16 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; -import type { ExportModel } from "../src/clients/config-export"; -import { claudeDesktopIntegrationEnabled, grokIntegrationEnabled } from "../src/codex/desired-state"; -import { INTEGRATION_CLIENTS } from "../src/integrations/registry"; -import { IntegrationMutationBusyError, runIntegrationMutationFlight } from "../src/integrations/mutation-flight"; -import { refreshOwnedIntegration } from "../src/integrations/owned-refresh"; -import { createIntegrationStateStore, type IntegrationStateStore } from "../src/integrations/store"; -import type { IntegrationWriterLockSeams } from "../src/integrations/writer-lock"; -import { applyIntegration, disableIntegrationCoordinated } from "../src/integrations/writer"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import type { ExportModel } from "../../src/clients/config-export"; +import { claudeDesktopIntegrationEnabled, grokIntegrationEnabled } from "../../src/codex/desired-state"; +import { INTEGRATION_CLIENTS } from "../../src/integrations/registry"; +import { IntegrationMutationBusyError, runIntegrationMutationFlight } from "../../src/integrations/mutation-flight"; +import { refreshOwnedIntegration } from "../../src/integrations/owned-refresh"; +import { createIntegrationStateStore, type IntegrationStateStore } from "../../src/integrations/store"; +import type { IntegrationWriterLockSeams } from "../../src/integrations/writer-lock"; +import { applyIntegration, disableIntegrationCoordinated } from "../../src/integrations/writer"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * `ocx sync` used to write the Codex catalog and stop, so a Grok fence or a Desktop profile @@ -40,7 +40,7 @@ describe("ocx sync fans out to enabled native clients and owned file integration }); test("Codex runs before the clients that read its catalog, and a refused sync stops the fan-out", async () => { - const src = await Bun.file(new URL("../src/server/management/config-routes.ts", import.meta.url)).text(); + const src = await Bun.file(new URL("../../src/server/management/config-routes.ts", import.meta.url)).text(); const routeStart = src.indexOf('url.pathname === "/api/sync"'); expect(routeStart).toBeGreaterThan(-1); const route = src.slice(routeStart, routeStart + 1400); @@ -52,7 +52,7 @@ describe("ocx sync fans out to enabled native clients and owned file integration }); test("each client is gated on its own toggle and its failure stays non-fatal", async () => { - const src = await Bun.file(new URL("../src/server/management/config-routes.ts", import.meta.url)).text(); + const src = await Bun.file(new URL("../../src/server/management/config-routes.ts", import.meta.url)).text(); const start = src.indexOf("async function syncEnabledClientIntegrations"); expect(start).toBeGreaterThan(-1); const fn = src.slice(start, src.indexOf("\nfunction publicVisionSidecarSettings", start)); @@ -303,7 +303,7 @@ describe("ocx sync refreshes an already-owned MCode integration", () => { }); test("the direct ocx sync command refreshes MCode instead of relying on /api/sync", async () => { - const src = await Bun.file(new URL("../src/cli/dispatch.ts", import.meta.url)).text(); + const src = await Bun.file(new URL("../../src/cli/dispatch.ts", import.meta.url)).text(); const start = src.indexOf("sync: async deps =>"); const command = src.slice(start, src.indexOf("v2: async deps =>", start)); expect(command).toContain("refreshOwnedIntegration"); diff --git a/tests/client-config-export-new-clients.test.ts b/tests/config/client-config-export-new-clients.test.ts similarity index 99% rename from tests/client-config-export-new-clients.test.ts rename to tests/config/client-config-export-new-clients.test.ts index 81cd5379b61..6b6b4c4e803 100644 --- a/tests/client-config-export-new-clients.test.ts +++ b/tests/config/client-config-export-new-clients.test.ts @@ -22,8 +22,8 @@ import { type HermesGeneratedConfig, type KimiGeneratedConfig, type OpenclawGeneratedConfig, -} from "../src/clients/config-export"; -import type { OcxConfig } from "../src/types"; +} from "../../src/clients/config-export"; +import type { OcxConfig } from "../../src/types"; /** * WP1 coverage for the four clients added past OpenCode and Pi diff --git a/tests/client-config-export.test.ts b/tests/config/client-config-export.test.ts similarity index 99% rename from tests/client-config-export.test.ts rename to tests/config/client-config-export.test.ts index eecd8889a27..19f1edc8daa 100644 --- a/tests/client-config-export.test.ts +++ b/tests/config/client-config-export.test.ts @@ -20,10 +20,10 @@ import { type ExportModel, type OpencodeGeneratedConfig, type PiGeneratedConfig, -} from "../src/clients/config-export"; -import { buildOpencodeProviderBlockFromCatalog, opencodeGlobalConfigPath } from "../src/cli/opencode"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/clients/config-export"; +import { buildOpencodeProviderBlockFromCatalog, opencodeGlobalConfigPath } from "../../src/cli/opencode"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * Fixture covering the four rows that exercise every emission branch: native, diff --git a/tests/client-config-new-clients.test.ts b/tests/config/client-config-new-clients.test.ts similarity index 98% rename from tests/client-config-new-clients.test.ts rename to tests/config/client-config-new-clients.test.ts index 00513d20478..65b52727c93 100644 --- a/tests/client-config-new-clients.test.ts +++ b/tests/config/client-config-new-clients.test.ts @@ -15,9 +15,9 @@ import { type HermesGeneratedConfig, type KimiGeneratedConfig, type OpenclawGeneratedConfig, -} from "../src/clients/config-export"; -import { serializeDocument } from "../src/integrations/serialize"; -import type { OcxConfig } from "../src/types"; +} from "../../src/clients/config-export"; +import { serializeDocument } from "../../src/integrations/serialize"; +import type { OcxConfig } from "../../src/types"; /** * Activation coverage for the four clients added in WP1 diff --git a/tests/config-load-degrade.test.ts b/tests/config/config-load-degrade.test.ts similarity index 97% rename from tests/config-load-degrade.test.ts rename to tests/config/config-load-degrade.test.ts index 43437a9a4b4..3d26ffd107d 100644 --- a/tests/config-load-degrade.test.ts +++ b/tests/config/config-load-degrade.test.ts @@ -8,8 +8,8 @@ import { loadConfig, saveConfig, validateConfigCandidate, -} from "../src/config"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/config"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let home = ""; let previousHome: string | undefined; diff --git a/tests/config-mutation-lock.test.ts b/tests/config/config-mutation-lock.test.ts similarity index 89% rename from tests/config-mutation-lock.test.ts rename to tests/config/config-mutation-lock.test.ts index bc3d22c603a..c0b37c28b46 100644 --- a/tests/config-mutation-lock.test.ts +++ b/tests/config/config-mutation-lock.test.ts @@ -2,11 +2,12 @@ import { afterEach, beforeEach, expect, test } from "bun:test"; import { existsSync, mkdtempSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import { pathToFileURL } from "node:url"; -import { ConfigMutationLockError, loadConfig, saveConfig, withConfigMutationLockSync } from "../src/config"; -import { CodexCredentialRefreshLockTimeoutError, getCodexAccountCredential, saveCodexAccountCredential } from "../src/codex/account-store"; -import type { OcxConfig } from "../src/types"; -import { ManagementRequest, managementHeaders } from "./helpers/management-auth"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { ConfigMutationLockError, loadConfig, saveConfig, withConfigMutationLockSync } from "../../src/config"; +import { CodexCredentialRefreshLockTimeoutError, getCodexAccountCredential, saveCodexAccountCredential } from "../../src/codex/account-store"; +import type { OcxConfig } from "../../src/types"; +import { ManagementRequest, managementHeaders } from "../helpers/management-auth"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath, repoRoot } from "../helpers/repo-root"; let testRoot = ""; let previousOpencodexHome: string | undefined; @@ -50,7 +51,7 @@ test("a live cross-process holder is not stolen and runtime writers fail immedia saveConfig(config()); const readyPath = join(testRoot, "holder-ready"); const releasePath = join(testRoot, "holder-release"); - const configModuleUrl = pathToFileURL(join(import.meta.dir, "../src/config.ts")).href; + const configModuleUrl = pathToFileURL(repoPath("src/config.ts")).href; const childSource = ` import { existsSync, writeFileSync } from "node:fs"; import { withConfigMutationLockSync } from ${JSON.stringify(configModuleUrl)}; @@ -60,7 +61,7 @@ test("a live cross-process holder is not stolen and runtime writers fail immedia }); `; const child = Bun.spawn([process.execPath, "-e", childSource], { - cwd: join(import.meta.dir, ".."), + cwd: repoRoot(), env: { ...process.env, OPENCODEX_HOME: testRoot }, stdin: "ignore", stdout: "pipe", @@ -106,7 +107,7 @@ test("a live cross-process holder is not stolen and runtime writers fail immedia test("an abruptly exited holder releases the OS-backed transaction without stale recovery", async () => { saveConfig(config()); const enteredPath = join(testRoot, "crashed-holder-entered"); - const configModuleUrl = pathToFileURL(join(import.meta.dir, "../src/config.ts")).href; + const configModuleUrl = pathToFileURL(repoPath("src/config.ts")).href; const childSource = ` import { writeFileSync } from "node:fs"; import { withConfigMutationLockSync } from ${JSON.stringify(configModuleUrl)}; @@ -116,7 +117,7 @@ test("an abruptly exited holder releases the OS-backed transaction without stale }); `; const child = Bun.spawn([process.execPath, "-e", childSource], { - cwd: join(import.meta.dir, ".."), + cwd: repoRoot(), env: { ...process.env, OPENCODEX_HOME: testRoot }, stdin: "ignore", stdout: "pipe", @@ -142,7 +143,7 @@ test("management API maps config mutation lock contention to retryable 503", asy saveConfig(config()); const readyPath = join(testRoot, "mgmt-holder-ready"); const releasePath = join(testRoot, "mgmt-holder-release"); - const configModuleUrl = pathToFileURL(join(import.meta.dir, "../src/config.ts")).href; + const configModuleUrl = pathToFileURL(repoPath("src/config.ts")).href; const childSource = ` import { existsSync, writeFileSync } from "node:fs"; import { withConfigMutationLockSync } from ${JSON.stringify(configModuleUrl)}; @@ -152,7 +153,7 @@ test("management API maps config mutation lock contention to retryable 503", asy }); `; const child = Bun.spawn([process.execPath, "-e", childSource], { - cwd: join(import.meta.dir, ".."), + cwd: repoRoot(), env: { ...process.env, OPENCODEX_HOME: testRoot }, stdin: "ignore", stdout: "pipe", @@ -161,7 +162,7 @@ test("management API maps config mutation lock contention to retryable 503", asy try { await waitForPath(readyPath); - const { handleManagementAPI } = await import("../src/server/management-api"); + const { handleManagementAPI } = await import("../../src/server/management-api"); const url = new URL("http://localhost/api/codex-auth/auto-switch"); const response = await handleManagementAPI( new ManagementRequest(url, { diff --git a/tests/config-ownership-uninstall.test.ts b/tests/config/config-ownership-uninstall.test.ts similarity index 98% rename from tests/config-ownership-uninstall.test.ts rename to tests/config/config-ownership-uninstall.test.ts index 512bb3ff211..79c8888f90b 100644 --- a/tests/config-ownership-uninstall.test.ts +++ b/tests/config/config-ownership-uninstall.test.ts @@ -7,9 +7,9 @@ import { CONFIG_UNINSTALL_MANIFEST, recordOwnedConfigPath, removeOwnedConfigState, -} from "../src/lib/config-ownership"; -import { getDefaultConfig, saveConfig } from "../src/config"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/lib/config-ownership"; +import { getDefaultConfig, saveConfig } from "../../src/config"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; describe("owned config uninstall", () => { test("first owned write creates a missing config root and its metadata", () => { diff --git a/tests/config-rebase-provenance-writers.test.ts b/tests/config/config-rebase-provenance-writers.test.ts similarity index 92% rename from tests/config-rebase-provenance-writers.test.ts rename to tests/config/config-rebase-provenance-writers.test.ts index c6d7ecf8148..2ad97f09aa3 100644 --- a/tests/config-rebase-provenance-writers.test.ts +++ b/tests/config/config-rebase-provenance-writers.test.ts @@ -1,6 +1,7 @@ import { expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; +import { repoPath } from "../helpers/repo-root"; const writerContracts: Record = { "src/server/management/agent-settings-routes.ts": [ @@ -24,7 +25,7 @@ const writerContracts: Record = { test("every enumerated top-level deletion writer records config rebase provenance", () => { for (const [path, keys] of Object.entries(writerContracts)) { - const source = readFileSync(join(import.meta.dir, "..", path), "utf8"); + const source = readFileSync(repoPath(path), "utf8"); for (const key of keys) { const configCall = `deleteConfigTopLevelKey(config, "${key}")`; const cliCall = `deleteConfigTopLevelKey(cfg, "${key}")`; @@ -39,7 +40,7 @@ test("every enumerated top-level deletion writer records config rebase provenanc test("live-config writers contain no untracked direct top-level deletion", () => { for (const path of Object.keys(writerContracts)) { - const source = readFileSync(join(import.meta.dir, "..", path), "utf8"); + const source = readFileSync(repoPath(path), "utf8"); expect(source.match(/delete (?:config|cfg)\.[A-Za-z_$][A-Za-z0-9_$]*[;\n]/g) ?? [], path) .toEqual([]); expect(source.match(/delete config\[[^\]]+\]/g) ?? [], path).toEqual([]); diff --git a/tests/config-save-boundary.test.ts b/tests/config/config-save-boundary.test.ts similarity index 97% rename from tests/config-save-boundary.test.ts rename to tests/config/config-save-boundary.test.ts index eeafc12a55f..36dac683039 100644 --- a/tests/config-save-boundary.test.ts +++ b/tests/config/config-save-boundary.test.ts @@ -1,6 +1,7 @@ import { expect, test } from "bun:test"; import { readFileSync, readdirSync } from "node:fs"; import { join } from "node:path"; +import { repoPath } from "../helpers/repo-root"; /** * "Every live-config writer goes through the guarded saver" is a claim until something @@ -12,7 +13,7 @@ import { join } from "node:path"; * requests, against a config nobody else holds. */ -const SRC = join(import.meta.dir, "..", "src"); +const SRC = repoPath("src"); /** Modules that hold a LIVE server config and must use the wrapper. */ const GUARDED_FILES = [ diff --git a/tests/config-user-edits.test.ts b/tests/config/config-user-edits.test.ts similarity index 98% rename from tests/config-user-edits.test.ts rename to tests/config/config-user-edits.test.ts index 9e26bfa4750..38ac41aa378 100644 --- a/tests/config-user-edits.test.ts +++ b/tests/config/config-user-edits.test.ts @@ -15,16 +15,16 @@ import { saveConfig, saveConfigPreservingClaudeCode, validateConfigCandidate, -} from "../src/config"; -import { legacyCustomModelCatalogSlugs } from "../src/codex/custom-model-catalog-migration"; -import { rateLimitRetryPolicyFor } from "../src/providers/key-failover"; +} from "../../src/config"; +import { legacyCustomModelCatalogSlugs } from "../../src/codex/custom-model-catalog-migration"; +import { rateLimitRetryPolicyFor } from "../../src/providers/key-failover"; import { activeUserCostOverlays, refreshUserCostOverlays, resetPreservedDiskOnlyProvidersForTests, -} from "../src/usage/user-cost-overlays"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/usage/user-cost-overlays"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * A user or cooperating process can edit config.json while the proxy runs. @@ -536,7 +536,7 @@ test("provider names with control characters are JSON-escaped before retryOn429 // R4-1: the request path. A 429 mid-turn rotates a key and saves, with no user action. test("a 429 key rotation does not clobber the hand edit", async () => { - const { rotateKeyOn429 } = await import("../src/providers/key-failover"); + const { rotateKeyOn429 } = await import("../../src/providers/key-failover"); const live = loadConfig(); live.providers.pool = { adapter: "openai-chat", diff --git a/tests/expand-user-path.test.ts b/tests/config/expand-user-path.test.ts similarity index 95% rename from tests/expand-user-path.test.ts rename to tests/config/expand-user-path.test.ts index ed9e811ea2d..f1600ec45b3 100644 --- a/tests/expand-user-path.test.ts +++ b/tests/config/expand-user-path.test.ts @@ -1,7 +1,7 @@ import { afterEach, describe, expect, test } from "bun:test"; import { homedir } from "node:os"; import { join } from "node:path"; -import { expandUserPath, getConfigDir } from "../src/config"; +import { expandUserPath, getConfigDir } from "../../src/config"; const previousOpenCodexHome = process.env.OPENCODEX_HOME; diff --git a/tests/settings-oauth-open-browser.test.ts b/tests/config/settings-oauth-open-browser.test.ts similarity index 91% rename from tests/settings-oauth-open-browser.test.ts rename to tests/config/settings-oauth-open-browser.test.ts index b897c3141b0..5d2cefae153 100644 --- a/tests/settings-oauth-open-browser.test.ts +++ b/tests/config/settings-oauth-open-browser.test.ts @@ -9,12 +9,12 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { loadConfig, saveConfig } from "../src/config"; -import { handleManagementAPI, type ManagementApiDeps } from "../src/server/management-api"; -import { invalidateStartupHealthCache } from "../src/server/startup-health-cache"; -import type { OcxConfig } from "../src/types"; -import { startupHealthFixture } from "./helpers/startup-health"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { loadConfig, saveConfig } from "../../src/config"; +import { handleManagementAPI, type ManagementApiDeps } from "../../src/server/management-api"; +import { invalidateStartupHealthCache } from "../../src/server/startup-health-cache"; +import type { OcxConfig } from "../../src/types"; +import { startupHealthFixture } from "../helpers/startup-health"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let TEST_DIR = ""; const previousHome = process.env.OPENCODEX_HOME; diff --git a/tests/settings-startup-health-seam.test.ts b/tests/config/settings-startup-health-seam.test.ts similarity index 85% rename from tests/settings-startup-health-seam.test.ts rename to tests/config/settings-startup-health-seam.test.ts index 657e49aed71..f17df8c63e8 100644 --- a/tests/settings-startup-health-seam.test.ts +++ b/tests/config/settings-startup-health-seam.test.ts @@ -1,8 +1,8 @@ import { expect, test } from "bun:test"; -import { handleManagementAPI, type ManagementApiDeps } from "../src/server/management-api"; -import type { OcxConfig } from "../src/types"; -import { ManagementRequest as Request } from "./helpers/management-auth"; -import { startupHealthFixture } from "./helpers/startup-health"; +import { handleManagementAPI, type ManagementApiDeps } from "../../src/server/management-api"; +import type { OcxConfig } from "../../src/types"; +import { ManagementRequest as Request } from "../helpers/management-auth"; +import { startupHealthFixture } from "../helpers/startup-health"; function baseConfig(): OcxConfig { return { diff --git a/tests/settings-stream-mode.test.ts b/tests/config/settings-stream-mode.test.ts similarity index 96% rename from tests/settings-stream-mode.test.ts rename to tests/config/settings-stream-mode.test.ts index 6e78651aa01..272e45be6ae 100644 --- a/tests/settings-stream-mode.test.ts +++ b/tests/config/settings-stream-mode.test.ts @@ -11,28 +11,28 @@ 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 { getConfigPath, loadConfig, saveConfig } from "../src/config"; -import { handleManagementAPI, type ManagementApiDeps } from "../src/server/management-api"; -import { invalidateStartupHealthCache } from "../src/server/startup-health-cache"; -import { USAGE_RANGES, USAGE_SURFACES } from "../src/usage/summary"; -import type { OcxConfig } from "../src/types"; +import { getConfigPath, loadConfig, saveConfig } from "../../src/config"; +import { handleManagementAPI, type ManagementApiDeps } from "../../src/server/management-api"; +import { invalidateStartupHealthCache } from "../../src/server/startup-health-cache"; +import { USAGE_RANGES, USAGE_SURFACES } from "../../src/usage/summary"; +import type { OcxConfig } from "../../src/types"; import { appOwnedBytesSnapshot, configureAppOwnedMemoryBudget, registerRetainedStore, resetAppOwnedMemoryForTests, -} from "../src/lib/app-owned-memory"; +} from "../../src/lib/app-owned-memory"; import { evictOldestUsageSummaryForBudget, getUsageSummaryCacheEntry, resetUsageSummaryCacheForTests, setUsageSummaryCacheEntry, usageSummaryRetainedStoreSnapshot, -} from "../src/server/management/usage-summary-cache"; -import { resetUsageAggregateCacheForTests } from "../src/server/management/usage-aggregate-cache"; -import { catalogConvergenceFactory } from "./helpers/catalog-convergence"; -import { startupHealthFixture } from "./helpers/startup-health"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/server/management/usage-summary-cache"; +import { resetUsageAggregateCacheForTests } from "../../src/server/management/usage-aggregate-cache"; +import { catalogConvergenceFactory } from "../helpers/catalog-convergence"; +import { startupHealthFixture } from "../helpers/startup-health"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let TEST_DIR = ""; const previousHome = process.env.OPENCODEX_HOME; @@ -147,7 +147,7 @@ describe("GET /api/settings", () => { const { persistEffortClamp, resetCodexRuntimeResolveCacheForTests, - } = await import("../src/codex/runtime"); + } = await import("../../src/codex/runtime"); resetCodexRuntimeResolveCacheForTests(); const fakeCodex = process.platform === "win32" @@ -603,4 +603,4 @@ describe("config.json schema resilience", () => { expect(reloaded.providers.openai?.apiKey).toBe("sk-secret-value"); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/types-barrel-identity.test.ts b/tests/config/types-barrel-identity.test.ts similarity index 95% rename from tests/types-barrel-identity.test.ts rename to tests/config/types-barrel-identity.test.ts index 975c6650cc9..120d36f4f63 100644 --- a/tests/types-barrel-identity.test.ts +++ b/tests/config/types-barrel-identity.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import * as barrel from "../src/types"; -import * as tools from "../src/types/tools"; -import * as wire from "../src/types/wire"; +import * as barrel from "../../src/types"; +import * as tools from "../../src/types/tools"; +import * as wire from "../../src/types/wire"; /** * The mega-file split turned `src/types.ts` into a re-export barrel. Its correctness diff --git a/tests/url-normalization.test.ts b/tests/config/url-normalization.test.ts similarity index 100% rename from tests/url-normalization.test.ts rename to tests/config/url-normalization.test.ts diff --git a/tests/yaml-fragment-source.test.ts b/tests/config/yaml-fragment-source.test.ts similarity index 98% rename from tests/yaml-fragment-source.test.ts rename to tests/config/yaml-fragment-source.test.ts index 8fba2d1af0a..68450fb7f91 100644 --- a/tests/yaml-fragment-source.test.ts +++ b/tests/config/yaml-fragment-source.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { patchYamlFragmentSource } from "../src/integrations/omp-yaml-source"; +import { patchYamlFragmentSource } from "../../src/integrations/omp-yaml-source"; const DSH_PATH = ["llm-pi-ai", "providers", "opencodex"] as const; const VALUE = { api: "openai-responses", baseURL: "http://127.0.0.1:10100/v1" }; diff --git a/tests/integrations-invariants.test.ts b/tests/integrations-invariants.test.ts index 1bf30ec95a3..b14a6e908c1 100644 --- a/tests/integrations-invariants.test.ts +++ b/tests/integrations-invariants.test.ts @@ -701,7 +701,7 @@ describe("the store's own root stays tidy", () => { test("a full lifecycle leaves exactly records, journal and snapshots", () => { /* * Scoped honestly: listing the root cannot prove nothing was written - * OUTSIDE it — `tests/integrations-journal.test.ts` owns that claim by + * OUTSIDE it — `tests/clients/integrations-journal.test.ts` owns that claim by * asserting the real config dir's manifest is untouched. What this * catches is a new bookkeeping file appearing without anyone deciding it * should exist. diff --git a/tests/abort-idle-deadline.test.ts b/tests/lib/abort-idle-deadline.test.ts similarity index 97% rename from tests/abort-idle-deadline.test.ts rename to tests/lib/abort-idle-deadline.test.ts index 0ac3c84abe8..9c8422ba53f 100644 --- a/tests/abort-idle-deadline.test.ts +++ b/tests/lib/abort-idle-deadline.test.ts @@ -1,5 +1,5 @@ import { expect, test } from "bun:test"; -import { idleDeadline } from "../src/lib/abort"; +import { idleDeadline } from "../../src/lib/abort"; const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); diff --git a/tests/acl-error-classification.test.ts b/tests/lib/acl-error-classification.test.ts similarity index 97% rename from tests/acl-error-classification.test.ts rename to tests/lib/acl-error-classification.test.ts index 83fc743dade..37a67108915 100644 --- a/tests/acl-error-classification.test.ts +++ b/tests/lib/acl-error-classification.test.ts @@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test"; import { adapterFailureFromMessage, inferHttpStatusFromAdapterMessage, -} from "../src/lib/errors"; +} from "../../src/lib/errors"; describe("Windows ACL error classification", () => { test("maps local ACL hardening failures to 503 server errors", () => { diff --git a/tests/bun-stream-caps.test.ts b/tests/lib/bun-stream-caps.test.ts similarity index 99% rename from tests/bun-stream-caps.test.ts rename to tests/lib/bun-stream-caps.test.ts index e373683c35a..b4de6e81190 100644 --- a/tests/bun-stream-caps.test.ts +++ b/tests/lib/bun-stream-caps.test.ts @@ -8,7 +8,7 @@ import { MIN_FIXED_BUN_VERSION, parseBunVersion, selectEagerPath, -} from "../src/lib/bun-stream-caps"; +} from "../../src/lib/bun-stream-caps"; describe("isWin32EagerRewrite (#864 transport gate)", () => { test("win32 + rewrite → eager inline rewrite; everything else stays out", () => { diff --git a/tests/clearable-deadline.test.ts b/tests/lib/clearable-deadline.test.ts similarity index 96% rename from tests/clearable-deadline.test.ts rename to tests/lib/clearable-deadline.test.ts index 70097eb8d1e..156f5ad0037 100644 --- a/tests/clearable-deadline.test.ts +++ b/tests/lib/clearable-deadline.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { clearableDeadline } from "../src/lib/abort"; +import { clearableDeadline } from "../../src/lib/abort"; const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); diff --git a/tests/credential-redirect-guard.test.ts b/tests/lib/credential-redirect-guard.test.ts similarity index 81% rename from tests/credential-redirect-guard.test.ts rename to tests/lib/credential-redirect-guard.test.ts index e8fcef70bb5..81213abd1ef 100644 --- a/tests/credential-redirect-guard.test.ts +++ b/tests/lib/credential-redirect-guard.test.ts @@ -9,6 +9,7 @@ * the second pins the fix at every credential-bearing call site. */ import { describe, expect, test } from "bun:test"; +import { repoPath } from "../helpers/repo-root"; describe("Bun forwards nonstandard headers across a redirect", () => { test("Authorization is dropped but Codex identity headers are not", async () => { @@ -57,17 +58,17 @@ describe("Bun forwards nonstandard headers across a redirect", () => { describe("credential-bearing sidecars refuse to follow redirects", () => { const sites: Array<{ file: string; label: string }> = [ - { file: "../src/server/images.ts", label: "images relay" }, - { file: "../src/images/xai-client.ts", label: "xAI images client" }, - { file: "../src/server/live.ts", label: "live relay" }, - { file: "../src/server/search.ts", label: "search relay" }, - { file: "../src/web-search/executor.ts", label: "web-search sidecar" }, - { file: "../src/vision/describe.ts", label: "vision sidecar" }, + { file: "src/server/images.ts", label: "images relay" }, + { file: "src/images/xai-client.ts", label: "xAI images client" }, + { file: "src/server/live.ts", label: "live relay" }, + { file: "src/server/search.ts", label: "search relay" }, + { file: "src/web-search/executor.ts", label: "web-search sidecar" }, + { file: "src/vision/describe.ts", label: "vision sidecar" }, ]; for (const { file, label } of sites) { test(`${label} sets redirect: "manual"`, async () => { - const source = await Bun.file(new URL(file, import.meta.url)).text(); + const source = await Bun.file(repoPath(file)).text(); expect(source).toContain('redirect: "manual"'); }); } @@ -77,11 +78,11 @@ describe("credential-bearing sidecars refuse to follow redirects", () => { // centrally (#914). Assert the shared helper still does that, so the two families cannot // drift apart silently. test("the shared credential-bearing fetch helper still applies manual redirects", async () => { - const helper = await Bun.file(new URL("../src/server/responses/fetch-helpers.ts", import.meta.url)).text(); + const helper = await Bun.file(new URL("../../src/server/responses/fetch-helpers.ts", import.meta.url)).text(); expect(helper).toContain('redirect: "manual" as const'); // And the callers still opt in for forward auth rather than dropping the flag. - const compact = await Bun.file(new URL("../src/server/responses/compact.ts", import.meta.url)).text(); + const compact = await Bun.file(new URL("../../src/server/responses/compact.ts", import.meta.url)).text(); expect(compact).toContain('sendProvider.authMode === "forward"'); }); }); diff --git a/tests/debug.test.ts b/tests/lib/debug.test.ts similarity index 96% rename from tests/debug.test.ts rename to tests/lib/debug.test.ts index 25fe1570944..6ce7359d2de 100644 --- a/tests/debug.test.ts +++ b/tests/lib/debug.test.ts @@ -1,10 +1,10 @@ import { afterEach, describe, expect, spyOn, test } from "bun:test"; -import { appendDebugLogLine, debugBufferMetrics, getDebugLogEntries, resetDebugLogBufferForTests, subscribeDebugLogEntries } from "../src/lib/debug-log-buffer"; -import { ResourceAdmissionError, RETAINED_TRUNCATION_MARKER, retainedUtf8Bytes } from "../src/lib/admission"; -import { getInjectionDebugLogEntries, injectionDebugLog, resetInjectionDebugLogBufferForTests } from "../src/lib/injection-debug-log"; -import { markActivity, activityBreadcrumb } from "../src/lib/sidecar-tracker"; -import { debugDroppedFrame, debugProviderDiagnostic } from "../src/lib/debug"; -import { resetDebugSettingsForTests, setDebugSettings } from "../src/lib/debug-settings"; +import { appendDebugLogLine, debugBufferMetrics, getDebugLogEntries, resetDebugLogBufferForTests, subscribeDebugLogEntries } from "../../src/lib/debug-log-buffer"; +import { ResourceAdmissionError, RETAINED_TRUNCATION_MARKER, retainedUtf8Bytes } from "../../src/lib/admission"; +import { getInjectionDebugLogEntries, injectionDebugLog, resetInjectionDebugLogBufferForTests } from "../../src/lib/injection-debug-log"; +import { markActivity, activityBreadcrumb } from "../../src/lib/sidecar-tracker"; +import { debugDroppedFrame, debugProviderDiagnostic } from "../../src/lib/debug"; +import { resetDebugSettingsForTests, setDebugSettings } from "../../src/lib/debug-settings"; describe("debug frame logging", () => { const previous = process.env.OCX_DEBUG; diff --git a/tests/optional-shutdown-hooks.test.ts b/tests/lib/optional-shutdown-hooks.test.ts similarity index 98% rename from tests/optional-shutdown-hooks.test.ts rename to tests/lib/optional-shutdown-hooks.test.ts index 72cc2b676f2..b778cecf033 100644 --- a/tests/optional-shutdown-hooks.test.ts +++ b/tests/lib/optional-shutdown-hooks.test.ts @@ -7,12 +7,12 @@ import { startLabAutomationScheduler, stopLabAutomationScheduler, isLabAutomationSchedulerRunning, -} from "../src/lab/automation/orchestrator"; +} from "../../src/lab/automation/orchestrator"; import { registerOptionalShutdownHook, runOptionalShutdownHooks, resetOptionalShutdownHooksForTests, -} from "../src/lib/optional-shutdown-hooks"; +} from "../../src/lib/optional-shutdown-hooks"; describe("optional shutdown hooks", () => { beforeEach(() => resetOptionalShutdownHooksForTests()); diff --git a/tests/pinned-http.test.ts b/tests/lib/pinned-http.test.ts similarity index 97% rename from tests/pinned-http.test.ts rename to tests/lib/pinned-http.test.ts index 24d81ed4561..1ec4c425c4d 100644 --- a/tests/pinned-http.test.ts +++ b/tests/lib/pinned-http.test.ts @@ -1,6 +1,6 @@ import { createServer, type Server, type Socket } from "node:net"; import { afterEach, describe, expect, test } from "bun:test"; -import { PinnedHttpError, pinnedHttpGet } from "../src/lib/pinned-http"; +import { PinnedHttpError, pinnedHttpGet } from "../../src/lib/pinned-http"; let server: Server | undefined; const sockets = new Set(); diff --git a/tests/privacy-mask-account.test.ts b/tests/lib/privacy-mask-account.test.ts similarity index 93% rename from tests/privacy-mask-account.test.ts rename to tests/lib/privacy-mask-account.test.ts index 181814e4351..017e265a9c1 100644 --- a/tests/privacy-mask-account.test.ts +++ b/tests/lib/privacy-mask-account.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { maskAccountId } from "../src/lib/privacy"; +import { maskAccountId } from "../../src/lib/privacy"; describe("maskAccountId", () => { test("redacts long account ids to account-…suffix", () => { diff --git a/tests/process-control-graceful.test.ts b/tests/lib/process-control-graceful.test.ts similarity index 97% rename from tests/process-control-graceful.test.ts rename to tests/lib/process-control-graceful.test.ts index 54c9ea6b9b5..ea1c5189c6c 100644 --- a/tests/process-control-graceful.test.ts +++ b/tests/lib/process-control-graceful.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { gracefulStopHost, stopProxyGracefully } from "../src/lib/process-control"; +import { gracefulStopHost, stopProxyGracefully } from "../../src/lib/process-control"; function okResponse(): Response { return new Response(JSON.stringify({ success: true }), { status: 200 }); diff --git a/tests/process-control.test.ts b/tests/lib/process-control.test.ts similarity index 84% rename from tests/process-control.test.ts rename to tests/lib/process-control.test.ts index 3669a5ad43e..0b0ffcb113c 100644 --- a/tests/process-control.test.ts +++ b/tests/lib/process-control.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { isProcessAlive, waitForExit } from "../src/lib/process-control"; +import { isProcessAlive, waitForExit } from "../../src/lib/process-control"; describe("process control helpers", () => { test("reports the current process as alive", () => { diff --git a/tests/reasoning-replay-scope-source.test.ts b/tests/lib/reasoning-replay-scope-source.test.ts similarity index 95% rename from tests/reasoning-replay-scope-source.test.ts rename to tests/lib/reasoning-replay-scope-source.test.ts index 8db776ae306..db7f8a05daa 100644 --- a/tests/reasoning-replay-scope-source.test.ts +++ b/tests/lib/reasoning-replay-scope-source.test.ts @@ -1,9 +1,10 @@ import { describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; +import { repoPath } from "../helpers/repo-root"; const source = (relative: string): string => - readFileSync(join(import.meta.dir, "..", "src", ...relative.split("/")), "utf8"); + readFileSync(repoPath("src", ...relative.split("/")), "utf8"); describe("reasoning replay scope propagation", () => { test("every production bridge call passes the provider-bound scope holder", () => { diff --git a/tests/redact.test.ts b/tests/lib/redact.test.ts similarity index 99% rename from tests/redact.test.ts rename to tests/lib/redact.test.ts index a1d75a3219d..13e912f34a1 100644 --- a/tests/redact.test.ts +++ b/tests/lib/redact.test.ts @@ -5,7 +5,7 @@ import { redactSecretString, redactSecrets, redactUrlForLog, -} from "../src/lib/redact"; +} from "../../src/lib/redact"; describe("redactSecretString", () => { test("masks bearer, api, access, refresh, and profile values", () => { diff --git a/tests/remove-tree-helper.test.ts b/tests/lib/remove-tree-helper.test.ts similarity index 95% rename from tests/remove-tree-helper.test.ts rename to tests/lib/remove-tree-helper.test.ts index f7c4cb4b173..4c4024e697c 100644 --- a/tests/remove-tree-helper.test.ts +++ b/tests/lib/remove-tree-helper.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; function codedError(code: string, message = code): Error & { code: string } { return Object.assign(new Error(message), { code }); diff --git a/tests/self-launch-argv.test.ts b/tests/lib/self-launch-argv.test.ts similarity index 91% rename from tests/self-launch-argv.test.ts rename to tests/lib/self-launch-argv.test.ts index f4555db2c3f..b9f1cdaeeea 100644 --- a/tests/self-launch-argv.test.ts +++ b/tests/lib/self-launch-argv.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { selfLaunchArgv } from "../src/lib/self-launch-argv"; +import { selfLaunchArgv } from "../../src/lib/self-launch-argv"; describe("selfLaunchArgv", () => { test("uses command arguments directly for a standalone executable", () => { diff --git a/tests/stall-timeout.test.ts b/tests/lib/stall-timeout.test.ts similarity index 96% rename from tests/stall-timeout.test.ts rename to tests/lib/stall-timeout.test.ts index 81e8fd3ab03..f1b53700e8b 100644 --- a/tests/stall-timeout.test.ts +++ b/tests/lib/stall-timeout.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { DEFAULT_STALL_TIMEOUT_SEC, resolveStallTimeoutSec } from "../src/stall-timeout"; +import { DEFAULT_STALL_TIMEOUT_SEC, resolveStallTimeoutSec } from "../../src/stall-timeout"; describe("resolveStallTimeoutSec", () => { test("defaults to 300 seconds when unset", () => { diff --git a/tests/strict-semver.test.ts b/tests/lib/strict-semver.test.ts similarity index 98% rename from tests/strict-semver.test.ts rename to tests/lib/strict-semver.test.ts index e47d511f2be..9ed0203eb04 100644 --- a/tests/strict-semver.test.ts +++ b/tests/lib/strict-semver.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { parseStrictSemver } from "../src/lib/strict-semver"; +import { parseStrictSemver } from "../../src/lib/strict-semver"; /** * The prerelease section used to be matched by the semver.org pattern verbatim, whose three diff --git a/tests/system-restart-contract-security.test.ts b/tests/lib/system-restart-contract-security.test.ts similarity index 97% rename from tests/system-restart-contract-security.test.ts rename to tests/lib/system-restart-contract-security.test.ts index 337d313c349..f444e276a16 100644 --- a/tests/system-restart-contract-security.test.ts +++ b/tests/lib/system-restart-contract-security.test.ts @@ -4,7 +4,7 @@ import { SYSTEM_RESTART_PATH, createSystemRestartCapability, verifySystemRestartCapability, -} from "../src/lib/system-restart-contract"; +} from "../../src/lib/system-restart-contract"; const SECRET = "A".repeat(43); const NONCE = "B".repeat(43); diff --git a/tests/token-estimate.test.ts b/tests/lib/token-estimate.test.ts similarity index 99% rename from tests/token-estimate.test.ts rename to tests/lib/token-estimate.test.ts index a911a4ac2b7..a7ba989da4d 100644 --- a/tests/token-estimate.test.ts +++ b/tests/lib/token-estimate.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { capEstimateAtContextWindow, charsPerToken, estimateTokens } from "../src/lib/token-estimate"; +import { capEstimateAtContextWindow, charsPerToken, estimateTokens } from "../../src/lib/token-estimate"; describe("script-segmented ratio", () => { const korean = "한국어 텍스트는 토큰 밀도가 높아서 영어 기준 추정이 과소계산됩니다 ".repeat(10); diff --git a/tests/transient-budget-scope-source.test.ts b/tests/lib/transient-budget-scope-source.test.ts similarity index 96% rename from tests/transient-budget-scope-source.test.ts rename to tests/lib/transient-budget-scope-source.test.ts index 437973ba32c..3c63b493df4 100644 --- a/tests/transient-budget-scope-source.test.ts +++ b/tests/lib/transient-budget-scope-source.test.ts @@ -1,9 +1,10 @@ import { describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; +import { repoPath } from "../helpers/repo-root"; const source = (relative: string): string => - readFileSync(join(import.meta.dir, "..", "src", ...relative.split("/")), "utf8"); + readFileSync(repoPath("src", ...relative.split("/")), "utf8"); /** * `transientRetryOn5xx.attempts` is ONE request-wide total-send budget, not a per-leg diff --git a/tests/upstream-retry.test.ts b/tests/lib/upstream-retry.test.ts similarity index 99% rename from tests/upstream-retry.test.ts rename to tests/lib/upstream-retry.test.ts index db6a3df5b65..59fca586372 100644 --- a/tests/upstream-retry.test.ts +++ b/tests/lib/upstream-retry.test.ts @@ -6,7 +6,7 @@ import { releaseResponseBodyBestEffort, retryBackoffDelayMs, sleepWithHeartbeats, -} from "../src/lib/upstream-retry"; +} from "../../src/lib/upstream-retry"; function bunResetError(): Error { // Shape of Bun's fetch rejection on a stale pooled socket. diff --git a/tests/test-layout-tooling.test.ts b/tests/test-layout-tooling.test.ts index dde2112c4e7..6268f6cf853 100644 --- a/tests/test-layout-tooling.test.ts +++ b/tests/test-layout-tooling.test.ts @@ -36,6 +36,7 @@ describe("rewriteSpecifier", () => { (s: string) => `const r = require("${s}");`, (s: string) => `const u = import.meta.resolve("${s}");`, (s: string) => `const f = new URL("${s}", import.meta.url);`, + (s: string) => `mock.module("${s}", () => ({}));`, ]; test("every declared prefix is rewritten for depth 1 and 2 in every syntax form", () => { @@ -173,6 +174,7 @@ describe("scanEscapes", () => { 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); expect(scanEscapes('const u = pathToFileURL(join(import.meta.dir, "../src/lib/x.ts")).href;')).toHaveLength(1); + expect(scanEscapes('const s = await Bun.file(new URL(file, import.meta.url)).text();')).toHaveLength(1); expect(scanEscapes("const self = import.meta.path;")).toEqual([]); }); }); diff --git a/tests/cost-cap-unknown-evidence.test.ts b/tests/usage/cost-cap-unknown-evidence.test.ts similarity index 96% rename from tests/cost-cap-unknown-evidence.test.ts rename to tests/usage/cost-cap-unknown-evidence.test.ts index 753a5eeb1f8..ca401d1506f 100644 --- a/tests/cost-cap-unknown-evidence.test.ts +++ b/tests/usage/cost-cap-unknown-evidence.test.ts @@ -26,14 +26,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 { costEvidenceForCandidate } from "../src/routing/cost"; -import { evaluatePolicyProfile } from "../src/routing/evaluator"; -import { normalizeRouteDecisionTrace } from "../src/routing/trace"; -import { NoEligiblePolicyCandidateError, routeModel } from "../src/router"; -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 { costEvidenceForCandidate } from "../../src/routing/cost"; +import { evaluatePolicyProfile } from "../../src/routing/evaluator"; +import { normalizeRouteDecisionTrace } from "../../src/routing/trace"; +import { NoEligiblePolicyCandidateError, routeModel } from "../../src/router"; +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"; let testDir = ""; let previousHome: string | undefined; diff --git a/tests/cost-scoring.test.ts b/tests/usage/cost-scoring.test.ts similarity index 97% rename from tests/cost-scoring.test.ts rename to tests/usage/cost-scoring.test.ts index 16b2420851f..e9c34d8d993 100644 --- a/tests/cost-scoring.test.ts +++ b/tests/usage/cost-scoring.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 { costEvidenceForCandidate, costScore } from "../src/routing/cost"; -import { evaluatePolicyProfile, COST_UNKNOWN_PENALTY_SCORE } from "../src/routing/evaluator"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { costEvidenceForCandidate, costScore } from "../../src/routing/cost"; +import { evaluatePolicyProfile, COST_UNKNOWN_PENALTY_SCORE } from "../../src/routing/evaluator"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testDir = ""; let previousHome: string | undefined; diff --git a/tests/quota-401-recovery-runtime.test.ts b/tests/usage/quota-401-recovery-runtime.test.ts similarity index 87% rename from tests/quota-401-recovery-runtime.test.ts rename to tests/usage/quota-401-recovery-runtime.test.ts index 0ab8381e191..be0ca4136e4 100644 --- a/tests/quota-401-recovery-runtime.test.ts +++ b/tests/usage/quota-401-recovery-runtime.test.ts @@ -2,12 +2,12 @@ import { afterEach, beforeEach, expect, test } from "bun:test"; import { mkdtempSync} 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"; /** * Runtime behaviour of the WHAM 401 recovery (#3019). * - * tests/quota-401-recovery.test.ts exercises the budget store in isolation, and every case + * tests/usage/quota-401-recovery.test.ts exercises the budget store in isolation, and every case * there stays green if the recovery is never wired into the quota path at all. These drive * the real primitive and the real store together: a refresh that actually happens, a * settlement that survives caller cancellation, and provenance that comes from the flight @@ -25,7 +25,7 @@ beforeEach(async () => { home = mkdtempSync(join(tmpdir(), "ocx-quota-401-")); process.env.OPENCODEX_HOME = home; originalFetch = globalThis.fetch; - const { resetQuotaRecoveryForTests } = await import("../src/codex/quota-401-recovery"); + const { resetQuotaRecoveryForTests } = await import("../../src/codex/quota-401-recovery"); resetQuotaRecoveryForTests(); }); @@ -34,12 +34,12 @@ afterEach(async () => { if (previousHome === undefined) delete process.env.OPENCODEX_HOME; else process.env.OPENCODEX_HOME = previousHome; removeTreeWithRetry(home); - const { resetQuotaRecoveryForTests } = await import("../src/codex/quota-401-recovery"); + const { resetQuotaRecoveryForTests } = await import("../../src/codex/quota-401-recovery"); resetQuotaRecoveryForTests(); }); async function seedAccount(id: string): Promise { - const { readCodexAccountRecord, saveCodexAccountCredential } = await import("../src/codex/account-store"); + const { readCodexAccountRecord, saveCodexAccountCredential } = await import("../../src/codex/account-store"); saveCodexAccountCredential(id, { accessToken: REJECTED, refreshToken: "grant", @@ -52,7 +52,7 @@ async function seedAccount(id: string): Promise { /** Register the account in config too, so the account-list API actually returns a row. */ async function seedListedAccount(id: string): Promise { const generation = await seedAccount(id); - const { loadConfig, saveConfig } = await import("../src/config"); + const { loadConfig, saveConfig } = await import("../../src/config"); const config = loadConfig(); const accounts = [...(config.codexAccounts ?? []).filter(a => a.id !== id), { id, label: id }]; saveConfig({ ...config, codexAccounts: accounts }); @@ -60,9 +60,9 @@ async function seedListedAccount(id: string): Promise { } test("a refresh settles the budget even when the caller cancels first", async () => { - const { forceRefreshCodexPoolToken } = await import("../src/codex/account-store"); + const { forceRefreshCodexPoolToken } = await import("../../src/codex/account-store"); const { claimQuotaRecovery, quotaRecoveryRecordForTests, settleQuotaRecovery, releaseQuotaRecovery } = - await import("../src/codex/quota-401-recovery"); + await import("../../src/codex/quota-401-recovery"); const generation = await seedAccount("cancelled-owner"); let released = 0; @@ -106,7 +106,7 @@ test("a refresh settles the budget even when the caller cancels first", async () }); test("exactly one of two callers on a shared flight performed the CAS", async () => { - const { forceRefreshCodexPoolToken } = await import("../src/codex/account-store"); + const { forceRefreshCodexPoolToken } = await import("../../src/codex/account-store"); const generation = await seedAccount("adopting-joiner"); globalThis.fetch = (async () => { @@ -139,14 +139,14 @@ test("exactly one of two callers on a shared flight performed the CAS", async () }); test("a revoked grant routes to terminal settlement, a slow one does not", async () => { - const { forceRefreshCodexPoolToken } = await import("../src/codex/account-store"); - const { claimQuotaRecovery, quotaRecoveryRecordForTests } = await import("../src/codex/quota-401-recovery"); + const { forceRefreshCodexPoolToken } = await import("../../src/codex/account-store"); + const { claimQuotaRecovery, quotaRecoveryRecordForTests } = await import("../../src/codex/quota-401-recovery"); // Drive the real primitive to a real refresh failure and route it exactly the way // recoverPoolQuotaFrom401 does, so a wiring that never calls terminal settlement fails. - const { TokenRefreshError } = await import("../src/codex/account-store"); + const { TokenRefreshError } = await import("../../src/codex/account-store"); const { releaseQuotaRecovery, settleQuotaRecoveryTerminal, quotaRecoveryTerminalFor } = - await import("../src/codex/quota-401-recovery"); + await import("../../src/codex/quota-401-recovery"); const route = (accountId: string, claimId: string, error: unknown) => { if (error instanceof TokenRefreshError && /invalid_grant|revoked|expired|invalid_refresh_token/i.test(String(error.message))) { settleQuotaRecoveryTerminal(accountId, claimId); @@ -184,8 +184,8 @@ test("a revoked grant routes to terminal settlement, a slow one does not", async }); test("a revoked grant stays needs-reauth across polls, through the real quota path", async () => { - const { listCodexAuthAccounts } = await import("../src/codex/auth-api"); - const { loadConfig } = await import("../src/config"); + const { listCodexAuthAccounts } = await import("../../src/codex/auth-api"); + const { loadConfig } = await import("../../src/config"); await seedListedAccount("dead-grant"); // Bare WHAM 401 -> token endpoint says invalid_grant -> the account list re-polls. @@ -207,7 +207,7 @@ test("a revoked grant stays needs-reauth across polls, through the real quota pa // The recovery record alone cannot carry it: by the time the next poll runs, the claim is // spent and a spent budget reports transient. Assert the account-level mark directly, so // dropping markAccountNeedsReauth fails here rather than being masked by a cached quota. - const { isAccountNeedsReauth } = await import("../src/codex/auth-api"); + const { isAccountNeedsReauth } = await import("../../src/codex/auth-api"); expect(isAccountNeedsReauth("dead-grant")).toBe(true); const second = await listCodexAuthAccounts(config, true); @@ -217,9 +217,9 @@ test("a revoked grant stays needs-reauth across polls, through the real quota pa }); test("a transient refresh failure does not quarantine the account", async () => { - const { listCodexAuthAccounts } = await import("../src/codex/auth-api"); - const { loadConfig } = await import("../src/config"); - const { quotaRecoveryRecordForTests } = await import("../src/codex/quota-401-recovery"); + const { listCodexAuthAccounts } = await import("../../src/codex/auth-api"); + const { loadConfig } = await import("../../src/config"); + const { quotaRecoveryRecordForTests } = await import("../../src/codex/quota-401-recovery"); await seedListedAccount("slow-grant"); globalThis.fetch = (async (input: string | URL | Request) => { @@ -231,15 +231,15 @@ test("a transient refresh failure does not quarantine the account", async () => // A network failure proves nothing about the grant. expect(rows.find(row => row.id === "slow-grant")?.needsReauth).toBe(false); // Nor may it leave a durable quarantine behind. - const { isAccountNeedsReauth } = await import("../src/codex/auth-api"); + const { isAccountNeedsReauth } = await import("../../src/codex/auth-api"); expect(isAccountNeedsReauth("slow-grant")).toBe(false); expect(quotaRecoveryRecordForTests("slow-grant")).toMatchObject({ state: "backoff" }); }); test("an already-aborted caller starts no refresh at all", async () => { - const { forceRefreshCodexPoolToken } = await import("../src/codex/account-store"); + const { forceRefreshCodexPoolToken } = await import("../../src/codex/account-store"); const { claimQuotaRecovery, quotaRecoveryRecordForTests, releaseQuotaRecovery, settleQuotaRecovery } = - await import("../src/codex/quota-401-recovery"); + await import("../../src/codex/quota-401-recovery"); const generation = await seedAccount("pre-aborted"); let fetches = 0; @@ -277,8 +277,8 @@ test("an already-aborted caller starts no refresh at all", async () => { }); test("structured terminal evidence on the FIRST 401 needs no refresh and is generation-scoped", async () => { - const { listCodexAuthAccounts, isAccountNeedsReauth } = await import("../src/codex/auth-api"); - const { loadConfig } = await import("../src/config"); + const { listCodexAuthAccounts, isAccountNeedsReauth } = await import("../../src/codex/auth-api"); + const { loadConfig } = await import("../../src/config"); const generation = await seedListedAccount("structured-first"); let tokenCalls = 0; @@ -297,7 +297,7 @@ test("structured terminal evidence on the FIRST 401 needs no refresh and is gene expect(isAccountNeedsReauth("structured-first")).toBe(true); // The evidence is about THAT credential. A replacement must not inherit the quarantine. - const { saveCodexAccountCredential } = await import("../src/codex/account-store"); + const { saveCodexAccountCredential } = await import("../../src/codex/account-store"); saveCodexAccountCredential("structured-first", { accessToken: "fresh-login", refreshToken: "fresh-grant", @@ -309,8 +309,8 @@ test("structured terminal evidence on the FIRST 401 needs no refresh and is gene }); test("structured terminal evidence on the REPLAY is scoped to the refreshed credential", async () => { - const { listCodexAuthAccounts, isAccountNeedsReauth } = await import("../src/codex/auth-api"); - const { loadConfig } = await import("../src/config"); + const { listCodexAuthAccounts, isAccountNeedsReauth } = await import("../../src/codex/auth-api"); + const { loadConfig } = await import("../../src/config"); await seedListedAccount("structured-replay"); let whamCalls = 0; @@ -330,7 +330,7 @@ test("structured terminal evidence on the REPLAY is scoped to the refreshed cred expect(rows.find(row => row.id === "structured-replay")?.needsReauth).toBe(true); expect(isAccountNeedsReauth("structured-replay")).toBe(true); - const { saveCodexAccountCredential } = await import("../src/codex/account-store"); + const { saveCodexAccountCredential } = await import("../../src/codex/account-store"); saveCodexAccountCredential("structured-replay", { accessToken: "fresh-login", refreshToken: "fresh-grant", @@ -341,8 +341,8 @@ test("structured terminal evidence on the REPLAY is scoped to the refreshed cred }); test("no bearer reaches the console, the debug buffer, or a serialized account row", async () => { - const { forceRefreshCodexPoolToken } = await import("../src/codex/account-store"); - const { getDebugLogEntries } = await import("../src/lib/debug-log-buffer"); + const { forceRefreshCodexPoolToken } = await import("../../src/codex/account-store"); + const { getDebugLogEntries } = await import("../../src/lib/debug-log-buffer"); // Registered, not just credentialed: an unlisted account produces no row at all, and the // serializer assertion below would then be checking an empty list. const generation = await seedListedAccount("quiet-refresh"); @@ -379,8 +379,8 @@ test("no bearer reaches the console, the debug buffer, or a serialized account r // And the REAL serializer, not a hand-built stand-in: a leak has to be caught in what // the management API actually returns. - const { listCodexAuthAccounts } = await import("../src/codex/auth-api"); - const { loadConfig } = await import("../src/config"); + const { listCodexAuthAccounts } = await import("../../src/codex/auth-api"); + const { loadConfig } = await import("../../src/config"); const rows = JSON.stringify(await listCodexAuthAccounts(loadConfig(), false)); expect(rows).toContain("quiet-refresh"); for (const secret of secrets) expect(rows).not.toContain(secret); diff --git a/tests/quota-401-recovery.test.ts b/tests/usage/quota-401-recovery.test.ts similarity index 98% rename from tests/quota-401-recovery.test.ts rename to tests/usage/quota-401-recovery.test.ts index bf49cb46b6a..6a36dcf98c3 100644 --- a/tests/quota-401-recovery.test.ts +++ b/tests/usage/quota-401-recovery.test.ts @@ -6,12 +6,12 @@ import { resetQuotaRecoveryForTests, settleQuotaRecovery, sweepExpiredQuotaRecovery, -} from "../src/codex/quota-401-recovery"; +} from "../../src/codex/quota-401-recovery"; import { CODEX_REFRESH_FLIGHT_CEILING_MS, QUOTA_RECOVERY_LEASE_MS, WHAM_REQUEST_TIMEOUT_MS, -} from "../src/codex/quota-recovery-timing"; +} from "../../src/codex/quota-recovery-timing"; /** * The budget that keeps a WHAM 401 recovery from becoming a retry loop (#3019). diff --git a/tests/quota-scoring.test.ts b/tests/usage/quota-scoring.test.ts similarity index 95% rename from tests/quota-scoring.test.ts rename to tests/usage/quota-scoring.test.ts index 505df9a780f..811e76af4ba 100644 --- a/tests/quota-scoring.test.ts +++ b/tests/usage/quota-scoring.test.ts @@ -2,15 +2,15 @@ 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 { updateAccountQuota } from "../src/codex/quota"; -import { setCachedProviderAccountQuotaForTests, clearAccountQuotaCache } from "../src/providers/quota"; -import { quotaEvidenceForCandidate, quotaScore } from "../src/routing/quota"; -import { evaluatePolicyProfile, QUOTA_UNKNOWN_PENALTY_SCORE } from "../src/routing/evaluator"; -import { routeModel } from "../src/router"; -import { getAccountSet, saveCredential } from "../src/oauth/store"; -import { closeRequestHistoryIndex } from "../src/routing/history/indexer"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { updateAccountQuota } from "../../src/codex/quota"; +import { setCachedProviderAccountQuotaForTests, clearAccountQuotaCache } from "../../src/providers/quota"; +import { quotaEvidenceForCandidate, quotaScore } from "../../src/routing/quota"; +import { evaluatePolicyProfile, QUOTA_UNKNOWN_PENALTY_SCORE } from "../../src/routing/evaluator"; +import { routeModel } from "../../src/router"; +import { getAccountSet, saveCredential } from "../../src/oauth/store"; +import { closeRequestHistoryIndex } from "../../src/routing/history/indexer"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testDir = ""; let previousHome: string | undefined; diff --git a/tests/request-decompress.test.ts b/tests/usage/request-decompress.test.ts similarity index 98% rename from tests/request-decompress.test.ts rename to tests/usage/request-decompress.test.ts index 81023496ae8..7a536600cc7 100644 --- a/tests/request-decompress.test.ts +++ b/tests/usage/request-decompress.test.ts @@ -6,10 +6,10 @@ import { readBoundedJsonRequestBody, readJsonRequestBody, UnsupportedContentEncodingError, -} from "../src/server/request-decompress"; -import { MANAGEMENT_JSON_BODY_MAX_BYTES } from "../src/server/management/body"; -import { handleManagementAPI } from "../src/server/management-api"; -import type { OcxConfig } from "../src/types"; +} from "../../src/server/request-decompress"; +import { MANAGEMENT_JSON_BODY_MAX_BYTES } from "../../src/server/management/body"; +import { handleManagementAPI } from "../../src/server/management-api"; +import type { OcxConfig } from "../../src/types"; const PAYLOAD = { model: "gpt-5.5", input: "hello", stream: true }; const PAYLOAD_BYTES = new TextEncoder().encode(JSON.stringify(PAYLOAD)); diff --git a/tests/request-evidence.test.ts b/tests/usage/request-evidence.test.ts similarity index 95% rename from tests/request-evidence.test.ts rename to tests/usage/request-evidence.test.ts index 21213c209f3..b89b090dc9c 100644 --- a/tests/request-evidence.test.ts +++ b/tests/usage/request-evidence.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { evidenceFromBody } from "../src/routing/request-evidence"; +import { evidenceFromBody } from "../../src/routing/request-evidence"; describe("request evidence extraction (RI-05)", () => { test("top-level responses input image part is detected", () => { diff --git a/tests/request-history-index.test.ts b/tests/usage/request-history-index.test.ts similarity index 95% rename from tests/request-history-index.test.ts rename to tests/usage/request-history-index.test.ts index fa12b49f645..240fd391c59 100644 --- a/tests/request-history-index.test.ts +++ b/tests/usage/request-history-index.test.ts @@ -11,14 +11,14 @@ import { } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { handleManagementAPI } from "../src/server/management-api"; -import { ManagementRequest } from "./helpers/management-auth"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { ManagementRequest } from "../helpers/management-auth"; import { appendUsageEntry, resetUsageReadCacheForTests, usageLogPath, type PersistedUsageEntry, -} from "../src/usage/log"; +} from "../../src/usage/log"; import { closeRequestHistoryIndex, queryRequestHistory, @@ -27,12 +27,12 @@ import { REQUEST_HISTORY_MAX_RECORD_BYTES, REQUEST_HISTORY_MAX_PAGE_SIZE, REQUEST_HISTORY_READ_CHUNK_BYTES, -} from "../src/routing/history/indexer"; -import { InvalidCursorError } from "../src/routing/history/cursor"; -import { HISTORY_DB_FILENAME } from "../src/routing/history/schema"; -import { getConfigDir } from "../src/config"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/routing/history/indexer"; +import { InvalidCursorError } from "../../src/routing/history/cursor"; +import { HISTORY_DB_FILENAME } from "../../src/routing/history/schema"; +import { getConfigDir } from "../../src/config"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testDir = ""; let previousHome: string | undefined; @@ -142,7 +142,7 @@ describe("request-history index (RI-02)", () => { test("rows missing mandatory columns are skipped, not rejected", async () => { for (const row of seedRows(3)) appendUsageEntry(row); const { appendFileSync } = await import("node:fs"); - const { usageLogPath } = await import("../src/usage/log"); + const { usageLogPath } = await import("../../src/usage/log"); // A complete row is indexable even with no usage details. appendFileSync( usageLogPath(), @@ -265,7 +265,7 @@ describe("request-history index (RI-02)", () => { test("JSONL truncation triggers a rebuild that mirrors the truncated ledger", async () => { for (const row of seedRows(10)) appendUsageEntry(row); await queryRequestHistory({}, undefined, 10); - const { usageLogPath } = await import("../src/usage/log"); + const { usageLogPath } = await import("../../src/usage/log"); truncateSync(usageLogPath(), 0); const page = await queryRequestHistory({}, undefined, 10); expect(page.rows.length).toBe(0); @@ -275,7 +275,7 @@ describe("request-history index (RI-02)", () => { test("JSONL replacement (new file identity) rebuilds from the new ledger", async () => { for (const row of seedRows(5, 500)) appendUsageEntry(row); await queryRequestHistory({}, undefined, 10); - const { usageLogPath } = await import("../src/usage/log"); + const { usageLogPath } = await import("../../src/usage/log"); // Replace the file wholesale (new inode on most platforms). rmSync(usageLogPath(), { force: true }); for (const row of seedRows(7, 7000, "b")) appendUsageEntry(row); diff --git a/tests/request-log-conversation.test.ts b/tests/usage/request-log-conversation.test.ts similarity index 97% rename from tests/request-log-conversation.test.ts rename to tests/usage/request-log-conversation.test.ts index 624612fc897..fd574cb1e21 100644 --- a/tests/request-log-conversation.test.ts +++ b/tests/usage/request-log-conversation.test.ts @@ -9,13 +9,13 @@ import { reasoningReplayConversationIdFromResponsesRequest, sessionIdHeaderFromRequest, summarizeConversationLogs, -} from "../src/server/request-log-conversation"; +} from "../../src/server/request-log-conversation"; import { filterRequestLogs, requestLogEntryFromPersistedUsage, type RequestLogEntry, -} from "../src/server/request-log"; -import type { PersistedUsageEntry } from "../src/usage/log"; +} from "../../src/server/request-log"; +import type { PersistedUsageEntry } from "../../src/usage/log"; function log(overrides: Partial): RequestLogEntry { return { diff --git a/tests/request-log-estimate-cap.test.ts b/tests/usage/request-log-estimate-cap.test.ts similarity index 99% rename from tests/request-log-estimate-cap.test.ts rename to tests/usage/request-log-estimate-cap.test.ts index 27b7abed2d8..c8e89c222cc 100644 --- a/tests/request-log-estimate-cap.test.ts +++ b/tests/usage/request-log-estimate-cap.test.ts @@ -3,7 +3,7 @@ import { beginRequestAttempt, finishRequestAttempt, noteAttemptSend, -} from "../src/server/request-log"; +} from "../../src/server/request-log"; /** * The token-estimate context-window cap (codex-router PR #140) in the request log: diff --git a/tests/request-log.test.ts b/tests/usage/request-log.test.ts similarity index 99% rename from tests/request-log.test.ts rename to tests/usage/request-log.test.ts index bbf5b1071fa..5b8d30c58cf 100644 --- a/tests/request-log.test.ts +++ b/tests/usage/request-log.test.ts @@ -8,7 +8,7 @@ import { requestLogErrorCode, requestLogSpeedLabel, type RequestLogEntry, -} from "../src/server"; +} from "../../src/server"; import { aggregateAttemptUsage, addRequestLog, @@ -23,20 +23,20 @@ import { requestLogEntryFromPersistedUsage, sealRequestAttemptIdentity, type RequestLogContext, -} from "../src/server/request-log"; -import { handleResponses } from "../src/server/responses"; -import { bridgeToResponsesSSE } from "../src/bridge"; -import type { AdapterEvent, OcxConfig, OcxUsage } from "../src/types"; +} from "../../src/server/request-log"; +import { handleResponses } from "../../src/server/responses"; +import { bridgeToResponsesSSE } from "../../src/bridge"; +import type { AdapterEvent, OcxConfig, OcxUsage } from "../../src/types"; import { appendUsageEntry, readUsageEntries, resetUsageReadCacheForTests, type PersistedUsageEntry, -} from "../src/usage/log"; +} from "../../src/usage/log"; import { mkdtempSync} 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"; async function* replayAdapterEvents(events: AdapterEvent[]): AsyncGenerator { for (const event of events) yield event; diff --git a/tests/request-pacing.test.ts b/tests/usage/request-pacing.test.ts similarity index 97% rename from tests/request-pacing.test.ts rename to tests/usage/request-pacing.test.ts index bf8cfbb1064..2b776cd8381 100644 --- a/tests/request-pacing.test.ts +++ b/tests/usage/request-pacing.test.ts @@ -9,11 +9,11 @@ import { setProviderRequestPacingRuntimeForTest, waitForProviderRequestSlot, type RequestPacingRuntime, -} from "../src/providers/request-pacing"; -import { providerFetch } from "../src/server/responses/fetch-helpers"; -import { fetchWithHeaderTimeout } from "../src/server/responses/fetch-helpers"; -import { requestPacingOverloadResponse } from "../src/server/responses/pacing-overload"; -import type { OcxProviderConfig } from "../src/types"; +} from "../../src/providers/request-pacing"; +import { providerFetch } from "../../src/server/responses/fetch-helpers"; +import { fetchWithHeaderTimeout } from "../../src/server/responses/fetch-helpers"; +import { requestPacingOverloadResponse } from "../../src/server/responses/pacing-overload"; +import type { OcxProviderConfig } from "../../src/types"; afterEach(() => resetProviderRequestPacingForTest()); diff --git a/tests/usage-aggregate-cache.test.ts b/tests/usage/usage-aggregate-cache.test.ts similarity index 96% rename from tests/usage-aggregate-cache.test.ts rename to tests/usage/usage-aggregate-cache.test.ts index b55f008dfd0..a4d23fa4351 100644 --- a/tests/usage-aggregate-cache.test.ts +++ b/tests/usage/usage-aggregate-cache.test.ts @@ -9,19 +9,19 @@ import { enforceAppOwnedMemoryBudget, registerRetainedStore, resetAppOwnedMemoryForTests, -} from "../src/lib/app-owned-memory"; -import { APP_OWNED_RETAINED_STORE_REGISTRATIONS } from "../src/lib/app-owned-memory-stores"; +} from "../../src/lib/app-owned-memory"; +import { APP_OWNED_RETAINED_STORE_REGISTRATIONS } from "../../src/lib/app-owned-memory-stores"; import { getFilteredUsageAggregate, getUsageAggregate, resetUsageAggregateCacheForTests, usageAggregateRetainedStats, type UsageAggregateResult, -} from "../src/server/management/usage-aggregate-cache"; -import type { OcxConfig } from "../src/types/config"; -import { resetUsageReadCacheForTests, type PersistedUsageEntry } from "../src/usage/log"; -import * as usageLedgerScannerModule from "../src/usage/ledger-scanner"; -import { refreshUserCostOverlays } from "../src/usage/user-cost-overlays"; +} from "../../src/server/management/usage-aggregate-cache"; +import type { OcxConfig } from "../../src/types/config"; +import { resetUsageReadCacheForTests, type PersistedUsageEntry } from "../../src/usage/log"; +import * as usageLedgerScannerModule from "../../src/usage/ledger-scanner"; +import { refreshUserCostOverlays } from "../../src/usage/user-cost-overlays"; const NOW = Date.parse("2026-09-01T10:00:00.000Z"); diff --git a/tests/usage-cost.test.ts b/tests/usage/usage-cost.test.ts similarity index 99% rename from tests/usage-cost.test.ts rename to tests/usage/usage-cost.test.ts index 4b98b565deb..849d7504967 100644 --- a/tests/usage-cost.test.ts +++ b/tests/usage/usage-cost.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { createAdapterTierMetadata } from "../src/providers/fastwire"; +import { createAdapterTierMetadata } from "../../src/providers/fastwire"; import { calculateCost, estimateAttemptCost, @@ -9,7 +9,7 @@ import { normalizeCostTokens, resolveMatchedPrice, tokensPerSecond, -} from "../src/usage/cost"; +} from "../../src/usage/cost"; import { EXPECTED_PRICE_OVERLAYS, PRIORITY_MULTIPLIERS, @@ -19,13 +19,13 @@ import { findPriorityPricingRule, resolvePriorityMultiplier, type ExpectedPriceOverlay, -} from "../src/usage/expected-prices"; +} from "../../src/usage/expected-prices"; import { activeUserCostOverlays, refreshUserCostOverlays, userCostOverlayVersion, -} from "../src/usage/user-cost-overlays"; -import type { OcxConfig } from "../src/types"; +} from "../../src/usage/user-cost-overlays"; +import type { OcxConfig } from "../../src/types"; const RATE = { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 }; diff --git a/tests/usage-debug.test.ts b/tests/usage/usage-debug.test.ts similarity index 98% rename from tests/usage-debug.test.ts rename to tests/usage/usage-debug.test.ts index e799112bb97..21a076c7e4a 100644 --- a/tests/usage-debug.test.ts +++ b/tests/usage/usage-debug.test.ts @@ -11,8 +11,8 @@ import { USAGE_DEBUG_KEEP_LINES, USAGE_DEBUG_MAX_LINES, usageDebugPath, -} from "../src/usage/debug"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/usage/debug"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testDir = ""; let previousHome: string | undefined; diff --git a/tests/usage-failure-persistence.test.ts b/tests/usage/usage-failure-persistence.test.ts similarity index 92% rename from tests/usage-failure-persistence.test.ts rename to tests/usage/usage-failure-persistence.test.ts index d6946372fe4..c53d740b839 100644 --- a/tests/usage-failure-persistence.test.ts +++ b/tests/usage/usage-failure-persistence.test.ts @@ -2,9 +2,9 @@ import { afterEach, beforeEach, expect, test } from "bun:test"; import { mkdtempSync, readFileSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { addRequestLog } from "../src/server/request-log"; -import { usageLogPath } from "../src/usage/log"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { addRequestLog } from "../../src/server/request-log"; +import { usageLogPath } from "../../src/usage/log"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testDir = ""; let previousHome: string | undefined; diff --git a/tests/usage-ledger-scanner.test.ts b/tests/usage/usage-ledger-scanner.test.ts similarity index 99% rename from tests/usage-ledger-scanner.test.ts rename to tests/usage/usage-ledger-scanner.test.ts index 81021a2bec4..b5bf34adc80 100644 --- a/tests/usage-ledger-scanner.test.ts +++ b/tests/usage/usage-ledger-scanner.test.ts @@ -8,8 +8,8 @@ import { USAGE_LEDGER_BOUNDARY_DIGEST_BYTES, USAGE_LEDGER_MAX_LINE_BYTES, UsageLedgerRebuildRequiredError, -} from "../src/usage/ledger-scanner"; -import { usageLogIdentityKey, usageLogPath, type PersistedUsageEntry } from "../src/usage/log"; +} from "../../src/usage/ledger-scanner"; +import { usageLogIdentityKey, usageLogPath, type PersistedUsageEntry } from "../../src/usage/log"; let testDir = ""; let previousHome: string | undefined; diff --git a/tests/usage-log.test.ts b/tests/usage/usage-log.test.ts similarity index 99% rename from tests/usage-log.test.ts rename to tests/usage/usage-log.test.ts index cc96db4921c..76c08c7212c 100644 --- a/tests/usage-log.test.ts +++ b/tests/usage/usage-log.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test"; -import { STORE_BUDGET_MS } from "./helpers/test-budget"; +import { STORE_BUDGET_MS } from "../helpers/test-budget"; import { closeSync, existsSync, mkdtempSync, openSync, readFileSync, rmSync, statSync, truncateSync, writeFileSync, writeSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; @@ -19,8 +19,8 @@ import { usageReadCacheStatsForTests, usageLogRevisionKey, type PersistedUsageEntry, -} from "../src/usage/log"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/usage/log"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testDir = ""; let previousHome: string | undefined; diff --git a/tests/usage-provider-label.test.ts b/tests/usage/usage-provider-label.test.ts similarity index 97% rename from tests/usage-provider-label.test.ts rename to tests/usage/usage-provider-label.test.ts index b1c576a99a9..66fefefe9a9 100644 --- a/tests/usage-provider-label.test.ts +++ b/tests/usage/usage-provider-label.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { baseProviderLabel } from "../src/providers/label"; +import { baseProviderLabel } from "../../src/providers/label"; describe("baseProviderLabel", () => { test("returns the input when there is no pool suffix", () => { diff --git a/tests/usage-shape-extraction.test.ts b/tests/usage/usage-shape-extraction.test.ts similarity index 97% rename from tests/usage-shape-extraction.test.ts rename to tests/usage/usage-shape-extraction.test.ts index 747a9368b14..4b52457e5a0 100644 --- a/tests/usage-shape-extraction.test.ts +++ b/tests/usage/usage-shape-extraction.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { usageFromResponsesPayload } from "../src/server"; -import { applyResponseLogMetadata, type RequestLogContext } from "../src/server/request-log"; +import { usageFromResponsesPayload } from "../../src/server"; +import { applyResponseLogMetadata, type RequestLogContext } from "../../src/server/request-log"; describe("usageFromResponsesPayload", () => { test("bridge-reported usage wins over re-parsed wire payload (provenance guard)", () => { diff --git a/tests/usage-summary.test.ts b/tests/usage/usage-summary.test.ts similarity index 99% rename from tests/usage-summary.test.ts rename to tests/usage/usage-summary.test.ts index 17db7ce4a44..e701b36b9e4 100644 --- a/tests/usage-summary.test.ts +++ b/tests/usage/usage-summary.test.ts @@ -9,8 +9,8 @@ import { parseUsageSurface, rangeWindow, summarizeUsage, -} from "../src/usage/summary"; -import type { PersistedUsageEntry } from "../src/usage/log"; +} from "../../src/usage/summary"; +import type { PersistedUsageEntry } from "../../src/usage/log"; const FIXED_NOW = Date.UTC(2026, 5, 28, 12, 0, 0); @@ -225,7 +225,7 @@ describe("day-level estimated cost", () => { }); }); -import { projectUsageSummary } from "../src/usage/summary"; +import { projectUsageSummary } from "../../src/usage/summary"; describe("canonical range and surface constants", () => { test("the exported members match what the parsers accept", () => { diff --git a/tests/usage-surfaces.test.ts b/tests/usage/usage-surfaces.test.ts similarity index 91% rename from tests/usage-surfaces.test.ts rename to tests/usage/usage-surfaces.test.ts index f23ca66eace..9e938d36780 100644 --- a/tests/usage-surfaces.test.ts +++ b/tests/usage/usage-surfaces.test.ts @@ -2,10 +2,10 @@ import { expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { parseUsageSurface, summarizeUsage } from "../src/usage/summary"; -import { appendUsageEntry, readUsageEntries } from "../src/usage/log"; -import type { PersistedUsageEntry } from "../src/usage/log"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { parseUsageSurface, summarizeUsage } from "../../src/usage/summary"; +import { appendUsageEntry, readUsageEntries } from "../../src/usage/log"; +import type { PersistedUsageEntry } from "../../src/usage/log"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * D3: the usage surface taxonomy. Before this fix the codex bucket was diff --git a/tests/user-cost-overlay-coderabbit-regressions.test.ts b/tests/usage/user-cost-overlay-coderabbit-regressions.test.ts similarity index 94% rename from tests/user-cost-overlay-coderabbit-regressions.test.ts rename to tests/usage/user-cost-overlay-coderabbit-regressions.test.ts index 376cc5d5c7a..0c18713515c 100644 --- a/tests/user-cost-overlay-coderabbit-regressions.test.ts +++ b/tests/usage/user-cost-overlay-coderabbit-regressions.test.ts @@ -8,22 +8,22 @@ import { loadConfig, readConfigDiagnostics, saveConfig, -} from "../src/config"; -import type { OcxConfig } from "../src/types"; -import { resolveMatchedPrice } from "../src/usage/cost"; +} from "../../src/config"; +import type { OcxConfig } from "../../src/types"; +import { resolveMatchedPrice } from "../../src/usage/cost"; import { activeUserCostOverlays, refreshUserCostOverlays, resetPreservedDiskOnlyProvidersForTests, -} from "../src/usage/user-cost-overlays"; +} from "../../src/usage/user-cost-overlays"; import { reconcileUserCostOverlaysFromDisk, resetUserCostOverlayReconcilerForTests, startUserCostOverlayReconciler, stopUserCostOverlayReconciler, userCostOverlayInvalidReconcileCountForTests, -} from "../src/usage/user-cost-overlay-reconciler"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/usage/user-cost-overlay-reconciler"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const OVERLAY = { input: 1, output: 2, cacheRead: 0.1, cacheWrite: 0 }; const BASE_CONFIG: OcxConfig = { diff --git a/tests/user-cost-overlay-live-reconcile.test.ts b/tests/usage/user-cost-overlay-live-reconcile.test.ts similarity index 98% rename from tests/user-cost-overlay-live-reconcile.test.ts rename to tests/usage/user-cost-overlay-live-reconcile.test.ts index 8600962d3fd..516b62c795e 100644 --- a/tests/user-cost-overlay-live-reconcile.test.ts +++ b/tests/usage/user-cost-overlay-live-reconcile.test.ts @@ -2,26 +2,27 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; -import { getConfigPath, loadConfig, saveConfig } from "../src/config"; -import { resolveMatchedPrice } from "../src/usage/cost"; +import { getConfigPath, loadConfig, saveConfig } from "../../src/config"; +import { resolveMatchedPrice } from "../../src/usage/cost"; import { activeUserCostOverlays, refreshUserCostOverlays, resetPreservedDiskOnlyProvidersForTests, userCostOverlayVersion, withPreservedDiskOnlyProviders, -} from "../src/usage/user-cost-overlays"; +} from "../../src/usage/user-cost-overlays"; import { reconcileUserCostOverlaysFromDisk, resetUserCostOverlayReconcilerForTests, startUserCostOverlayReconciler, stopUserCostOverlayReconciler, userCostOverlayInvalidReconcileCountForTests, -} from "../src/usage/user-cost-overlay-reconciler"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/usage/user-cost-overlay-reconciler"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; -const repoRoot = resolve(import.meta.dir, ".."); +const repoRoot = resolveRepoRoot(); const DISK_CONFIG: OcxConfig = { port: 0, diff --git a/tests/user-cost-overlay-provider-delete.test.ts b/tests/usage/user-cost-overlay-provider-delete.test.ts similarity index 94% rename from tests/user-cost-overlay-provider-delete.test.ts rename to tests/usage/user-cost-overlay-provider-delete.test.ts index f1f26c0646f..d224168fd3a 100644 --- a/tests/user-cost-overlay-provider-delete.test.ts +++ b/tests/usage/user-cost-overlay-provider-delete.test.ts @@ -8,23 +8,23 @@ import { loadConfig, saveConfig, saveConfigPreservingClaudeCode, -} from "../src/config"; -import type { OcxConfig } from "../src/types"; -import { resolveMatchedPrice } from "../src/usage/cost"; +} from "../../src/config"; +import type { OcxConfig } from "../../src/types"; +import { resolveMatchedPrice } from "../../src/usage/cost"; import { activeUserCostOverlays, refreshUserCostOverlays, resetPreservedDiskOnlyProvidersForTests, userCostOverlayVersion, withPreservedDiskOnlyProviders, -} from "../src/usage/user-cost-overlays"; +} from "../../src/usage/user-cost-overlays"; import { reconcileUserCostOverlaysFromDisk, resetUserCostOverlayReconcilerForTests, startUserCostOverlayReconciler, stopUserCostOverlayReconciler, -} from "../src/usage/user-cost-overlay-reconciler"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/usage/user-cost-overlay-reconciler"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const OVERLAY = { input: 1, output: 2, cacheRead: 0.1, cacheWrite: 0 }; diff --git a/tests/sidecar-abort.test.ts b/tests/vision/sidecar-abort.test.ts similarity index 97% rename from tests/sidecar-abort.test.ts rename to tests/vision/sidecar-abort.test.ts index 13ee59eebe6..348de2a69a2 100644 --- a/tests/sidecar-abort.test.ts +++ b/tests/vision/sidecar-abort.test.ts @@ -1,12 +1,12 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { runWebSearch } from "../src/web-search/executor"; -import { runWithWebSearch as runWithWebSearchProduction, type WebSearchLoopDeps } from "../src/web-search/loop"; -import { describeImage } from "../src/vision/describe"; -import { parseRequest } from "../src/responses/parser"; -import { headersForCodexAuthContext } from "../src/codex/auth-context"; -import type { ProviderAdapter } from "../src/adapters/base"; -import type { OcxProviderConfig } from "../src/types"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; +import { runWebSearch } from "../../src/web-search/executor"; +import { runWithWebSearch as runWithWebSearchProduction, type WebSearchLoopDeps } from "../../src/web-search/loop"; +import { describeImage } from "../../src/vision/describe"; +import { parseRequest } from "../../src/responses/parser"; +import { headersForCodexAuthContext } from "../../src/codex/auth-context"; +import type { ProviderAdapter } from "../../src/adapters/base"; +import type { OcxProviderConfig } from "../../src/types"; +import { createTestTranslatorBudget } from "../helpers/translator-budget"; function runWithWebSearch( deps: Omit & { incomingMeta?: WebSearchLoopDeps["incomingMeta"] }, diff --git a/tests/sidecar-auth.test.ts b/tests/vision/sidecar-auth.test.ts similarity index 90% rename from tests/sidecar-auth.test.ts rename to tests/vision/sidecar-auth.test.ts index 919ecf18e69..8d603619f66 100644 --- a/tests/sidecar-auth.test.ts +++ b/tests/vision/sidecar-auth.test.ts @@ -1,6 +1,6 @@ import { afterEach, describe, expect, mock, test } from "bun:test"; -import * as storeModule from "../src/oauth/store"; -import * as usabilityModule from "../src/codex/account-usability"; +import * as storeModule from "../../src/oauth/store"; +import * as usabilityModule from "../../src/codex/account-usability"; // The shared auth module reads two stores: the OAuth account store (Anthropic // side) and the Codex account credential state (ChatGPT side). Both are mocked @@ -8,20 +8,20 @@ import * as usabilityModule from "../src/codex/account-usability"; let accountSets: Record; activeAccountId?: string }> = {}; let usableCodexAccounts: Set = new Set(); -mock.module("../src/oauth/store", () => ({ +mock.module("../../src/oauth/store", () => ({ ...storeModule, getAccountSet: (provider: string) => accountSets[provider] ?? null, })); -mock.module("../src/codex/account-usability", () => ({ +mock.module("../../src/codex/account-usability", () => ({ ...usabilityModule, isCodexAccountUsable: (_config: unknown, accountId: string) => usableCodexAccounts.has(accountId), })); -import { AUTH_SLOT_MODELS, resolveSidecarAuth, sidecarAuthSlots } from "../src/sidecar/auth"; -import { findAnthropicSidecarProvider } from "../src/web-search"; -import { findAnthropicVisionProvider } from "../src/vision"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/account-id"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { AUTH_SLOT_MODELS, resolveSidecarAuth, sidecarAuthSlots } from "../../src/sidecar/auth"; +import { findAnthropicSidecarProvider } from "../../src/web-search"; +import { findAnthropicVisionProvider } from "../../src/vision"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/account-id"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; const forward: OcxProviderConfig = { adapter: "openai-responses", baseUrl: "https://chatgpt.com/backend-api/codex", authMode: "forward" }; const anthropicOAuth: OcxProviderConfig = { adapter: "anthropic", baseUrl: "https://api.anthropic.com", authMode: "oauth" }; diff --git a/tests/sidecar-candidates.test.ts b/tests/vision/sidecar-candidates.test.ts similarity index 89% rename from tests/sidecar-candidates.test.ts rename to tests/vision/sidecar-candidates.test.ts index 908abe4f5ec..467d10eb26b 100644 --- a/tests/sidecar-candidates.test.ts +++ b/tests/vision/sidecar-candidates.test.ts @@ -1,22 +1,22 @@ import { afterEach, describe, expect, mock, test } from "bun:test"; -import * as storeModule from "../src/oauth/store"; -import * as usabilityModule from "../src/codex/account-usability"; -import * as modelRowsModule from "../src/server/management/model-rows"; +import * as storeModule from "../../src/oauth/store"; +import * as usabilityModule from "../../src/codex/account-usability"; +import * as modelRowsModule from "../../src/server/management/model-rows"; let accountSets: Record; activeAccountId?: string }> = {}; let usableCodexAccounts: Set = new Set(); let managementRows: Array> | Error = []; let entitlementWaitMs: number | undefined; -mock.module("../src/oauth/store", () => ({ +mock.module("../../src/oauth/store", () => ({ ...storeModule, getAccountSet: (provider: string) => accountSets[provider] ?? null, })); -mock.module("../src/codex/account-usability", () => ({ +mock.module("../../src/codex/account-usability", () => ({ ...usabilityModule, isCodexAccountUsable: (_config: unknown, accountId: string) => usableCodexAccounts.has(accountId), })); -mock.module("../src/server/management/model-rows", () => ({ +mock.module("../../src/server/management/model-rows", () => ({ ...modelRowsModule, listManagementModelRows: async (_config: unknown, options?: { entitlementWaitMs?: number }) => { entitlementWaitMs = options?.entitlementWaitMs; @@ -25,11 +25,11 @@ mock.module("../src/server/management/model-rows", () => ({ }, })); -import { pickerVisibleSidecarCandidates, visionSidecarCandidates } from "../src/sidecar/candidates"; -import { resolveSidecarAuth } from "../src/sidecar/auth"; -import { visionCandidateRows, visionDescriberIsProvablyBlind } from "../src/server/management/vision-sidecar-options"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/account-id"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { pickerVisibleSidecarCandidates, visionSidecarCandidates } from "../../src/sidecar/candidates"; +import { resolveSidecarAuth } from "../../src/sidecar/auth"; +import { visionCandidateRows, visionDescriberIsProvablyBlind } from "../../src/server/management/vision-sidecar-options"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/account-id"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; const forward: OcxProviderConfig = { adapter: "openai-responses", baseUrl: "https://chatgpt.com/backend-api/codex", authMode: "forward" }; const anthropicOAuth: OcxProviderConfig = { adapter: "anthropic", baseUrl: "https://api.anthropic.com", authMode: "oauth" }; diff --git a/tests/sidecar-settings-vision-controls.test.ts b/tests/vision/sidecar-settings-vision-controls.test.ts similarity index 96% rename from tests/sidecar-settings-vision-controls.test.ts rename to tests/vision/sidecar-settings-vision-controls.test.ts index e47413d25c5..4fb4028ee7d 100644 --- a/tests/sidecar-settings-vision-controls.test.ts +++ b/tests/vision/sidecar-settings-vision-controls.test.ts @@ -2,17 +2,17 @@ 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 { 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"; import { DEFAULT_VISION_TIMEOUT_MS, MAX_VISION_TIMEOUT_MS, MIN_VISION_TIMEOUT_MS, resolveMaxDescriptionsPerTurn, resolveVisionTimeoutMs, -} from "../src/vision"; -import { ManagementRequest as Request } from "./helpers/management-auth"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/vision"; +import { ManagementRequest as Request } from "../helpers/management-auth"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; async function getSidecarSettings(config: OcxConfig): Promise { const url = new URL("http://localhost/api/sidecar-settings"); diff --git a/tests/sidecar-settings-vision-filter.test.ts b/tests/vision/sidecar-settings-vision-filter.test.ts similarity index 96% rename from tests/sidecar-settings-vision-filter.test.ts rename to tests/vision/sidecar-settings-vision-filter.test.ts index e7eb0daf76a..0582f0cff00 100644 --- a/tests/sidecar-settings-vision-filter.test.ts +++ b/tests/vision/sidecar-settings-vision-filter.test.ts @@ -2,12 +2,12 @@ import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test"; import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { handleManagementAPI } from "../src/server/management-api"; -import * as modelRows from "../src/server/management/model-rows"; -import type { OcxConfig } from "../src/types"; -import { BASELINE_VISION_MODELS } from "../src/vision/eligibility"; -import { ManagementRequest as Request } from "./helpers/management-auth"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { handleManagementAPI } from "../../src/server/management-api"; +import * as modelRows from "../../src/server/management/model-rows"; +import type { OcxConfig } from "../../src/types"; +import { BASELINE_VISION_MODELS } from "../../src/vision/eligibility"; +import { ManagementRequest as Request } from "../helpers/management-auth"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; async function getSidecarSettings(config: OcxConfig): Promise { const url = new URL("http://localhost/api/sidecar-settings"); @@ -284,7 +284,7 @@ describe("sidecar-settings vision model filter", () => { test("13. the reject path does not persist to disk", async () => { // In-memory equality alone would not prove a disk write did not happen if the // gate were ever reordered after the mutation block. - const configModule = await import("../src/config"); + const configModule = await import("../../src/config"); const saveSpy = spyOn(configModule, "saveConfigPreservingClaudeCode"); try { const config = emptyConfig(); @@ -301,7 +301,7 @@ describe("sidecar-settings vision model filter", () => { // contract: web-search rejects on non-membership (closed executor set), // while vision keeps rejecting only on proven blindness. The two gates // remain different predicates; full web-search coverage lives in - // tests/sidecar-settings-web-search-gate.test.ts. + // tests/vision/sidecar-settings-web-search-gate.test.ts. const config = emptyConfig(); const url = new URL("http://localhost/api/sidecar-settings"); const response = await handleManagementAPI( diff --git a/tests/sidecar-settings-web-search-gate.test.ts b/tests/vision/sidecar-settings-web-search-gate.test.ts similarity index 95% rename from tests/sidecar-settings-web-search-gate.test.ts rename to tests/vision/sidecar-settings-web-search-gate.test.ts index 4b703f7209c..1cfbd41af26 100644 --- a/tests/sidecar-settings-web-search-gate.test.ts +++ b/tests/vision/sidecar-settings-web-search-gate.test.ts @@ -1,21 +1,21 @@ import { afterEach, describe, expect, mock, test } from "bun:test"; -import * as storeModule from "../src/oauth/store"; -import * as usabilityModule from "../src/codex/account-usability"; -import * as modelRowsModule from "../src/server/management/model-rows"; +import * as storeModule from "../../src/oauth/store"; +import * as usabilityModule from "../../src/codex/account-usability"; +import * as modelRowsModule from "../../src/server/management/model-rows"; let accountSets: Record; activeAccountId?: string }> = {}; let usableCodexAccounts: Set = new Set(); let managementRows: Array> = []; -mock.module("../src/oauth/store", () => ({ +mock.module("../../src/oauth/store", () => ({ ...storeModule, getAccountSet: (provider: string) => accountSets[provider] ?? null, })); -mock.module("../src/codex/account-usability", () => ({ +mock.module("../../src/codex/account-usability", () => ({ ...usabilityModule, isCodexAccountUsable: (_config: unknown, accountId: string) => usableCodexAccounts.has(accountId), })); -mock.module("../src/server/management/model-rows", () => ({ +mock.module("../../src/server/management/model-rows", () => ({ ...modelRowsModule, listManagementModelRows: async () => managementRows, })); @@ -25,12 +25,12 @@ import { webSearchModelIsRejected, webSearchModelOptionsFrom, webSearchModelRejection, -} from "../src/server/management/web-search-sidecar-options"; -import { handleManagementAPI } from "../src/server/management-api"; -import { ManagementRequest as Request } from "./helpers/management-auth"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/account-id"; -import { xaiSearchOptionsFromConfig } from "../src/web-search"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +} from "../../src/server/management/web-search-sidecar-options"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { ManagementRequest as Request } from "../helpers/management-auth"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/account-id"; +import { xaiSearchOptionsFromConfig } from "../../src/web-search"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; const forward: OcxProviderConfig = { adapter: "openai-responses", baseUrl: "https://chatgpt.com/backend-api/codex", authMode: "forward" }; const anthropicOAuth: OcxProviderConfig = { adapter: "anthropic", baseUrl: "https://api.anthropic.com", authMode: "oauth" }; diff --git a/tests/sidecar-settings-web-search-stream.test.ts b/tests/vision/sidecar-settings-web-search-stream.test.ts similarity index 93% rename from tests/sidecar-settings-web-search-stream.test.ts rename to tests/vision/sidecar-settings-web-search-stream.test.ts index d6f1ba0bb15..c87167cb257 100644 --- a/tests/sidecar-settings-web-search-stream.test.ts +++ b/tests/vision/sidecar-settings-web-search-stream.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 { loadConfig } from "../src/config"; -import { handleManagementAPI } from "../src/server/management-api"; -import type { OcxConfig } from "../src/types"; -import { ManagementRequest as Request } from "./helpers/management-auth"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { loadConfig } from "../../src/config"; +import { handleManagementAPI } from "../../src/server/management-api"; +import type { OcxConfig } from "../../src/types"; +import { ManagementRequest as Request } from "../helpers/management-auth"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; async function getSidecarSettings(config: OcxConfig): Promise { const url = new URL("http://localhost/api/sidecar-settings"); diff --git a/tests/sidecar-tracker.test.ts b/tests/vision/sidecar-tracker.test.ts similarity index 96% rename from tests/sidecar-tracker.test.ts rename to tests/vision/sidecar-tracker.test.ts index 455bf300ea5..30e527b7b2c 100644 --- a/tests/sidecar-tracker.test.ts +++ b/tests/vision/sidecar-tracker.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { sidecarEnter, sidecarBreadcrumb, markActivity, activityBreadcrumb } from "../src/lib/sidecar-tracker"; +import { sidecarEnter, sidecarBreadcrumb, markActivity, activityBreadcrumb } from "../../src/lib/sidecar-tracker"; // Drain any leftover in-flight counters between tests (defensive; each test balances its own). afterEach(() => { diff --git a/tests/vision-anthropic.test.ts b/tests/vision/vision-anthropic.test.ts similarity index 97% rename from tests/vision-anthropic.test.ts rename to tests/vision/vision-anthropic.test.ts index 579f34f1cd5..ee4b01b4218 100644 --- a/tests/vision-anthropic.test.ts +++ b/tests/vision/vision-anthropic.test.ts @@ -2,11 +2,11 @@ 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 * as oauthModule from "../src/oauth"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import * as oauthModule from "../../src/oauth"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let oauthAccessError: Error | undefined; -mock.module("../src/oauth", () => ({ +mock.module("../../src/oauth", () => ({ ...oauthModule, getValidAccessToken: async () => { if (oauthAccessError) throw oauthAccessError; @@ -14,17 +14,17 @@ mock.module("../src/oauth", () => ({ }, })); -import { CLAUDE_CODE_SYSTEM_INSTRUCTION } from "../src/oauth/anthropic"; -import { parseRequest } from "../src/responses/parser"; -import { handleManagementAPI } from "../src/server/management-api"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { CLAUDE_CODE_SYSTEM_INSTRUCTION } from "../../src/oauth/anthropic"; +import { parseRequest } from "../../src/responses/parser"; +import { handleManagementAPI } from "../../src/server/management-api"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; import { describeImagesInPlace, describeImageAnthropic, parseAnthropicVisionSSE, planVisionSidecar, type VisionPlan, -} from "../src/vision"; +} from "../../src/vision"; const DATA_IMAGE = "data:image/png;base64,aGVsbG8="; const anthropicProvider: OcxProviderConfig = { @@ -440,4 +440,4 @@ describe("Anthropic vision planning and management config", () => { } }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/vision-backend-union.test.ts b/tests/vision/vision-backend-union.test.ts similarity index 90% rename from tests/vision-backend-union.test.ts rename to tests/vision/vision-backend-union.test.ts index f55b46abb36..a31cf22da22 100644 --- a/tests/vision-backend-union.test.ts +++ b/tests/vision/vision-backend-union.test.ts @@ -1,37 +1,37 @@ import { afterEach, describe, expect, mock, test } from "bun:test"; -import * as storeModule from "../src/oauth/store"; -import * as usabilityModule from "../src/codex/account-usability"; -import * as modelRowsModule from "../src/server/management/model-rows"; +import * as storeModule from "../../src/oauth/store"; +import * as usabilityModule from "../../src/codex/account-usability"; +import * as modelRowsModule from "../../src/server/management/model-rows"; let accountSets: Record; activeAccountId?: string }> = {}; let usableCodexAccounts: Set = new Set(); let managementRows: Array> = []; -mock.module("../src/oauth/store", () => ({ +mock.module("../../src/oauth/store", () => ({ ...storeModule, getAccountSet: (provider: string) => accountSets[provider] ?? null, })); -mock.module("../src/codex/account-usability", () => ({ +mock.module("../../src/codex/account-usability", () => ({ ...usabilityModule, isCodexAccountUsable: (_config: unknown, accountId: string) => usableCodexAccounts.has(accountId), })); -mock.module("../src/server/management/model-rows", () => ({ +mock.module("../../src/server/management/model-rows", () => ({ ...modelRowsModule, listManagementModelRows: async () => managementRows, })); -import { handleManagementAPI } from "../src/server/management-api"; -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { ManagementRequest as Request } from "../helpers/management-auth"; import { enabledVisionBackends, visionCandidateRows, visionDescriberIsProvablyBlind, visionModelOptionsFrom, -} from "../src/server/management/vision-sidecar-options"; -import { activeVisionBackends } from "../src/vision/backends"; -import { visionBackendForCandidate } from "../src/vision/eligibility"; -import { resolveSidecarAuth } from "../src/sidecar/auth"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +} from "../../src/server/management/vision-sidecar-options"; +import { activeVisionBackends } from "../../src/vision/backends"; +import { visionBackendForCandidate } from "../../src/vision/eligibility"; +import { resolveSidecarAuth } from "../../src/sidecar/auth"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; const forward: OcxProviderConfig = { adapter: "openai-responses", baseUrl: "https://chatgpt.com/backend-api/codex", authMode: "forward" }; const xaiOAuth: OcxProviderConfig = { adapter: "openai-responses", baseUrl: "https://api.x.ai/v1", authMode: "oauth" }; diff --git a/tests/vision-cache.test.ts b/tests/vision/vision-cache.test.ts similarity index 98% rename from tests/vision-cache.test.ts rename to tests/vision/vision-cache.test.ts index b2369bc00f2..dce18586f09 100644 --- a/tests/vision-cache.test.ts +++ b/tests/vision/vision-cache.test.ts @@ -1,10 +1,10 @@ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test"; -import * as oauthModule from "../src/oauth"; +import * as oauthModule from "../../src/oauth"; -mock.module("../src/oauth", () => ({ ...oauthModule, getValidAccessToken: async () => "vision-cache-token" })); +mock.module("../../src/oauth", () => ({ ...oauthModule, getValidAccessToken: async () => "vision-cache-token" })); -import { parseRequest } from "../src/responses/parser"; -import type { OcxConfig, OcxContentPart, OcxProviderConfig } from "../src/types"; +import { parseRequest } from "../../src/responses/parser"; +import type { OcxConfig, OcxContentPart, OcxProviderConfig } from "../../src/types"; import { describeImagesInPlace, evictOldestVisionDescriptionForBudget, @@ -19,7 +19,7 @@ import { shouldResolveOpenAiVisionSidecar, visionDescriptionRetainedStoreSnapshot, type VisionPlan, -} from "../src/vision"; +} from "../../src/vision"; const DATA_A = "data:image/png;base64,YQ=="; const DATA_B = "data:image/png;base64,Yg=="; diff --git a/tests/vision-eligibility.test.ts b/tests/vision/vision-eligibility.test.ts similarity index 97% rename from tests/vision-eligibility.test.ts rename to tests/vision/vision-eligibility.test.ts index e28d4069782..2344fc4d698 100644 --- a/tests/vision-eligibility.test.ts +++ b/tests/vision/vision-eligibility.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { NATIVE_OPENAI_MODELS } from "../src/codex/catalog/native-models"; -import type { OcxConfig } from "../src/types"; +import { NATIVE_OPENAI_MODELS } from "../../src/codex/catalog/native-models"; +import type { OcxConfig } from "../../src/types"; import { BASELINE_VISION_MODELS, isVisionEligibleModel, @@ -9,7 +9,7 @@ import { visionBackendForCandidate, visionEligibleModelOptions, type VisionCandidateModel, -} from "../src/vision/eligibility"; +} from "../../src/vision/eligibility"; const emptyConfig: Pick = { providers: {} }; @@ -115,7 +115,7 @@ describe("vision eligibility core", () => { // WP2's PUT guard falls back to `{ provider: openai|anthropic, id }` when no // catalog row matches. These three cases pin that path, because collapsing // undefined into false here would silently start rejecting models the runtime - // has always accepted (tests/vision-reasoning-contract.test.ts:149-152 pins + // has always accepted (tests/vision/vision-reasoning-contract.test.ts:149-152 pins // `custom-vision` at HTTP 200). expect(modelAcceptsImageInput(emptyConfig, { provider: "openai", id: "custom-vision" })).toBeUndefined(); // The openai table's only text-only rows are codex-mini-latest, gpt-4, o3-mini; diff --git a/tests/vision-fail-closed.test.ts b/tests/vision/vision-fail-closed.test.ts similarity index 92% rename from tests/vision-fail-closed.test.ts rename to tests/vision/vision-fail-closed.test.ts index 286395d3983..b0fdfdddc05 100644 --- a/tests/vision-fail-closed.test.ts +++ b/tests/vision/vision-fail-closed.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { stripImagesInPlace } from "../src/vision"; -import { parseRequest } from "../src/responses/parser"; +import { stripImagesInPlace } from "../../src/vision"; +import { parseRequest } from "../../src/responses/parser"; function parsedWithImage() { return parseRequest({ diff --git a/tests/vision-reasoning-contract.test.ts b/tests/vision/vision-reasoning-contract.test.ts similarity index 94% rename from tests/vision-reasoning-contract.test.ts rename to tests/vision/vision-reasoning-contract.test.ts index 890f908eda5..38d8378996e 100644 --- a/tests/vision-reasoning-contract.test.ts +++ b/tests/vision/vision-reasoning-contract.test.ts @@ -2,17 +2,17 @@ import { describe, expect, test } from "bun:test"; import { mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { handleConfigCommand } from "../src/cli/config-command"; -import { handleManagementAPI } from "../src/server/management-api"; -import { listManagementModelRows } from "../src/server/management/model-rows"; +import { handleConfigCommand } from "../../src/cli/config-command"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { listManagementModelRows } from "../../src/server/management/model-rows"; import { resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests, -} from "../src/codex/model-entitlements"; -import type { OcxConfig } from "../src/types"; -import { resolveOpenAiVisionModel } from "../src/vision"; -import { ManagementRequest as Request } from "./helpers/management-auth"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/model-entitlements"; +import type { OcxConfig } from "../../src/types"; +import { resolveOpenAiVisionModel } from "../../src/vision"; +import { ManagementRequest as Request } from "../helpers/management-auth"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; async function getVision(config: OcxConfig): Promise { const url = new URL("http://localhost/api/sidecar-settings"); diff --git a/tests/vision-routed.test.ts b/tests/vision/vision-routed.test.ts similarity index 97% rename from tests/vision-routed.test.ts rename to tests/vision/vision-routed.test.ts index ad4ef2760c3..aa36de25cdb 100644 --- a/tests/vision-routed.test.ts +++ b/tests/vision/vision-routed.test.ts @@ -2,17 +2,17 @@ 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 { startServer } from "../src/server"; -import type { OcxConfig } from "../src/types"; -import { resetVisionDescriptionCache } from "../src/vision"; +import { saveConfig } from "../../src/config"; +import { startServer } from "../../src/server"; +import type { OcxConfig } from "../../src/types"; +import { resetVisionDescriptionCache } from "../../src/vision"; import { describeImageRouted, routedDescribeAdmissionToken, VISION_DESCRIBE_TERMINAL_HEADER, -} from "../src/vision/routed-describe"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/vision/routed-describe"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; // Roadmap 180 (revised): the routed describer loops back through the proxy's // own chat surface, and its terminal marker is the depth-cap-1 recursion diff --git a/tests/vision-sidecar-e2e.test.ts b/tests/vision/vision-sidecar-e2e.test.ts similarity index 97% rename from tests/vision-sidecar-e2e.test.ts rename to tests/vision/vision-sidecar-e2e.test.ts index 0e108b946d1..ee8a3d15223 100644 --- a/tests/vision-sidecar-e2e.test.ts +++ b/tests/vision/vision-sidecar-e2e.test.ts @@ -2,15 +2,15 @@ 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 { startServer } from "../src/server"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import type { OcxConfig } from "../src/types"; -import { parseRequest } from "../src/responses/parser"; -import { resetVisionDescriptionCache, stripImagesInPlace } from "../src/vision"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; -import { fakeChatGptJwt } from "./helpers/fake-chatgpt-jwt"; +import { saveConfig } from "../../src/config"; +import { startServer } from "../../src/server"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import type { OcxConfig } from "../../src/types"; +import { parseRequest } from "../../src/responses/parser"; +import { resetVisionDescriptionCache, stripImagesInPlace } from "../../src/vision"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { fakeChatGptJwt } from "../helpers/fake-chatgpt-jwt"; // Issue #88: text-only input models (DeepSeek, ...) get "eyes" — the vision sidecar describes // attached images via a vision-capable forward model and replaces them with text BEFORE the main diff --git a/tests/vision-text-only-predicate.test.ts b/tests/vision/vision-text-only-predicate.test.ts similarity index 94% rename from tests/vision-text-only-predicate.test.ts rename to tests/vision/vision-text-only-predicate.test.ts index 05574bf9bb2..6a78872a044 100644 --- a/tests/vision-text-only-predicate.test.ts +++ b/tests/vision/vision-text-only-predicate.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { isModelTextOnly } from "../src/vision"; -import type { OcxProviderConfig } from "../src/types"; +import { isModelTextOnly } from "../../src/vision"; +import type { OcxProviderConfig } from "../../src/types"; function provider(overrides: Partial = {}): OcxProviderConfig { return { name: "test", baseUrl: "https://example.com", ...overrides } as OcxProviderConfig; diff --git a/tests/format-result.test.ts b/tests/web-search/format-result.test.ts similarity index 98% rename from tests/format-result.test.ts rename to tests/web-search/format-result.test.ts index 97f5198c457..b6b48c5fd44 100644 --- a/tests/format-result.test.ts +++ b/tests/web-search/format-result.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { formatWebSearchResult, formatWebSearchResults } from "../src/web-search/format-result"; +import { formatWebSearchResult, formatWebSearchResults } from "../../src/web-search/format-result"; describe("formatWebSearchResult hardening", () => { test("long query strings are clamped to 200 chars", () => { diff --git a/tests/web-search-anthropic.test.ts b/tests/web-search/web-search-anthropic.test.ts similarity index 97% rename from tests/web-search-anthropic.test.ts rename to tests/web-search/web-search-anthropic.test.ts index 4f884b0a8a3..f5b7f1df261 100644 --- a/tests/web-search-anthropic.test.ts +++ b/tests/web-search/web-search-anthropic.test.ts @@ -1,10 +1,10 @@ import { afterEach, describe, expect, mock, test } from "bun:test"; -import * as oauthModule from "../src/oauth"; +import * as oauthModule from "../../src/oauth"; // Stub the stored-OAuth token fetch so the anthropic executor request-shape test is deterministic // and never touches the real credential store or network (mirrors tests/destination-policy-resolved). let oauthAccessError: Error | undefined; -mock.module("../src/oauth", () => ({ +mock.module("../../src/oauth", () => ({ ...oauthModule, getValidAccessToken: async () => { if (oauthAccessError) throw oauthAccessError; @@ -12,15 +12,15 @@ mock.module("../src/oauth", () => ({ }, })); -import { parseRequest } from "../src/responses/parser"; +import { parseRequest } from "../../src/responses/parser"; import { findAnthropicSidecarProvider, planWebSearch, resolveSidecarBackend, -} from "../src/web-search"; -import { parseAnthropicSidecarSSE, runAnthropicWebSearch } from "../src/web-search/anthropic-executor"; -import { CLAUDE_CODE_SYSTEM_INSTRUCTION } from "../src/oauth/anthropic"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +} from "../../src/web-search"; +import { parseAnthropicSidecarSSE, runAnthropicWebSearch } from "../../src/web-search/anthropic-executor"; +import { CLAUDE_CODE_SYSTEM_INSTRUCTION } from "../../src/oauth/anthropic"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; const routedProvider: OcxProviderConfig = { adapter: "openai-chat", baseUrl: "https://routed.test/v1", apiKey: "routed-key" }; const forwardProvider: OcxProviderConfig = { adapter: "openai-responses", baseUrl: "https://chatgpt.test/v1", authMode: "forward" }; diff --git a/tests/web-search-backend-union.test.ts b/tests/web-search/web-search-backend-union.test.ts similarity index 92% rename from tests/web-search-backend-union.test.ts rename to tests/web-search/web-search-backend-union.test.ts index 7f7d29a4626..3189151287c 100644 --- a/tests/web-search-backend-union.test.ts +++ b/tests/web-search/web-search-backend-union.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from "bun:test"; -import { parseRequest } from "../src/responses/parser"; -import { planWebSearch, resolveSidecarBackend, shouldResolveOpenAiWebSearchSidecar } from "../src/web-search"; -import { handleManagementAPI } from "../src/server/management-api"; -import { ManagementRequest as Request } from "./helpers/management-auth"; -import { redactSecrets } from "../src/lib/redact"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { parseRequest } from "../../src/responses/parser"; +import { planWebSearch, resolveSidecarBackend, shouldResolveOpenAiWebSearchSidecar } from "../../src/web-search"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { ManagementRequest as Request } from "../helpers/management-auth"; +import { redactSecrets } from "../../src/lib/redact"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; const routed: OcxProviderConfig = { adapter: "openai-chat", baseUrl: "https://routed.test/v1", apiKey: "routed-key" }; const forward: OcxProviderConfig = { adapter: "openai-responses", baseUrl: "https://chatgpt.test/v1", authMode: "forward" }; diff --git a/tests/web-search-candidates.test.ts b/tests/web-search/web-search-candidates.test.ts similarity index 87% rename from tests/web-search-candidates.test.ts rename to tests/web-search/web-search-candidates.test.ts index 8bc85ebdcd7..18f8c86f3e1 100644 --- a/tests/web-search-candidates.test.ts +++ b/tests/web-search/web-search-candidates.test.ts @@ -1,31 +1,31 @@ import { afterEach, describe, expect, mock, test } from "bun:test"; -import * as storeModule from "../src/oauth/store"; -import * as usabilityModule from "../src/codex/account-usability"; -import * as modelRowsModule from "../src/server/management/model-rows"; +import * as storeModule from "../../src/oauth/store"; +import * as usabilityModule from "../../src/codex/account-usability"; +import * as modelRowsModule from "../../src/server/management/model-rows"; let accountSets: Record; activeAccountId?: string }> = {}; let usableCodexAccounts: Set = new Set(); let managementRows: Array> = []; -mock.module("../src/oauth/store", () => ({ +mock.module("../../src/oauth/store", () => ({ ...storeModule, getAccountSet: (provider: string) => accountSets[provider] ?? null, })); -mock.module("../src/codex/account-usability", () => ({ +mock.module("../../src/codex/account-usability", () => ({ ...usabilityModule, isCodexAccountUsable: (_config: unknown, accountId: string) => usableCodexAccounts.has(accountId), })); -mock.module("../src/server/management/model-rows", () => ({ +mock.module("../../src/server/management/model-rows", () => ({ ...modelRowsModule, listManagementModelRows: async () => managementRows, })); -import { isWebSearchAuthSlotModel, webSearchSidecarCandidates } from "../src/web-search/backends"; -import { pickerVisibleSidecarCandidates } from "../src/sidecar/candidates"; -import { resolveSidecarAuth } from "../src/sidecar/auth"; -import { resolveSidecarBackend } from "../src/web-search"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/account-id"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { isWebSearchAuthSlotModel, webSearchSidecarCandidates } from "../../src/web-search/backends"; +import { pickerVisibleSidecarCandidates } from "../../src/sidecar/candidates"; +import { resolveSidecarAuth } from "../../src/sidecar/auth"; +import { resolveSidecarBackend } from "../../src/web-search"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/account-id"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; const forward: OcxProviderConfig = { adapter: "openai-responses", baseUrl: "https://chatgpt.com/backend-api/codex", authMode: "forward" }; const anthropicOAuth: OcxProviderConfig = { adapter: "anthropic", baseUrl: "https://api.anthropic.com", authMode: "oauth" }; diff --git a/tests/web-search-parse.test.ts b/tests/web-search/web-search-parse.test.ts similarity index 99% rename from tests/web-search-parse.test.ts rename to tests/web-search/web-search-parse.test.ts index a64582942c6..8ea42f583d4 100644 --- a/tests/web-search-parse.test.ts +++ b/tests/web-search/web-search-parse.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { MAX_SIDECAR_RESPONSE_BYTES, parseSidecarSSE } from "../src/web-search/parse"; +import { MAX_SIDECAR_RESPONSE_BYTES, parseSidecarSSE } from "../../src/web-search/parse"; function sse(events: { type: string; [k: string]: unknown }[]): Response { const body = events.map(e => `event: ${e.type}\ndata: ${JSON.stringify(e)}\n\n`).join(""); diff --git a/tests/web-search-progress-stream.test.ts b/tests/web-search/web-search-progress-stream.test.ts similarity index 99% rename from tests/web-search-progress-stream.test.ts rename to tests/web-search/web-search-progress-stream.test.ts index e994459bee5..ddb325b2fbe 100644 --- a/tests/web-search-progress-stream.test.ts +++ b/tests/web-search/web-search-progress-stream.test.ts @@ -1,11 +1,11 @@ import { describe, expect, test } from "bun:test"; -import type { ProviderAdapter } from "../src/adapters/base"; +import type { ProviderAdapter } from "../../src/adapters/base"; import { parseStreamWithProgress, RoutedModelInactivityError, WebSearchStreamProtocolError, -} from "../src/web-search/progress-stream"; -import type { AdapterEvent } from "../src/types"; +} from "../../src/web-search/progress-stream"; +import type { AdapterEvent } from "../../src/types"; type ParseStream = ProviderAdapter["parseStream"]; diff --git a/tests/web-search-sources.test.ts b/tests/web-search/web-search-sources.test.ts similarity index 98% rename from tests/web-search-sources.test.ts rename to tests/web-search/web-search-sources.test.ts index cb81d71fd42..00be9590ac1 100644 --- a/tests/web-search-sources.test.ts +++ b/tests/web-search/web-search-sources.test.ts @@ -6,7 +6,7 @@ import { MAX_WEB_SEARCH_URL_BYTES, appendSafeWebSearchSource, safeWebSearchSources, -} from "../src/web-search/sources"; +} from "../../src/web-search/sources"; const byteLength = (value: string): number => new TextEncoder().encode(value).byteLength; diff --git a/tests/web-search-timeout-contract.test.ts b/tests/web-search/web-search-timeout-contract.test.ts similarity index 97% rename from tests/web-search-timeout-contract.test.ts rename to tests/web-search/web-search-timeout-contract.test.ts index 73278fa92f3..d1ab2c8f67e 100644 --- a/tests/web-search-timeout-contract.test.ts +++ b/tests/web-search/web-search-timeout-contract.test.ts @@ -1,10 +1,10 @@ import { afterEach, describe, expect, test } from "bun:test"; -import type { AdapterFetchContext, ProviderAdapter } from "../src/adapters/base"; -import { parseRequest } from "../src/responses/parser"; -import { responseWithDeferredRequestLog, type RequestLogEntry } from "../src/server"; -import type { AdapterEvent, OcxProviderConfig } from "../src/types"; -import { runWithWebSearch as runWithWebSearchProduction, type WebSearchLoopDeps } from "../src/web-search/loop"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; +import type { AdapterFetchContext, ProviderAdapter } from "../../src/adapters/base"; +import { parseRequest } from "../../src/responses/parser"; +import { responseWithDeferredRequestLog, type RequestLogEntry } from "../../src/server"; +import type { AdapterEvent, OcxProviderConfig } from "../../src/types"; +import { runWithWebSearch as runWithWebSearchProduction, type WebSearchLoopDeps } from "../../src/web-search/loop"; +import { createTestTranslatorBudget } from "../helpers/translator-budget"; function runWithWebSearch( deps: Omit & { incomingMeta?: WebSearchLoopDeps["incomingMeta"] }, diff --git a/tests/web-search-timeout-plan.test.ts b/tests/web-search/web-search-timeout-plan.test.ts similarity index 95% rename from tests/web-search-timeout-plan.test.ts rename to tests/web-search/web-search-timeout-plan.test.ts index 8970436d387..40f8d5e8008 100644 --- a/tests/web-search-timeout-plan.test.ts +++ b/tests/web-search/web-search-timeout-plan.test.ts @@ -1,11 +1,11 @@ import { describe, expect, test } from "bun:test"; -import { parseRequest } from "../src/responses/parser"; +import { parseRequest } from "../../src/responses/parser"; import { planWebSearch, resolveRoutedModelStallTimeoutMs, webSearchStallTimeoutSec, -} from "../src/web-search"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +} from "../../src/web-search"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; const routedProvider: OcxProviderConfig = { adapter: "openai-chat", diff --git a/tests/web-search.test.ts b/tests/web-search/web-search.test.ts similarity index 99% rename from tests/web-search.test.ts rename to tests/web-search/web-search.test.ts index a212b4f8929..ce8f6e0f8a7 100644 --- a/tests/web-search.test.ts +++ b/tests/web-search/web-search.test.ts @@ -1,19 +1,19 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { parseRequest } from "../src/responses/parser"; -import { planWebSearch, shouldResolveOpenAiWebSearchSidecar, webSearchStallTimeoutSec } from "../src/web-search"; -import { runWithWebSearch as runWithWebSearchProduction, type WebSearchLoopDeps } from "../src/web-search/loop"; -import { runWebSearch as runOpenAiWebSearch } from "../src/web-search/executor"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { headersForCodexAuthContext } from "../src/codex/auth-context"; -import { listOpenAiForwardSidecarCandidates, resolveFirstUsableOpenAiSidecar } from "../src/providers/openai-sidecar"; -import { handleResponses } from "../src/server/responses/core"; -import { providerFetch } from "../src/server/responses/fetch-helpers"; -import type { AdapterEvent, OcxConfig, OcxProviderConfig } from "../src/types"; -import type { AdapterFetchContext, ProviderAdapter } from "../src/adapters/base"; -import type { OcxMessage, OcxParsedRequest } from "../src/types"; -import { fakeChatGptJwt } from "./helpers/fake-chatgpt-jwt"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import { withUpstreamHttpVersion } from "../src/lib/upstream-http-version"; +import { parseRequest } from "../../src/responses/parser"; +import { planWebSearch, shouldResolveOpenAiWebSearchSidecar, webSearchStallTimeoutSec } from "../../src/web-search"; +import { runWithWebSearch as runWithWebSearchProduction, type WebSearchLoopDeps } from "../../src/web-search/loop"; +import { runWebSearch as runOpenAiWebSearch } from "../../src/web-search/executor"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { headersForCodexAuthContext } from "../../src/codex/auth-context"; +import { listOpenAiForwardSidecarCandidates, resolveFirstUsableOpenAiSidecar } from "../../src/providers/openai-sidecar"; +import { handleResponses } from "../../src/server/responses/core"; +import { providerFetch } from "../../src/server/responses/fetch-helpers"; +import type { AdapterEvent, OcxConfig, OcxProviderConfig } from "../../src/types"; +import type { AdapterFetchContext, ProviderAdapter } from "../../src/adapters/base"; +import type { OcxMessage, OcxParsedRequest } from "../../src/types"; +import { fakeChatGptJwt } from "../helpers/fake-chatgpt-jwt"; +import { createTestTranslatorBudget } from "../helpers/translator-budget"; +import { withUpstreamHttpVersion } from "../../src/lib/upstream-http-version"; /** * Wrap a fetch so it applies the provider's HTTP-version pin the way `providerFetch` does in