From e60c7781f254c900d93edd9af8b3fd491fd17437 Mon Sep 17 00:00:00 2001 From: jun Date: Sat, 5 Sep 2026 04:14:41 +0900 Subject: [PATCH 1/2] test(layout): rebind a local repoRoot through an aliased import; rewrite root URLs; treat mock.module as a specifier site; flag variable URL specifiers --- scripts/test-layout/schema.ts | 19 +++++++++++++++---- tests/test-layout-tooling.test.ts | 22 ++++++++++++++++++---- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/scripts/test-layout/schema.ts b/scripts/test-layout/schema.ts index 04d33f48c1..8d3936a494 100644 --- a/scripts/test-layout/schema.ts +++ b/scripts/test-layout/schema.ts @@ -170,11 +170,18 @@ function maskKeepStrings(source: string, tokens = tokenize(source)): string { export function rewriteMetaDirEscapes(source: string, depth: number): { source: string; rewrites: number } { const tokens = tokenize(source); const code = maskNonCode(source, tokens); - if (new RegExp(`\\b(?:const|let|var|function)\\s+(?:${HELPER_NAMES.join("|")})\\b`).test(code)) { - return { source, rewrites: 0 }; - } const view = maskKeepStrings(source, tokens); + // `const repoRoot = join(import.meta.dir, "..")` is the commonest escape of all: rebind the + // local through an aliased import instead of refusing the file. Any other local named like a + // helper (or a function) still stops the rewrite so nothing gets shadowed. + const localRoot = /\bconst\s+repoRoot\s*=\s*(?:(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\."\s*\)|fileURLToPath\(\s*new\s+URL\(\s*"\.\.\/"\s*,\s*import\.meta\.url\s*\)\s*\)|resolve\(\s*dirname\(\s*fileURLToPath\(\s*import\.meta\.url\s*\)\s*\)\s*,\s*"\.\."\s*\))\s*;/; + const rebindsRoot = localRoot.test(view); + const otherLocals = new RegExp(`\\b(?:const|let|var|function)\\s+(?:${HELPER_NAMES.filter(n => !(rebindsRoot && n === "repoRoot")).join("|")})\\b`); + if (otherLocals.test(code)) return { source, rewrites: 0 }; const rules: Array<[RegExp, (m: RegExpMatchArray) => string]> = [ + [new RegExp(localRoot.source, "g"), () => "const repoRoot = resolveRepoRoot();"], + // `const root = new URL("../../", import.meta.url)` -> a file URL of the repository root. + [/\bconst\s+root\s*=\s*new\s+URL\(\s*"(?:\.\.\/)+"\s*,\s*import\.meta\.url\s*\)\s*;/g, () => 'const root = pathToFileURL(repoRoot() + "/");'], [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\."\s*\)/g, () => "repoRoot()"], [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\."\s*,\s*/g, () => "repoPath("], [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\.\/([^"]+)"/g, m => `repoPath("${m[1]}"`], @@ -199,7 +206,11 @@ export function rewriteMetaDirEscapes(source: string, depth: number): { source: } out += source.slice(cursor); const codeOut = maskNonCode(out); - const used = HELPER_NAMES.filter(name => new RegExp(`\\b${name}\\(`).test(codeOut)); + const used = HELPER_NAMES.filter(name => new RegExp(`\\b${name}\\(`).test(codeOut)).map(name => (name === "repoRoot" && rebindsRoot ? "repoRoot as resolveRepoRoot" : name)); + if (rebindsRoot && !used.includes("repoRoot as resolveRepoRoot")) used.push("repoRoot as resolveRepoRoot"); + if (/\bpathToFileURL\(repoRoot\(\)/.test(codeOut) && !/\bimport\s*\{[^}]*\bpathToFileURL\b[^}]*\}\s*from\s*["']node:url["']/.test(view)) { + out = insertAfterImports(out, 'import { pathToFileURL } from "node:url";'); + } const existing = /^import\s*\{([^}]*)\}\s*from\s*(["'])([^"']*helpers\/repo-root)\2;?/m.exec(maskKeepStrings(out)); if (existing) { // Augment a partial import rather than adding a second one. diff --git a/tests/test-layout-tooling.test.ts b/tests/test-layout-tooling.test.ts index 6268f6cf85..acffde0624 100644 --- a/tests/test-layout-tooling.test.ts +++ b/tests/test-layout-tooling.test.ts @@ -115,12 +115,26 @@ describe("scanEscapes", () => { expect(scanEscapes(src)).toEqual([]); }); - test("a file that already binds repoRoot is left for the scanner instead of being shadowed", () => { + test("a local repoRoot binding is rebound through an aliased import; other helper-named locals stop the rewrite", () => { const src = 'import { join } from "node:path";\nconst repoRoot = join(import.meta.dir, "..");\nconst read = (rel: string) => readFileSync(join(repoRoot, rel), "utf8");\n'; const out = rewriteMetaDirEscapes(src, 1); - expect(out.rewrites).toBe(0); - expect(out.source).toBe(src); - expect(scanEscapes(src).map(h => h.line)).toEqual([2]); + expect(out.rewrites).toBe(1); + expect(out.source.split("\n")[1]).toBe('import { repoRoot as resolveRepoRoot } from "../helpers/repo-root";'); + expect(out.source).toContain("const repoRoot = resolveRepoRoot();"); + expect(out.source).toContain('readFileSync(join(repoRoot, rel), "utf8")'); + expect(scanEscapes(out.source)).toEqual([]); + + const url = 'import { join } from "node:path";\nconst root = new URL("../../", import.meta.url);\nconst t = await Bun.file(new URL(p, root)).text();\n'; + const outUrl = rewriteMetaDirEscapes(url, 2); + expect(outUrl.source).toContain('const root = pathToFileURL(repoRoot() + "/");'); + expect(outUrl.source).toContain('import { pathToFileURL } from "node:url";'); + expect(outUrl.source).toContain('import { repoRoot } from "../../helpers/repo-root";'); + + const other = 'import { join } from "node:path";\nconst repoPath = (x: string) => x;\nconst s = join(import.meta.dir, "..", "src");\n'; + const outOther = rewriteMetaDirEscapes(other, 1); + expect(outOther.rewrites).toBe(0); + expect(outOther.source).toBe(other); + expect(scanEscapes(other).map(h => h.line)).toEqual([3]); }); test("resolve/dirname/fileURLToPath and multi-line import blocks are handled", () => { From 66fb811ec117e360a6eb4171fb1c5963ab432f44 Mon Sep 17 00:00:00 2001 From: jun Date: Sat, 5 Sep 2026 04:17:30 +0900 Subject: [PATCH 2/2] test(layout): move cli, oauth, routing, claude-integration into tests// (#3497) --- .github/scripts/pr-hygiene.test.cjs | 2 +- AGENTS.md | 2 +- AGENTS_INSTALL.md | 2 +- bin/ocx.mjs | 2 +- docs-site/src/content/docs/contributing.md | 4 +- docs-site/src/content/docs/fr/contributing.md | 4 +- docs-site/src/content/docs/ja/contributing.md | 4 +- docs-site/src/content/docs/ko/contributing.md | 4 +- docs-site/src/content/docs/ru/contributing.md | 4 +- docs-site/src/content/docs/tr/contributing.md | 4 +- .../src/content/docs/zh-cn/contributing.md | 4 +- .../src/content/docs/zh-tw/contributing.md | 4 +- .../2026-07-26-oauth-reliability-integrity.md | 48 +++++++------- scripts/openai-provider-option-final-gates.ts | 2 +- scripts/test-layout/layout.json | 4 ++ scripts/test-layout/schema.ts | 2 +- src/cli/capabilities.ts | 4 +- src/cli/dispatch.ts | 2 +- src/cli/models-runtime.ts | 2 +- tests/anthropic-baseurl-override.test.ts | 2 +- tests/antigravity-baseurl-override.test.ts | 2 +- .../claude-529-mapping.test.ts | 12 ++-- .../claude-agent-startup-sync.test.ts | 10 +-- .../claude-agents-inject.test.ts | 12 ++-- .../claude-alias.test.ts | 4 +- .../claude-auth-detect.test.ts | 2 +- .../claude-auth-mode.test.ts | 10 +-- .../claude-authmode-migration.test.ts | 4 +- .../claude-cli.test.ts | 8 +-- ...laude-code-thought-signature-scope.test.ts | 10 +-- .../claude-context-windows.test.ts | 6 +- .../claude-desktop-1m.test.ts | 8 +-- .../claude-desktop-cli.test.ts | 10 +-- .../claude-desktop-config-path.test.ts | 8 +-- .../claude-desktop-native-context.test.ts | 12 ++-- .../claude-desktop-policy.test.ts | 2 +- ...claude-dotenv-provenance-transport.test.ts | 5 +- .../claude-gateway-cache.test.ts | 4 +- .../claude-inbound-debug.test.ts | 4 +- .../claude-inbound.test.ts | 8 +-- .../claude-management-api.test.ts | 20 +++--- .../claude-messages-endpoint.test.ts | 34 +++++----- .../claude-model-info.test.ts | 4 +- .../claude-models-discovery.test.ts | 34 +++++----- .../claude-native-passthrough.test.ts | 20 +++--- .../claude-outbound.test.ts | 6 +- .../claude-shell-hook.test.ts | 6 +- .../claude-sidecar-override.test.ts | 10 +-- .../claude-system-env-auto.test.ts | 6 +- tests/{ => cli}/agent-driven.test.ts | 2 +- .../{ => cli}/cli-account-pool-verbs.test.ts | 6 +- tests/{ => cli}/cli-account.test.ts | 22 +++---- tests/{ => cli}/cli-capabilities.test.ts | 17 ++--- tests/{ => cli}/cli-catalog-prewarm.test.ts | 8 ++- tests/{ => cli}/cli-codex-cli-update.test.ts | 6 +- .../cli-codex-log-guard-compact.test.ts | 2 +- .../cli-codex-log-guard-protection.test.ts | 2 +- tests/{ => cli}/cli-codex-log-guard.test.ts | 2 +- tests/{ => cli}/cli-config-command.test.ts | 6 +- tests/{ => cli}/cli-dispatch.test.ts | 17 ++--- tests/{ => cli}/cli-dto-fidelity.test.ts | 10 +-- tests/{ => cli}/cli-export-command.test.ts | 12 ++-- tests/{ => cli}/cli-head.test.ts | 4 +- tests/{ => cli}/cli-headless-parity.test.ts | 25 +++---- tests/{ => cli}/cli-help.test.ts | 8 +-- tests/{ => cli}/cli-json-contract.test.ts | 7 +- tests/{ => cli}/cli-management-auth.test.ts | 10 +-- tests/{ => cli}/cli-models-reasoning.test.ts | 6 +- .../cli-models-runtime-dispatch.test.ts | 6 +- tests/{ => cli}/cli-models.test.ts | 12 ++-- tests/{ => cli}/cli-native-profile.test.ts | 8 +-- tests/{ => cli}/cli-provider.test.ts | 6 +- tests/{ => cli}/cli-ready-subprocess.test.ts | 6 +- tests/{ => cli}/cli-ready.test.ts | 25 +++---- tests/{ => cli}/cli-registry.test.ts | 6 +- tests/{ => cli}/cli-restart-health.test.ts | 8 +-- tests/{ => cli}/cli-restore-back.test.ts | 9 +-- .../{ => cli}/cli-start-journal-order.test.ts | 7 +- tests/{ => cli}/cli-status-json.test.ts | 10 +-- .../{ => cli}/cli-status-oauth-health.test.ts | 8 +-- tests/{ => cli}/cli-storage-inspect.test.ts | 4 +- tests/{ => cli}/cli-transport-honesty.test.ts | 19 +++--- tests/{ => cli}/cli-usage-report.test.ts | 4 +- tests/{ => cli}/cli-version-skew.test.ts | 4 +- .../ensure-desired-integrations-race.test.ts | 8 +-- tests/{ => cli}/interactive-confirm.test.ts | 2 +- tests/{ => cli}/ocx-launcher-runtime.test.ts | 7 +- tests/{ => cli}/ocx-launcher-source.test.ts | 7 +- tests/{ => cli}/ocx-run.test.ts | 5 +- .../restore-completes-shared-teardown.test.ts | 8 +-- tests/{ => cli}/route-explainability.test.ts | 20 +++--- tests/{ => cli}/star-deferral.test.ts | 4 +- tests/{ => cli}/system-restart-client.test.ts | 8 +-- tests/{ => cli}/uninstall.test.ts | 12 ++-- tests/clients/desktop-3p.test.ts | 2 +- tests/codex-model-entitlements.test.ts | 2 +- tests/grok-lifecycle.test.ts | 2 +- .../adapter-event-oauth-failover.test.ts | 16 ++--- tests/{ => oauth}/chatgpt-device-auth.test.ts | 8 +-- tests/{ => oauth}/chatgpt-oauth.test.ts | 2 +- .../{ => oauth}/chatgpt-token-expiry.test.ts | 2 +- .../generic-oauth-failover.test.ts | 17 ++--- .../{ => oauth}/key-login-live-update.test.ts | 20 +++--- .../key-login-preserves-model-costs.test.ts | 6 +- tests/{ => oauth}/local-token-detect.test.ts | 4 +- .../oauth-account-attribution.test.ts | 22 +++---- .../oauth-account-id-collision.test.ts | 6 +- tests/{ => oauth}/oauth-accounts-api.test.ts | 24 +++---- .../{ => oauth}/oauth-callback-binds.test.ts | 5 +- .../{ => oauth}/oauth-callback-server.test.ts | 4 +- .../oauth-device-code-contract.test.ts | 4 +- tests/{ => oauth}/oauth-health.test.ts | 18 ++--- tests/{ => oauth}/oauth-log.test.ts | 2 +- .../oauth-login-cli-live-update.test.ts | 18 ++--- .../oauth-login-open-browser.test.ts | 8 +-- tests/{ => oauth}/oauth-login-summary.test.ts | 2 +- tests/{ => oauth}/oauth-manual-code.test.ts | 20 +++--- .../oauth-open-browser-choice.test.ts | 12 ++-- .../oauth-provider-reconcile.test.ts | 16 ++--- .../{ => oauth}/oauth-public-surface.test.ts | 24 +++---- tests/{ => oauth}/oauth-reauth-bind.test.ts | 18 ++--- .../oauth-refresh-generic-lock.test.ts | 8 +-- .../oauth-refresh-lock-multiprocess.test.ts | 8 +-- tests/{ => oauth}/oauth-refresh.test.ts | 16 ++--- .../{ => oauth}/oauth-status-privacy.test.ts | 20 +++--- tests/{ => oauth}/oauth-store-multi.test.ts | 10 +-- .../oauth-upsert-preserves-api-key.test.ts | 10 +-- tests/{ => oauth}/state-store-sweeper.test.ts | 24 +++---- .../always-on-429-failover.test.ts | 12 ++-- ...claude-outbound-review-regressions.test.ts | 4 +- ...l01-openai-chat-review-regressions.test.ts | 4 +- .../cl01-review-regressions.test.ts | 8 +-- .../{ => routing}/combo-child-headers.test.ts | 4 +- .../combo-management-api.test.ts | 24 +++---- .../combo-stream-preflight.test.ts | 6 +- ...compatibility-provider-equivalence.test.ts | 10 +-- .../destination-policy-resolved.test.ts | 2 +- .../fastwire-characterization-routing.test.ts | 14 ++-- .../fastwire-characterization-wire.test.ts | 14 ++-- .../fastwire-observability.test.ts | 30 ++++----- tests/{ => routing}/fastwire-policy.test.ts | 14 ++-- tests/{ => routing}/policy-execution.test.ts | 14 ++-- .../router-discarded-baseurl-warning.test.ts | 6 +- .../router-template-baseurl.test.ts | 4 +- tests/{ => routing}/router.test.ts | 6 +- tests/{ => routing}/routing-analytics.test.ts | 14 ++-- .../routing-capability-catalog.test.ts | 14 ++-- .../routing-capability-model-matching.test.ts | 12 ++-- ...outing-compatibility-auth-identity.test.ts | 6 +- .../routing-compatibility-boundaries.test.ts | 14 ++-- ...uting-compatibility-model-matching.test.ts | 12 ++-- .../routing-compatibility.test.ts | 36 +++++----- .../routing-policy-fallback.test.ts | 12 ++-- .../routing-policy-pool-quota.test.ts | 4 +- .../routing-policy-surface-parity.test.ts | 22 +++---- .../routing-profile-management-editor.test.ts | 10 +-- tests/{ => routing}/routing-profile.test.ts | 26 ++++---- .../subagent-context-staleness.test.ts | 6 +- tests/{ => routing}/subagent-defaults.test.ts | 2 +- ...subagent-fallback-handle-responses.test.ts | 66 +++++++++---------- .../subagent-model-fallback-api.test.ts | 8 +-- .../subagent-model-fallback.test.ts | 18 ++--- .../subagent-roster-retention.test.ts | 6 +- 163 files changed, 824 insertions(+), 802 deletions(-) rename tests/{ => claude-integration}/claude-529-mapping.test.ts (93%) rename tests/{ => claude-integration}/claude-agent-startup-sync.test.ts (93%) rename tests/{ => claude-integration}/claude-agents-inject.test.ts (97%) rename tests/{ => claude-integration}/claude-alias.test.ts (98%) rename tests/{ => claude-integration}/claude-auth-detect.test.ts (99%) rename tests/{ => claude-integration}/claude-auth-mode.test.ts (98%) rename tests/{ => claude-integration}/claude-authmode-migration.test.ts (95%) rename tests/{ => claude-integration}/claude-cli.test.ts (98%) rename tests/{ => claude-integration}/claude-code-thought-signature-scope.test.ts (93%) rename tests/{ => claude-integration}/claude-context-windows.test.ts (98%) rename tests/{ => claude-integration}/claude-desktop-1m.test.ts (89%) rename tests/{ => claude-integration}/claude-desktop-cli.test.ts (95%) rename tests/{ => claude-integration}/claude-desktop-config-path.test.ts (96%) rename tests/{ => claude-integration}/claude-desktop-native-context.test.ts (88%) rename tests/{ => claude-integration}/claude-desktop-policy.test.ts (98%) rename tests/{ => claude-integration}/claude-dotenv-provenance-transport.test.ts (95%) rename tests/{ => claude-integration}/claude-gateway-cache.test.ts (98%) rename tests/{ => claude-integration}/claude-inbound-debug.test.ts (98%) rename tests/{ => claude-integration}/claude-inbound.test.ts (98%) rename tests/{ => claude-integration}/claude-management-api.test.ts (98%) rename tests/{ => claude-integration}/claude-messages-endpoint.test.ts (98%) rename tests/{ => claude-integration}/claude-model-info.test.ts (99%) rename tests/{ => claude-integration}/claude-models-discovery.test.ts (96%) rename tests/{ => claude-integration}/claude-native-passthrough.test.ts (97%) rename tests/{ => claude-integration}/claude-outbound.test.ts (99%) rename tests/{ => claude-integration}/claude-shell-hook.test.ts (96%) rename tests/{ => claude-integration}/claude-sidecar-override.test.ts (92%) rename tests/{ => claude-integration}/claude-system-env-auto.test.ts (97%) rename tests/{ => cli}/agent-driven.test.ts (96%) rename tests/{ => cli}/cli-account-pool-verbs.test.ts (98%) rename tests/{ => cli}/cli-account.test.ts (99%) rename tests/{ => cli}/cli-capabilities.test.ts (95%) rename tests/{ => cli}/cli-catalog-prewarm.test.ts (91%) rename tests/{ => cli}/cli-codex-cli-update.test.ts (98%) rename tests/{ => cli}/cli-codex-log-guard-compact.test.ts (96%) rename tests/{ => cli}/cli-codex-log-guard-protection.test.ts (98%) rename tests/{ => cli}/cli-codex-log-guard.test.ts (96%) rename tests/{ => cli}/cli-config-command.test.ts (92%) rename tests/{ => cli}/cli-dispatch.test.ts (98%) rename tests/{ => cli}/cli-dto-fidelity.test.ts (96%) rename tests/{ => cli}/cli-export-command.test.ts (97%) rename tests/{ => cli}/cli-head.test.ts (97%) rename tests/{ => cli}/cli-headless-parity.test.ts (98%) rename tests/{ => cli}/cli-help.test.ts (98%) rename tests/{ => cli}/cli-json-contract.test.ts (95%) rename tests/{ => cli}/cli-management-auth.test.ts (92%) rename tests/{ => cli}/cli-models-reasoning.test.ts (97%) rename tests/{ => cli}/cli-models-runtime-dispatch.test.ts (93%) rename tests/{ => cli}/cli-models.test.ts (98%) rename tests/{ => cli}/cli-native-profile.test.ts (98%) rename tests/{ => cli}/cli-provider.test.ts (98%) rename tests/{ => cli}/cli-ready-subprocess.test.ts (97%) rename tests/{ => cli}/cli-ready.test.ts (97%) rename tests/{ => cli}/cli-registry.test.ts (96%) rename tests/{ => cli}/cli-restart-health.test.ts (94%) rename tests/{ => cli}/cli-restore-back.test.ts (96%) rename tests/{ => cli}/cli-start-journal-order.test.ts (98%) rename tests/{ => cli}/cli-status-json.test.ts (98%) rename tests/{ => cli}/cli-status-oauth-health.test.ts (94%) rename tests/{ => cli}/cli-storage-inspect.test.ts (99%) rename tests/{ => cli}/cli-transport-honesty.test.ts (95%) rename tests/{ => cli}/cli-usage-report.test.ts (98%) rename tests/{ => cli}/cli-version-skew.test.ts (95%) rename tests/{ => cli}/ensure-desired-integrations-race.test.ts (95%) rename tests/{ => cli}/interactive-confirm.test.ts (98%) rename tests/{ => cli}/ocx-launcher-runtime.test.ts (98%) rename tests/{ => cli}/ocx-launcher-source.test.ts (97%) rename tests/{ => cli}/ocx-run.test.ts (88%) rename tests/{ => cli}/restore-completes-shared-teardown.test.ts (96%) rename tests/{ => cli}/route-explainability.test.ts (94%) rename tests/{ => cli}/star-deferral.test.ts (98%) rename tests/{ => cli}/system-restart-client.test.ts (97%) rename tests/{ => cli}/uninstall.test.ts (97%) rename tests/{ => oauth}/adapter-event-oauth-failover.test.ts (94%) rename tests/{ => oauth}/chatgpt-device-auth.test.ts (97%) rename tests/{ => oauth}/chatgpt-oauth.test.ts (99%) rename tests/{ => oauth}/chatgpt-token-expiry.test.ts (97%) rename tests/{ => oauth}/generic-oauth-failover.test.ts (97%) rename tests/{ => oauth}/key-login-live-update.test.ts (87%) rename tests/{ => oauth}/key-login-preserves-model-costs.test.ts (93%) rename tests/{ => oauth}/local-token-detect.test.ts (97%) rename tests/{ => oauth}/oauth-account-attribution.test.ts (95%) rename tests/{ => oauth}/oauth-account-id-collision.test.ts (96%) rename tests/{ => oauth}/oauth-accounts-api.test.ts (97%) rename tests/{ => oauth}/oauth-callback-binds.test.ts (87%) rename tests/{ => oauth}/oauth-callback-server.test.ts (95%) rename tests/{ => oauth}/oauth-device-code-contract.test.ts (95%) rename tests/{ => oauth}/oauth-health.test.ts (96%) rename tests/{ => oauth}/oauth-log.test.ts (98%) rename tests/{ => oauth}/oauth-login-cli-live-update.test.ts (94%) rename tests/{ => oauth}/oauth-login-open-browser.test.ts (91%) rename tests/{ => oauth}/oauth-login-summary.test.ts (95%) rename tests/{ => oauth}/oauth-manual-code.test.ts (96%) rename tests/{ => oauth}/oauth-open-browser-choice.test.ts (92%) rename tests/{ => oauth}/oauth-provider-reconcile.test.ts (96%) rename tests/{ => oauth}/oauth-public-surface.test.ts (97%) rename tests/{ => oauth}/oauth-reauth-bind.test.ts (95%) rename tests/{ => oauth}/oauth-refresh-generic-lock.test.ts (97%) rename tests/{ => oauth}/oauth-refresh-lock-multiprocess.test.ts (95%) rename tests/{ => oauth}/oauth-refresh.test.ts (99%) rename tests/{ => oauth}/oauth-status-privacy.test.ts (97%) rename tests/{ => oauth}/oauth-store-multi.test.ts (98%) rename tests/{ => oauth}/oauth-upsert-preserves-api-key.test.ts (98%) rename tests/{ => oauth}/state-store-sweeper.test.ts (96%) rename tests/{ => routing}/always-on-429-failover.test.ts (94%) rename tests/{ => routing}/cl01-claude-outbound-review-regressions.test.ts (91%) rename tests/{ => routing}/cl01-openai-chat-review-regressions.test.ts (97%) rename tests/{ => routing}/cl01-review-regressions.test.ts (89%) rename tests/{ => routing}/combo-child-headers.test.ts (92%) rename tests/{ => routing}/combo-management-api.test.ts (98%) rename tests/{ => routing}/combo-stream-preflight.test.ts (98%) rename tests/{ => routing}/compatibility-provider-equivalence.test.ts (87%) rename tests/{ => routing}/destination-policy-resolved.test.ts (99%) rename tests/{ => routing}/fastwire-characterization-routing.test.ts (92%) rename tests/{ => routing}/fastwire-characterization-wire.test.ts (96%) rename tests/{ => routing}/fastwire-observability.test.ts (97%) rename tests/{ => routing}/fastwire-policy.test.ts (98%) rename tests/{ => routing}/policy-execution.test.ts (96%) rename tests/{ => routing}/router-discarded-baseurl-warning.test.ts (97%) rename tests/{ => routing}/router-template-baseurl.test.ts (96%) rename tests/{ => routing}/router.test.ts (99%) rename tests/{ => routing}/routing-analytics.test.ts (96%) rename tests/{ => routing}/routing-capability-catalog.test.ts (94%) rename tests/{ => routing}/routing-capability-model-matching.test.ts (96%) rename tests/{ => routing}/routing-compatibility-auth-identity.test.ts (84%) rename tests/{ => routing}/routing-compatibility-boundaries.test.ts (92%) rename tests/{ => routing}/routing-compatibility-model-matching.test.ts (95%) rename tests/{ => routing}/routing-compatibility.test.ts (94%) rename tests/{ => routing}/routing-policy-fallback.test.ts (97%) rename tests/{ => routing}/routing-policy-pool-quota.test.ts (97%) rename tests/{ => routing}/routing-policy-surface-parity.test.ts (94%) rename tests/{ => routing}/routing-profile-management-editor.test.ts (98%) rename tests/{ => routing}/routing-profile.test.ts (97%) rename tests/{ => routing}/subagent-context-staleness.test.ts (94%) rename tests/{ => routing}/subagent-defaults.test.ts (99%) rename tests/{ => routing}/subagent-fallback-handle-responses.test.ts (96%) rename tests/{ => routing}/subagent-model-fallback-api.test.ts (92%) rename tests/{ => routing}/subagent-model-fallback.test.ts (99%) rename tests/{ => routing}/subagent-roster-retention.test.ts (93%) diff --git a/.github/scripts/pr-hygiene.test.cjs b/.github/scripts/pr-hygiene.test.cjs index 9f01f87868..e36435ed33 100644 --- a/.github/scripts/pr-hygiene.test.cjs +++ b/.github/scripts/pr-hygiene.test.cjs @@ -40,7 +40,7 @@ describe("assessHygiene", () => { it("accepts behavior changes with tests or approved exception", () => { assert.deepEqual(assessHygiene({ files: [ { filename: "src/router.ts", patch: "+change" }, - { filename: "tests/router.test.ts", patch: "+test" }, + { filename: "tests/routing/router.test.ts", patch: "+test" }, ] }), []); assert.deepEqual(assessHygiene({ files: [{ filename: "src/router.ts", patch: "+change" }], diff --git a/AGENTS.md b/AGENTS.md index 4433ce4921..eb8e0f47af 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -161,7 +161,7 @@ What matters for development work: the enforcement is code, not prose — [`src/cli/agent-driven.ts`](./src/cli/agent-driven.ts), [`src/cli/star-prompt.ts`](./src/cli/star-prompt.ts), and [`src/server/management/sidebar-routes.ts`](./src/server/management/sidebar-routes.ts), -covered by `tests/startup-prompt.test.ts`, `tests/agent-driven.test.ts`, and +covered by `tests/startup-prompt.test.ts`, `tests/cli/agent-driven.test.ts`, and `tests/sidebar-routes.test.ts`. If you add another action that spends the user's identity, credits, or reputation, gate it the same way rather than relying on a prompt an agent can answer, and document it in `AGENTS_INSTALL.md`. diff --git a/AGENTS_INSTALL.md b/AGENTS_INSTALL.md index 36cb3b383a..ac630b2a02 100644 --- a/AGENTS_INSTALL.md +++ b/AGENTS_INSTALL.md @@ -70,7 +70,7 @@ agent-driven callers regardless: — the `403 agent_consent_required` refusal. Regression coverage: `tests/startup-prompt.test.ts`, -`tests/agent-driven.test.ts`, `tests/sidebar-routes.test.ts`. +`tests/cli/agent-driven.test.ts`, `tests/sidebar-routes.test.ts`. If a future action spends the user's identity, credits, or reputation, gate it the same way rather than relying on a prompt an agent can answer, and document diff --git a/bin/ocx.mjs b/bin/ocx.mjs index 08eb51262d..59818de2f5 100755 --- a/bin/ocx.mjs +++ b/bin/ocx.mjs @@ -506,7 +506,7 @@ function bunBinDir() { const BUN_OVERRIDE_ENV = "OPENCODEX_BUN_PATH"; // Mirrors BUN_RUNTIME_SOURCE_ENV in src/lib/bun-runtime.ts. This launcher is plain // Node and runs before any TypeScript is loaded, so the name is repeated rather than -// imported; tests/ocx-launcher-source.test.ts pins the two together. +// imported; tests/cli/ocx-launcher-source.test.ts pins the two together. const BUN_RUNTIME_SOURCE_ENV = "OCX_BUN_RUNTIME_SOURCE"; const BUN_RUNTIME_PATH_ENV = "OCX_BUN_RUNTIME_PATH"; diff --git a/docs-site/src/content/docs/contributing.md b/docs-site/src/content/docs/contributing.md index f4e1c84d0e..55fae41667 100644 --- a/docs-site/src/content/docs/contributing.md +++ b/docs-site/src/content/docs/contributing.md @@ -16,7 +16,7 @@ bun run dev:proxy # proxy API in dev mode bun run dev:gui # dashboard dev server (another terminal) bun run typecheck # bun x tsc --noEmit bun run test:changed # routine import-graph test selection -bun test tests/router.test.ts # routine focused test +bun test tests/routing/router.test.ts # routine focused test bun run test # complete suite (PR-ready / explicit ask) ``` @@ -32,7 +32,7 @@ scripts so local commands match CI: bun run typecheck # strict TypeScript check bun run test:changed # import-graph tests against the resolved dev merge base bun run test # complete tests/ suite (PR-ready / explicit ask) -bun test tests/router.test.ts # focused test file +bun test tests/routing/router.test.ts # focused test file bun run build:gui # Vite GUI build + package preparation bun run privacy:scan # credential/privacy scan used by CI bun run prepare:package # refresh package launchers/assets diff --git a/docs-site/src/content/docs/fr/contributing.md b/docs-site/src/content/docs/fr/contributing.md index facce7337b..e7bba298fb 100644 --- a/docs-site/src/content/docs/fr/contributing.md +++ b/docs-site/src/content/docs/fr/contributing.md @@ -16,7 +16,7 @@ bun run dev:proxy # proxy API in dev mode bun run dev:gui # dashboard dev server (another terminal) bun run typecheck # bun x tsc --noEmit bun run test:changed # routine import-graph test selection -bun test tests/router.test.ts # routine focused test +bun test tests/routing/router.test.ts # routine focused test bun run test # complete suite (PR-ready / explicit ask) ``` @@ -32,7 +32,7 @@ distincte. Utilisez les scripts enregistrés afin que les commandes locales corr bun run typecheck # strict TypeScript check bun run test:changed # import-graph tests against the resolved dev merge base bun run test # complete tests/ suite (PR-ready / explicit ask) -bun test tests/router.test.ts # focused test file +bun test tests/routing/router.test.ts # focused test file bun run build:gui # Vite GUI build + package preparation bun run privacy:scan # credential/privacy scan used by CI bun run prepare:package # refresh package launchers/assets diff --git a/docs-site/src/content/docs/ja/contributing.md b/docs-site/src/content/docs/ja/contributing.md index 26a1de8c42..297f9169b5 100644 --- a/docs-site/src/content/docs/ja/contributing.md +++ b/docs-site/src/content/docs/ja/contributing.md @@ -13,7 +13,7 @@ bun run dev:proxy # 開発モードのプロキシ API bun run dev:gui # ダッシュボード dev サーバー(別ターミナル) bun run typecheck # bun x tsc --noEmit bun run test:changed # routine import-graph test selection -bun test tests/router.test.ts # routine focused test +bun test tests/routing/router.test.ts # routine focused test bun run test # complete suite (PR-ready / explicit ask) ``` @@ -29,7 +29,7 @@ bun run test # complete suite (PR-ready / explicit ask) ```bash bun run typecheck # 厳密な TypeScript 検査 bun run test # tests/ の全体スイート -bun test tests/router.test.ts # 特定テストファイル +bun test tests/routing/router.test.ts # 特定テストファイル bun run build:gui # Vite GUI ビルド + パッケージ準備 bun run privacy:scan # CI で使う資格情報/個人情報検査 bun run prepare:package # パッケージランチャー/asset 更新 diff --git a/docs-site/src/content/docs/ko/contributing.md b/docs-site/src/content/docs/ko/contributing.md index 21892e69cf..52fd95b279 100644 --- a/docs-site/src/content/docs/ko/contributing.md +++ b/docs-site/src/content/docs/ko/contributing.md @@ -13,7 +13,7 @@ bun run dev:proxy # 개발 모드 프록시 API bun run dev:gui # 대시보드 dev 서버(다른 터미널) bun run typecheck # bun x tsc --noEmit bun run test:changed # routine import-graph test selection -bun test tests/router.test.ts # routine focused test +bun test tests/routing/router.test.ts # routine focused test bun run test # complete suite (PR-ready / explicit ask) ``` @@ -29,7 +29,7 @@ bun run test # complete suite (PR-ready / explicit ask) ```bash bun run typecheck # 엄격한 TypeScript 검사 bun run test # tests/ 전체 스위트 -bun test tests/router.test.ts # 특정 테스트 파일 +bun test tests/routing/router.test.ts # 특정 테스트 파일 bun run build:gui # Vite GUI 빌드 + 패키지 준비 bun run privacy:scan # CI에서 쓰는 자격 증명/개인정보 검사 bun run prepare:package # 패키지 런처/asset 갱신 diff --git a/docs-site/src/content/docs/ru/contributing.md b/docs-site/src/content/docs/ru/contributing.md index 7ac718ae2d..042700d0bc 100644 --- a/docs-site/src/content/docs/ru/contributing.md +++ b/docs-site/src/content/docs/ru/contributing.md @@ -13,7 +13,7 @@ bun run dev:proxy # прокси-API в режиме разработки bun run dev:gui # dev-сервер дашборда (другой терминал) bun run typecheck # bun x tsc --noEmit bun run test:changed # routine import-graph test selection -bun test tests/router.test.ts # routine focused test +bun test tests/routing/router.test.ts # routine focused test bun run test # complete suite (PR-ready / explicit ask) ``` @@ -28,7 +28,7 @@ bun run test # complete suite (PR-ready / explicit ask) ```bash bun run typecheck # строгая проверка TypeScript bun run test # полный набор tests/ -bun test tests/router.test.ts # отдельный тестовый файл +bun test tests/routing/router.test.ts # отдельный тестовый файл bun run build:gui # сборка GUI на Vite + подготовка пакета bun run privacy:scan # проверка учётных данных/приватности, используемая в CI bun run prepare:package # обновление лаунчеров/ресурсов пакета diff --git a/docs-site/src/content/docs/tr/contributing.md b/docs-site/src/content/docs/tr/contributing.md index 9fd8c71a20..0b6b890ded 100644 --- a/docs-site/src/content/docs/tr/contributing.md +++ b/docs-site/src/content/docs/tr/contributing.md @@ -18,7 +18,7 @@ bun run dev:proxy # geliştirme modunda proxy API bun run dev:gui # kontrol paneli geliştirme sunucusu (başka bir terminalde) bun run typecheck # bun x tsc --noEmit bun run test:changed # routine import-graph test selection -bun test tests/router.test.ts # routine focused test +bun test tests/routing/router.test.ts # routine focused test bun run test # complete suite (PR-ready / explicit ask) ``` @@ -35,7 +35,7 @@ Yerel komutların CI ile eşleşmesi için depodaki betikleri kullanın: ```bash bun run typecheck # katı TypeScript denetimi bun run test # tests/ paketinin tamamı -bun test tests/router.test.ts # odaklanmış test dosyası +bun test tests/routing/router.test.ts # odaklanmış test dosyası bun run build:gui # Vite GUI derlemesi + paket hazırlığı bun run privacy:scan # CI tarafından kullanılan kimlik/gizlilik taraması bun run prepare:package # paket başlatıcılarını ve varlıklarını yenileme diff --git a/docs-site/src/content/docs/zh-cn/contributing.md b/docs-site/src/content/docs/zh-cn/contributing.md index 5f102c587f..cdd345b62c 100644 --- a/docs-site/src/content/docs/zh-cn/contributing.md +++ b/docs-site/src/content/docs/zh-cn/contributing.md @@ -13,7 +13,7 @@ bun run dev:proxy # 开发模式代理 API bun run dev:gui # 仪表盘 dev 服务器(另一个终端) bun run typecheck # bun x tsc --noEmit bun run test:changed # routine import-graph test selection -bun test tests/router.test.ts # routine focused test +bun test tests/routing/router.test.ts # routine focused test bun run test # complete suite (PR-ready / explicit ask) ``` @@ -28,7 +28,7 @@ bun run test # complete suite (PR-ready / explicit ask) ```bash bun run typecheck # 严格 TypeScript 检查 bun run test # 完整 tests/ suite -bun test tests/router.test.ts # 聚焦单个测试文件 +bun test tests/routing/router.test.ts # 聚焦单个测试文件 bun run build:gui # Vite GUI 构建 + package 准备 bun run privacy:scan # CI 使用的 credential/privacy 扫描 bun run prepare:package # 刷新 package launcher/asset diff --git a/docs-site/src/content/docs/zh-tw/contributing.md b/docs-site/src/content/docs/zh-tw/contributing.md index e39c0d1f66..1910eeba85 100644 --- a/docs-site/src/content/docs/zh-tw/contributing.md +++ b/docs-site/src/content/docs/zh-tw/contributing.md @@ -13,7 +13,7 @@ bun run dev:proxy # 開發模式代理 API bun run dev:gui # 儀表板 dev 伺服器(另一個終端) bun run typecheck # bun x tsc --noEmit bun run test:changed # routine import-graph test selection -bun test tests/router.test.ts # routine focused test +bun test tests/routing/router.test.ts # routine focused test bun run test # complete suite (PR-ready / explicit ask) ``` @@ -28,7 +28,7 @@ bun run test # complete suite (PR-ready / explicit ask) ```bash bun run typecheck # 嚴格 TypeScript 檢查 bun run test # 完整 tests/ suite -bun test tests/router.test.ts # 聚焦單個測試檔案 +bun test tests/routing/router.test.ts # 聚焦單個測試檔案 bun run build:gui # Vite GUI 建置 + package 準備 bun run privacy:scan # CI 使用的 credential/privacy 掃描 bun run prepare:package # 重新整理 package launcher/asset 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 8a0bd1cf73..fb535a1ca4 100644 --- a/docs/superpowers/plans/2026-07-26-oauth-reliability-integrity.md +++ b/docs/superpowers/plans/2026-07-26-oauth-reliability-integrity.md @@ -119,7 +119,7 @@ EOF **Files:** - Create: `src/oauth/log.ts` -- Test: `tests/oauth-log.test.ts` +- Test: `tests/oauth/oauth-log.test.ts` **Interfaces:** - Consumes: `maskAccountId` from `src/lib/privacy.ts` @@ -158,7 +158,7 @@ describe("logOAuthEvent", () => { - [ ] **Step 2: Run test to verify it fails** -Run: `bun test tests/oauth-log.test.ts` +Run: `bun test tests/oauth/oauth-log.test.ts` Expected: FAIL — module missing @@ -188,14 +188,14 @@ export function logOAuthEvent( - [ ] **Step 4: Run test to verify it passes** -Run: `bun test tests/oauth-log.test.ts` +Run: `bun test tests/oauth/oauth-log.test.ts` Expected: PASS - [ ] **Step 5: Commit** ```bash -git add src/oauth/log.ts tests/oauth-log.test.ts +git add src/oauth/log.ts tests/oauth/oauth-log.test.ts git commit -m "$(cat <<'EOF' feat(oauth): add redacted structured OAuth event logger @@ -209,7 +209,7 @@ EOF **Files:** - Modify: `src/oauth/index.ts` (`refreshAndPersistAccessToken` generic branch ~352–400) -- Test: `tests/oauth-refresh-generic-lock.test.ts` (new; mirror patterns from `tests/xai-refresh-lock.test.ts` / `tests/oauth-refresh.test.ts`) +- Test: `tests/oauth/oauth-refresh-generic-lock.test.ts` (new; mirror patterns from `tests/xai-refresh-lock.test.ts` / `tests/oauth/oauth-refresh.test.ts`) **Interfaces:** - Consumes: `createOAuthRefreshIntentLock`, `mergeAccountCredential`, `credentialGeneration`, `markAccountNeedsReauthIfGeneration`, `getAccountCredential`, `logOAuthEvent` @@ -220,7 +220,7 @@ EOF - [ ] **Step 1: Write the failing tests** -Create `tests/oauth-refresh-generic-lock.test.ts` covering at least: +Create `tests/oauth/oauth-refresh-generic-lock.test.ts` covering at least: 1. Ten concurrent `getValidAccessTokenForAccount("kimi", id)` (or another non-xAI/Anthropic provider with injectable `refresh`) trigger **one** IdP refresh; all get same access token 2. Failed refresh clears single-flight so a later call can retry @@ -228,7 +228,7 @@ Create `tests/oauth-refresh-generic-lock.test.ts` covering at least: 4. Older refresh result cannot overwrite newer stored token (`mergeAccountCredential` superseded path) 5. Rotated refresh token is persisted on disk -Use the existing test helpers that point `OPENCODEX_HOME` at a temp dir and stub `OAUTH_PROVIDERS[provider].refresh` / fetch. Follow `tests/oauth-refresh.test.ts` setup patterns for auth store isolation. +Use the existing test helpers that point `OPENCODEX_HOME` at a temp dir and stub `OAUTH_PROVIDERS[provider].refresh` / fetch. Follow `tests/oauth/oauth-refresh.test.ts` setup patterns for auth store isolation. Sketch for concurrent refresh: @@ -249,7 +249,7 @@ test("ten concurrent generic refreshes share one IdP call and same credential", - [ ] **Step 2: Run test to verify it fails** -Run: `bun test tests/oauth-refresh-generic-lock.test.ts` +Run: `bun test tests/oauth/oauth-refresh-generic-lock.test.ts` Expected: FAIL — generic path still uses unlocked `saveAccountCredential` / can double-refresh under injected dual locks or pre-persist races (assert the specific failure your test constructs) @@ -308,7 +308,7 @@ Also log `"OAuth refresh joined existing operation"` when `tokenRefreshes.get(ke Run: ```bash -bun test tests/oauth-refresh-generic-lock.test.ts tests/oauth-refresh.test.ts tests/xai-refresh-lock.test.ts +bun test tests/oauth/oauth-refresh-generic-lock.test.ts tests/oauth/oauth-refresh.test.ts tests/xai-refresh-lock.test.ts ``` Expected: PASS (no regressions on xAI/Anthropic) @@ -316,7 +316,7 @@ Expected: PASS (no regressions on xAI/Anthropic) - [ ] **Step 5: Commit** ```bash -git add src/oauth/index.ts tests/oauth-refresh-generic-lock.test.ts +git add src/oauth/index.ts tests/oauth/oauth-refresh-generic-lock.test.ts git commit -m "$(cat <<'EOF' feat(oauth): lock and CAS generic provider token refresh @@ -330,7 +330,7 @@ EOF **Files:** - Create: `src/oauth/health.ts` -- Test: `tests/oauth-health.test.ts` +- Test: `tests/oauth/oauth-health.test.ts` - Modify: export from `src/oauth/index.ts` if that is the public surface used by CLI **Interfaces:** @@ -396,7 +396,7 @@ Also test `collectOAuthHealthEntries` with a temp auth store marking one account - [ ] **Step 2: Run test to verify it fails** -Run: `bun test tests/oauth-health.test.ts` +Run: `bun test tests/oauth/oauth-health.test.ts` Expected: FAIL — module missing @@ -420,14 +420,14 @@ Set `action` strings: - [ ] **Step 4: Run test to verify it passes** -Run: `bun test tests/oauth-health.test.ts tests/codex-routing.test.ts` +Run: `bun test tests/oauth/oauth-health.test.ts tests/codex-routing.test.ts` Expected: PASS - [ ] **Step 5: Commit** ```bash -git add src/oauth/health.ts src/oauth/index.ts src/codex/routing.ts tests/oauth-health.test.ts +git add src/oauth/health.ts src/oauth/index.ts src/codex/routing.ts tests/oauth/oauth-health.test.ts git commit -m "$(cat <<'EOF' feat(oauth): add shared account health projection @@ -442,7 +442,7 @@ EOF **Files:** - Modify: `src/cli/index.ts` (status human printer that currently calls `oauthLoginSummary`) - Modify: `src/cli/status.ts` only if JSON status should gain a redacted health summary (prefer human-first; add JSON only if existing tests/docs allow a non-secret block) -- Test: `tests/cli-status-oauth-health.test.ts` +- Test: `tests/cli/cli-status-oauth-health.test.ts` **Interfaces:** - Consumes: `collectOAuthHealthEntries`, `maskAccountId` @@ -471,7 +471,7 @@ test("formats reauthentication required", () => { - [ ] **Step 2: Run test to verify it fails** -Run: `bun test tests/cli-status-oauth-health.test.ts` +Run: `bun test tests/cli/cli-status-oauth-health.test.ts` Expected: FAIL @@ -481,14 +481,14 @@ Create `src/cli/status-oauth.ts` with `formatOAuthHealthForStatus`. Wire into `h - [ ] **Step 4: Run tests** -Run: `bun test tests/cli-status-oauth-health.test.ts tests/cli-status-json.test.ts` +Run: `bun test tests/cli/cli-status-oauth-health.test.ts tests/cli/cli-status-json.test.ts` Expected: PASS - [ ] **Step 5: Commit** ```bash -git add src/cli/status-oauth.ts src/cli/index.ts tests/cli-status-oauth-health.test.ts +git add src/cli/status-oauth.ts src/cli/index.ts tests/cli/cli-status-oauth-health.test.ts git commit -m "$(cat <<'EOF' feat(cli): show OAuth health in ocx status @@ -553,7 +553,7 @@ EOF - Modify: `gui/src/components/provider-workspace/ProviderAuthPanel.tsx` - Modify: `gui/src/components/CodexAccountPool.tsx` (if showing Codex cooldown/reauth) - Possibly: `gui/src/provider-workspace/catalog.ts` / types for account DTO -- Test: `tests/oauth-accounts-api.test.ts` (extend) +- Test: `tests/oauth/oauth-accounts-api.test.ts` (extend) - Test: GUI unit/render test if the repo already has a pattern; otherwise a pure formatter test for badge labels in `gui/src/...` plus API contract test **Interfaces:** @@ -572,7 +572,7 @@ Assert `/api/oauth/accounts?provider=...` includes `health` and redacted display - [ ] **Step 2: Run test to verify it fails** -Run: `bun test tests/oauth-accounts-api.test.ts` +Run: `bun test tests/oauth/oauth-accounts-api.test.ts` Expected: FAIL on missing `health` @@ -585,7 +585,7 @@ Attach projected health to account DTOs. In GUI, show badge + short explanation Run: ```bash -bun test tests/oauth-accounts-api.test.ts +bun test tests/oauth/oauth-accounts-api.test.ts bun run lint:gui ``` @@ -594,7 +594,7 @@ Expected: PASS / lint clean for touched files - [ ] **Step 5: Commit** ```bash -git add src/server/management/oauth-account-routes.ts src/codex/auth-api.ts gui/src/components/provider-workspace/ProviderAuthPanel.tsx gui/src/components/CodexAccountPool.tsx tests/oauth-accounts-api.test.ts +git add src/server/management/oauth-account-routes.ts src/codex/auth-api.ts gui/src/components/provider-workspace/ProviderAuthPanel.tsx gui/src/components/CodexAccountPool.tsx tests/oauth/oauth-accounts-api.test.ts git commit -m "$(cat <<'EOF' feat(gui): surface OAuth account health diagnostics @@ -713,8 +713,8 @@ EOF - [ ] **Step 1: Run verification commands** ```bash -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 test tests/lib/privacy-mask-account.test.ts tests/oauth/oauth-log.test.ts tests/oauth/oauth-refresh-generic-lock.test.ts tests/oauth/oauth-health.test.ts tests/cli/cli-status-oauth-health.test.ts tests/service/doctor-oauth.test.ts tests/oauth/oauth-accounts-api.test.ts tests/codex-metadata-integrity.test.ts +bun test tests/oauth/oauth-refresh.test.ts tests/xai-refresh-lock.test.ts tests/codex-routing.test.ts tests/session-affinity.test.ts tests/codex-auth-context.test.ts bun run test bun run typecheck bun run lint:gui diff --git a/scripts/openai-provider-option-final-gates.ts b/scripts/openai-provider-option-final-gates.ts index 303f9b348c..cce9242bab 100644 --- a/scripts/openai-provider-option-final-gates.ts +++ b/scripts/openai-provider-option-final-gates.ts @@ -50,7 +50,7 @@ const focusedTests = [ "tests/provider-registry-parity.test.ts", "tests/provider-payload.test.ts", "tests/codex-account-mode-state.test.ts", - "tests/router.test.ts", + "tests/routing/router.test.ts", "tests/codex-routing.test.ts", "tests/server-auth.test.ts", "tests/codex-catalog.test.ts", diff --git a/scripts/test-layout/layout.json b/scripts/test-layout/layout.json index 29b264ddaf..9c2444011a 100644 --- a/scripts/test-layout/layout.json +++ b/scripts/test-layout/layout.json @@ -1227,9 +1227,13 @@ "zz-pr-coderabbit-readiness-revalidation.test.ts": "ci-workflows" }, "migrated": [ + "claude-integration", + "cli", "clients", "config", "lib", + "oauth", + "routing", "service", "update", "usage", diff --git a/scripts/test-layout/schema.ts b/scripts/test-layout/schema.ts index 8d3936a494..d88410d6dd 100644 --- a/scripts/test-layout/schema.ts +++ b/scripts/test-layout/schema.ts @@ -174,7 +174,7 @@ export function rewriteMetaDirEscapes(source: string, depth: number): { source: // `const repoRoot = join(import.meta.dir, "..")` is the commonest escape of all: rebind the // local through an aliased import instead of refusing the file. Any other local named like a // helper (or a function) still stops the rewrite so nothing gets shadowed. - const localRoot = /\bconst\s+repoRoot\s*=\s*(?:(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\."\s*\)|fileURLToPath\(\s*new\s+URL\(\s*"\.\.\/"\s*,\s*import\.meta\.url\s*\)\s*\)|resolve\(\s*dirname\(\s*fileURLToPath\(\s*import\.meta\.url\s*\)\s*\)\s*,\s*"\.\."\s*\))\s*;/; + const localRoot = /\bconst\s+repoRoot\s*=\s*(?:(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\."\s*\)|fileURLToPath\(\s*new\s+URL\(\s*"(?:\.\.\/)+"\s*,\s*import\.meta\.url\s*\)\s*\)|resolve\(\s*dirname\(\s*fileURLToPath\(\s*import\.meta\.url\s*\)\s*\)\s*,\s*"\.\."\s*\))\s*;/; const rebindsRoot = localRoot.test(view); const otherLocals = new RegExp(`\\b(?:const|let|var|function)\\s+(?:${HELPER_NAMES.filter(n => !(rebindsRoot && n === "repoRoot")).join("|")})\\b`); if (otherLocals.test(code)) return { source, rewrites: 0 }; diff --git a/src/cli/capabilities.ts b/src/cli/capabilities.ts index d4ae958829..6fcdd7cb16 100644 --- a/src/cli/capabilities.ts +++ b/src/cli/capabilities.ts @@ -11,7 +11,7 @@ * top-level `const USAGE`, evaluated at import time, so a cycle back into this table * would resolve to `undefined` under ESM rather than throwing -- silently emptying the * usage text that `rejectArgs` hands to `CliUsageError`, in the exact error-reporting - * surface the CLI-operability issues are about. `tests/cli-capabilities.test.ts` asserts + * surface the CLI-operability issues are about. `tests/cli/cli-capabilities.test.ts` asserts * the absence of those imports and that every rendered usage string is non-empty, so the * failure mode is loud instead of degraded. * @@ -19,7 +19,7 @@ * `HEAD_CAPABILITIES`. They exit in the CLI head (`root.ts`) before dispatch and have no * runner key, so listing them as ordinary capabilities would break the registry parity * assertion that every canonical entry is a direct runner. `help` is excluded from - * `CLI_COMMANDS` deliberately -- `tests/cli-registry.test.ts` documents it as a + * `CLI_COMMANDS` deliberately -- `tests/cli/cli-registry.test.ts` documents it as a * head-handled pseudo-case -- and that decision is preserved here rather than reversed. */ diff --git a/src/cli/dispatch.ts b/src/cli/dispatch.ts index 2f94753043..b6e094c54a 100644 --- a/src/cli/dispatch.ts +++ b/src/cli/dispatch.ts @@ -349,7 +349,7 @@ const commandRunners: Record = { : "Remote hub catalog synchronized."); await handleConnectedSyncCatalogWrite(result, restartCodex, restartDesktopApp); // `process.exitCode` rather than a literal 0, for the same reason every other - // runner does it (tests/cli-transport-honesty.test.ts): the catalog-write helper + // runner does it (tests/cli/cli-transport-honesty.test.ts): the catalog-write helper // drives app-server restarts, and one of those recording a failure must not be // erased by the value this runner returns. It reads 0 on the ordinary path. Node // types it as `number | string`; only a numeric code means anything here. diff --git a/src/cli/models-runtime.ts b/src/cli/models-runtime.ts index d5174ef603..a2fc07ed03 100644 --- a/src/cli/models-runtime.ts +++ b/src/cli/models-runtime.ts @@ -323,7 +323,7 @@ async function shadow(argv: string[], deps: RuntimeApiDeps): Promise { export async function handleModelsRuntimeCommand(sub: string, argv: string[], deps: RuntimeApiDeps = {}): Promise { // The dispatch below and MODELS_RUNTIME_SUBCOMMANDS must name the same set; - // tests/cli-models-runtime-dispatch.test.ts fails if they drift (#3094). + // tests/cli/cli-models-runtime-dispatch.test.ts fails if they drift (#3094). if (!isModelsRuntimeSubcommand(sub)) return null; let action: (() => Promise) | undefined; if (sub === "live") action = () => live(argv, deps); diff --git a/tests/anthropic-baseurl-override.test.ts b/tests/anthropic-baseurl-override.test.ts index b64e0feaab..992652b2a2 100644 --- a/tests/anthropic-baseurl-override.test.ts +++ b/tests/anthropic-baseurl-override.test.ts @@ -9,7 +9,7 @@ import type { OcxConfig, OcxProviderConfig } from "../src/types"; * * Before the opt-in, the pinned registry endpoint silently outranked a saved * baseUrl and the router emitted the discarded-baseUrl diagnostic (see - * tests/router-discarded-baseurl-warning.test.ts, which now pins google as + * tests/routing/router-discarded-baseurl-warning.test.ts, which now pins google as * its fixture). Users routing Claude traffic through a local relay or an * enterprise gateway therefore could not redirect the provider at all. These * tests pin the new contract: a resolved user baseUrl wins, no warning fires, diff --git a/tests/antigravity-baseurl-override.test.ts b/tests/antigravity-baseurl-override.test.ts index 5bc190c715..98d23b6c9c 100644 --- a/tests/antigravity-baseurl-override.test.ts +++ b/tests/antigravity-baseurl-override.test.ts @@ -9,7 +9,7 @@ import type { OcxConfig, OcxProviderConfig } from "../src/types"; * * Before the opt-in, the pinned registry endpoint silently outranked a saved * baseUrl and the router emitted the discarded-baseUrl diagnostic (see - * tests/router-discarded-baseurl-warning.test.ts). Users routing Antigravity + * tests/routing/router-discarded-baseurl-warning.test.ts). Users routing Antigravity * traffic through a local relay or region-specific proxy therefore could not * redirect the provider at all. These tests pin the new contract: a resolved * user baseUrl wins, no warning fires, and the registry endpoint remains the diff --git a/tests/claude-529-mapping.test.ts b/tests/claude-integration/claude-529-mapping.test.ts similarity index 93% rename from tests/claude-529-mapping.test.ts rename to tests/claude-integration/claude-529-mapping.test.ts index 5df9795800..480ba7bd22 100644 --- a/tests/claude-529-mapping.test.ts +++ b/tests/claude-integration/claude-529-mapping.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 { saveConfig } from "../src/config"; -import { startServer } from "../src/server"; -import { getRequestLogEntries } from "../src/server/request-log"; -import type { OcxConfig } from "../src/types"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { saveConfig } from "../../src/config"; +import { startServer } from "../../src/server"; +import { getRequestLogEntries } from "../../src/server/request-log"; +import type { OcxConfig } from "../../src/types"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testDir = ""; let previousHome: string | undefined; diff --git a/tests/claude-agent-startup-sync.test.ts b/tests/claude-integration/claude-agent-startup-sync.test.ts similarity index 93% rename from tests/claude-agent-startup-sync.test.ts rename to tests/claude-integration/claude-agent-startup-sync.test.ts index 1b7c8b8a2d..33d374eacb 100644 --- a/tests/claude-agent-startup-sync.test.ts +++ b/tests/claude-integration/claude-agent-startup-sync.test.ts @@ -5,11 +5,11 @@ import { tmpdir } from "node:os"; import { reconcileClientStartupBeforeReady, syncClaudeAgentDefsAtProxyStartup, -} from "../src/cli/claude-agent-startup-sync"; -import { injectClaudeAgentDefs } from "../src/claude/agents-inject"; -import { createReadinessGate } from "../src/server/readiness"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/cli/claude-agent-startup-sync"; +import { injectClaudeAgentDefs } from "../../src/claude/agents-inject"; +import { createReadinessGate } from "../../src/server/readiness"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const config = (claudeCode: OcxConfig["claudeCode"] = {}): OcxConfig => ({ providers: [], diff --git a/tests/claude-agents-inject.test.ts b/tests/claude-integration/claude-agents-inject.test.ts similarity index 97% rename from tests/claude-agents-inject.test.ts rename to tests/claude-integration/claude-agents-inject.test.ts index e936c8fccf..9eb36e85b1 100644 --- a/tests/claude-agents-inject.test.ts +++ b/tests/claude-integration/claude-agents-inject.test.ts @@ -2,12 +2,12 @@ import { afterEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, symlinkSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { buildClaudeAgentDefs, injectClaudeAgentDefs, syncClaudeAgentDefs } from "../src/claude/agents-inject"; -import { buildClaudeContextWindows } from "../src/claude/context-windows"; -import { fetchProviderModels } from "../src/codex/catalog/provider-fetch"; -import { OAUTH_PROVIDERS } from "../src/oauth"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { buildClaudeAgentDefs, injectClaudeAgentDefs, syncClaudeAgentDefs } from "../../src/claude/agents-inject"; +import { buildClaudeContextWindows } from "../../src/claude/context-windows"; +import { fetchProviderModels } from "../../src/codex/catalog/provider-fetch"; +import { OAUTH_PROVIDERS } from "../../src/oauth"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const dirs: string[] = []; function tempDir(): string { diff --git a/tests/claude-alias.test.ts b/tests/claude-integration/claude-alias.test.ts similarity index 98% rename from tests/claude-alias.test.ts rename to tests/claude-integration/claude-alias.test.ts index 213c0af28d..c5c9483325 100644 --- a/tests/claude-alias.test.ts +++ b/tests/claude-integration/claude-alias.test.ts @@ -8,8 +8,8 @@ import { claudeCodeAlias, claudeCodeNativeAlias, resolveAlias, -} from "../src/claude/alias"; -import { resolveInboundModel } from "../src/claude/inbound"; +} from "../../src/claude/alias"; +import { resolveInboundModel } from "../../src/claude/inbound"; describe("claude discovery aliases", () => { test("round-trips every realistic provider/model shape", () => { diff --git a/tests/claude-auth-detect.test.ts b/tests/claude-integration/claude-auth-detect.test.ts similarity index 99% rename from tests/claude-auth-detect.test.ts rename to tests/claude-integration/claude-auth-detect.test.ts index 89237cb5f1..a7f3031eaa 100644 --- a/tests/claude-auth-detect.test.ts +++ b/tests/claude-integration/claude-auth-detect.test.ts @@ -11,7 +11,7 @@ import { detectClaudeAuth, type AuthDetectDeps, type AuthPresence, -} from "../src/claude/auth-detect"; +} from "../../src/claude/auth-detect"; /** * The safety contract: `unknown` must never collapse into `absent`, because that is diff --git a/tests/claude-auth-mode.test.ts b/tests/claude-integration/claude-auth-mode.test.ts similarity index 98% rename from tests/claude-auth-mode.test.ts rename to tests/claude-integration/claude-auth-mode.test.ts index bbdbd8b7ad..e352c7bd72 100644 --- a/tests/claude-auth-mode.test.ts +++ b/tests/claude-integration/claude-auth-mode.test.ts @@ -1,9 +1,9 @@ import { expect, spyOn, test } from "bun:test"; -import { buildClaudeEnv } from "../src/cli/claude"; -import { PROXY_MARKER, type AuthDetectDeps, type AuthPresence } from "../src/claude/auth-detect"; -import { authModeIntent, resolveClaudeAuthMode } from "../src/claude/auth-mode"; -import { detectClaudeAuth } from "../src/claude/auth-detect"; -import type { OcxConfig } from "../src/types"; +import { buildClaudeEnv } from "../../src/cli/claude"; +import { PROXY_MARKER, type AuthDetectDeps, type AuthPresence } from "../../src/claude/auth-detect"; +import { authModeIntent, resolveClaudeAuthMode } from "../../src/claude/auth-mode"; +import { detectClaudeAuth } from "../../src/claude/auth-detect"; +import type { OcxConfig } from "../../src/types"; /** * Auto is a RESOLUTION, not stored state: registering a Claude login changes the next diff --git a/tests/claude-authmode-migration.test.ts b/tests/claude-integration/claude-authmode-migration.test.ts similarity index 95% rename from tests/claude-authmode-migration.test.ts rename to tests/claude-integration/claude-authmode-migration.test.ts index 5ae76758b2..9067b86625 100644 --- a/tests/claude-authmode-migration.test.ts +++ b/tests/claude-integration/claude-authmode-migration.test.ts @@ -1,6 +1,6 @@ import { expect, test } from "bun:test"; -import { runClaudeAuthModeMigration } from "../src/claude/auth-mode-migration"; -import type { OcxConfig } from "../src/types"; +import { runClaudeAuthModeMigration } from "../../src/claude/auth-mode-migration"; +import type { OcxConfig } from "../../src/types"; /** * Before auto existed, "Subscription" was stored by DELETING the key. So the upgrade diff --git a/tests/claude-cli.test.ts b/tests/claude-integration/claude-cli.test.ts similarity index 98% rename from tests/claude-cli.test.ts rename to tests/claude-integration/claude-cli.test.ts index 8381b99e84..e4922aaccd 100644 --- a/tests/claude-cli.test.ts +++ b/tests/claude-integration/claude-cli.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { buildClaudeEnv, claudeNotFoundHint, ensureProxyForClaude, rootSkipPermissionsNotice, shouldAllowRootSkipPermissions } from "../src/cli/claude"; -import { commandInvocation } from "../src/lib/win-exec"; -import type { LivenessIo, LiveProxy } from "../src/server/proxy-liveness"; -import type { OcxConfig } from "../src/types"; +import { buildClaudeEnv, claudeNotFoundHint, ensureProxyForClaude, rootSkipPermissionsNotice, shouldAllowRootSkipPermissions } from "../../src/cli/claude"; +import { commandInvocation } from "../../src/lib/win-exec"; +import type { LivenessIo, LiveProxy } from "../../src/server/proxy-liveness"; +import type { OcxConfig } from "../../src/types"; function cfg(extra?: Partial): OcxConfig { return { diff --git a/tests/claude-code-thought-signature-scope.test.ts b/tests/claude-integration/claude-code-thought-signature-scope.test.ts similarity index 93% rename from tests/claude-code-thought-signature-scope.test.ts rename to tests/claude-integration/claude-code-thought-signature-scope.test.ts index d6a3de65f6..2437a8d157 100644 --- a/tests/claude-code-thought-signature-scope.test.ts +++ b/tests/claude-integration/claude-code-thought-signature-scope.test.ts @@ -9,21 +9,21 @@ */ import { afterEach, describe, expect, mock, test } from "bun:test"; -import type { ProviderAdapter } from "../src/adapters/base"; -import type { AdapterEvent, OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import type { ProviderAdapter } from "../../src/adapters/base"; +import type { AdapterEvent, OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../../src/types"; -const actualResolver = await import("../src/server/adapter-resolve"); +const actualResolver = await import("../../src/server/adapter-resolve"); let adapterFactory: ((provider: OcxProviderConfig) => ProviderAdapter) | undefined; -mock.module("../src/server/adapter-resolve", () => ({ +mock.module("../../src/server/adapter-resolve", () => ({ ...actualResolver, resolveAdapter(provider: OcxProviderConfig, cacheRetention?: "none" | "short" | "long") { return adapterFactory?.(provider) ?? actualResolver.resolveAdapter(provider, cacheRetention); }, })); -const { handleResponses } = await import("../src/server/responses"); +const { handleResponses } = await import("../../src/server/responses"); afterEach(() => { adapterFactory = undefined; diff --git a/tests/claude-context-windows.test.ts b/tests/claude-integration/claude-context-windows.test.ts similarity index 98% rename from tests/claude-context-windows.test.ts rename to tests/claude-integration/claude-context-windows.test.ts index 85c70d321e..d411fce9aa 100644 --- a/tests/claude-context-windows.test.ts +++ b/tests/claude-integration/claude-context-windows.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { AUTO_COMPACT_WINDOW_DEFAULT, boundedContextWindows, buildClaudeContextWindows, effectiveModelEnv, resolveAutoContext, shouldMarkOneMillion, withOneMillionMarker } from "../src/claude/context-windows"; -import { desktop3pAlias } from "../src/claude/desktop-3p"; -import type { CatalogModel } from "../src/codex/catalog"; +import { AUTO_COMPACT_WINDOW_DEFAULT, boundedContextWindows, buildClaudeContextWindows, effectiveModelEnv, resolveAutoContext, shouldMarkOneMillion, withOneMillionMarker } from "../../src/claude/context-windows"; +import { desktop3pAlias } from "../../src/claude/desktop-3p"; +import type { CatalogModel } from "../../src/codex/catalog"; describe("claude context-window map (devlog 260712 B2)", () => { const routed = [ diff --git a/tests/claude-desktop-1m.test.ts b/tests/claude-integration/claude-desktop-1m.test.ts similarity index 89% rename from tests/claude-desktop-1m.test.ts rename to tests/claude-integration/claude-desktop-1m.test.ts index 00892dff52..7a9c1875e0 100644 --- a/tests/claude-desktop-1m.test.ts +++ b/tests/claude-integration/claude-desktop-1m.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 { buildClaudeDesktopState } from "../src/server/management/shared"; -import { DESKTOP_SUPPORTS_1M_THRESHOLD } from "../src/claude/desktop-3p"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { buildClaudeDesktopState } from "../../src/server/management/shared"; +import { DESKTOP_SUPPORTS_1M_THRESHOLD } from "../../src/claude/desktop-3p"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * D1c: the dashboard surfaces the same 1M eligibility the writer emits, from one diff --git a/tests/claude-desktop-cli.test.ts b/tests/claude-integration/claude-desktop-cli.test.ts similarity index 95% rename from tests/claude-desktop-cli.test.ts rename to tests/claude-integration/claude-desktop-cli.test.ts index f31f894d13..6c810b53da 100644 --- a/tests/claude-desktop-cli.test.ts +++ b/tests/claude-integration/claude-desktop-cli.test.ts @@ -2,11 +2,11 @@ import { afterEach, beforeEach, expect, spyOn, test } from "bun:test"; import { existsSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { applyProfile, handleClaudeDesktopCommand } from "../src/cli/claude-desktop"; -import { buildClaudeDesktopState } from "../src/server/management-api"; -import { loadConfig, saveConfig } from "../src/config"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { applyProfile, handleClaudeDesktopCommand } from "../../src/cli/claude-desktop"; +import { buildClaudeDesktopState } from "../../src/server/management-api"; +import { loadConfig, saveConfig } from "../../src/config"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let dir = ""; let previousHome: string | undefined; diff --git a/tests/claude-desktop-config-path.test.ts b/tests/claude-integration/claude-desktop-config-path.test.ts similarity index 96% rename from tests/claude-desktop-config-path.test.ts rename to tests/claude-integration/claude-desktop-config-path.test.ts index f946982746..9a141d7f65 100644 --- a/tests/claude-desktop-config-path.test.ts +++ b/tests/claude-integration/claude-desktop-config-path.test.ts @@ -1,16 +1,16 @@ import { expect, test, describe } from "bun:test"; -import { managementFetch as fetch } from "./helpers/management-auth"; +import { managementFetch as fetch } from "../helpers/management-auth"; import { mkdtempSync, writeFileSync } from "node:fs"; import { homedir, tmpdir } from "node:os"; import { join, posix, win32 } from "node:path"; -import { startServer } from "../src/server"; +import { startServer } from "../../src/server"; import { claudeDesktopConfigLibraryDir, resolveConfigLibraryDir, resolveElectronUserData, resolveUserDataDir, -} from "../src/claude/desktop-3p-paths"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/claude/desktop-3p-paths"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * GitHub #539. Claude Desktop derives its configLibrary through `GE()`, which has diff --git a/tests/claude-desktop-native-context.test.ts b/tests/claude-integration/claude-desktop-native-context.test.ts similarity index 88% rename from tests/claude-desktop-native-context.test.ts rename to tests/claude-integration/claude-desktop-native-context.test.ts index 1fe82e24da..715df8ee29 100644 --- a/tests/claude-desktop-native-context.test.ts +++ b/tests/claude-integration/claude-desktop-native-context.test.ts @@ -2,15 +2,15 @@ import { expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { buildClaudeDesktopState } from "../src/server/management/shared"; -import { nativeOpenAiContextWindow, visibleNativeSlugs } from "../src/codex/catalog"; -import { generateDesktop3pModels } from "../src/claude/desktop-3p"; +import { buildClaudeDesktopState } from "../../src/server/management/shared"; +import { nativeOpenAiContextWindow, visibleNativeSlugs } from "../../src/codex/catalog"; +import { generateDesktop3pModels } from "../../src/claude/desktop-3p"; import { resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests, -} from "../src/codex/model-entitlements"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/model-entitlements"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * D1b: native Desktop models carry their real context window, and the DTO and the diff --git a/tests/claude-desktop-policy.test.ts b/tests/claude-integration/claude-desktop-policy.test.ts similarity index 98% rename from tests/claude-desktop-policy.test.ts rename to tests/claude-integration/claude-desktop-policy.test.ts index 648c3f16dd..badae004fb 100644 --- a/tests/claude-desktop-policy.test.ts +++ b/tests/claude-integration/claude-desktop-policy.test.ts @@ -3,7 +3,7 @@ import { claudeDesktopPolicyHealth, probeClaudeDesktopPolicy, type ClaudeDesktopPolicyProbeRunner, -} from "../src/claude/desktop-policy"; +} from "../../src/claude/desktop-policy"; function result(overrides: Partial> = {}) { return { diff --git a/tests/claude-dotenv-provenance-transport.test.ts b/tests/claude-integration/claude-dotenv-provenance-transport.test.ts similarity index 95% rename from tests/claude-dotenv-provenance-transport.test.ts rename to tests/claude-integration/claude-dotenv-provenance-transport.test.ts index 67de017f0b..290b28497f 100644 --- a/tests/claude-dotenv-provenance-transport.test.ts +++ b/tests/claude-integration/claude-dotenv-provenance-transport.test.ts @@ -4,7 +4,8 @@ import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { pathToFileURL } from "node:url"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath } from "../helpers/repo-root"; const PROBE_TIMEOUT_MS = 3_000; @@ -16,7 +17,7 @@ const PROBE_TIMEOUT_MS = 3_000; describe("Node launcher context transport", () => { const dir = mkdtempSync(join(tmpdir(), "ocx-launch-context-")); const probe = join(dir, "probe.ts"); - const moduleUrl = pathToFileURL(join(import.meta.dir, "..", "src", "cli", "launcher-context.ts")).href; + const moduleUrl = pathToFileURL(repoPath("src", "cli", "launcher-context.ts")).href; writeFileSync( probe, `import { initializeNodeLauncherContext } from ${JSON.stringify(moduleUrl)};\n` diff --git a/tests/claude-gateway-cache.test.ts b/tests/claude-integration/claude-gateway-cache.test.ts similarity index 98% rename from tests/claude-gateway-cache.test.ts rename to tests/claude-integration/claude-gateway-cache.test.ts index 2e0dbe4e77..5d2229f111 100644 --- a/tests/claude-gateway-cache.test.ts +++ b/tests/claude-integration/claude-gateway-cache.test.ts @@ -2,8 +2,8 @@ import { afterEach, describe, expect, test } from "bun:test"; import { mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { claudeConfigDir, refreshGatewayModelCacheFromProxy, writeGatewayModelCache } from "../src/claude/gateway-cache"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { claudeConfigDir, refreshGatewayModelCacheFromProxy, writeGatewayModelCache } from "../../src/claude/gateway-cache"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const dirs: string[] = []; function tempDir(): string { diff --git a/tests/claude-inbound-debug.test.ts b/tests/claude-integration/claude-inbound-debug.test.ts similarity index 98% rename from tests/claude-inbound-debug.test.ts rename to tests/claude-integration/claude-inbound-debug.test.ts index 4bff93f5f4..32f049c550 100644 --- a/tests/claude-inbound-debug.test.ts +++ b/tests/claude-integration/claude-inbound-debug.test.ts @@ -1,6 +1,6 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { captureClaudeInbound, claudeInboundDebugMetrics, clearClaudeInboundDebug, evictOldestClaudeInboundForBudget, getClaudeInboundDebugEntries } from "../src/claude/inbound-debug"; -import { resetDebugSettingsForTests, setDebugSettings } from "../src/lib/debug-settings"; +import { captureClaudeInbound, claudeInboundDebugMetrics, clearClaudeInboundDebug, evictOldestClaudeInboundForBudget, getClaudeInboundDebugEntries } from "../../src/claude/inbound-debug"; +import { resetDebugSettingsForTests, setDebugSettings } from "../../src/lib/debug-settings"; afterEach(() => { resetDebugSettingsForTests(); diff --git a/tests/claude-inbound.test.ts b/tests/claude-integration/claude-inbound.test.ts similarity index 98% rename from tests/claude-inbound.test.ts rename to tests/claude-integration/claude-inbound.test.ts index f56275e26d..b1d537055d 100644 --- a/tests/claude-inbound.test.ts +++ b/tests/claude-integration/claude-inbound.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { AnthropicRequestError, anthropicToResponsesBody, anthropicToResponsesTranslation, effortForThinkingBudget, extractOcxEffortDirective, resolveInboundModel } from "../src/claude/inbound"; -import { parseRequest } from "../src/responses/parser"; -import { responsesRequestSchema } from "../src/responses/schema"; +import { AnthropicRequestError, anthropicToResponsesBody, anthropicToResponsesTranslation, effortForThinkingBudget, extractOcxEffortDirective, resolveInboundModel } from "../../src/claude/inbound"; +import { parseRequest } from "../../src/responses/parser"; +import { responsesRequestSchema } from "../../src/responses/schema"; // Full Claude Code-shaped request: system array, tool cycle, image, thinking, options. function claudeCodeRequest(): Record { @@ -509,7 +509,7 @@ describe("bundled-skill elision for routed models (devlog 260712 060)", () => { }); describe("ocx-route directive (devlog 072)", () => { - const { extractOcxRouteDirective } = require("../src/claude/inbound") as typeof import("../src/claude/inbound"); + const { extractOcxRouteDirective } = require("../../src/claude/inbound") as typeof import("../../src/claude/inbound"); test("extracts from string and block-array system; first directive wins", () => { expect(extractOcxRouteDirective({ system: "intro\n\nrest" })) diff --git a/tests/claude-management-api.test.ts b/tests/claude-integration/claude-management-api.test.ts similarity index 98% rename from tests/claude-management-api.test.ts rename to tests/claude-integration/claude-management-api.test.ts index 9b231e9a8a..1bb7a323da 100644 --- a/tests/claude-management-api.test.ts +++ b/tests/claude-integration/claude-management-api.test.ts @@ -1,15 +1,15 @@ import { afterEach, beforeEach, expect, setDefaultTimeout, spyOn, test } from "bun:test"; -import { managementFetch as fetch } from "./helpers/management-auth"; +import { managementFetch as fetch } from "../helpers/management-auth"; import { mkdtempSync, readdirSync, readFileSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { loadConfig, saveConfig } from "../src/config"; -import { startServer } from "../src/server"; -import * as systemEnv from "../src/server/system-env"; -import type { OcxConfig } from "../src/types"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { MANAGEMENT_JSON_BODY_MAX_BYTES } from "../src/server/management/body"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { loadConfig, saveConfig } from "../../src/config"; +import { startServer } from "../../src/server"; +import * as systemEnv from "../../src/server/system-env"; +import type { OcxConfig } from "../../src/types"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { MANAGEMENT_JSON_BODY_MAX_BYTES } from "../../src/server/management/body"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; // Full-suite Windows load: startServer + multi-PUT management flows often exceed bun's // default 5s per-test budget (same flake class as 810fa115 / kiro-oauth). @@ -708,11 +708,11 @@ test("Claude Desktop profile GET, PUT and apply round-trip four-family assignmen /* * Mechanism guard for #859: the apply route must keep building the alias * registry in the serving process. (The CLI→daemon delegation half is pinned - * in tests/claude-desktop-cli.test.ts; this module-global registry is shared + * in tests/claude-integration/claude-desktop-cli.test.ts; this module-global registry is shared * in-process, so this test guards the route, not the delegation.) */ test("Claude Desktop apply installs the alias registry in the serving process (#859)", async () => { - const { resolveDesktop3pAlias, activeDesktop3pAlias } = await import("../src/claude/desktop-3p"); + const { resolveDesktop3pAlias, activeDesktop3pAlias } = await import("../../src/claude/desktop-3p"); // A provider unique to this test: no prior test can have populated its // alias, so resolution proves THIS apply built the registry in-process. const seeded = loadConfig(); diff --git a/tests/claude-messages-endpoint.test.ts b/tests/claude-integration/claude-messages-endpoint.test.ts similarity index 98% rename from tests/claude-messages-endpoint.test.ts rename to tests/claude-integration/claude-messages-endpoint.test.ts index 86dbcff532..b977278908 100644 --- a/tests/claude-messages-endpoint.test.ts +++ b/tests/claude-integration/claude-messages-endpoint.test.ts @@ -1,19 +1,19 @@ import { afterEach, beforeEach, expect, test } from "bun:test"; -import { managementFetch as fetch } from "./helpers/management-auth"; -import { logsFromApiBody } from "./helpers/logs-api"; +import { managementFetch as fetch } from "../helpers/management-auth"; +import { logsFromApiBody } from "../helpers/logs-api"; import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; -import { createAnthropicAdapter } from "../src/adapters/anthropic"; -import { clearableDeadline } from "../src/lib/abort"; +import { saveConfig } from "../../src/config"; +import { createAnthropicAdapter } from "../../src/adapters/anthropic"; +import { clearableDeadline } from "../../src/lib/abort"; import { clearRequestLogsForTests, getRequestLogEntries, type RequestLogContext, -} from "../src/server/request-log"; -import { startServer } from "../src/server"; -import { ownedServiceHomeInspection } from "./helpers/owned-service-home-inspection"; +} from "../../src/server/request-log"; +import { startServer } from "../../src/server"; +import { ownedServiceHomeInspection } from "../helpers/owned-service-home-inspection"; import { estimateClaudeRequestTokens, fetchWithHeaderDeadline, @@ -21,25 +21,25 @@ import { readBoundedPassthroughBody, resolvePassthroughBodyGuard, tapAnthropicSseForLog, -} from "../src/server/claude-messages"; -import { estimateTokens } from "../src/lib/token-estimate"; -import type { OcxConfig } from "../src/types"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; -import { SERVER_BUDGET_MS } from "./helpers/test-budget"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../src/server/claude-messages"; +import { estimateTokens } from "../../src/lib/token-estimate"; +import type { OcxConfig } from "../../src/types"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { SERVER_BUDGET_MS } from "../helpers/test-budget"; +import { createTestTranslatorBudget } from "../helpers/translator-budget"; import { acquireNativeMainProfileDrain, getNativeMainProfileRequestCount, resetLifecycleDrainStateForTests, tryAdmitTurn, -} from "../src/server/lifecycle"; +} from "../../src/server/lifecycle"; import { blockNativeMainRecovery, completeNativeMainRecovery, nativeMainStartupGateSnapshot, waitForNativeMainStartupGate, -} from "../src/codex/native-profile-startup"; +} from "../../src/codex/native-profile-startup"; let testDir = ""; let previousHome: string | undefined; diff --git a/tests/claude-model-info.test.ts b/tests/claude-integration/claude-model-info.test.ts similarity index 99% rename from tests/claude-model-info.test.ts rename to tests/claude-integration/claude-model-info.test.ts index aec31fa889..0a2d151a1b 100644 --- a/tests/claude-model-info.test.ts +++ b/tests/claude-integration/claude-model-info.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { buildAnthropicModelInfos, nativeEffectiveLadder } from "../src/claude/model-info"; -import { nativeEffortClamp } from "../src/codex/catalog"; +import { buildAnthropicModelInfos, nativeEffectiveLadder } from "../../src/claude/model-info"; +import { nativeEffortClamp } from "../../src/codex/catalog"; describe("anthropic-flavor ModelInfo discovery entries (devlog 130 B4b)", () => { test("routed model with adapter-reported ladder advertises exactly those rungs", () => { diff --git a/tests/claude-models-discovery.test.ts b/tests/claude-integration/claude-models-discovery.test.ts similarity index 96% rename from tests/claude-models-discovery.test.ts rename to tests/claude-integration/claude-models-discovery.test.ts index 241eee177d..5fd77c96ec 100644 --- a/tests/claude-models-discovery.test.ts +++ b/tests/claude-integration/claude-models-discovery.test.ts @@ -2,16 +2,16 @@ import { afterEach, beforeEach, expect, setDefaultTimeout, test } from "bun:test import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; +import { saveConfig } from "../../src/config"; import { resetCodexModelEntitlementCacheForTests, -} from "../src/codex/model-entitlements"; -import { handleManagementAPI } from "../src/server/management-api"; -import { startServer } from "../src/server"; -import type { OcxConfig } from "../src/types"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { ManagementRequest } from "./helpers/management-auth"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/model-entitlements"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { startServer } from "../../src/server"; +import type { OcxConfig } from "../../src/types"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { ManagementRequest } from "../helpers/management-auth"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; // Full-suite Windows load: startServer + discovery GETs exceed the default 5s budget // (same flake class as 810fa115 / claude-management-api). @@ -64,7 +64,7 @@ test("anthropic-version header flips /v1/models to the discovery contract", asyn headers: { "anthropic-version": "2023-06-01", "authorization": "Bearer placeholder" }, }); expect(response.status).toBe(200); - const { desktop3pAlias } = await import("../src/claude/desktop-3p"); + const { desktop3pAlias } = await import("../../src/claude/desktop-3p"); const json = await response.json() as { data: { id: string; display_name?: string; type?: string; created_at?: string; capabilities?: Record; max_tokens?: unknown }[] }; expect(Array.isArray(json.data)).toBe(true); const mockAlias = desktop3pAlias("mock", "test-model"); @@ -95,7 +95,7 @@ test("?flavor=anthropic works without the header; disabled -> empty data", async try { const response = await fetch(new URL("/v1/models?flavor=anthropic", server.url)); const json = await response.json() as { data: { id: string }[] }; - const { desktop3pAlias } = await import("../src/claude/desktop-3p"); + const { desktop3pAlias } = await import("../../src/claude/desktop-3p"); expect(json.data.some(m => m.id === desktop3pAlias("mock", "other-model"))).toBe(true); } finally { await server.stop(true); @@ -290,7 +290,7 @@ test("Codex discovery restores account rows for supported natives hidden on disk listCatalogNativeSlugs, resetCatalogRuntimeStateForTests, visibleNativeSlugs, - } = await import("../src/codex/catalog"); + } = await import("../../src/codex/catalog"); resetCatalogRuntimeStateForTests(); expect(listCatalogNativeSlugs()).toContain("gpt-5.5"); expect(listCatalogNativeSlugs()).not.toContain("gpt-99-internal"); @@ -397,8 +397,8 @@ test("Codex discovery exposes the observed native as a selector row plus one glo tokens: { access_token: "main-token", account_id: "main-account" }, }), "utf8"); - const { resetCatalogRuntimeStateForTests } = await import("../src/codex/catalog"); - const { resetCodexModelEntitlementCacheForTests } = await import("../src/codex/model-entitlements"); + const { resetCatalogRuntimeStateForTests } = await import("../../src/codex/catalog"); + const { resetCodexModelEntitlementCacheForTests } = await import("../../src/codex/model-entitlements"); resetCatalogRuntimeStateForTests(); resetCodexModelEntitlementCacheForTests(); const originalFetch = globalThis.fetch; @@ -444,7 +444,7 @@ test("Codex discovery exposes the observed native as a selector row plus one glo .toMatchObject({ visibility: "list" }); expect(catalog.models.find(model => model.slug === "gpt-daybreak-blue-latest")?.visibility).toBe("hide"); - const { claudeCodeNativeAlias } = await import("../src/claude/alias"); + const { claudeCodeNativeAlias } = await import("../../src/claude/alias"); const anthropic = await fetch(new URL("/v1/models?flavor=anthropic&ids=cli", server.url), { headers: { "anthropic-version": "2023-06-01" }, }).then(response => response.json()) as { data: Array<{ id: string }> }; @@ -532,7 +532,7 @@ test("the request's client_version reaches entitlement discovery (#2886)", async tokens: { access_token: "main-token", account_id: "main-account" }, }), "utf8"); - const { resetCatalogRuntimeStateForTests } = await import("../src/codex/catalog"); + const { resetCatalogRuntimeStateForTests } = await import("../../src/codex/catalog"); resetCatalogRuntimeStateForTests(); resetCodexModelEntitlementCacheForTests(); @@ -585,8 +585,8 @@ test("with no inbound or runtime version, /v1/models still exposes the gated row tokens: { access_token: "main-token", account_id: "main-account" }, }), "utf8"); - const { resetCatalogRuntimeStateForTests } = await import("../src/codex/catalog"); - const { resetCodexModelEntitlementCacheForTests } = await import("../src/codex/model-entitlements"); + const { resetCatalogRuntimeStateForTests } = await import("../../src/codex/catalog"); + const { resetCodexModelEntitlementCacheForTests } = await import("../../src/codex/model-entitlements"); resetCatalogRuntimeStateForTests(); resetCodexModelEntitlementCacheForTests(); diff --git a/tests/claude-native-passthrough.test.ts b/tests/claude-integration/claude-native-passthrough.test.ts similarity index 97% rename from tests/claude-native-passthrough.test.ts rename to tests/claude-integration/claude-native-passthrough.test.ts index b481dbf7c9..c8c798ac9a 100644 --- a/tests/claude-native-passthrough.test.ts +++ b/tests/claude-integration/claude-native-passthrough.test.ts @@ -1,14 +1,14 @@ import { afterEach, beforeEach, expect, test } from "bun:test"; -import { managementFetch as fetch } from "./helpers/management-auth"; -import { logsFromApiBody } from "./helpers/logs-api"; +import { managementFetch as fetch } from "../helpers/management-auth"; +import { logsFromApiBody } from "../helpers/logs-api"; 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 { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { saveConfig } from "../../src/config"; +import { startServer } from "../../src/server"; +import type { OcxConfig } from "../../src/types"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testDir = ""; let previousHome: string | undefined; @@ -151,7 +151,7 @@ test("unmapped claude model + sk-ant credential passes through verbatim", async test("native passthrough persists conversationId from metadata.user_id", async () => { const { createHash } = await import("node:crypto"); - const { clearRequestLogsForTests } = await import("../src/server/request-log"); + const { clearRequestLogsForTests } = await import("../../src/server/request-log"); clearRequestLogsForTests(); const captured: Captured[] = []; const upstream = mockAnthropicUpstream(captured); @@ -356,8 +356,8 @@ test("nativePassthrough:false disables the pierce", async () => { // --- Generous image pipeline on the native branch (devlog 260714 .../040, P1-P5) --- -import { resetNormalizeStateForTests } from "../src/adapters/anthropic-image-normalize"; -import { sniffImageDimensions } from "../src/adapters/anthropic-image-guard"; +import { resetNormalizeStateForTests } from "../../src/adapters/anthropic-image-normalize"; +import { sniffImageDimensions } from "../../src/adapters/anthropic-image-guard"; const ONE_PX_PNG = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="; diff --git a/tests/claude-outbound.test.ts b/tests/claude-integration/claude-outbound.test.ts similarity index 99% rename from tests/claude-outbound.test.ts rename to tests/claude-integration/claude-outbound.test.ts index 5283f3453c..299ce5135d 100644 --- a/tests/claude-outbound.test.ts +++ b/tests/claude-integration/claude-outbound.test.ts @@ -7,12 +7,12 @@ import { responsesJsonToAnthropicMessage, responsesSseToAnthropicSse as responsesSseToAnthropicSseProduction, sanitizeWebSearchInput, -} from "../src/claude/outbound"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../src/claude/outbound"; +import { createTestTranslatorBudget } from "../helpers/translator-budget"; import { TRANSLATOR_MAX_CALL_ARGUMENT_BYTES, type TranslatorBudget, -} from "../src/lib/translator-budget"; +} from "../../src/lib/translator-budget"; const streamBudgets = new WeakMap, TranslatorBudget>(); diff --git a/tests/claude-shell-hook.test.ts b/tests/claude-integration/claude-shell-hook.test.ts similarity index 96% rename from tests/claude-shell-hook.test.ts rename to tests/claude-integration/claude-shell-hook.test.ts index 0073d9d11a..dfdd7fa7a4 100644 --- a/tests/claude-shell-hook.test.ts +++ b/tests/claude-integration/claude-shell-hook.test.ts @@ -2,8 +2,8 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { delimiter, join } from "node:path"; -import { claudeCodeCliInstalled, reconcileShellHook } from "../src/server/system-env"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { claudeCodeCliInstalled, reconcileShellHook } from "../../src/server/system-env"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const originalPlatform = process.platform; let originalHome: string | undefined; @@ -178,7 +178,7 @@ describe("Claude Code shell-hook reconciliation", () => { }); test("start and ensure reconcile the hook from the actual injection result", async () => { - const source = await Bun.file(new URL("../src/cli/index.ts", import.meta.url)).text(); + const source = await Bun.file(new URL("../../src/cli/index.ts", import.meta.url)).text(); expect(source).not.toMatch(/\n\s*installShellHook\(\);/); expect(source.match(/reconcileShellHook\(systemEnv\.injected\)/g)).toHaveLength(2); diff --git a/tests/claude-sidecar-override.test.ts b/tests/claude-integration/claude-sidecar-override.test.ts similarity index 92% rename from tests/claude-sidecar-override.test.ts rename to tests/claude-integration/claude-sidecar-override.test.ts index 17130e5474..cfdbc46ca0 100644 --- a/tests/claude-sidecar-override.test.ts +++ b/tests/claude-integration/claude-sidecar-override.test.ts @@ -1,9 +1,9 @@ import { expect, test } from "bun:test"; -import { parseRequest } from "../src/responses/parser"; -import { buildClaudeReplayConfig } from "../src/server/claude-messages"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { planVisionSidecar } from "../src/vision"; -import { planWebSearch } from "../src/web-search"; +import { parseRequest } from "../../src/responses/parser"; +import { buildClaudeReplayConfig } from "../../src/server/claude-messages"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { planVisionSidecar } from "../../src/vision"; +import { planWebSearch } from "../../src/web-search"; const routed: OcxProviderConfig = { adapter: "openai-chat", diff --git a/tests/claude-system-env-auto.test.ts b/tests/claude-integration/claude-system-env-auto.test.ts similarity index 97% rename from tests/claude-system-env-auto.test.ts rename to tests/claude-integration/claude-system-env-auto.test.ts index 659f3ce898..20eb447b8d 100644 --- a/tests/claude-system-env-auto.test.ts +++ b/tests/claude-integration/claude-system-env-auto.test.ts @@ -3,9 +3,9 @@ import * as childProcess from "node:child_process"; import * as fs from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { injectSystemEnv } from "../src/server/system-env"; -import { PROXY_MARKER } from "../src/claude/auth-detect"; -import type { OcxConfig } from "../src/types"; +import { injectSystemEnv } from "../../src/server/system-env"; +import { PROXY_MARKER } from "../../src/claude/auth-detect"; +import type { OcxConfig } from "../../src/types"; /** * Auto must reach PLAIN `claude` launches, not just `ocx claude`. Before this, the diff --git a/tests/agent-driven.test.ts b/tests/cli/agent-driven.test.ts similarity index 96% rename from tests/agent-driven.test.ts rename to tests/cli/agent-driven.test.ts index ac587b2b94..e1872847fb 100644 --- a/tests/agent-driven.test.ts +++ b/tests/cli/agent-driven.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { agentDrivenMarkers, isAgentDriven } from "../src/cli/agent-driven"; +import { agentDrivenMarkers, isAgentDriven } from "../../src/cli/agent-driven"; describe("isAgentDriven", () => { test("a plain user shell is not agent-driven", () => { diff --git a/tests/cli-account-pool-verbs.test.ts b/tests/cli/cli-account-pool-verbs.test.ts similarity index 98% rename from tests/cli-account-pool-verbs.test.ts rename to tests/cli/cli-account-pool-verbs.test.ts index 1ebd48f730..41c4c170fd 100644 --- a/tests/cli-account-pool-verbs.test.ts +++ b/tests/cli/cli-account-pool-verbs.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { cmdPause, cmdPauseExhausted, cmdStrategy, cmdSticky } from "../src/cli/account-extended"; -import type { AccountDeps } from "../src/cli/account-api"; +import { cmdPause, cmdPauseExhausted, cmdStrategy, cmdSticky } from "../../src/cli/account-extended"; +import type { AccountDeps } from "../../src/cli/account-api"; /** * #2702: pause, resume, pause-exhausted, strategy, and sticky existed as server routes with @@ -313,7 +313,7 @@ describe("ocx account strategy / sticky on the anthropic pool", () => { }); describe("generic OAuth pool-settings contract (#695)", () => { - const { cmdAutoSwitch } = require("../src/cli/account-extended") as typeof import("../src/cli/account-extended"); + const { cmdAutoSwitch } = require("../../src/cli/account-extended") as typeof import("../../src/cli/account-extended"); function genericDeps( respond: (captured: Captured) => { status?: number; json: unknown }, calls: Captured[], diff --git a/tests/cli-account.test.ts b/tests/cli/cli-account.test.ts similarity index 99% rename from tests/cli-account.test.ts rename to tests/cli/cli-account.test.ts index 3aacf76b43..6f1dc0a09e 100644 --- a/tests/cli-account.test.ts +++ b/tests/cli/cli-account.test.ts @@ -4,24 +4,24 @@ import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { fileURLToPath } from "node:url"; -import { cmdAccount, classifyAccount, formatAccountTable, type AccountDeps } from "../src/cli/account"; -import type { AccountStdin } from "../src/cli/account-api"; -import { printSubcommandUsage } from "../src/cli/help"; +import { cmdAccount, classifyAccount, formatAccountTable, type AccountDeps } from "../../src/cli/account"; +import type { AccountStdin } from "../../src/cli/account-api"; +import { printSubcommandUsage } from "../../src/cli/help"; import { DEFAULT_ACCOUNT_PRIORITY, MAX_ACCOUNT_PRIORITY, MIN_ACCOUNT_PRIORITY, -} from "../src/codex/pool-rotation"; +} from "../../src/codex/pool-rotation"; import { ACCOUNT_PRIORITY_PRESETS, accountPriorityPresetKey, DEFAULT_ACCOUNT_PRIORITY as GUI_DEFAULT_PRIORITY, MAX_ACCOUNT_PRIORITY as GUI_MAX_PRIORITY, MIN_ACCOUNT_PRIORITY as GUI_MIN_PRIORITY, -} from "../gui/src/account-priority"; -import type { OcxConfig } from "../src/types"; -import { ACCOUNT_IMPORT_MAX_BYTES } from "../src/oauth/account-import"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../gui/src/account-priority"; +import type { OcxConfig } from "../../src/types"; +import { ACCOUNT_IMPORT_MAX_BYTES } from "../../src/oauth/account-import"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const RAW_SENTINEL = "test-key-rawsentinel1234567890"; const MASKED_SENTINEL = "test****7890"; @@ -386,7 +386,7 @@ function stdinFrom(value: string, isTTY = false): AccountStdin { test("the login URL reaches piped stdout before the polling window (#1007)", async () => { const child = Bun.spawn({ - cmd: [process.execPath, "run", fileURLToPath(new URL("./helpers/account-login-pipe-child.ts", import.meta.url))], + cmd: [process.execPath, "run", fileURLToPath(new URL("../helpers/account-login-pipe-child.ts", import.meta.url))], stdout: "pipe", stderr: "pipe", }); @@ -433,7 +433,7 @@ describe("account login --device", () => { test("prints the verification URL and device code to a piped stdout while polling", async () => { // The block is written to fd 1 directly (#1007), so it needs a real pipe. const child = Bun.spawn({ - cmd: [process.execPath, "run", fileURLToPath(new URL("./helpers/account-login-device-child.ts", import.meta.url))], + cmd: [process.execPath, "run", fileURLToPath(new URL("../helpers/account-login-device-child.ts", import.meta.url))], stdout: "pipe", stderr: "pipe", }); @@ -498,7 +498,7 @@ describe("account login --device", () => { test("waits out the full 15-minute grant instead of the 5-minute browser budget", async () => { // A budget regression to 150 attempts is invisible to an output assertion, // so read the loop bound from the source itself. - const source = await Bun.file(new URL("../src/cli/account-auth.ts", import.meta.url)).text(); + const source = await Bun.file(new URL("../../src/cli/account-auth.ts", import.meta.url)).text(); const budget = /const maxAttempts = device \? (\d+) : (\d+);/.exec(source); expect(budget).toBeTruthy(); // 2s per attempt. 900s is the grant itself; the budget must also leave diff --git a/tests/cli-capabilities.test.ts b/tests/cli/cli-capabilities.test.ts similarity index 95% rename from tests/cli-capabilities.test.ts rename to tests/cli/cli-capabilities.test.ts index e8584cc839..f8c7b26d04 100644 --- a/tests/cli-capabilities.test.ts +++ b/tests/cli/cli-capabilities.test.ts @@ -8,11 +8,12 @@ import { capabilitiesForRoute, capabilityInvocation, capabilityRouteKeys, -} from "../src/cli/capabilities"; -import { CLI_COMMANDS, findCommand } from "../src/cli/registry"; -import { runCapabilities } from "../src/cli/capabilities-command"; +} from "../../src/cli/capabilities"; +import { CLI_COMMANDS, findCommand } from "../../src/cli/registry"; +import { runCapabilities } from "../../src/cli/capabilities-command"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; -const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); +const repoRoot = resolveRepoRoot(); function captureStdout(): { lines: string[]; restore: () => void } { const lines: string[] = []; @@ -58,7 +59,7 @@ describe("capability table is a leaf data module", () => { }); test("head-handled surfaces are NOT registry commands", () => { - // tests/cli-registry.test.ts excludes help/--help/-h as head-handled pseudo-cases, + // tests/cli/cli-registry.test.ts excludes help/--help/-h as head-handled pseudo-cases, // and --version exits in the CLI head before dispatch. Declaring either as a // CLI_COMMANDS entry would break the runner-key parity assertion. const names = new Set(CLI_COMMANDS.map(e => e.name)); @@ -172,7 +173,7 @@ describe("ocx capabilities output", () => { test("every route a capability declares exists in the management registry", async () => { // The capability table must not advertise a route the server does not serve. - const { MANAGEMENT_ROUTES } = await import("../src/server/management/route-registry"); + const { MANAGEMENT_ROUTES } = await import("../../src/server/management/route-registry"); const declared = new Set(MANAGEMENT_ROUTES.map(r => `${r.method} ${r.path}`)); const unknown = [...capabilityRouteKeys()].filter(k => !declared.has(k)); expect(unknown).toEqual([]); @@ -345,7 +346,7 @@ describe("capability/route parity is bidirectional", () => { // The reverse direction. Without it, 139 routes carried no verb and no exemption and the // suite stayed green -- which is how `capabilities --route /api/keys` came to return an // empty list while `ocx access key` worked. - const { MANAGEMENT_ROUTES } = await import("../src/server/management/route-registry"); + const { MANAGEMENT_ROUTES } = await import("../../src/server/management/route-registry"); const covered = capabilityRouteKeys(); const ratchet = new Set(UNDECLARED_ROUTES_2026_08_28); const unexplained = MANAGEMENT_ROUTES @@ -360,7 +361,7 @@ describe("capability/route parity is bidirectional", () => { test("the ratchet only shrinks: every listed route is still unexplained", async () => { // A stale entry is as bad as a missing one. Once a route gains a capability or an // exemption it must leave this list, or the count stops being evidence of progress. - const { MANAGEMENT_ROUTES } = await import("../src/server/management/route-registry"); + const { MANAGEMENT_ROUTES } = await import("../../src/server/management/route-registry"); const covered = capabilityRouteKeys(); const byKey = new Map(MANAGEMENT_ROUTES.map(r => [`${r.method} ${r.path}`, r] as const)); const stale = UNDECLARED_ROUTES_2026_08_28.filter(k => { diff --git a/tests/cli-catalog-prewarm.test.ts b/tests/cli/cli-catalog-prewarm.test.ts similarity index 91% rename from tests/cli-catalog-prewarm.test.ts rename to tests/cli/cli-catalog-prewarm.test.ts index 1b10ec3a12..e2c1af3e1f 100644 --- a/tests/cli-catalog-prewarm.test.ts +++ b/tests/cli/cli-catalog-prewarm.test.ts @@ -1,8 +1,10 @@ import { describe, expect, mock, spyOn, test } from "bun:test"; -import type { OcxConfig } from "../src/types"; -import { scheduleCatalogPrewarm } from "../src/cli/catalog-prewarm"; +import type { OcxConfig } from "../../src/types"; +import { scheduleCatalogPrewarm } from "../../src/cli/catalog-prewarm"; +import { pathToFileURL } from "node:url"; +import { repoRoot } from "../helpers/repo-root"; -const root = new URL("../", import.meta.url); +const root = pathToFileURL(repoRoot() + "/"); async function readText(path: string): Promise { return await Bun.file(new URL(path, root)).text(); diff --git a/tests/cli-codex-cli-update.test.ts b/tests/cli/cli-codex-cli-update.test.ts similarity index 98% rename from tests/cli-codex-cli-update.test.ts rename to tests/cli/cli-codex-cli-update.test.ts index e0231e40b6..bc1ba26bf5 100644 --- a/tests/cli-codex-cli-update.test.ts +++ b/tests/cli/cli-codex-cli-update.test.ts @@ -1,11 +1,11 @@ import { describe, expect, test } from "bun:test"; -import { handleCodexCliUpdateCommand, parseCodexCliUpdateArgs } from "../src/cli/codex-cli-update"; +import { handleCodexCliUpdateCommand, parseCodexCliUpdateArgs } from "../../src/cli/codex-cli-update"; import { initializeNodeLauncherContext, NODE_LAUNCH_CONTEXT_ENV, NODE_LAUNCH_PROOF_PREFIX, -} from "../src/cli/launcher-context"; -import type { CodexCliInstallProvenanceDeps, CodexCliInstallReport } from "../src/codex/cli-install-provenance"; +} from "../../src/cli/launcher-context"; +import type { CodexCliInstallProvenanceDeps, CodexCliInstallReport } from "../../src/codex/cli-install-provenance"; const report: CodexCliInstallReport = { schemaVersion: 1, diff --git a/tests/cli-codex-log-guard-compact.test.ts b/tests/cli/cli-codex-log-guard-compact.test.ts similarity index 96% rename from tests/cli-codex-log-guard-compact.test.ts rename to tests/cli/cli-codex-log-guard-compact.test.ts index 2a6be54bc6..c0781c2f29 100644 --- a/tests/cli-codex-log-guard-compact.test.ts +++ b/tests/cli/cli-codex-log-guard-compact.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { handleObserveCommand } from "../src/cli/observe"; +import { handleObserveCommand } from "../../src/cli/observe"; describe("Codex Log Guard compact CLI", () => { test("compact POSTs to the dedicated maintenance endpoint", async () => { diff --git a/tests/cli-codex-log-guard-protection.test.ts b/tests/cli/cli-codex-log-guard-protection.test.ts similarity index 98% rename from tests/cli-codex-log-guard-protection.test.ts rename to tests/cli/cli-codex-log-guard-protection.test.ts index 69dd104ebc..bb6e08f55f 100644 --- a/tests/cli-codex-log-guard-protection.test.ts +++ b/tests/cli/cli-codex-log-guard-protection.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { handleObserveCommand } from "../src/cli/observe"; +import { handleObserveCommand } from "../../src/cli/observe"; function responseBody() { return { diff --git a/tests/cli-codex-log-guard.test.ts b/tests/cli/cli-codex-log-guard.test.ts similarity index 96% rename from tests/cli-codex-log-guard.test.ts rename to tests/cli/cli-codex-log-guard.test.ts index aef6b2e790..61d89a06d0 100644 --- a/tests/cli-codex-log-guard.test.ts +++ b/tests/cli/cli-codex-log-guard.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { handleObserveCommand } from "../src/cli/observe"; +import { handleObserveCommand } from "../../src/cli/observe"; describe("Codex Log Guard CLI", () => { test("ocx storage codex-logs status uses the dedicated diagnostics endpoint", async () => { diff --git a/tests/cli-config-command.test.ts b/tests/cli/cli-config-command.test.ts similarity index 92% rename from tests/cli-config-command.test.ts rename to tests/cli/cli-config-command.test.ts index ab68eb07c5..ed45884680 100644 --- a/tests/cli-config-command.test.ts +++ b/tests/cli/cli-config-command.test.ts @@ -4,10 +4,10 @@ import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import { SPAWN_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { SPAWN_BUDGET_MS } from "../helpers/test-budget"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); const cliPath = join(repoRoot, "src", "cli", "index.ts"); const isolatedCodexHome = mkdtempSync(join(tmpdir(), "ocx-config-codex-home-")); diff --git a/tests/cli-dispatch.test.ts b/tests/cli/cli-dispatch.test.ts similarity index 98% rename from tests/cli-dispatch.test.ts rename to tests/cli/cli-dispatch.test.ts index 1225b2983e..88ef3ed85f 100644 --- a/tests/cli-dispatch.test.ts +++ b/tests/cli/cli-dispatch.test.ts @@ -1,14 +1,15 @@ import { describe, expect, spyOn, test } from "bun:test"; -import { CLI_COMMANDS } from "../src/cli/registry"; -import { DISPATCH_ALIASES, DISPATCH_COMMANDS, dispatchCommand, resolveDispatchCommand, decideStartWithLiveOwner } from "../src/cli/dispatch"; -import type { CliDispatchDeps } from "../src/cli/dispatch"; -import { runGuiCommand } from "../src/cli/gui"; +import { CLI_COMMANDS } from "../../src/cli/registry"; +import { DISPATCH_ALIASES, DISPATCH_COMMANDS, dispatchCommand, resolveDispatchCommand, decideStartWithLiveOwner } from "../../src/cli/dispatch"; +import type { CliDispatchDeps } from "../../src/cli/dispatch"; +import { runGuiCommand } from "../../src/cli/gui"; import { existsSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { getConfigDir } from "../src/config"; -import { getAccountSet, removeCredential, saveCredential } from "../src/oauth/store"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { getConfigDir } from "../../src/config"; +import { getAccountSet, removeCredential, saveCredential } from "../../src/oauth/store"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath } from "../helpers/repo-root"; /** Minimal fake deps. dispatchCommand only touches deps for real command * runners, which these tests never invoke, so an empty object is enough. */ @@ -203,7 +204,7 @@ describe("health retries a just-started proxy", () => { * `handleEnsure` call site that already had it right. */ describe("start probes the configured port before shadowing it (source-level)", () => { - const cliSource = readFileSync(join(import.meta.dir, "../src/cli/index.ts"), "utf8"); + const cliSource = readFileSync(repoPath("src/cli/index.ts"), "utf8"); test("every findProxyOwnerBeforeJournalRecovery call site asks for the probe", () => { const calls = cliSource.match(/findProxyOwnerBeforeJournalRecovery\s*\(([^)]*)\)/g) ?? []; diff --git a/tests/cli-dto-fidelity.test.ts b/tests/cli/cli-dto-fidelity.test.ts similarity index 96% rename from tests/cli-dto-fidelity.test.ts rename to tests/cli/cli-dto-fidelity.test.ts index fa15d2adbd..7b5d22d8fa 100644 --- a/tests/cli-dto-fidelity.test.ts +++ b/tests/cli/cli-dto-fidelity.test.ts @@ -1,9 +1,9 @@ import { describe, expect, test } from "bun:test"; -import { formatUsageReport } from "../src/cli/usage-report"; +import { formatUsageReport } from "../../src/cli/usage-report"; /** formatUsageReport returns lines; assertions here are about rendered text. */ const joinReport = (input: Parameters[0]): string => formatUsageReport(input).join("\n"); -import { formatAccountTable, type AccountRowForTest } from "../src/cli/account"; +import { formatAccountTable, type AccountRowForTest } from "../../src/cli/account"; /** * #2700, #2703: the CLI discarded fields the API already returned. @@ -132,7 +132,7 @@ describe("#2703 the projection does not strip the 5h window", () => { * So this drives the real path: a server payload in, a projected row out. */ async function rowsFromServer(quota: Record): Promise<{ quota?: unknown }[]> { - const { fetchCodexRows } = await import("../src/cli/account-api"); + const { fetchCodexRows } = await import("../../src/cli/account-api"); const fetchImpl = (async (url: string | URL | Request) => { const href = String(url); if (href.includes("/api/codex-auth/active")) { @@ -147,7 +147,7 @@ describe("#2703 the projection does not strip the 5h window", () => { } test("account list --quota attaches cached quota without ?refresh=1", async () => { - const { fetchRows } = await import("../src/cli/account-api"); + const { fetchRows } = await import("../../src/cli/account-api"); const hrefs: string[] = []; const fetchImpl = (async (url: string | URL | Request) => { const href = String(url); @@ -194,7 +194,7 @@ describe("#2703 the projection does not strip the 5h window", () => { describe("#2705 access key usage columns", () => { async function listOutput(payload: Record): Promise { - const { handleAccessCommand } = await import("../src/cli/access"); + const { handleAccessCommand } = await import("../../src/cli/access"); const lines: string[] = []; const original = console.log; console.log = (...args: unknown[]) => { lines.push(args.map(String).join(" ")); }; diff --git a/tests/cli-export-command.test.ts b/tests/cli/cli-export-command.test.ts similarity index 97% rename from tests/cli-export-command.test.ts rename to tests/cli/cli-export-command.test.ts index cdc3fe4a0b..28fce31d44 100644 --- a/tests/cli-export-command.test.ts +++ b/tests/cli/cli-export-command.test.ts @@ -12,13 +12,13 @@ import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import { handleExportCommand, exportModelsFromProxyRows } from "../src/cli/export-command"; -import { resetCodexModelEntitlementCacheForTests } from "../src/codex/model-entitlements"; -import { handleManagementAPI } from "../src/server/management-api"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { handleExportCommand, exportModelsFromProxyRows } from "../../src/cli/export-command"; +import { resetCodexModelEntitlementCacheForTests } from "../../src/codex/model-entitlements"; +import { handleManagementAPI } from "../../src/server/management-api"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); const cliPath = join(repoRoot, "src", "cli", "index.ts"); const servers: Array> = []; diff --git a/tests/cli-head.test.ts b/tests/cli/cli-head.test.ts similarity index 97% rename from tests/cli-head.test.ts rename to tests/cli/cli-head.test.ts index 9b35a93597..0fc06874e3 100644 --- a/tests/cli-head.test.ts +++ b/tests/cli/cli-head.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { parseCliHead } from "../src/cli/root"; -import { DEFAULT_READY_WAIT_TIMEOUT_SECONDS } from "../src/cli/ready"; +import { parseCliHead } from "../../src/cli/root"; +import { DEFAULT_READY_WAIT_TIMEOUT_SECONDS } from "../../src/cli/ready"; describe("parseCliHead (pure CLI head, Phase 1)", () => { test("version flags exit as version", () => { diff --git a/tests/cli-headless-parity.test.ts b/tests/cli/cli-headless-parity.test.ts similarity index 98% rename from tests/cli-headless-parity.test.ts rename to tests/cli/cli-headless-parity.test.ts index 1435b17a81..42d66d3f04 100644 --- a/tests/cli-headless-parity.test.ts +++ b/tests/cli/cli-headless-parity.test.ts @@ -3,17 +3,18 @@ import { mkdtempSync, readFileSync, readdirSync, statSync, writeFileSync } from import { tmpdir } from "node:os"; import { join } from "node:path"; import { Readable } from "node:stream"; -import { handleAccessCommand } from "../src/cli/access"; -import { handleAgentCommand } from "../src/cli/agent"; -import { handleComboCommand } from "../src/cli/combo"; -import { handleConfigCommand } from "../src/cli/config-command"; -import { handleClientIntegrationCommand, handleGrokCommand } from "../src/cli/integrations"; -import { handleModelsRuntimeCommand } from "../src/cli/models-runtime"; -import { handleProviderRuntimeCommand } from "../src/cli/provider-runtime"; -import { providerQuotaLine } from "../src/cli/account-extended"; -import { formatAccountTable } from "../src/cli/account"; -import { handleConnectCommand } from "../src/cli/connect"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { handleAccessCommand } from "../../src/cli/access"; +import { handleAgentCommand } from "../../src/cli/agent"; +import { handleComboCommand } from "../../src/cli/combo"; +import { handleConfigCommand } from "../../src/cli/config-command"; +import { handleClientIntegrationCommand, handleGrokCommand } from "../../src/cli/integrations"; +import { handleModelsRuntimeCommand } from "../../src/cli/models-runtime"; +import { handleProviderRuntimeCommand } from "../../src/cli/provider-runtime"; +import { providerQuotaLine } from "../../src/cli/account-extended"; +import { formatAccountTable } from "../../src/cli/account"; +import { handleConnectCommand } from "../../src/cli/connect"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath } from "../helpers/repo-root"; type Recorded = { path: string; method: string; body: unknown }; const servers: Array> = []; @@ -211,7 +212,7 @@ function sourceFiles(root: string): string[] { describe("headless GUI parity CLI", () => { test("every GUI management endpoint belongs to a documented CLI resource", () => { - const guiRoot = join(import.meta.dir, "..", "gui", "src"); + const guiRoot = repoPath("gui", "src"); const endpoints = new Set(); for (const path of sourceFiles(guiRoot)) { const source = readFileSync(path, "utf8"); diff --git a/tests/cli-help.test.ts b/tests/cli/cli-help.test.ts similarity index 98% rename from tests/cli-help.test.ts rename to tests/cli/cli-help.test.ts index 2649bca27e..d101b75bc8 100644 --- a/tests/cli-help.test.ts +++ b/tests/cli/cli-help.test.ts @@ -5,11 +5,11 @@ import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { Database } from "bun:sqlite"; -import { EXPORT_CLIENT_IDS } from "../src/clients/config-export"; -import { SPAWN_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { EXPORT_CLIENT_IDS } from "../../src/clients/config-export"; +import { SPAWN_BUDGET_MS } from "../helpers/test-budget"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); const cliPath = join(repoRoot, "src", "cli", "index.ts"); const binPath = join(repoRoot, "bin", "ocx.mjs"); diff --git a/tests/cli-json-contract.test.ts b/tests/cli/cli-json-contract.test.ts similarity index 95% rename from tests/cli-json-contract.test.ts rename to tests/cli/cli-json-contract.test.ts index a4b65f1a7c..a4672cb81b 100644 --- a/tests/cli-json-contract.test.ts +++ b/tests/cli/cli-json-contract.test.ts @@ -2,7 +2,8 @@ import { describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { dirname, join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; -import { CAPABILITIES } from "../src/cli/capabilities"; +import { CAPABILITIES } from "../../src/cli/capabilities"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; /** * The `--json` contract, enforced rather than conventional. @@ -17,7 +18,7 @@ import { CAPABILITIES } from "../src/cli/capabilities"; * subprocesses is slow and, worse, several of these commands mutate real config. Source * assertions pin the parsing SHAPE, which is what regressed. */ -const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); +const repoRoot = resolveRepoRoot(); const read = (rel: string): string => readFileSync(join(repoRoot, rel), "utf8"); describe("--json is order-independent", () => { @@ -84,7 +85,7 @@ describe("doctor can gate a script", () => { test("doctorFailed is exported and resets per run", async () => { // Reset matters: the suite drives runDoctor several times in one process, and a sticky // flag would fail the second call because the first saw a problem. - const mod = await import("../src/cli/doctor"); + const mod = await import("../../src/cli/doctor"); expect(typeof mod.doctorFailed).toBe("function"); const src = read("src/cli/doctor.ts"); expect(src).toContain("doctorSawFailure = false;"); diff --git a/tests/cli-management-auth.test.ts b/tests/cli/cli-management-auth.test.ts similarity index 92% rename from tests/cli-management-auth.test.ts rename to tests/cli/cli-management-auth.test.ts index c9cd312cde..24f90bf33d 100644 --- a/tests/cli-management-auth.test.ts +++ b/tests/cli/cli-management-auth.test.ts @@ -2,11 +2,11 @@ import { afterEach, describe, expect, test } from "bun:test"; import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { runtimeRequest } from "../src/cli/runtime-api"; -import { stopProxyGracefully } from "../src/lib/process-control"; -import { fetchClaudeContextWindows } from "../src/cli/claude"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { runtimeRequest } from "../../src/cli/runtime-api"; +import { stopProxyGracefully } from "../../src/lib/process-control"; +import { fetchClaudeContextWindows } from "../../src/cli/claude"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const previousHome = process.env.OPENCODEX_HOME; const previousDataToken = process.env.OPENCODEX_API_AUTH_TOKEN; diff --git a/tests/cli-models-reasoning.test.ts b/tests/cli/cli-models-reasoning.test.ts similarity index 97% rename from tests/cli-models-reasoning.test.ts rename to tests/cli/cli-models-reasoning.test.ts index 6e5028302b..fa25f025e7 100644 --- a/tests/cli-models-reasoning.test.ts +++ b/tests/cli/cli-models-reasoning.test.ts @@ -2,9 +2,9 @@ import { afterAll, beforeAll, describe, expect, test } from "bun:test"; import { mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { parseReasoningArgs, handleModels } from "../src/cli/models"; -import { handleModelsRuntimeCommand } from "../src/cli/models-runtime"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { parseReasoningArgs, handleModels } from "../../src/cli/models"; +import { handleModelsRuntimeCommand } from "../../src/cli/models-runtime"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * The API validates reasoning ladders (9 tests in catalog-input-modality-enum.test.ts), diff --git a/tests/cli-models-runtime-dispatch.test.ts b/tests/cli/cli-models-runtime-dispatch.test.ts similarity index 93% rename from tests/cli-models-runtime-dispatch.test.ts rename to tests/cli/cli-models-runtime-dispatch.test.ts index d5bba5abf0..3608fe9457 100644 --- a/tests/cli-models-runtime-dispatch.test.ts +++ b/tests/cli/cli-models-runtime-dispatch.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; -import { MODELS_RUNTIME_SUBCOMMANDS, isModelsRuntimeSubcommand } from "../src/cli/models-runtime-subcommands"; -import { MODELS_RUNTIME_USAGE, handleModelsRuntimeCommand } from "../src/cli/models-runtime"; +import { MODELS_RUNTIME_SUBCOMMANDS, isModelsRuntimeSubcommand } from "../../src/cli/models-runtime-subcommands"; +import { MODELS_RUNTIME_USAGE, handleModelsRuntimeCommand } from "../../src/cli/models-runtime"; /** * #3094: `ocx models new-policy` and `ocx models new-arrivals` were implemented in @@ -40,7 +40,7 @@ describe("models runtime subcommand dispatch (#3094)", () => { test("handleModels routes exactly the shared set to the runtime module", () => { // Reading the source keeps this honest without booting the CLI: the dispatch must // consult the shared predicate rather than re-listing names inline. - const source = readFileSync(new URL("../src/cli/models.ts", import.meta.url), "utf8"); + const source = readFileSync(new URL("../../src/cli/models.ts", import.meta.url), "utf8"); expect(source).toContain("isModelsRuntimeSubcommand(subcommand)"); // The old inline array is what allowed the drift; it must not come back. expect(source).not.toMatch(/\["live",\s*"edit"/); diff --git a/tests/cli-models.test.ts b/tests/cli/cli-models.test.ts similarity index 98% rename from tests/cli-models.test.ts rename to tests/cli/cli-models.test.ts index 5e4185dce9..e6788116a4 100644 --- a/tests/cli-models.test.ts +++ b/tests/cli/cli-models.test.ts @@ -4,13 +4,13 @@ import { mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import { INTERNAL_DEADLINE_MS, SPAWN_BUDGET_MS } from "./helpers/test-budget"; -import { configuredReasoningEfforts } from "../src/reasoning-effort"; -import { isModelTextOnly } from "../src/vision"; -import type { OcxProviderConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { INTERNAL_DEADLINE_MS, SPAWN_BUDGET_MS } from "../helpers/test-budget"; +import { configuredReasoningEfforts } from "../../src/reasoning-effort"; +import { isModelTextOnly } from "../../src/vision"; +import type { OcxProviderConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); const cliPath = join(repoRoot, "src", "cli", "index.ts"); setDefaultTimeout(SPAWN_BUDGET_MS); diff --git a/tests/cli-native-profile.test.ts b/tests/cli/cli-native-profile.test.ts similarity index 98% rename from tests/cli-native-profile.test.ts rename to tests/cli/cli-native-profile.test.ts index 27a2ad9258..c1930a8e27 100644 --- a/tests/cli-native-profile.test.ts +++ b/tests/cli/cli-native-profile.test.ts @@ -2,10 +2,10 @@ import { afterEach, describe, expect, test } from "bun:test"; import { mkdtempSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import { tmpdir } from "node:os"; -import { cmdAccount } from "../src/cli/account"; -import { apiError } from "../src/cli/account-api"; -import { nativeMainCodexLoginInvocation } from "../src/cli/account-main"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { cmdAccount } from "../../src/cli/account"; +import { apiError } from "../../src/cli/account-api"; +import { nativeMainCodexLoginInvocation } from "../../src/cli/account-main"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const originalLog = console.log; const originalError = console.error; diff --git a/tests/cli-provider.test.ts b/tests/cli/cli-provider.test.ts similarity index 98% rename from tests/cli-provider.test.ts rename to tests/cli/cli-provider.test.ts index ab1ac925c9..b58adfd8cb 100644 --- a/tests/cli-provider.test.ts +++ b/tests/cli/cli-provider.test.ts @@ -4,10 +4,10 @@ import { mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import { SPAWN_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { SPAWN_BUDGET_MS } from "../helpers/test-budget"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); const cliPath = join(repoRoot, "src", "cli", "index.ts"); const isolatedCodexHome = mkdtempSync(join(tmpdir(), "ocx-prov-codex-home-")); diff --git a/tests/cli-ready-subprocess.test.ts b/tests/cli/cli-ready-subprocess.test.ts similarity index 97% rename from tests/cli-ready-subprocess.test.ts rename to tests/cli/cli-ready-subprocess.test.ts index 66208fc18d..54a5416a62 100644 --- a/tests/cli-ready-subprocess.test.ts +++ b/tests/cli/cli-ready-subprocess.test.ts @@ -1,7 +1,7 @@ /** * Real subprocess/loopback coverage for ocx ready dispatch boundaries. * - * Keep tests/cli-ready.test.ts injected-only. These focused integration tests + * Keep tests/cli/cli-ready.test.ts injected-only. These focused integration tests * prove that the top-level CLI preserves terminal-failed and pre-parse behavior * with isolated homes and an actual discovered proxy fixture. */ @@ -10,9 +10,9 @@ import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); const cliPath = join(repoRoot, "src", "cli", "index.ts"); interface CliResult { diff --git a/tests/cli-ready.test.ts b/tests/cli/cli-ready.test.ts similarity index 97% rename from tests/cli-ready.test.ts rename to tests/cli/cli-ready.test.ts index 388abfb3c7..81e486859c 100644 --- a/tests/cli-ready.test.ts +++ b/tests/cli/cli-ready.test.ts @@ -18,7 +18,8 @@ import { type ReadyIo, type ReadyLive, type ReadyProbe, -} from "../src/cli/ready"; +} from "../../src/cli/ready"; +import { repoPath } from "../helpers/repo-root"; // ── parseReadyArgs ──────────────────────────────────────────────────────────── @@ -639,9 +640,9 @@ describe("runReady --wait deadline correctness", () => { // (3) passed to reconcileClientStartupBeforeReady before that helper gives a // deferred gate to syncCodexOnStartIfEnabled. The successful transition is held // until the Claude roster fence settles; this source guard complements the -// executable delayed-roster test in tests/claude-agent-startup-sync.test.ts. +// executable delayed-roster test in tests/claude-integration/claude-agent-startup-sync.test.ts. describe("handleStart readinessGate wiring (source-level)", () => { - const cliSource = readFileSync(join(import.meta.dir, "../src/cli/index.ts"), "utf8"); + const cliSource = readFileSync(repoPath("src/cli/index.ts"), "utf8"); test("readinessGate is created, threaded into startServer, and into the startup sync — in order", () => { const createMatch = cliSource.match(/const\s+readinessGate\s*=\s*createReadinessGate\(\)/); @@ -690,8 +691,8 @@ describe("handleStart readinessGate wiring (source-level)", () => { // CLI deepening); the dispatch switch stays in src/cli/index.ts. No // subprocess/network/HOME is used. describe("ready pre-parse before maybeAutoRestoreCodexShim (source-level, P1)", () => { - const rootSource = readFileSync(join(import.meta.dir, "../src/cli/root.ts"), "utf8"); - const cliSource = readFileSync(join(import.meta.dir, "../src/cli/index.ts"), "utf8"); + const rootSource = readFileSync(repoPath("src/cli/root.ts"), "utf8"); + const cliSource = readFileSync(repoPath("src/cli/index.ts"), "utf8"); test("ready pre-parse call runs BEFORE maybeAutoRestoreCodexShim", () => { const preparseIdx = rootSource.indexOf("parseReadyArgs(args.slice(1))"); @@ -747,7 +748,7 @@ describe("ready pre-parse before maybeAutoRestoreCodexShim (source-level, P1)", expect(rootSource).toContain("maybeAutoRestoreCodexShim(head.command, head.args)"); // The ready runner lives in dispatch.ts (keyed "ready:"); slice its body // up to the next runner key, not a fixed width. - const dispatchSource = readFileSync(join(import.meta.dir, "../src/cli/dispatch.ts"), "utf8"); + const dispatchSource = readFileSync(repoPath("src/cli/dispatch.ts"), "utf8"); const readyCaseIdx = dispatchSource.indexOf("ready: async"); expect(readyCaseIdx, 'a "ready" runner must exist in dispatch.ts').toBeGreaterThanOrEqual(0); // The ready runner is followed by the provider runner; slice to that key. @@ -812,7 +813,7 @@ describe("invalid ready matrices never invoke findLive/probe (P1 counters)", () // real wall-clock time, so Date.now is authoritative for the network deadline. // The non-wait path keeps findLiveProxy's built-in default (no deadlineAt). describe("runReady production findLiveProxy deadline wiring (source-level)", () => { - const readySource = readFileSync(join(import.meta.dir, "../src/cli/ready.ts"), "utf8"); + const readySource = readFileSync(repoPath("src/cli/ready.ts"), "utf8"); test("the --wait path derives deadlineAt from Date.now() + remainingMs (not the injected now)", () => { // Date.now (real wall clock) is authoritative for the AbortSignal deadline; @@ -847,12 +848,12 @@ describe("runReady production findLiveProxy deadline wiring (source-level)", () // (retry on non-zero) does not respawn every 5s against a listener it can never // claim. Source-level pin so a future edit cannot drop the guard silently. describe("handleStart OCX_SERVICE exit guard (source-level)", () => { - const cliSource = readFileSync(join(import.meta.dir, "../src/cli/index.ts"), "utf8"); + const cliSource = readFileSync(repoPath("src/cli/index.ts"), "utf8"); test("an already-live proxy exits 0 in OCX_SERVICE context", () => { // The `OCX_SERVICE === "1"` comparison moved into `decideStartWithLiveOwner` // (src/cli/dispatch.ts), where the sentinel semantics are asserted at runtime - // across the whole matrix (tests/cli-dispatch.test.ts). This oracle pins the + // across the whole matrix (tests/cli/cli-dispatch.test.ts). This oracle pins the // exits that the decision routes to: stay-out exits 0, the conflict exits 1. expect(cliSource).toMatch(/decideStartWithLiveOwner\(\{/); const stayOut = cliSource.match(/decision === "service-stay-out"[\s\S]{0,800}?process\.exit\(0\)/); @@ -862,7 +863,7 @@ describe("handleStart OCX_SERVICE exit guard (source-level)", () => { }); test("service.ts teardown kills surviving wrapper processes on stop", () => { - const serviceSource = readFileSync(join(import.meta.dir, "../src/service.ts"), "utf8"); + const serviceSource = readFileSync(repoPath("src/service.ts"), "utf8"); expect(serviceSource).toMatch(/killWindowsServiceWrapperProcesses/); // The boolean `stopServiceIfInstalled` is gone — it collapsed a live manager into the // same false as "not installed" (#3008). The stop itself is the detailed function. @@ -875,7 +876,7 @@ describe("handleStart OCX_SERVICE exit guard (source-level)", () => { // wrapper from another OpenCodex home (or any process whose command line // merely contains the name). The kill must target the exact canonical // paths windowsServiceScriptPath()/windowsLauncherVbsPath() produce. - const serviceSource = readFileSync(join(import.meta.dir, "../src/service.ts"), "utf8"); + const serviceSource = readFileSync(repoPath("src/service.ts"), "utf8"); expect(serviceSource).toMatch(/windowsServiceScriptPath\(\)/); expect(serviceSource).toMatch(/windowsLauncherVbsPath\(\)/); const killBody = serviceSource.match(/function killWindowsServiceWrapperProcesses\(\)[\s\S]*?\n}/); @@ -896,7 +897,7 @@ describe("handleStart OCX_SERVICE exit guard (source-level)", () => { // the update job so the two teardown paths cannot drift apart again, so the // token-boundary rule is asserted where it is implemented. const sharedSource = readFileSync( - join(import.meta.dir, "../src/lib/windows-service-wrappers.ts"), + repoPath("src/lib/windows-service-wrappers.ts"), "utf8", ); const killScript = sharedSource.match(/export function windowsWrapperKillScript\([\s\S]*?\n}/); diff --git a/tests/cli-registry.test.ts b/tests/cli/cli-registry.test.ts similarity index 96% rename from tests/cli-registry.test.ts rename to tests/cli/cli-registry.test.ts index ccfdf87404..27084cecae 100644 --- a/tests/cli-registry.test.ts +++ b/tests/cli/cli-registry.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { fileURLToPath } from "node:url"; -import { CLI_COMMANDS, findCommand } from "../src/cli/registry"; -import { DISPATCH_ALIASES, DISPATCH_COMMANDS } from "../src/cli/dispatch"; +import { CLI_COMMANDS, findCommand } from "../../src/cli/registry"; +import { DISPATCH_ALIASES, DISPATCH_COMMANDS } from "../../src/cli/dispatch"; describe("CLI command registry parity", () => { /** Runner keys in src/cli/dispatch.ts (the dispatch table that replaced the @@ -128,7 +128,7 @@ describe("help banner command coverage", () => { // not required to match the registry exactly. It must never drop a visible // command entirely: every visible canonical command has to appear. test("every visible canonical command appears in the printUsage banner", () => { - const helpSrc = readFileSync(fileURLToPath(new URL("../src/cli/help.ts", import.meta.url)), "utf8"); + const helpSrc = readFileSync(fileURLToPath(new URL("../../src/cli/help.ts", import.meta.url)), "utf8"); // Commands whose `name` is only ever used as another entry's alias // (setup/eject/remove/model) are shown inline as "(alias: ...)" rather diff --git a/tests/cli-restart-health.test.ts b/tests/cli/cli-restart-health.test.ts similarity index 94% rename from tests/cli-restart-health.test.ts rename to tests/cli/cli-restart-health.test.ts index 253d23e8d1..ac2dfae50d 100644 --- a/tests/cli-restart-health.test.ts +++ b/tests/cli/cli-restart-health.test.ts @@ -4,9 +4,9 @@ import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); const cliPath = join(repoRoot, "src", "cli", "index.ts"); /** @@ -14,7 +14,7 @@ const cliPath = join(repoRoot, "src", "cli", "index.ts"); * check can ever discover/inspect/mutate the operator's real proxy state. The * ready describe keeps ONLY the help-routing subprocess checks: the * network/no-proxy/argument-validation ready tests live as injected tests in - * tests/cli-ready.test.ts (no real loopback/home). + * tests/cli/cli-ready.test.ts (no real loopback/home). */ function runCli(args: string[], env: Record = {}) { return spawnSync(process.execPath, [cliPath, ...args], { @@ -115,7 +115,7 @@ describe("ocx health", () => { describe("ocx ready", () => { // Only the help-routing subprocess checks live here. The default-probe, // --json, --wait, --timeout, and argument-validation cases are injected tests - // in tests/cli-ready.test.ts (no real loopback/home). + // in tests/cli/cli-ready.test.ts (no real loopback/home). test("ready --help prints usage (exit 0)", () => { const dir = isolatedHome("ocx-ready-help-"); try { diff --git a/tests/cli-restore-back.test.ts b/tests/cli/cli-restore-back.test.ts similarity index 96% rename from tests/cli-restore-back.test.ts rename to tests/cli/cli-restore-back.test.ts index e3cdc3be5c..04051a4b10 100644 --- a/tests/cli-restore-back.test.ts +++ b/tests/cli/cli-restore-back.test.ts @@ -3,11 +3,12 @@ import { spawnSync } from "node:child_process"; import { mkdirSync, mkdtempSync, readFileSync, statSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { claimOwnedServiceHome, withOwnedServiceHomePreload } from "./helpers/owned-service-home"; -import { SPAWN_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { claimOwnedServiceHome, withOwnedServiceHomePreload } from "../helpers/owned-service-home"; +import { SPAWN_BUDGET_MS } from "../helpers/test-budget"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; -const repoRoot = join(import.meta.dir, ".."); +const repoRoot = resolveRepoRoot(); // Every case spawns the real CLI; match cli-provider.test.ts budgets so a wedged // child fails fast instead of burning the whole shard timeout on Linux CI. diff --git a/tests/cli-start-journal-order.test.ts b/tests/cli/cli-start-journal-order.test.ts similarity index 98% rename from tests/cli-start-journal-order.test.ts rename to tests/cli/cli-start-journal-order.test.ts index e99f0bbeb4..15e6758b7a 100644 --- a/tests/cli-start-journal-order.test.ts +++ b/tests/cli/cli-start-journal-order.test.ts @@ -2,8 +2,9 @@ import { afterEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; -import { watchdogMs } from "./helpers/ci-watchdog"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { watchdogMs } from "../helpers/ci-watchdog"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath } from "../helpers/repo-root"; // Every wait here is bounded by a real `ocx start` child coming up: spawning Bun, // binding a port, and writing its runtime record. That is intrinsic to the @@ -19,7 +20,7 @@ const OWNER_WAIT_MS = watchdogMs(10_000); // is derived from the deadline rather than pinned next to it. const JOURNAL_OWNERSHIP_BUDGET_MS = Math.max(30_000, OWNER_WAIT_MS * 4); -const cliPath = resolve(import.meta.dir, "../src/cli/index.ts"); +const cliPath = repoPath("src/cli/index.ts"); const roots: string[] = []; const children: Array> = []; diff --git a/tests/cli-status-json.test.ts b/tests/cli/cli-status-json.test.ts similarity index 98% rename from tests/cli-status-json.test.ts rename to tests/cli/cli-status-json.test.ts index fa402923ef..9d82916b4a 100644 --- a/tests/cli-status-json.test.ts +++ b/tests/cli/cli-status-json.test.ts @@ -6,11 +6,11 @@ import type { AddressInfo } from "node:net"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import { isConnectionRefused, isUncleanExitEvidence, proxyHealthFailureReason, resolveStatusPid, selectListenTarget } from "../src/cli/status"; -import { findDeadPid } from "./helpers/dead-pid"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { isConnectionRefused, isUncleanExitEvidence, proxyHealthFailureReason, resolveStatusPid, selectListenTarget } from "../../src/cli/status"; +import { findDeadPid } from "../helpers/dead-pid"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); const cliPath = join(repoRoot, "src", "cli", "index.ts"); function runStatusJson(opencodexHome: string) { @@ -155,7 +155,7 @@ describe("CLI status JSON", () => { test("status --json reports catalogClamp.runtimeVersion when clamp is active", async () => { const { chmodSync } = await import("node:fs"); - const { persistEffortClamp, resetCodexRuntimeResolveCacheForTests } = await import("../src/codex/runtime"); + const { persistEffortClamp, resetCodexRuntimeResolveCacheForTests } = await import("../../src/codex/runtime"); const opencodexHome = mkdtempSync(join(tmpdir(), "ocx-status-clamp-")); try { writeFileSync(join(opencodexHome, "config.json"), JSON.stringify({ diff --git a/tests/cli-status-oauth-health.test.ts b/tests/cli/cli-status-oauth-health.test.ts similarity index 94% rename from tests/cli-status-oauth-health.test.ts rename to tests/cli/cli-status-oauth-health.test.ts index 9d16cfab68..5661105412 100644 --- a/tests/cli-status-oauth-health.test.ts +++ b/tests/cli/cli-status-oauth-health.test.ts @@ -2,10 +2,10 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdirSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { formatOAuthHealthForStatus } from "../src/cli/status-oauth"; -import { collectOAuthHealthEntries } from "../src/oauth/health"; -import { getAccountSet, markAccountNeedsReauth, saveCredential } from "../src/oauth/store"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { formatOAuthHealthForStatus } from "../../src/cli/status-oauth"; +import { collectOAuthHealthEntries } from "../../src/oauth/health"; +import { getAccountSet, markAccountNeedsReauth, saveCredential } from "../../src/oauth/store"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const origHome = process.env.HOME; const origOcxHome = process.env.OPENCODEX_HOME; diff --git a/tests/cli-storage-inspect.test.ts b/tests/cli/cli-storage-inspect.test.ts similarity index 99% rename from tests/cli-storage-inspect.test.ts rename to tests/cli/cli-storage-inspect.test.ts index cdf992e852..336cc7fc90 100644 --- a/tests/cli-storage-inspect.test.ts +++ b/tests/cli/cli-storage-inspect.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { handleStorageCommand } from "../src/cli/storage"; -import { handleInspectCommand, handleIntegrationCommand } from "../src/cli/inspect"; +import { handleStorageCommand } from "../../src/cli/storage"; +import { handleInspectCommand, handleIntegrationCommand } from "../../src/cli/inspect"; /** * wp7: the storage, inspect, and native-integration routes had no CLI caller at all. diff --git a/tests/cli-transport-honesty.test.ts b/tests/cli/cli-transport-honesty.test.ts similarity index 95% rename from tests/cli-transport-honesty.test.ts rename to tests/cli/cli-transport-honesty.test.ts index 9a12d2a9e5..a253381f4d 100644 --- a/tests/cli-transport-honesty.test.ts +++ b/tests/cli/cli-transport-honesty.test.ts @@ -1,11 +1,12 @@ import { describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { RuntimeApiError, runtimeRequest } from "../src/cli/runtime-api"; -import { apiError, apiJson, proxyUnreachable } from "../src/cli/account-api"; -import { assertNotAdminToken, assertServiceAuthEnvironment } from "../src/service"; -import { dataPlaneCredentialCollisionCheck } from "../src/cli/doctor"; -import type { AccountDeps } from "../src/cli/account-api"; +import { RuntimeApiError, runtimeRequest } from "../../src/cli/runtime-api"; +import { apiError, apiJson, proxyUnreachable } from "../../src/cli/account-api"; +import { assertNotAdminToken, assertServiceAuthEnvironment } from "../../src/service"; +import { dataPlaneCredentialCollisionCheck } from "../../src/cli/doctor"; +import type { AccountDeps } from "../../src/cli/account-api"; +import { repoPath } from "../helpers/repo-root"; /** * wp2 (#2696 #2697 #2698): the CLI must not lie about a failed management call. @@ -16,7 +17,7 @@ import type { AccountDeps } from "../src/cli/account-api"; * data-plane secret and fence the whole management API closed. */ -const DISPATCH_SOURCE = readFileSync(join(import.meta.dir, "..", "src", "cli", "dispatch.ts"), "utf8"); +const DISPATCH_SOURCE = readFileSync(repoPath("src", "cli", "dispatch.ts"), "utf8"); /** * Matches `await someHandler(...); return 0;` — the shape that silently discards a @@ -125,7 +126,7 @@ describe("#2698 the status mapping and transport cause are actually reachable", * assertions are about the CALL SITES rather than the helpers. */ const SOURCES = ["account.ts", "account-extended.ts", "account-main.ts"].map(name => - readFileSync(join(import.meta.dir, "..", "src", "cli", name), "utf8")); + readFileSync(repoPath("src", "cli", name), "utf8")); test("every apiError call site forwards the response status", () => { const bare: string[] = []; @@ -287,12 +288,12 @@ describe("#2696 a management token is refused as the data-plane secret", () => { }); test("handleStart asserts the token it is about to export", () => { - const source = readFileSync(join(import.meta.dir, "..", "src", "cli", "index.ts"), "utf8"); + const source = readFileSync(repoPath("src", "cli", "index.ts"), "utf8"); expect(source).toContain("assertNotAdminToken(present)"); }); test("familyFailure forwards the transport cause", () => { - const source = readFileSync(join(import.meta.dir, "..", "src", "cli", "account-extended.ts"), "utf8"); + const source = readFileSync(repoPath("src", "cli", "account-extended.ts"), "utf8"); expect(source).toMatch(/networkDown\) return proxyUnreachable\(result\.transportError\)/); }); }); diff --git a/tests/cli-usage-report.test.ts b/tests/cli/cli-usage-report.test.ts similarity index 98% rename from tests/cli-usage-report.test.ts rename to tests/cli/cli-usage-report.test.ts index d446533f0f..b20112ee12 100644 --- a/tests/cli-usage-report.test.ts +++ b/tests/cli/cli-usage-report.test.ts @@ -8,8 +8,8 @@ */ import { describe, expect, spyOn, test } from "bun:test"; -import { handleObserveCommand } from "../src/cli/observe"; -import { formatUsageReport } from "../src/cli/usage-report"; +import { handleObserveCommand } from "../../src/cli/observe"; +import { formatUsageReport } from "../../src/cli/usage-report"; function payload(overrides: Record = {}): Record { return { diff --git a/tests/cli-version-skew.test.ts b/tests/cli/cli-version-skew.test.ts similarity index 95% rename from tests/cli-version-skew.test.ts rename to tests/cli/cli-version-skew.test.ts index 05594a1498..6e45f83c28 100644 --- a/tests/cli-version-skew.test.ts +++ b/tests/cli/cli-version-skew.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { computeVersionSkew } from "../src/cli/version-skew"; -import { packageVersion } from "../src/cli/help"; +import { computeVersionSkew } from "../../src/cli/version-skew"; +import { packageVersion } from "../../src/cli/help"; /** * #2701: an older `ocx` earlier on PATH than the running proxy described a different diff --git a/tests/ensure-desired-integrations-race.test.ts b/tests/cli/ensure-desired-integrations-race.test.ts similarity index 95% rename from tests/ensure-desired-integrations-race.test.ts rename to tests/cli/ensure-desired-integrations-race.test.ts index e29c7bd1b8..09755c22f1 100644 --- a/tests/ensure-desired-integrations-race.test.ts +++ b/tests/cli/ensure-desired-integrations-race.test.ts @@ -2,10 +2,10 @@ import { describe, expect, test } from "bun:test"; import { reconcileEnsureDesiredIntegrations, type EnsureDesiredIntegrationsDeps, -} from "../src/cli/ensure-desired-integrations"; -import type { OcxConfig } from "../src/types"; -import type { GrokInjectResult } from "../src/grok/inject"; -import type { Desktop3pRemovalResult } from "../src/claude/desktop-3p"; +} from "../../src/cli/ensure-desired-integrations"; +import type { OcxConfig } from "../../src/types"; +import type { GrokInjectResult } from "../../src/grok/inject"; +import type { Desktop3pRemovalResult } from "../../src/claude/desktop-3p"; function config(overrides: { grok?: boolean; diff --git a/tests/interactive-confirm.test.ts b/tests/cli/interactive-confirm.test.ts similarity index 98% rename from tests/interactive-confirm.test.ts rename to tests/cli/interactive-confirm.test.ts index 4b551f899f..21e941ea04 100644 --- a/tests/interactive-confirm.test.ts +++ b/tests/cli/interactive-confirm.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; import { PassThrough } from "node:stream"; -import { interactiveConfirm } from "../src/cli/interactive-confirm"; +import { interactiveConfirm } from "../../src/cli/interactive-confirm"; /** * A fake TTY pair: the input side supports raw mode (so the selector takes the diff --git a/tests/ocx-launcher-runtime.test.ts b/tests/cli/ocx-launcher-runtime.test.ts similarity index 98% rename from tests/ocx-launcher-runtime.test.ts rename to tests/cli/ocx-launcher-runtime.test.ts index 7c295dcb29..b6064d2284 100644 --- a/tests/ocx-launcher-runtime.test.ts +++ b/tests/cli/ocx-launcher-runtime.test.ts @@ -4,10 +4,11 @@ import { chmodSync, copyFileSync, mkdirSync, mkdtempSync, realpathSync, rmSync, import { createServer } from "node:net"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; -import { bundledBunPath } from "../src/lib/bun-runtime"; -import { killProxy } from "../src/lib/process-control"; +import { bundledBunPath } from "../../src/lib/bun-runtime"; +import { killProxy } from "../../src/lib/process-control"; +import { repoPath } from "../helpers/repo-root"; -const BIN_OCX = join(import.meta.dir, "..", "bin", "ocx.mjs"); +const BIN_OCX = repoPath("bin", "ocx.mjs"); const nodeAvailable = spawnSync("node", ["--version"], { stdio: "ignore", windowsHide: true, diff --git a/tests/ocx-launcher-source.test.ts b/tests/cli/ocx-launcher-source.test.ts similarity index 97% rename from tests/ocx-launcher-source.test.ts rename to tests/cli/ocx-launcher-source.test.ts index d44855b2da..169646aeba 100644 --- a/tests/ocx-launcher-source.test.ts +++ b/tests/cli/ocx-launcher-source.test.ts @@ -1,15 +1,16 @@ import { describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; +import { repoPath } from "../helpers/repo-root"; /** * bin/ocx.mjs is the Node bin launcher — it executes top-level logic on import, so it * cannot be imported by tests. Guard its Windows-critical invariants at the source level. */ -const source = readFileSync(join(import.meta.dir, "..", "bin", "ocx.mjs"), "utf8"); -const runtimeSource = readFileSync(join(import.meta.dir, "..", "src", "lib", "bun-runtime.ts"), "utf8"); +const source = readFileSync(repoPath("bin", "ocx.mjs"), "utf8"); +const runtimeSource = readFileSync(repoPath("src", "lib", "bun-runtime.ts"), "utf8"); const validatorSource = readFileSync( - join(import.meta.dir, "..", "src", "lib", "bun-binary-validator.mjs"), + repoPath("src", "lib", "bun-binary-validator.mjs"), "utf8", ); diff --git a/tests/ocx-run.test.ts b/tests/cli/ocx-run.test.ts similarity index 88% rename from tests/ocx-run.test.ts rename to tests/cli/ocx-run.test.ts index 388167801e..dea16ef3e1 100644 --- a/tests/ocx-run.test.ts +++ b/tests/cli/ocx-run.test.ts @@ -8,9 +8,10 @@ import { import { tmpdir } from "node:os"; import { join } from "node:path"; import { fileURLToPath } from "node:url"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; -const repoRoot = fileURLToPath(new URL("../", import.meta.url)); +const repoRoot = resolveRepoRoot(); const runner = join(repoRoot, "scripts", "ocx-run"); describe("ocx-run", () => { diff --git a/tests/restore-completes-shared-teardown.test.ts b/tests/cli/restore-completes-shared-teardown.test.ts similarity index 96% rename from tests/restore-completes-shared-teardown.test.ts rename to tests/cli/restore-completes-shared-teardown.test.ts index ff5a84be11..ac85ce158c 100644 --- a/tests/restore-completes-shared-teardown.test.ts +++ b/tests/cli/restore-completes-shared-teardown.test.ts @@ -2,8 +2,8 @@ import { afterEach, beforeEach, expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { dispatchCommand, type CliDispatchDeps } from "../src/cli/dispatch"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { dispatchCommand, type CliDispatchDeps } from "../../src/cli/dispatch"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * `ocx restore` must finish the WHOLE shared teardown, including when Codex is already @@ -50,7 +50,7 @@ async function seedOffConfig(): Promise { // Codex already OFF in this home, so the desired-state write reports "unchanged" and the // residue classifier reports clean — the no-op path under test. Written through the real // saver so the file satisfies the same schema the CLI validates. - const { loadConfig, saveConfig } = await import("../src/config"); + const { loadConfig, saveConfig } = await import("../../src/config"); const config = loadConfig(); saveConfig({ ...config, clientIntegrations: { ...(config.clientIntegrations ?? {}), codex: false } }); } @@ -58,7 +58,7 @@ async function seedOffConfig(): Promise { async function seedOnConfig(): Promise { // Codex ON, so the desired-state write is a real change and restore takes its ordinary // forward path rather than the already-clean branch. - const { loadConfig, saveConfig } = await import("../src/config"); + const { loadConfig, saveConfig } = await import("../../src/config"); const config = loadConfig(); const integrations = { ...(config.clientIntegrations ?? {}) }; delete integrations.codex; diff --git a/tests/route-explainability.test.ts b/tests/cli/route-explainability.test.ts similarity index 94% rename from tests/route-explainability.test.ts rename to tests/cli/route-explainability.test.ts index 10c4c0316c..0a583692f5 100644 --- a/tests/route-explainability.test.ts +++ b/tests/cli/route-explainability.test.ts @@ -2,13 +2,13 @@ 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 { handleManagementAPI } from "../src/server/management-api"; -import { ManagementRequest } from "./helpers/management-auth"; -import { appendUsageEntry, resetUsageReadCacheForTests, type PersistedUsageEntry } from "../src/usage/log"; -import { closeRequestHistoryIndex } from "../src/routing/history/indexer"; -import { candidateCapabilityEvidence } from "../src/routing/capability"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { ManagementRequest } from "../helpers/management-auth"; +import { appendUsageEntry, resetUsageReadCacheForTests, type PersistedUsageEntry } from "../../src/usage/log"; +import { closeRequestHistoryIndex } from "../../src/routing/history/indexer"; +import { candidateCapabilityEvidence } from "../../src/routing/capability"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testDir = ""; let previousHome: string | undefined; @@ -234,7 +234,7 @@ describe("route explainability (RI-09)", () => { }); test("CLI logs explain encodes request ids and supports --json", async () => { - const { handleObserveCommand } = await import("../src/cli/observe"); + const { handleObserveCommand } = await import("../../src/cli/observe"); const calls: Array<{ path: string; init?: RequestInit }> = []; const payload = { requestId: "id with spaces", @@ -257,7 +257,7 @@ describe("route explainability (RI-09)", () => { }); test("CLI logs explain rejects missing request ids", async () => { - const { handleObserveCommand } = await import("../src/cli/observe"); + const { handleObserveCommand } = await import("../../src/cli/observe"); const code = await handleObserveCommand(["logs", "explain"], { baseUrl: "http://cli.test", fetchImpl: async () => { @@ -268,7 +268,7 @@ describe("route explainability (RI-09)", () => { }); test("CLI route policy evaluate posts dry-run evidence and rejects option-like ids", async () => { - const { handleRoutePolicyCommand } = await import("../src/cli/route-policy"); + const { handleRoutePolicyCommand } = await import("../../src/cli/route-policy"); const calls: Array<{ path: string; init?: RequestInit }> = []; const ok = await handleRoutePolicyCommand(["evaluate", "fast", "--tools", "--json"], { baseUrl: "http://cli.test", diff --git a/tests/star-deferral.test.ts b/tests/cli/star-deferral.test.ts similarity index 98% rename from tests/star-deferral.test.ts rename to tests/cli/star-deferral.test.ts index 3561d45a93..8ab158ed46 100644 --- a/tests/star-deferral.test.ts +++ b/tests/cli/star-deferral.test.ts @@ -3,8 +3,8 @@ import { mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { existsSync } from "node:fs"; -import { isDeferralCurrent, maybeShowStarPrompt, setStarPromptDepsForTests } from "../src/cli/star-prompt"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { isDeferralCurrent, maybeShowStarPrompt, setStarPromptDepsForTests } from "../../src/cli/star-prompt"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const NOW = Date.parse("2026-08-02T00:00:00.000Z"); const DAY = 24 * 60 * 60 * 1000; diff --git a/tests/system-restart-client.test.ts b/tests/cli/system-restart-client.test.ts similarity index 97% rename from tests/system-restart-client.test.ts rename to tests/cli/system-restart-client.test.ts index 3eb9c7e3b4..f7c8c7657a 100644 --- a/tests/system-restart-client.test.ts +++ b/tests/cli/system-restart-client.test.ts @@ -4,7 +4,7 @@ import { LOCAL_ATTESTATION_PROOF_HEADER, createLocalAttestationProof, createLocalAttestationSecret, -} from "../src/lib/local-management-attestation"; +} from "../../src/lib/local-management-attestation"; import { SYSTEM_RESTART_CAPABILITY_HEADER, SYSTEM_RESTART_CAPABILITY_VERSION, @@ -13,9 +13,9 @@ import { SYSTEM_RESTART_NONCE_HEADER, SYSTEM_RESTART_PATH, verifySystemRestartCapability, -} from "../src/lib/system-restart-contract"; -import { requestBoundSystemRestart } from "../src/cli/system-restart-client"; -import type { LiveProxy } from "../src/server/proxy-liveness"; +} from "../../src/lib/system-restart-contract"; +import { requestBoundSystemRestart } from "../../src/cli/system-restart-client"; +import type { LiveProxy } from "../../src/server/proxy-liveness"; const target: LiveProxy = { pid: 4242, diff --git a/tests/uninstall.test.ts b/tests/cli/uninstall.test.ts similarity index 97% rename from tests/uninstall.test.ts rename to tests/cli/uninstall.test.ts index a0d233a1f4..18b5f3e951 100644 --- a/tests/uninstall.test.ts +++ b/tests/cli/uninstall.test.ts @@ -2,9 +2,11 @@ import { afterEach, describe, expect, test } from "bun:test"; import { setUninstallServiceHooksForTests, uninstallServiceIfInstalled, -} from "../src/service"; +} from "../../src/service"; +import { pathToFileURL } from "node:url"; +import { repoRoot } from "../helpers/repo-root"; -const root = new URL("../", import.meta.url); +const root = pathToFileURL(repoRoot() + "/"); async function readText(path: string): Promise { return await Bun.file(new URL(path, root)).text(); @@ -103,7 +105,7 @@ describe("full uninstall command", () => { }); describe("uninstall gates shared teardown on a proven service stop", () => { test("the authorization rule, exercised for every failure permutation", async () => { - const { sharedTeardownAuthorized } = await import("../src/cli/uninstall-plan"); + const { sharedTeardownAuthorized } = await import("../../src/cli/uninstall-plan"); const base = { serviceStop: "stopped" as const, proxyProvenDown: true, @@ -131,7 +133,7 @@ describe("uninstall gates shared teardown on a proven service stop", () => { }); test("a removal failure is distinguishable from nothing being installed", async () => { - const { setUninstallServiceHooksForTests, uninstallServiceDetailed } = await import("../src/service"); + const { setUninstallServiceHooksForTests, uninstallServiceDetailed } = await import("../../src/service"); // Windows is the platform whose hooks are injectable; the darwin/linux catch arms that // returned the same false as absence are now typed outcomes rather than a boolean. setUninstallServiceHooksForTests({ @@ -214,7 +216,7 @@ describe("uninstall gates shared teardown on a proven service stop", () => { }); }); test("proof covers every distinct endpoint, not just the preferred one", async () => { - const { endpointsToProve, everyEndpointProvenDown } = await import("../src/cli/uninstall-plan"); + const { endpointsToProve, everyEndpointProvenDown } = await import("../../src/cli/uninstall-plan"); // A stale runtime record pointing at a closed port, and the live proxy on the // configured one. Probing only the runtime candidate reports "dead" for a port nobody diff --git a/tests/clients/desktop-3p.test.ts b/tests/clients/desktop-3p.test.ts index 6b1857ff9f..4fae0f4253 100644 --- a/tests/clients/desktop-3p.test.ts +++ b/tests/clients/desktop-3p.test.ts @@ -23,7 +23,7 @@ describe("Claude Desktop 3P models", () => { test("resolves the actual cross-platform Claude Desktop config library (#539)", () => { // Claude Desktop appends "-3p" to its userData root (app.asar `GE()`), so the // suffix-less path is one Desktop never reads. Branch-by-branch coverage lives in - // tests/claude-desktop-config-path.test.ts; this pins the public entry point. + // tests/claude-integration/claude-desktop-config-path.test.ts; this pins the public entry point. expect(resolveDesktop3pConfigLibraryPath({ env: { OPENCODEX_CLAUDE_DESKTOP_CONFIG_DIR: " /custom/library " }, platform: "darwin", diff --git a/tests/codex-model-entitlements.test.ts b/tests/codex-model-entitlements.test.ts index 1ecd6820b9..9ca38fb9a5 100644 --- a/tests/codex-model-entitlements.test.ts +++ b/tests/codex-model-entitlements.test.ts @@ -1084,7 +1084,7 @@ describe("entitlement client version (#2886)", () => { // been resolved, no persisted runtime either — yet it is the path that publishes // account-confirmed native rows. An earlier revision of this fix skipped discovery in // that state, which suppressed exactly the rows the fix exists to restore - // (tests/claude-models-discovery.test.ts and tests/codex-catalog-sync-hardening.test.ts + // (tests/claude-integration/claude-models-discovery.test.ts and tests/codex-catalog-sync-hardening.test.ts // both failed on it). The last tier therefore has to be a real, answerable version. expect(resolveCodexEntitlementClientVersion(null, () => null)) .toBe(GATED_MODEL_CLIENT_VERSION_FLOOR); diff --git a/tests/grok-lifecycle.test.ts b/tests/grok-lifecycle.test.ts index a30e716765..7166a99dfc 100644 --- a/tests/grok-lifecycle.test.ts +++ b/tests/grok-lifecycle.test.ts @@ -20,7 +20,7 @@ function sliceFn(source: string, start: string, end: string): string { // `src/cli/index.ts` runs its command switch on import, so the handlers cannot be called from a // test. Wiring assertions therefore read the source — the house pattern established by -// tests/service/stale-state-purge.test.ts and tests/uninstall.test.ts. +// tests/service/stale-state-purge.test.ts and tests/cli/uninstall.test.ts. describe("Grok fence lifecycle wiring", () => { test("handleStart syncs the Grok fence outside the Desktop-3P try", () => { const startFn = sliceFn(CLI_SOURCE, "async function handleStart(", "async function handleEnsure("); diff --git a/tests/adapter-event-oauth-failover.test.ts b/tests/oauth/adapter-event-oauth-failover.test.ts similarity index 94% rename from tests/adapter-event-oauth-failover.test.ts rename to tests/oauth/adapter-event-oauth-failover.test.ts index bb3b4c37ea..8d5b4dc17d 100644 --- a/tests/adapter-event-oauth-failover.test.ts +++ b/tests/oauth/adapter-event-oauth-failover.test.ts @@ -2,13 +2,13 @@ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import type { ProviderAdapter } from "../src/adapters/base"; -import { clearGenericFailoverHealth } from "../src/oauth/generic-account-failover"; -import { saveCredential } from "../src/oauth/store"; -import type { AdapterEvent, OcxConfig, OcxProviderConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import type { ProviderAdapter } from "../../src/adapters/base"; +import { clearGenericFailoverHealth } from "../../src/oauth/generic-account-failover"; +import { saveCredential } from "../../src/oauth/store"; +import type { AdapterEvent, OcxConfig, OcxProviderConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const actualResolver = await import("../src/server/adapter-resolve"); +const actualResolver = await import("../../src/server/adapter-resolve"); const actualResolveAdapter = actualResolver.resolveAdapter; let attempts: AdapterEvent[][] = []; let attemptKeys: string[] = []; @@ -31,7 +31,7 @@ function fixtureAdapter(provider: OcxProviderConfig): ProviderAdapter { }; } -mock.module("../src/server/adapter-resolve", () => ({ +mock.module("../../src/server/adapter-resolve", () => ({ ...actualResolver, resolveAdapter(provider: OcxProviderConfig, cacheRetention?: "none" | "short" | "long") { if (provider.adapter === "cursor") return fixtureAdapter(provider); @@ -39,7 +39,7 @@ mock.module("../src/server/adapter-resolve", () => ({ }, })); -const { handleResponses } = await import("../src/server/responses"); +const { handleResponses } = await import("../../src/server/responses"); const originalHome = process.env.OPENCODEX_HOME; let home = ""; diff --git a/tests/chatgpt-device-auth.test.ts b/tests/oauth/chatgpt-device-auth.test.ts similarity index 97% rename from tests/chatgpt-device-auth.test.ts rename to tests/oauth/chatgpt-device-auth.test.ts index 5b7dbe7817..533f4da015 100644 --- a/tests/chatgpt-device-auth.test.ts +++ b/tests/oauth/chatgpt-device-auth.test.ts @@ -1,14 +1,14 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { loginChatGPT } from "../src/oauth/chatgpt"; -import { loginChatGPTDevice } from "../src/oauth/chatgpt-device"; -import type { OAuthController } from "../src/oauth/types"; +import { loginChatGPT } from "../../src/oauth/chatgpt"; +import { loginChatGPTDevice } from "../../src/oauth/chatgpt-device"; +import type { OAuthController } from "../../src/oauth/types"; /** * The OpenAI deviceauth grant (#3366): the login path for a hub with no local * browser and no listener on localhost:1455. * * Every test stubs `globalThis.fetch` and routes by URL, the same style as - * `tests/oauth-device-code-contract.test.ts`. + * `tests/oauth/oauth-device-code-contract.test.ts`. */ const realFetch = globalThis.fetch; diff --git a/tests/chatgpt-oauth.test.ts b/tests/oauth/chatgpt-oauth.test.ts similarity index 99% rename from tests/chatgpt-oauth.test.ts rename to tests/oauth/chatgpt-oauth.test.ts index 161baca024..24213b7e44 100644 --- a/tests/chatgpt-oauth.test.ts +++ b/tests/oauth/chatgpt-oauth.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { decodeJwtPayload, extractAccountId, extractEmail } from "../src/oauth/chatgpt"; +import { decodeJwtPayload, extractAccountId, extractEmail } from "../../src/oauth/chatgpt"; function fakeJwt(payload: Record): string { const header = Buffer.from(JSON.stringify({ alg: "none" })).toString("base64url"); diff --git a/tests/chatgpt-token-expiry.test.ts b/tests/oauth/chatgpt-token-expiry.test.ts similarity index 97% rename from tests/chatgpt-token-expiry.test.ts rename to tests/oauth/chatgpt-token-expiry.test.ts index 7b0460e1f9..9565ebce02 100644 --- a/tests/chatgpt-token-expiry.test.ts +++ b/tests/oauth/chatgpt-token-expiry.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { refreshChatGPTToken } from "../src/oauth/chatgpt"; +import { refreshChatGPTToken } from "../../src/oauth/chatgpt"; const originalFetch = globalThis.fetch; afterEach(() => { globalThis.fetch = originalFetch; }); diff --git a/tests/generic-oauth-failover.test.ts b/tests/oauth/generic-oauth-failover.test.ts similarity index 97% rename from tests/generic-oauth-failover.test.ts rename to tests/oauth/generic-oauth-failover.test.ts index f4028247d1..0bb219d07e 100644 --- a/tests/generic-oauth-failover.test.ts +++ b/tests/oauth/generic-oauth-failover.test.ts @@ -11,13 +11,14 @@ import { isGenericOAuthFailoverEnabled, preferredInitialAccount, rotateGenericOAuthAccountOn429, -} from "../src/oauth/generic-account-failover"; -import { getAccountSet, markAccountNeedsReauth, saveCredential } from "../src/oauth/store"; -import { clearAccountQuotaCache, setCachedProviderAccountQuotaForTests } from "../src/providers/quota"; -import { resolveCopilotApiBaseUrl } from "../src/oauth/github-copilot"; -import { resolveProviderTransport } from "../src/providers/xai-transport"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/oauth/generic-account-failover"; +import { getAccountSet, markAccountNeedsReauth, saveCredential } from "../../src/oauth/store"; +import { clearAccountQuotaCache, setCachedProviderAccountQuotaForTests } from "../../src/providers/quota"; +import { resolveCopilotApiBaseUrl } from "../../src/oauth/github-copilot"; +import { resolveProviderTransport } from "../../src/providers/xai-transport"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath } from "../helpers/repo-root"; const originalHome = process.env.OPENCODEX_HOME; let home: string; @@ -225,7 +226,7 @@ describe("#2568 generic OAuth account failover", () => { */ describe("sidecar on429 wiring", () => { const coreSource = readFileSync( - join(import.meta.dir, "..", "src", "server", "responses", "core.ts"), + repoPath("src", "server", "responses", "core.ts"), "utf8", ); diff --git a/tests/key-login-live-update.test.ts b/tests/oauth/key-login-live-update.test.ts similarity index 87% rename from tests/key-login-live-update.test.ts rename to tests/oauth/key-login-live-update.test.ts index a240d9f2af..837f936732 100644 --- a/tests/key-login-live-update.test.ts +++ b/tests/oauth/key-login-live-update.test.ts @@ -2,16 +2,16 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync, readFileSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { loadConfig, saveConfig, writePid, writeRuntimePort } from "../src/config"; -import { commitKeyLoginProvider, providerConfigFromKeyLoginProvider } from "../src/oauth/login-cli"; -import { KEY_LOGIN_PROVIDERS } from "../src/oauth/key-providers"; -import { startServer } from "../src/server"; -import { createLocalAttestationSecret } from "../src/lib/local-management-attestation"; -import type { OcxConfig } from "../src/types"; -import { refreshUserCostOverlays } from "../src/usage/user-cost-overlays"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { managementFetch as fetch } from "./helpers/management-auth"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { loadConfig, saveConfig, writePid, writeRuntimePort } from "../../src/config"; +import { commitKeyLoginProvider, providerConfigFromKeyLoginProvider } from "../../src/oauth/login-cli"; +import { KEY_LOGIN_PROVIDERS } from "../../src/oauth/key-providers"; +import { startServer } from "../../src/server"; +import { createLocalAttestationSecret } from "../../src/lib/local-management-attestation"; +import type { OcxConfig } from "../../src/types"; +import { refreshUserCostOverlays } from "../../src/usage/user-cost-overlays"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { managementFetch as fetch } from "../helpers/management-auth"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * Regression: `ocx login ` used to POST the unmerged preset row diff --git a/tests/key-login-preserves-model-costs.test.ts b/tests/oauth/key-login-preserves-model-costs.test.ts similarity index 93% rename from tests/key-login-preserves-model-costs.test.ts rename to tests/oauth/key-login-preserves-model-costs.test.ts index d653faa99b..8fa9c59023 100644 --- a/tests/key-login-preserves-model-costs.test.ts +++ b/tests/oauth/key-login-preserves-model-costs.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { mergeKeyLoginProviderRow, providerConfigFromKeyLoginProvider } from "../src/oauth/login-cli"; -import { KEY_LOGIN_PROVIDERS } from "../src/oauth/key-providers"; -import type { OcxProviderConfig } from "../src/types"; +import { mergeKeyLoginProviderRow, providerConfigFromKeyLoginProvider } from "../../src/oauth/login-cli"; +import { KEY_LOGIN_PROVIDERS } from "../../src/oauth/key-providers"; +import type { OcxProviderConfig } from "../../src/types"; describe("key login preserves user-configured price overlays", () => { test("rotating the API key carries modelCosts onto the replacement row", () => { diff --git a/tests/local-token-detect.test.ts b/tests/oauth/local-token-detect.test.ts similarity index 97% rename from tests/local-token-detect.test.ts rename to tests/oauth/local-token-detect.test.ts index 4d669d63f7..c6a92f620b 100644 --- a/tests/local-token-detect.test.ts +++ b/tests/oauth/local-token-detect.test.ts @@ -7,8 +7,8 @@ import { parseClaudeOauthPayload, readClaudeCredentialsFile, shouldAdoptGrokGeneration, -} from "../src/oauth/local-token-detect"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/oauth/local-token-detect"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let tmp: string; let prevConfigDir: string | undefined; diff --git a/tests/oauth-account-attribution.test.ts b/tests/oauth/oauth-account-attribution.test.ts similarity index 95% rename from tests/oauth-account-attribution.test.ts rename to tests/oauth/oauth-account-attribution.test.ts index 8189d25d3f..317108fd86 100644 --- a/tests/oauth-account-attribution.test.ts +++ b/tests/oauth/oauth-account-attribution.test.ts @@ -2,17 +2,17 @@ import { afterEach, describe, expect, test } from "bun:test"; import { mkdtempSync, readFileSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { oauthAccountLogLabel, ACCOUNT_LOG_LABEL_RE } from "../src/codex/account-label"; -import { getAccountSet, saveCredential } from "../src/oauth/store"; -import { clearGenericFailoverHealth } from "../src/oauth/generic-account-failover"; -import { stampOAuthAccountLabel } from "../src/providers/label"; -import { isCodexUsageAccountLogLabel, isCodexPoolAccountLogLabel } from "../src/usage/log"; -import type { PersistedUsageEntry } from "../src/usage/log"; -import { summarizeUsage } from "../src/usage/summary"; -import type { RequestLogContext } from "../src/server/request-log"; -import { handleResponses } from "../src/server/responses"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { oauthAccountLogLabel, ACCOUNT_LOG_LABEL_RE } from "../../src/codex/account-label"; +import { getAccountSet, saveCredential } from "../../src/oauth/store"; +import { clearGenericFailoverHealth } from "../../src/oauth/generic-account-failover"; +import { stampOAuthAccountLabel } from "../../src/providers/label"; +import { isCodexUsageAccountLogLabel, isCodexPoolAccountLogLabel } from "../../src/usage/log"; +import type { PersistedUsageEntry } from "../../src/usage/log"; +import { summarizeUsage } from "../../src/usage/summary"; +import type { RequestLogContext } from "../../src/server/request-log"; +import { handleResponses } from "../../src/server/responses"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * #2699: usage could not be attributed per account for non-Codex OAuth providers. The label type diff --git a/tests/oauth-account-id-collision.test.ts b/tests/oauth/oauth-account-id-collision.test.ts similarity index 96% rename from tests/oauth-account-id-collision.test.ts rename to tests/oauth/oauth-account-id-collision.test.ts index 3972268aa7..2e57b467ea 100644 --- a/tests/oauth-account-id-collision.test.ts +++ b/tests/oauth/oauth-account-id-collision.test.ts @@ -4,13 +4,13 @@ import { join } from "node:path"; import { resetHardenedStateForTests, setIcaclsRunnerForTests, -} from "../src/lib/windows-secret-acl"; +} from "../../src/lib/windows-secret-acl"; import { getAccountSet, getCredential, saveCredential, -} from "../src/oauth/store"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/oauth/store"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-oauth-account-id-collision-test"); let previousOpencodexHome: string | undefined; diff --git a/tests/oauth-accounts-api.test.ts b/tests/oauth/oauth-accounts-api.test.ts similarity index 97% rename from tests/oauth-accounts-api.test.ts rename to tests/oauth/oauth-accounts-api.test.ts index 504d683754..cbeb165e59 100644 --- a/tests/oauth-accounts-api.test.ts +++ b/tests/oauth/oauth-accounts-api.test.ts @@ -1,19 +1,19 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; -import { managementFetch as fetch } from "./helpers/management-auth"; +import { managementFetch as fetch } from "../helpers/management-auth"; import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; -import { startServer } from "../src/server"; -import { gatherRoutedModels as gatherRoutedModelsDirect } from "../src/codex/catalog"; -import { clearModelCache, getStaleCached, setCached } from "../src/codex/model-cache"; -import type { OcxConfig } from "../src/types"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import { getAccountSet } from "../src/oauth/store"; -import { ACCOUNT_IMPORT_DEADLINE_MS, ACCOUNT_IMPORT_MAX_BYTES, ACCOUNT_IMPORT_MAX_REQUEST_BYTES } from "../src/oauth/account-import/types"; -import { handleOauthAccountRoutes } from "../src/server/management/oauth-account-routes"; +import { saveConfig } from "../../src/config"; +import { startServer } from "../../src/server"; +import { gatherRoutedModels as gatherRoutedModelsDirect } from "../../src/codex/catalog"; +import { clearModelCache, getStaleCached, setCached } from "../../src/codex/model-cache"; +import type { OcxConfig } from "../../src/types"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { getAccountSet } from "../../src/oauth/store"; +import { ACCOUNT_IMPORT_DEADLINE_MS, ACCOUNT_IMPORT_MAX_BYTES, ACCOUNT_IMPORT_MAX_REQUEST_BYTES } from "../../src/oauth/account-import/types"; +import { handleOauthAccountRoutes } from "../../src/server/management/oauth-account-routes"; let testDir = ""; let previousHome: string | undefined; diff --git a/tests/oauth-callback-binds.test.ts b/tests/oauth/oauth-callback-binds.test.ts similarity index 87% rename from tests/oauth-callback-binds.test.ts rename to tests/oauth/oauth-callback-binds.test.ts index 33f275f589..d74191cc1b 100644 --- a/tests/oauth-callback-binds.test.ts +++ b/tests/oauth/oauth-callback-binds.test.ts @@ -1,7 +1,8 @@ import { describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { loopbackBindHostnames } from "../src/oauth/callback-server"; +import { loopbackBindHostnames } from "../../src/oauth/callback-server"; +import { repoPath } from "../helpers/repo-root"; describe("loopbackBindHostnames", () => { test("localhost redirect over IPv4 bind also binds ::1 (Windows resolves localhost to ::1 first)", () => { @@ -21,7 +22,7 @@ describe("loopbackBindHostnames", () => { test("an occupied IPv6 loopback abandons the whole port instead of leaving ::1 to a foreign listener", () => { // localhost may resolve to ::1 first — silently serving IPv4-only while another // process holds ::1: would hand the OAuth callback (auth code) to that process. - const source = readFileSync(join(import.meta.dir, "..", "src", "oauth", "callback-server.ts"), "utf8"); + const source = readFileSync(repoPath("src", "oauth", "callback-server.ts"), "utf8"); expect(source).toContain('import { isAddrInUse } from "../server/ports";'); const createServers = source.slice(source.indexOf("#createServers(port: number"), source.indexOf("#handleCallback(req: Request")); expect(createServers).toContain("if (isAddrInUse(err))"); diff --git a/tests/oauth-callback-server.test.ts b/tests/oauth/oauth-callback-server.test.ts similarity index 95% rename from tests/oauth-callback-server.test.ts rename to tests/oauth/oauth-callback-server.test.ts index bd246d01cc..a327e1df0d 100644 --- a/tests/oauth-callback-server.test.ts +++ b/tests/oauth/oauth-callback-server.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { OAuthCallbackFlow } from "../src/oauth/callback-server"; -import type { OAuthController, OAuthCredentials } from "../src/oauth/types"; +import { OAuthCallbackFlow } from "../../src/oauth/callback-server"; +import type { OAuthController, OAuthCredentials } from "../../src/oauth/types"; class TestFlow extends OAuthCallbackFlow { async generateAuthUrl(): Promise<{ url: string }> { diff --git a/tests/oauth-device-code-contract.test.ts b/tests/oauth/oauth-device-code-contract.test.ts similarity index 95% rename from tests/oauth-device-code-contract.test.ts rename to tests/oauth/oauth-device-code-contract.test.ts index 522a1d0e27..6ed938d1f7 100644 --- a/tests/oauth-device-code-contract.test.ts +++ b/tests/oauth/oauth-device-code-contract.test.ts @@ -1,6 +1,6 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { loginKimi } from "../src/oauth/kimi"; -import type { OAuthController } from "../src/oauth/types"; +import { loginKimi } from "../../src/oauth/kimi"; +import type { OAuthController } from "../../src/oauth/types"; /** * Every device-flow provider must report the human-typed user code in the diff --git a/tests/oauth-health.test.ts b/tests/oauth/oauth-health.test.ts similarity index 96% rename from tests/oauth-health.test.ts rename to tests/oauth/oauth-health.test.ts index 1342151ded..1f04fbc996 100644 --- a/tests/oauth-health.test.ts +++ b/tests/oauth/oauth-health.test.ts @@ -8,20 +8,20 @@ import { collectOAuthHealthEntries, collectOAuthHealthEntriesForCli, projectOAuthAccountHealth, -} from "../src/oauth/health"; -import { getAccountSet, markAccountNeedsReauth, saveCredential } from "../src/oauth/store"; +} from "../../src/oauth/health"; +import { getAccountSet, markAccountNeedsReauth, saveCredential } from "../../src/oauth/store"; import { clearAccountNeedsReauth, markAccountNeedsReauth as markCodexAccountNeedsReauth, -} from "../src/codex/account-runtime-state"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/main-account"; +} from "../../src/codex/account-runtime-state"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/main-account"; import { clearCodexUpstreamHealth, getCodexAccountHealthSnapshot, recordCodexUpstreamOutcome, -} from "../src/codex/routing"; -import type { OcxConfig } from "../src/types"; -import { formatOAuthHealthForStatus } from "../src/cli/status-oauth"; +} from "../../src/codex/routing"; +import type { OcxConfig } from "../../src/types"; +import { formatOAuthHealthForStatus } from "../../src/cli/status-oauth"; import { LOCAL_MANAGEMENT_CAPABILITY_HEADER, LOCAL_MANAGEMENT_CAPABILITY_EXPIRES_AT_HEADER, @@ -29,8 +29,8 @@ import { LOCAL_MANAGEMENT_NONCE_HEADER, LOCAL_MANAGEMENT_READ_PATHS, verifyLocalManagementReadCapability, -} from "../src/lib/local-management-capability"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/lib/local-management-capability"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const origHome = process.env.HOME; const origOcxHome = process.env.OPENCODEX_HOME; diff --git a/tests/oauth-log.test.ts b/tests/oauth/oauth-log.test.ts similarity index 98% rename from tests/oauth-log.test.ts rename to tests/oauth/oauth-log.test.ts index 136c803cb8..74e22db432 100644 --- a/tests/oauth-log.test.ts +++ b/tests/oauth/oauth-log.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { logOAuthEvent } from "../src/oauth/log"; +import { logOAuthEvent } from "../../src/oauth/log"; describe("logOAuthEvent", () => { test("emits redacted account and never prints a token-looking field value", () => { diff --git a/tests/oauth-login-cli-live-update.test.ts b/tests/oauth/oauth-login-cli-live-update.test.ts similarity index 94% rename from tests/oauth-login-cli-live-update.test.ts rename to tests/oauth/oauth-login-cli-live-update.test.ts index 38d8a08da0..f205ffdef6 100644 --- a/tests/oauth-login-cli-live-update.test.ts +++ b/tests/oauth/oauth-login-cli-live-update.test.ts @@ -1,20 +1,20 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; -import { managementFetch as fetch } from "./helpers/management-auth"; +import { managementFetch as fetch } from "../helpers/management-auth"; import { mkdtempSync, readFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { loadConfig, saveConfig, writePid, writeRuntimePort } from "../src/config"; -import { upsertOAuthProvider } from "../src/oauth"; +import { loadConfig, saveConfig, writePid, writeRuntimePort } from "../../src/config"; +import { upsertOAuthProvider } from "../../src/oauth"; import { commitKeyLoginProvider, notifyRunningProxy, notifyRunningProxyAfterOAuthLogin, -} from "../src/oauth/login-cli"; -import { startServer } from "../src/server"; -import { createLocalAttestationSecret } from "../src/lib/local-management-attestation"; -import type { OcxConfig } from "../src/types"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/oauth/login-cli"; +import { startServer } from "../../src/server"; +import { createLocalAttestationSecret } from "../../src/lib/local-management-attestation"; +import type { OcxConfig } from "../../src/types"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * Regression: CLI OAuth login used to POST the bare OAuth preset into a running proxy. diff --git a/tests/oauth-login-open-browser.test.ts b/tests/oauth/oauth-login-open-browser.test.ts similarity index 91% rename from tests/oauth-login-open-browser.test.ts rename to tests/oauth/oauth-login-open-browser.test.ts index 90d3b83d76..0b7928d219 100644 --- a/tests/oauth-login-open-browser.test.ts +++ b/tests/oauth/oauth-login-open-browser.test.ts @@ -1,6 +1,6 @@ import { describe, expect, spyOn, test } from "bun:test"; -import { handleOauthAccountRoutes } from "../src/server/management/oauth-account-routes"; -import type { OcxConfig } from "../src/types"; +import { handleOauthAccountRoutes } from "../../src/server/management/oauth-account-routes"; +import type { OcxConfig } from "../../src/types"; /** * The login route decides whether to spawn a browser on the machine running the @@ -29,8 +29,8 @@ async function startLogin(flow: { url: string; instructions?: string; deviceCode opened: string[]; body: { url?: string; deviceCode?: string; instructions?: string }; }> { - const oauth = await import("../src/oauth"); - const openUrlMod = await import("../src/lib/open-url"); + const oauth = await import("../../src/oauth"); + const openUrlMod = await import("../../src/lib/open-url"); const opened: string[] = []; const startSpy = spyOn(oauth, "startLoginFlow").mockResolvedValue(flow); const openSpy = spyOn(openUrlMod, "openUrl").mockImplementation((url: string) => { opened.push(url); }); diff --git a/tests/oauth-login-summary.test.ts b/tests/oauth/oauth-login-summary.test.ts similarity index 95% rename from tests/oauth-login-summary.test.ts rename to tests/oauth/oauth-login-summary.test.ts index 2b1034a498..b127ff9b95 100644 --- a/tests/oauth-login-summary.test.ts +++ b/tests/oauth/oauth-login-summary.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { oauthLoginSummary } from "../src/oauth"; +import { oauthLoginSummary } from "../../src/oauth"; describe("oauthLoginSummary (ocx status OAuth logins)", () => { test("lists every OAuth provider with a boolean login state, including cursor", () => { diff --git a/tests/oauth-manual-code.test.ts b/tests/oauth/oauth-manual-code.test.ts similarity index 96% rename from tests/oauth-manual-code.test.ts rename to tests/oauth/oauth-manual-code.test.ts index 4187abc17e..766fcdce77 100644 --- a/tests/oauth-manual-code.test.ts +++ b/tests/oauth/oauth-manual-code.test.ts @@ -1,9 +1,9 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; -import { managementFetch as fetch } from "./helpers/management-auth"; +import { managementFetch as fetch } from "../helpers/management-auth"; import { createHash } from "node:crypto"; import { existsSync, mkdtempSync, readFileSync } from "node:fs"; import { tmpdir } from "node:os"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; import { join } from "node:path"; import { cancelLoginFlow, @@ -11,14 +11,14 @@ import { getLoginStatus, startLoginFlow, submitManualLoginCode, -} from "../src/oauth"; -import { parseCallbackInput } from "../src/oauth/callback-server"; -import { saveConfig } from "../src/config"; -import { startServer } from "../src/server"; -import { findAvailablePort } from "../src/server/ports"; -import type { OcxConfig } from "../src/types"; -import { flushConfigDirHardeningForTests } from "../src/config/paths"; -import { setAsyncIcaclsRunnerForTests, setIcaclsRunnerForTests } from "../src/lib/windows-secret-acl"; +} from "../../src/oauth"; +import { parseCallbackInput } from "../../src/oauth/callback-server"; +import { saveConfig } from "../../src/config"; +import { startServer } from "../../src/server"; +import { findAvailablePort } from "../../src/server/ports"; +import type { OcxConfig } from "../../src/types"; +import { flushConfigDirHardeningForTests } from "../../src/config/paths"; +import { setAsyncIcaclsRunnerForTests, setIcaclsRunnerForTests } from "../../src/lib/windows-secret-acl"; // Per-test scratch home with both icacls runners stubbed: this file tests the manual-code // login flow, not Windows ACLs. With a real icacls the credential persist failed on the hosted diff --git a/tests/oauth-open-browser-choice.test.ts b/tests/oauth/oauth-open-browser-choice.test.ts similarity index 92% rename from tests/oauth-open-browser-choice.test.ts rename to tests/oauth/oauth-open-browser-choice.test.ts index 364b9e2885..48c7f54278 100644 --- a/tests/oauth-open-browser-choice.test.ts +++ b/tests/oauth/oauth-open-browser-choice.test.ts @@ -1,7 +1,7 @@ import { describe, expect, spyOn, test } from "bun:test"; -import { shouldOpenBrowserForLogin } from "../src/oauth/open-browser-choice"; -import { handleOauthAccountRoutes } from "../src/server/management/oauth-account-routes"; -import type { OcxConfig } from "../src/types"; +import { shouldOpenBrowserForLogin } from "../../src/oauth/open-browser-choice"; +import { handleOauthAccountRoutes } from "../../src/server/management/oauth-account-routes"; +import type { OcxConfig } from "../../src/types"; /** * The operator can stop the proxy from opening a browser on its own machine — @@ -45,8 +45,8 @@ async function startLogin( body: Record, cfg: OcxConfig, ): Promise<{ opened: string[]; url?: string }> { - const oauth = await import("../src/oauth"); - const openUrlMod = await import("../src/lib/open-url"); + const oauth = await import("../../src/oauth"); + const openUrlMod = await import("../../src/lib/open-url"); const opened: string[] = []; const startSpy = spyOn(oauth, "startLoginFlow").mockResolvedValue({ url: "https://accounts.x.ai/oauth/authorize?code_challenge=x" }); const openSpy = spyOn(openUrlMod, "openUrl").mockImplementation((url: string) => { opened.push(url); }); @@ -99,7 +99,7 @@ describe("POST /api/oauth/login honors the choice", () => { describe("the rollback path keeps the setting honest", () => { test("a failed save restores the previous value instead of leaving it half-applied", async () => { - const { handleManagementAPI } = await import("../src/server/management-api"); + const { handleManagementAPI } = await import("../../src/server/management-api"); const cfg = { port: 10100, defaultProvider: "openai", providers: {} } as OcxConfig; const req = new Request("http://127.0.0.1:10100/api/settings", { method: "PUT", diff --git a/tests/oauth-provider-reconcile.test.ts b/tests/oauth/oauth-provider-reconcile.test.ts similarity index 96% rename from tests/oauth-provider-reconcile.test.ts rename to tests/oauth/oauth-provider-reconcile.test.ts index f57c70b6d5..4f1ef9768f 100644 --- a/tests/oauth-provider-reconcile.test.ts +++ b/tests/oauth/oauth-provider-reconcile.test.ts @@ -2,14 +2,14 @@ import { afterEach, 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 { OAUTH_PROVIDERS, reconcileOAuthProviders, upsertOAuthProvider } from "../src/oauth"; -import { getCredential, saveCredential } from "../src/oauth/store"; -import { routeModel } from "../src/router"; -import { CURSOR_NO_VISION_MODELS, CURSOR_STATIC_MODELS, cursorModelIds } from "../src/adapters/cursor/discovery"; -import { modelInList } from "../src/types"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { loadConfig } from "../../src/config"; +import { OAUTH_PROVIDERS, reconcileOAuthProviders, upsertOAuthProvider } from "../../src/oauth"; +import { getCredential, saveCredential } from "../../src/oauth/store"; +import { routeModel } from "../../src/router"; +import { CURSOR_NO_VISION_MODELS, CURSOR_STATIC_MODELS, cursorModelIds } from "../../src/adapters/cursor/discovery"; +import { modelInList } from "../../src/types"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const originalHome = process.env.OPENCODEX_HOME; const homes: string[] = []; diff --git a/tests/oauth-public-surface.test.ts b/tests/oauth/oauth-public-surface.test.ts similarity index 97% rename from tests/oauth-public-surface.test.ts rename to tests/oauth/oauth-public-surface.test.ts index 71c884496f..fd9bb74a9e 100644 --- a/tests/oauth-public-surface.test.ts +++ b/tests/oauth/oauth-public-surface.test.ts @@ -12,21 +12,21 @@ import { runLogin, startLoginFlow, upsertOAuthProvider, -} from "../src/oauth"; -import { handleManagementAPI } from "../src/server/management-api"; -import type { OcxConfig } from "../src/types"; -import type { OAuthController } from "../src/oauth/types"; -import { getCredential } from "../src/oauth/store"; -import * as oauthStore from "../src/oauth/store"; -import { flushConfigDirHardeningForTests } from "../src/config/paths"; -import { setAsyncIcaclsRunnerForTests, setIcaclsRunnerForTests } from "../src/lib/windows-secret-acl"; +} from "../../src/oauth"; +import { handleManagementAPI } from "../../src/server/management-api"; +import type { OcxConfig } from "../../src/types"; +import type { OAuthController } from "../../src/oauth/types"; +import { getCredential } from "../../src/oauth/store"; +import * as oauthStore from "../../src/oauth/store"; +import { flushConfigDirHardeningForTests } from "../../src/config/paths"; +import { setAsyncIcaclsRunnerForTests, setIcaclsRunnerForTests } from "../../src/lib/windows-secret-acl"; // Server-less OAuth store test: nothing drains hardenConfigDir()'s icacls flight before // teardown (run 33612731522 shard 3). Same treatment as oauth-reauth-bind. const ICACLS_OK = { success: true, exitCode: 0, timedOut: false, stdout: "" }; -import { armClaudeCodeBaseline, loadConfig, saveConfig, saveConfigPreservingClaudeCode } from "../src/config"; -import { isApiAuthRequired, requireApiAuth } from "../src/server/auth-cors"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { armClaudeCodeBaseline, loadConfig, saveConfig, saveConfigPreservingClaudeCode } from "../../src/config"; +import { isApiAuthRequired, requireApiAuth } from "../../src/server/auth-cors"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-oauth-public-surface"); const PUBLIC_OAUTH_ERROR = "OAuth authentication failed. Check the OpenCodex account status and retry."; @@ -681,4 +681,4 @@ describe("legacy ChatGPT OAuth public-surface exclusion", () => { } }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/oauth-reauth-bind.test.ts b/tests/oauth/oauth-reauth-bind.test.ts similarity index 95% rename from tests/oauth-reauth-bind.test.ts rename to tests/oauth/oauth-reauth-bind.test.ts index 7c93e4925d..27ae71607e 100644 --- a/tests/oauth-reauth-bind.test.ts +++ b/tests/oauth/oauth-reauth-bind.test.ts @@ -1,14 +1,14 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdirSync} from "node:fs"; import { join } from "node:path"; -import { OAUTH_PROVIDERS, runLogin } from "../src/oauth"; -import { getAccountCredential, getAccountSet, saveCredential } from "../src/oauth/store"; -import type { OAuthController, OAuthCredentials } from "../src/oauth/types"; -import { handleManagementAPI } from "../src/server/management-api"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; -import { flushConfigDirHardeningForTests } from "../src/config/paths"; -import { setAsyncIcaclsRunnerForTests, setIcaclsRunnerForTests } from "../src/lib/windows-secret-acl"; +import { OAUTH_PROVIDERS, runLogin } from "../../src/oauth"; +import { getAccountCredential, getAccountSet, saveCredential } from "../../src/oauth/store"; +import type { OAuthController, OAuthCredentials } from "../../src/oauth/types"; +import { handleManagementAPI } from "../../src/server/management-api"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { flushConfigDirHardeningForTests } from "../../src/config/paths"; +import { setAsyncIcaclsRunnerForTests, setIcaclsRunnerForTests } from "../../src/lib/windows-secret-acl"; const TEST_DIR = join(import.meta.dir, ".tmp-oauth-reauth-bind"); const previousHome = process.env.OPENCODEX_HOME; @@ -308,4 +308,4 @@ describe("OAuth account-scoped reauth", () => { expect(source).toContain("Unknown account for reauth"); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/oauth-refresh-generic-lock.test.ts b/tests/oauth/oauth-refresh-generic-lock.test.ts similarity index 97% rename from tests/oauth-refresh-generic-lock.test.ts rename to tests/oauth/oauth-refresh-generic-lock.test.ts index 99e82c359a..020473358a 100644 --- a/tests/oauth-refresh-generic-lock.test.ts +++ b/tests/oauth/oauth-refresh-generic-lock.test.ts @@ -6,10 +6,10 @@ import { getValidAccessTokenForAccount, OAuthLoginRequiredError, OAUTH_PROVIDERS, -} from "../src/oauth"; -import type { OAuthCredentials } from "../src/oauth/types"; -import { getAccountCredential, getAccountSet, saveCredential } from "../src/oauth/store"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/oauth"; +import type { OAuthCredentials } from "../../src/oauth/types"; +import { getAccountCredential, getAccountSet, saveCredential } from "../../src/oauth/store"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; // Gate/CAS refresh races can exceed the 5s default under windows-latest contention // (same flake class as kiro-oauth / oauth queue budgets). diff --git a/tests/oauth-refresh-lock-multiprocess.test.ts b/tests/oauth/oauth-refresh-lock-multiprocess.test.ts similarity index 95% rename from tests/oauth-refresh-lock-multiprocess.test.ts rename to tests/oauth/oauth-refresh-lock-multiprocess.test.ts index 929c7955ef..524c9397b4 100644 --- a/tests/oauth-refresh-lock-multiprocess.test.ts +++ b/tests/oauth/oauth-refresh-lock-multiprocess.test.ts @@ -6,17 +6,17 @@ import { fileURLToPath } from "node:url"; import { OAUTH_PROVIDERS, refreshGenericAccountWithLock, -} from "../src/oauth"; +} from "../../src/oauth"; import { OAUTH_REFRESH_LOCK_WAIT_MS, createOAuthRefreshIntentLock, getAccountCredential, getAccountSet, saveCredential, -} from "../src/oauth/store"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/oauth/store"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); const origHome = process.env.HOME; const origOcxHome = process.env.OPENCODEX_HOME; const origKimiRefresh = OAUTH_PROVIDERS.kimi!.refresh; diff --git a/tests/oauth-refresh.test.ts b/tests/oauth/oauth-refresh.test.ts similarity index 99% rename from tests/oauth-refresh.test.ts rename to tests/oauth/oauth-refresh.test.ts index a87af8630f..6ec50816ba 100644 --- a/tests/oauth-refresh.test.ts +++ b/tests/oauth/oauth-refresh.test.ts @@ -3,10 +3,10 @@ import { Database } from "bun:sqlite"; import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { getValidAccessToken, getValidAccessTokenForAccount, OAuthLoginRequiredError, OAuthTokenRefreshBusyError, OAuthTokenRefreshStaleError, OAUTH_PROVIDERS, refreshAnthropicAccountWithLock, seedOAuthTokenRefreshFlightsForTests } from "../src/oauth"; -import { RefreshIntentIOError, nousRefreshIntentBlocksReplay } from "../src/oauth/nous"; -import * as nousModule from "../src/oauth/nous"; -import { AnthropicTokenError } from "../src/oauth/anthropic"; +import { getValidAccessToken, getValidAccessTokenForAccount, OAuthLoginRequiredError, OAuthTokenRefreshBusyError, OAuthTokenRefreshStaleError, OAUTH_PROVIDERS, refreshAnthropicAccountWithLock, seedOAuthTokenRefreshFlightsForTests } from "../../src/oauth"; +import { RefreshIntentIOError, nousRefreshIntentBlocksReplay } from "../../src/oauth/nous"; +import * as nousModule from "../../src/oauth/nous"; +import { AnthropicTokenError } from "../../src/oauth/anthropic"; import { OAuthRefreshIntentIOError, credentialGeneration, @@ -19,10 +19,10 @@ import { readOAuthRefreshIntent, saveCredential, writeOAuthRefreshIntent, -} from "../src/oauth/store"; -import * as storeModule from "../src/oauth/store"; -import * as configModule from "../src/config"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/oauth/store"; +import * as storeModule from "../../src/oauth/store"; +import * as configModule from "../../src/config"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const origHome = process.env.HOME; const origLocalAppData = process.env.LOCALAPPDATA; diff --git a/tests/oauth-status-privacy.test.ts b/tests/oauth/oauth-status-privacy.test.ts similarity index 97% rename from tests/oauth-status-privacy.test.ts rename to tests/oauth/oauth-status-privacy.test.ts index fde4156f64..6d73b05ef4 100644 --- a/tests/oauth-status-privacy.test.ts +++ b/tests/oauth/oauth-status-privacy.test.ts @@ -15,15 +15,15 @@ import { OAUTH_PROVIDERS, publicOAuthAuthenticationErrorMessage, UnsupportedOAuthProviderError, -} from "../src/oauth"; -import { OAuthMutationBusyError, saveCredential } from "../src/oauth/store"; -import { handleManagementAPI } from "../src/server/management-api"; -import { handleResponses } from "../src/server/responses"; -import type { OcxConfig } from "../src/types"; -import { ManagementRequest } from "./helpers/management-auth"; -import { flushConfigDirHardeningForTests } from "../src/config/paths"; -import { setAsyncIcaclsRunnerForTests, setIcaclsRunnerForTests } from "../src/lib/windows-secret-acl"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/oauth"; +import { OAuthMutationBusyError, saveCredential } from "../../src/oauth/store"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { handleResponses } from "../../src/server/responses"; +import type { OcxConfig } from "../../src/types"; +import { ManagementRequest } from "../helpers/management-auth"; +import { flushConfigDirHardeningForTests } from "../../src/config/paths"; +import { setAsyncIcaclsRunnerForTests, setIcaclsRunnerForTests } from "../../src/lib/windows-secret-acl"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let TEST_DIR = ""; const PUBLIC_OAUTH_ERROR = "OAuth authentication failed. Check the OpenCodex account status and retry."; @@ -172,7 +172,7 @@ describe("OAuth status privacy", () => { accountId: "acct-xai", source: "local-cli", }); - const { markAccountNeedsReauth, getAccountSet } = await import("../src/oauth/store"); + const { markAccountNeedsReauth, getAccountSet } = await import("../../src/oauth/store"); await markAccountNeedsReauth("xai", getAccountSet("xai")!.activeAccountId, true); expect(getLoginStatus("xai").loggedIn).toBe(false); diff --git a/tests/oauth-store-multi.test.ts b/tests/oauth/oauth-store-multi.test.ts similarity index 98% rename from tests/oauth-store-multi.test.ts rename to tests/oauth/oauth-store-multi.test.ts index 5d529e824d..58791494de 100644 --- a/tests/oauth-store-multi.test.ts +++ b/tests/oauth/oauth-store-multi.test.ts @@ -1,11 +1,11 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; -import { INTERNAL_DEADLINE_MS, STORE_BUDGET_MS } from "./helpers/test-budget"; +import { INTERNAL_DEADLINE_MS, STORE_BUDGET_MS } from "../helpers/test-budget"; import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import { resetHardenedStateForTests, setIcaclsRunnerForTests, -} from "../src/lib/windows-secret-acl"; +} from "../../src/lib/windows-secret-acl"; import { getAccountCredential, getAccountSet, @@ -24,9 +24,9 @@ import { saveCredential, setAccountAlias, setActiveAccount, -} from "../src/oauth/store"; -import type { OAuthCredentials } from "../src/oauth/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/oauth/store"; +import type { OAuthCredentials } from "../../src/oauth/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-oauth-store-multi-test"); let previousOpencodexHome: string | undefined; diff --git a/tests/oauth-upsert-preserves-api-key.test.ts b/tests/oauth/oauth-upsert-preserves-api-key.test.ts similarity index 98% rename from tests/oauth-upsert-preserves-api-key.test.ts rename to tests/oauth/oauth-upsert-preserves-api-key.test.ts index 3291546b09..dc5b55e1c6 100644 --- a/tests/oauth-upsert-preserves-api-key.test.ts +++ b/tests/oauth/oauth-upsert-preserves-api-key.test.ts @@ -2,16 +2,16 @@ import { describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { upsertOAuthProvider } from "../src/oauth"; +import { upsertOAuthProvider } from "../../src/oauth"; import { apiKeyPoolEntryId, listProviderApiKeys, removeProviderApiKey, setActiveProviderApiKey, -} from "../src/providers/api-keys"; -import { routeModel } from "../src/router"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/api-keys"; +import { routeModel } from "../../src/router"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * Regression: `upsertOAuthProvider` used to overwrite the provider entry with the bare preset diff --git a/tests/state-store-sweeper.test.ts b/tests/oauth/state-store-sweeper.test.ts similarity index 96% rename from tests/state-store-sweeper.test.ts rename to tests/oauth/state-store-sweeper.test.ts index a479a4be80..7bd9a8d298 100644 --- a/tests/state-store-sweeper.test.ts +++ b/tests/oauth/state-store-sweeper.test.ts @@ -14,40 +14,40 @@ import { sweepExpiredOnWrite, sweepLiveness, type GenerationContext, -} from "../src/lib/state-store-sweeper"; +} from "../../src/lib/state-store-sweeper"; import { ocxStartProcessCacheSizeForTests, setOcxStartProcessCacheForTests, setOcxStartProcessProbeForTests, sweepDeadOcxStartProcessCache, -} from "../src/config"; -import { STATE_STORE_REGISTRATIONS } from "../src/lib/state-store-registrations"; -import { getAccountSet, saveCredential } from "../src/oauth/store"; +} from "../../src/config"; +import { STATE_STORE_REGISTRATIONS } from "../../src/lib/state-store-registrations"; +import { getAccountSet, saveCredential } from "../../src/oauth/store"; import { clearAccountQuotaCache, clearProviderQuotaCache, fetchProviderQuotaReports, getCachedProviderAccountQuota, -} from "../src/providers/quota"; -import type { OcxConfig } from "../src/types"; -import { __resetVertexTokenCache, getVertexAccessToken } from "../src/lib/gcp-adc"; +} from "../../src/providers/quota"; +import type { OcxConfig } from "../../src/types"; +import { __resetVertexTokenCache, getVertexAccessToken } from "../../src/lib/gcp-adc"; import { configureAppOwnedMemoryBudget, registerRetainedStore, resetAppOwnedMemoryForTests, -} from "../src/lib/app-owned-memory"; -import { registerAppOwnedMemorySweepFallback } from "../src/lib/app-owned-memory-stores"; +} from "../../src/lib/app-owned-memory"; +import { registerAppOwnedMemorySweepFallback } from "../../src/lib/app-owned-memory-stores"; import { clearResponseStateMemoryForTests, rememberResponseState, responseStateMetrics, -} from "../src/responses/state"; +} from "../../src/responses/state"; import { __resetAntigravityReplayCache, antigravityReplayMetrics, observeAntigravityReplay, -} from "../src/adapters/google-antigravity-replay"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/adapters/google-antigravity-replay"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; function context( generation: number, diff --git a/tests/always-on-429-failover.test.ts b/tests/routing/always-on-429-failover.test.ts similarity index 94% rename from tests/always-on-429-failover.test.ts rename to tests/routing/always-on-429-failover.test.ts index 1ab40da0ad..59cbe084ca 100644 --- a/tests/always-on-429-failover.test.ts +++ b/tests/routing/always-on-429-failover.test.ts @@ -21,12 +21,12 @@ import { isAnthropicAccountPoolEnabled, resolveAnthropicAccountForSession, rotateAnthropicAccountOn429, -} from "../src/oauth/anthropic-routing"; -import { clearPoolRotationState } from "../src/codex/pool-rotation"; -import { getAccountSet, saveCredential, setActiveAccount } from "../src/oauth/store"; -import { clearAccountQuotaCache } from "../src/providers/quota"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/oauth/anthropic-routing"; +import { clearPoolRotationState } from "../../src/codex/pool-rotation"; +import { getAccountSet, saveCredential, setActiveAccount } from "../../src/oauth/store"; +import { clearAccountQuotaCache } from "../../src/providers/quota"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const originalHome = process.env.OPENCODEX_HOME; let home: string; diff --git a/tests/cl01-claude-outbound-review-regressions.test.ts b/tests/routing/cl01-claude-outbound-review-regressions.test.ts similarity index 91% rename from tests/cl01-claude-outbound-review-regressions.test.ts rename to tests/routing/cl01-claude-outbound-review-regressions.test.ts index 731f471e56..dd10b48c9b 100644 --- a/tests/cl01-claude-outbound-review-regressions.test.ts +++ b/tests/routing/cl01-claude-outbound-review-regressions.test.ts @@ -1,6 +1,6 @@ import { expect, test } from "bun:test"; -import { responsesSseToAnthropicSse } from "../src/claude/outbound"; -import { createTranslatorBudget } from "../src/lib/translator-budget"; +import { responsesSseToAnthropicSse } from "../../src/claude/outbound"; +import { createTranslatorBudget } from "../../src/lib/translator-budget"; async function collect(stream: ReadableStream): Promise { const reader = stream.getReader(); diff --git a/tests/cl01-openai-chat-review-regressions.test.ts b/tests/routing/cl01-openai-chat-review-regressions.test.ts similarity index 97% rename from tests/cl01-openai-chat-review-regressions.test.ts rename to tests/routing/cl01-openai-chat-review-regressions.test.ts index 0d755e0dd9..ca0e68781b 100644 --- a/tests/cl01-openai-chat-review-regressions.test.ts +++ b/tests/routing/cl01-openai-chat-review-regressions.test.ts @@ -1,6 +1,6 @@ import { expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import type { OcxMessage, OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import type { OcxMessage, OcxParsedRequest, OcxProviderConfig } from "../../src/types"; const baseProvider: OcxProviderConfig = { adapter: "openai-chat", diff --git a/tests/cl01-review-regressions.test.ts b/tests/routing/cl01-review-regressions.test.ts similarity index 89% rename from tests/cl01-review-regressions.test.ts rename to tests/routing/cl01-review-regressions.test.ts index 8cb219e8f8..66dd4d1390 100644 --- a/tests/cl01-review-regressions.test.ts +++ b/tests/routing/cl01-review-regressions.test.ts @@ -1,8 +1,8 @@ import { expect, test } from "bun:test"; -import { nonstreamObservationJson, runScenario } from "../src/lab/conformance/executor"; -import { loadCaseAuthority } from "../src/lab/conformance/manifest"; -import { emptyObservation, finalizeObservation } from "../src/lab/conformance/observation"; -import type { CaseRecord, NormalizedEvent } from "../src/lab/conformance/types"; +import { nonstreamObservationJson, runScenario } from "../../src/lab/conformance/executor"; +import { loadCaseAuthority } from "../../src/lab/conformance/manifest"; +import { emptyObservation, finalizeObservation } from "../../src/lab/conformance/observation"; +import type { CaseRecord, NormalizedEvent } from "../../src/lab/conformance/types"; test("duplicate event tool-call ids stay rejected instead of falling back to JSON", () => { const observation = emptyObservation(); diff --git a/tests/combo-child-headers.test.ts b/tests/routing/combo-child-headers.test.ts similarity index 92% rename from tests/combo-child-headers.test.ts rename to tests/routing/combo-child-headers.test.ts index 0d6e1fafd2..16fb99d4d3 100644 --- a/tests/combo-child-headers.test.ts +++ b/tests/routing/combo-child-headers.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; import { zstdCompressSync } from "node:zlib"; -import { readJsonRequestBody } from "../src/server/request-decompress"; -import { buildComboChildHeaders } from "../src/server/responses"; +import { readJsonRequestBody } from "../../src/server/request-decompress"; +import { buildComboChildHeaders } from "../../src/server/responses"; describe("combo child request headers", () => { test("strips content-encoding when re-serializing an already-decoded combo body", async () => { diff --git a/tests/combo-management-api.test.ts b/tests/routing/combo-management-api.test.ts similarity index 98% rename from tests/combo-management-api.test.ts rename to tests/routing/combo-management-api.test.ts index 4bb3e64943..2edf73fd54 100644 --- a/tests/combo-management-api.test.ts +++ b/tests/routing/combo-management-api.test.ts @@ -32,16 +32,16 @@ import { targetKey, tryPickComboModel, UnknownComboError, -} from "../src/combos"; -import { getConfigPath, readConfigDiagnostics, saveConfig } from "../src/config"; -import { routeModel } from "../src/router"; -import { handleManagementAPI } from "../src/server/management-api"; -import { handleResponses } from "../src/server/responses"; -import type { OcxConfig } from "../src/types"; -import { syncCatalogModels } from "../src/codex/catalog"; -import { injectClaudeAgentDefs } from "../src/claude/agents-inject"; -import { catalogConvergenceFactory } from "./helpers/catalog-convergence"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/combos"; +import { getConfigPath, readConfigDiagnostics, saveConfig } from "../../src/config"; +import { routeModel } from "../../src/router"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { handleResponses } from "../../src/server/responses"; +import type { OcxConfig } from "../../src/types"; +import { syncCatalogModels } from "../../src/codex/catalog"; +import { injectClaudeAgentDefs } from "../../src/claude/agents-inject"; +import { catalogConvergenceFactory } from "../helpers/catalog-convergence"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const VALID_COMBO = { targets: [{ provider: "a", model: "m1" }] }; @@ -720,7 +720,7 @@ describe("combo management API", () => { // Disabling an alias hides it from the pickable set, but NOT while it still holds a // saved roster slot: the dashboard PUTs exactly the rows it can render, so dropping a // chosen id here silently truncates the persisted roster on the next Save. Covered by - // tests/subagent-roster-retention.test.ts. + // tests/routing/subagent-roster-retention.test.ts. config.disabledModels = ["deepseek-v4-flash"]; const disabledResponse = await comboApi(config, "GET", "/api/subagent-models"); const disabledBody = await disabledResponse!.json() as { chosen: string[]; available: string[] }; @@ -1208,4 +1208,4 @@ describe("combo response-path strategy accounting", () => { } }, 10_000); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/combo-stream-preflight.test.ts b/tests/routing/combo-stream-preflight.test.ts similarity index 98% rename from tests/combo-stream-preflight.test.ts rename to tests/routing/combo-stream-preflight.test.ts index b4422727d2..97c927e391 100644 --- a/tests/combo-stream-preflight.test.ts +++ b/tests/routing/combo-stream-preflight.test.ts @@ -2,9 +2,9 @@ import { describe, expect, test } from "bun:test"; import { comboStreamPayloadCommitsOutput, preflightComboStreamResponse, -} from "../src/server/responses/combo-stream-preflight"; -import type { RequestLogContext } from "../src/server/request-log"; -import { MAX_CLIENT_SSE_FRAME_BYTES } from "../src/server/sse-frame-buffer"; +} from "../../src/server/responses/combo-stream-preflight"; +import type { RequestLogContext } from "../../src/server/request-log"; +import { MAX_CLIENT_SSE_FRAME_BYTES } from "../../src/server/sse-frame-buffer"; const sse = (...payloads: unknown[]): Response => new Response( payloads.map(payload => `data: ${JSON.stringify(payload)}\n\n`).join(""), diff --git a/tests/compatibility-provider-equivalence.test.ts b/tests/routing/compatibility-provider-equivalence.test.ts similarity index 87% rename from tests/compatibility-provider-equivalence.test.ts rename to tests/routing/compatibility-provider-equivalence.test.ts index a25abbea88..95faec6f46 100644 --- a/tests/compatibility-provider-equivalence.test.ts +++ b/tests/routing/compatibility-provider-equivalence.test.ts @@ -15,11 +15,11 @@ * devlog/_fin/260814_lab_core_decoupling/030_router_and_startup_activation.md */ import { describe, expect, test } from "bun:test"; -import { assemblePolicyCandidateEvidence } from "../src/routing/compatibility/assemble"; -import { setCompatibilityEvidenceProvider, resetCompatibilityEvidenceProviderForTests } from "../src/routing/compatibility/provider-slot"; -import { labCompatibilityEvidenceProvider } from "../src/routing/compatibility/lab-evidence-provider"; -import { getRoutingProfile } from "../src/routing/profile"; -import type { OcxConfig } from "../src/types"; +import { assemblePolicyCandidateEvidence } from "../../src/routing/compatibility/assemble"; +import { setCompatibilityEvidenceProvider, resetCompatibilityEvidenceProviderForTests } from "../../src/routing/compatibility/provider-slot"; +import { labCompatibilityEvidenceProvider } from "../../src/routing/compatibility/lab-evidence-provider"; +import { getRoutingProfile } from "../../src/routing/profile"; +import type { OcxConfig } from "../../src/types"; const config = { providers: { a: { baseUrl: "https://a.test", adapter: "openai-responses", apiKey: "k" } }, diff --git a/tests/destination-policy-resolved.test.ts b/tests/routing/destination-policy-resolved.test.ts similarity index 99% rename from tests/destination-policy-resolved.test.ts rename to tests/routing/destination-policy-resolved.test.ts index 0269dfc457..7b471bd793 100644 --- a/tests/destination-policy-resolved.test.ts +++ b/tests/routing/destination-policy-resolved.test.ts @@ -4,7 +4,7 @@ import { describe, expect, mock, test } from "bun:test"; const lookupMock = mock(async (_hostname: string, _opts: unknown): Promise<{ address: string; family: number }[]> => []); mock.module("node:dns/promises", () => ({ lookup: lookupMock })); -const { providerDestinationConfigError, providerDestinationResolvedError, resolvePublicAddresses } = await import("../src/lib/destination-policy"); +const { providerDestinationConfigError, providerDestinationResolvedError, resolvePublicAddresses } = await import("../../src/lib/destination-policy"); const provider = (baseUrl: string, allowPrivateNetwork?: boolean) => ({ baseUrl, allowPrivateNetwork }); diff --git a/tests/fastwire-characterization-routing.test.ts b/tests/routing/fastwire-characterization-routing.test.ts similarity index 92% rename from tests/fastwire-characterization-routing.test.ts rename to tests/routing/fastwire-characterization-routing.test.ts index 3286a09c36..938c12b58f 100644 --- a/tests/fastwire-characterization-routing.test.ts +++ b/tests/routing/fastwire-characterization-routing.test.ts @@ -1,11 +1,11 @@ import { describe, expect, test } from "bun:test"; -import { applyProviderConfigHints } from "../src/codex/catalog"; -import { applyCatalogModelMetadata } from "../src/codex/catalog/effort"; -import type { CatalogModel, RawEntry } from "../src/codex/catalog/parsing"; -import { candidateCapabilityEvidence } from "../src/routing/capability"; -import { resolveProductionBehaviorValues } from "../src/routing/compatibility/behavior"; -import { evaluatePolicyProfile } from "../src/routing/evaluator"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { applyProviderConfigHints } from "../../src/codex/catalog"; +import { applyCatalogModelMetadata } from "../../src/codex/catalog/effort"; +import type { CatalogModel, RawEntry } from "../../src/codex/catalog/parsing"; +import { candidateCapabilityEvidence } from "../../src/routing/capability"; +import { resolveProductionBehaviorValues } from "../../src/routing/compatibility/behavior"; +import { evaluatePolicyProfile } from "../../src/routing/evaluator"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; describe("FastWire characterization: routing profile service-tier evidence", () => { // FastWire #1886 B1 capability semantic migration: Chat caller-forward permission no longer diff --git a/tests/fastwire-characterization-wire.test.ts b/tests/routing/fastwire-characterization-wire.test.ts similarity index 96% rename from tests/fastwire-characterization-wire.test.ts rename to tests/routing/fastwire-characterization-wire.test.ts index 4ae9e38242..7d3c01d0dc 100644 --- a/tests/fastwire-characterization-wire.test.ts +++ b/tests/routing/fastwire-characterization-wire.test.ts @@ -1,11 +1,11 @@ import { afterEach, describe, expect, spyOn, test } from "bun:test"; -import { buildOpenAIChatPassthroughRequest } from "../src/adapters/openai-chat"; -import { chatCompletionsToResponsesBody } from "../src/chat/inbound"; -import { fastPolicyForModel } from "../src/providers/service-tier"; -import * as adapterResolveModule from "../src/server/adapter-resolve"; -import type { RequestLogContext } from "../src/server/request-log"; -import { handleResponses } from "../src/server/responses/core"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { buildOpenAIChatPassthroughRequest } from "../../src/adapters/openai-chat"; +import { chatCompletionsToResponsesBody } from "../../src/chat/inbound"; +import { fastPolicyForModel } from "../../src/providers/service-tier"; +import * as adapterResolveModule from "../../src/server/adapter-resolve"; +import type { RequestLogContext } from "../../src/server/request-log"; +import { handleResponses } from "../../src/server/responses/core"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; const originalFetch = globalThis.fetch; diff --git a/tests/fastwire-observability.test.ts b/tests/routing/fastwire-observability.test.ts similarity index 97% rename from tests/fastwire-observability.test.ts rename to tests/routing/fastwire-observability.test.ts index 3a21681cae..57434f8f7c 100644 --- a/tests/fastwire-observability.test.ts +++ b/tests/routing/fastwire-observability.test.ts @@ -1,14 +1,14 @@ import { describe, expect, test } from "bun:test"; -import type { AdapterRequest } from "../src/adapters/base"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { createResponsesPassthroughAdapter } from "../src/adapters/openai-responses"; -import { buildBehaviorFingerprintV1 } from "../src/lab/subject/behavior-fingerprint"; -import { sanitizeLogMetadataString } from "../src/lib/redact"; +import type { AdapterRequest } from "../../src/adapters/base"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { createResponsesPassthroughAdapter } from "../../src/adapters/openai-responses"; +import { buildBehaviorFingerprintV1 } from "../../src/lab/subject/behavior-fingerprint"; +import { sanitizeLogMetadataString } from "../../src/lib/redact"; import { createAdapterTierMetadata, type ResolvedFastPolicy, -} from "../src/providers/fastwire"; -import { resolveProductionBehaviorValues } from "../src/routing/compatibility/behavior"; +} from "../../src/providers/fastwire"; +import { resolveProductionBehaviorValues } from "../../src/routing/compatibility/behavior"; import { addFinalRequestLog, applyResponseLogMetadata, @@ -18,14 +18,14 @@ import { recordAdapterTier, type RequestLogContext, type RequestLogEntry, -} from "../src/server/request-log"; -import { applyServiceTierGate, handleResponses } from "../src/server/responses/core"; -import { costResult } from "../src/server/management/shared"; -import type { OcxConfig, OcxParsedRequest, TierObservationContext } from "../src/types"; -import { estimateComboCost, serviceTierContextFromOutcome } from "../src/usage/cost"; -import type { ExpectedPriceOverlay } from "../src/usage/expected-prices"; -import { normalizeUsageEntryForTest } from "../src/usage/log"; -import { createTestTranslatorBudget, withTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../src/server/request-log"; +import { applyServiceTierGate, handleResponses } from "../../src/server/responses/core"; +import { costResult } from "../../src/server/management/shared"; +import type { OcxConfig, OcxParsedRequest, TierObservationContext } from "../../src/types"; +import { estimateComboCost, serviceTierContextFromOutcome } from "../../src/usage/cost"; +import type { ExpectedPriceOverlay } from "../../src/usage/expected-prices"; +import { normalizeUsageEntryForTest } from "../../src/usage/log"; +import { createTestTranslatorBudget, withTestTranslatorBudget } from "../helpers/translator-budget"; const SERVICE_WIRE = { kind: "service-tier" as const, diff --git a/tests/fastwire-policy.test.ts b/tests/routing/fastwire-policy.test.ts similarity index 98% rename from tests/fastwire-policy.test.ts rename to tests/routing/fastwire-policy.test.ts index 14d1c4da72..2f85fb8fb9 100644 --- a/tests/fastwire-policy.test.ts +++ b/tests/routing/fastwire-policy.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { createResponsesPassthroughAdapter } from "../src/adapters/openai-responses"; -import { validateConfigCandidate } from "../src/config"; +import { createResponsesPassthroughAdapter } from "../../src/adapters/openai-responses"; +import { validateConfigCandidate } from "../../src/config"; import { canonicalFastTierMarker, cloneFastWire, @@ -10,9 +10,9 @@ import { tierValueAfterDecision, type FastPolicyAuthority, type ResolvedFastPolicy, -} from "../src/providers/fastwire"; -import { captureFastPolicyAuthority, fastPolicyForModel } from "../src/providers/service-tier"; -import { PROVIDER_REGISTRY, providerRegistryFastWireError } from "../src/providers/registry"; +} from "../../src/providers/fastwire"; +import { captureFastPolicyAuthority, fastPolicyForModel } from "../../src/providers/service-tier"; +import { PROVIDER_REGISTRY, providerRegistryFastWireError } from "../../src/providers/registry"; import { captureWireAdapterHardPins, isWirePinnedModel, @@ -20,8 +20,8 @@ import { type OcxConfig, type OcxParsedRequest, type TierDecision, -} from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; const MODEL = "model"; const SERVICE_WIRE: FastWire = { diff --git a/tests/policy-execution.test.ts b/tests/routing/policy-execution.test.ts similarity index 96% rename from tests/policy-execution.test.ts rename to tests/routing/policy-execution.test.ts index 2902f509d3..a286c8c15d 100644 --- a/tests/policy-execution.test.ts +++ b/tests/routing/policy-execution.test.ts @@ -2,13 +2,13 @@ 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 { NoEligiblePolicyCandidateError, routeModel } from "../src/router"; -import { isValidProviderName } from "../src/config"; -import { getRoutingProfile } from "../src/routing/profile"; -import { closeRequestHistoryIndex } from "../src/routing/history/indexer"; -import { evidenceFromBody } from "../src/routing/request-evidence"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { NoEligiblePolicyCandidateError, routeModel } from "../../src/router"; +import { isValidProviderName } from "../../src/config"; +import { getRoutingProfile } from "../../src/routing/profile"; +import { closeRequestHistoryIndex } from "../../src/routing/history/indexer"; +import { evidenceFromBody } from "../../src/routing/request-evidence"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testDir = ""; let previousHome: string | undefined; diff --git a/tests/router-discarded-baseurl-warning.test.ts b/tests/routing/router-discarded-baseurl-warning.test.ts similarity index 97% rename from tests/router-discarded-baseurl-warning.test.ts rename to tests/routing/router-discarded-baseurl-warning.test.ts index dc31220a3a..d1413c4aa0 100644 --- a/tests/router-discarded-baseurl-warning.test.ts +++ b/tests/routing/router-discarded-baseurl-warning.test.ts @@ -1,10 +1,10 @@ import { expect, test } from "bun:test"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; /** * A pinned registry entry outranks a saved `baseUrl`. That behavior is intentional and is - * asserted in tests/router-template-baseurl.test.ts; these tests cover the diagnostic that + * asserted in tests/routing/router-template-baseurl.test.ts; these tests cover the diagnostic that * tells the user it happened, so a wrong-region URL stops surfacing as a bare 401. * * `google` is the pinned fixture: a fixed remote registry endpoint, no `allowBaseUrlOverride`. diff --git a/tests/router-template-baseurl.test.ts b/tests/routing/router-template-baseurl.test.ts similarity index 96% rename from tests/router-template-baseurl.test.ts rename to tests/routing/router-template-baseurl.test.ts index 053f2ff7b7..73215265e5 100644 --- a/tests/router-template-baseurl.test.ts +++ b/tests/routing/router-template-baseurl.test.ts @@ -1,6 +1,6 @@ import { expect, test } from "bun:test"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; const OVERRIDE_PROVIDERS = [ { id: "ollama", registryBaseUrl: "http://localhost:11434/v1" }, diff --git a/tests/router.test.ts b/tests/routing/router.test.ts similarity index 99% rename from tests/router.test.ts rename to tests/routing/router.test.ts index 6a95292935..83be39818e 100644 --- a/tests/router.test.ts +++ b/tests/routing/router.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { mapReasoningEffort } from "../src/reasoning-effort"; -import { NoEnabledOpenAiProviderError, routeCompactionModel, routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { mapReasoningEffort } from "../../src/reasoning-effort"; +import { NoEnabledOpenAiProviderError, routeCompactionModel, routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; describe("routeModel registry effort defaults", () => { test("allows only opted-in OAuth presets to use explicit API-key billing", () => { diff --git a/tests/routing-analytics.test.ts b/tests/routing/routing-analytics.test.ts similarity index 96% rename from tests/routing-analytics.test.ts rename to tests/routing/routing-analytics.test.ts index 705292b677..68e00e77fd 100644 --- a/tests/routing-analytics.test.ts +++ b/tests/routing/routing-analytics.test.ts @@ -2,18 +2,18 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { appendFileSync, mkdtempSync} 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"; -import { closeRequestHistoryIndex } from "../src/routing/history/indexer"; -import { computeRoutingAnalytics } from "../src/routing/analytics"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/usage/log"; +import { closeRequestHistoryIndex } from "../../src/routing/history/indexer"; +import { computeRoutingAnalytics } from "../../src/routing/analytics"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testDir = ""; let previousHome: string | undefined; diff --git a/tests/routing-capability-catalog.test.ts b/tests/routing/routing-capability-catalog.test.ts similarity index 94% rename from tests/routing-capability-catalog.test.ts rename to tests/routing/routing-capability-catalog.test.ts index c9fd8a84aa..55ba735b39 100644 --- a/tests/routing-capability-catalog.test.ts +++ b/tests/routing/routing-capability-catalog.test.ts @@ -2,13 +2,13 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { candidateCapabilityEvidence } from "../src/routing/capability"; -import { applyCatalogModelMetadata } from "../src/codex/catalog/effort"; -import { applyCatalogMetadata, ensureStrictCatalogFields } from "../src/codex/catalog/parsing"; -import type { CatalogModel, RawEntry } from "../src/codex/catalog/parsing"; -import { parseAntigravityAvailableModels } from "../src/providers/antigravity-models"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { candidateCapabilityEvidence } from "../../src/routing/capability"; +import { applyCatalogModelMetadata } from "../../src/codex/catalog/effort"; +import { applyCatalogMetadata, ensureStrictCatalogFields } from "../../src/codex/catalog/parsing"; +import type { CatalogModel, RawEntry } from "../../src/codex/catalog/parsing"; +import { parseAntigravityAvailableModels } from "../../src/providers/antigravity-models"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * Regression coverage for #1796. diff --git a/tests/routing-capability-model-matching.test.ts b/tests/routing/routing-capability-model-matching.test.ts similarity index 96% rename from tests/routing-capability-model-matching.test.ts rename to tests/routing/routing-capability-model-matching.test.ts index cc00b6d912..bb956c2d8d 100644 --- a/tests/routing-capability-model-matching.test.ts +++ b/tests/routing/routing-capability-model-matching.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from "bun:test"; -import { candidateCapabilityEvidence } from "../src/routing/capability"; -import { evaluatePolicyProfile } from "../src/routing/evaluator"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { modelRecordValue } from "../src/reasoning-effort"; -import { isModelTextOnly } from "../src/vision"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { candidateCapabilityEvidence } from "../../src/routing/capability"; +import { evaluatePolicyProfile } from "../../src/routing/evaluator"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { modelRecordValue } from "../../src/reasoning-effort"; +import { isModelTextOnly } from "../../src/vision"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; /** * `candidateCapabilityEvidence` describes what the resolver will do with a candidate, diff --git a/tests/routing-compatibility-auth-identity.test.ts b/tests/routing/routing-compatibility-auth-identity.test.ts similarity index 84% rename from tests/routing-compatibility-auth-identity.test.ts rename to tests/routing/routing-compatibility-auth-identity.test.ts index 9a32447dcb..50dcf2b314 100644 --- a/tests/routing-compatibility-auth-identity.test.ts +++ b/tests/routing/routing-compatibility-auth-identity.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { resolveProductionBehaviorValues } from "../src/routing/compatibility/behavior"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { resolveProductionBehaviorValues } from "../../src/routing/compatibility/behavior"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; describe("CL-06 registry auth compatibility identity", () => { test("registry-derived OAuth matches explicit OAuth behavior identity", () => { diff --git a/tests/routing-compatibility-boundaries.test.ts b/tests/routing/routing-compatibility-boundaries.test.ts similarity index 92% rename from tests/routing-compatibility-boundaries.test.ts rename to tests/routing/routing-compatibility-boundaries.test.ts index d9aaea691e..e89340a1a8 100644 --- a/tests/routing-compatibility-boundaries.test.ts +++ b/tests/routing/routing-compatibility-boundaries.test.ts @@ -2,16 +2,16 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { handleManagementAPI } from "../src/server/management-api"; -import { routeModel } from "../src/router"; -import { readInstallationSalt } from "../src/lab/subject/installation-salt"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { routeModel } from "../../src/router"; +import { readInstallationSalt } from "../../src/lab/subject/installation-salt"; import { resetCompatibilityVersionCacheForTests, setCompatibilityVersionOverrideForTests, -} from "../src/routing/compatibility/version"; -import { ManagementRequest } from "./helpers/management-auth"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/routing/compatibility/version"; +import { ManagementRequest } from "../helpers/management-auth"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testDir = ""; let previousHome: string | undefined; diff --git a/tests/routing-compatibility-model-matching.test.ts b/tests/routing/routing-compatibility-model-matching.test.ts similarity index 95% rename from tests/routing-compatibility-model-matching.test.ts rename to tests/routing/routing-compatibility-model-matching.test.ts index f3a26f39dd..2c3ebb4def 100644 --- a/tests/routing-compatibility-model-matching.test.ts +++ b/tests/routing/routing-compatibility-model-matching.test.ts @@ -5,12 +5,12 @@ * adapter actually builds, then assert the report describes that same wire. */ import { describe, expect, test } from "bun:test"; -import { resolveProductionBehaviorValues } from "../src/routing/compatibility/behavior"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { buildBehaviorFingerprintV1 } from "../src/lab/subject/behavior-fingerprint"; -import { resolveOpenRouterRouting } from "../src/providers/openrouter-routing"; -import { modelRecordValue } from "../src/reasoning-effort"; -import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { resolveProductionBehaviorValues } from "../../src/routing/compatibility/behavior"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { buildBehaviorFingerprintV1 } from "../../src/lab/subject/behavior-fingerprint"; +import { resolveOpenRouterRouting } from "../../src/providers/openrouter-routing"; +import { modelRecordValue } from "../../src/reasoning-effort"; +import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../../src/types"; // ollama-cloud ships `gpt-oss:120b` verbatim (src/providers/registry.ts) and the same // registry row lists the bare `gpt-oss` in noVisionModels, i.e. the bare-prefix form is diff --git a/tests/routing-compatibility.test.ts b/tests/routing/routing-compatibility.test.ts similarity index 94% rename from tests/routing-compatibility.test.ts rename to tests/routing/routing-compatibility.test.ts index 74ce4a4818..2a9b1bec4d 100644 --- a/tests/routing-compatibility.test.ts +++ b/tests/routing/routing-compatibility.test.ts @@ -2,29 +2,29 @@ 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 { evaluatePolicyProfile } from "../src/routing/evaluator"; -import { assemblePolicyCandidateEvidence } from "../src/routing/compatibility/assemble"; -import { setCompatibilityEvidenceProvider } from "../src/routing/compatibility/provider-slot"; -import { labCompatibilityEvidenceProvider } from "../src/routing/compatibility/lab-evidence-provider"; -import { evaluateCompatibilityForCandidate } from "../src/routing/compatibility/policy"; -import { findVerdictForSuite, loadCompatibilityEvidenceSnapshot } from "../src/routing/compatibility/reader"; +import { evaluatePolicyProfile } from "../../src/routing/evaluator"; +import { assemblePolicyCandidateEvidence } from "../../src/routing/compatibility/assemble"; +import { setCompatibilityEvidenceProvider } from "../../src/routing/compatibility/provider-slot"; +import { labCompatibilityEvidenceProvider } from "../../src/routing/compatibility/lab-evidence-provider"; +import { evaluateCompatibilityForCandidate } from "../../src/routing/compatibility/policy"; +import { findVerdictForSuite, loadCompatibilityEvidenceSnapshot } from "../../src/routing/compatibility/reader"; import { resolvePolicyCompatibilitySubjects, resolvePolicyRouteSubject, -} from "../src/routing/compatibility/subject"; -import { subjectIdForSubject } from "../src/lab/digest"; -import { buildProtocolSubjectV1 } from "../src/lab/subject/protocol-subject"; -import { readInstallationSalt } from "../src/lab/subject/installation-salt"; -import { labRoot } from "../src/lab/paths"; -import { getRoutingProfile, normalizeRoutingProfile, routingProfileIssues } from "../src/routing/profile"; +} from "../../src/routing/compatibility/subject"; +import { subjectIdForSubject } from "../../src/lab/digest"; +import { buildProtocolSubjectV1 } from "../../src/lab/subject/protocol-subject"; +import { readInstallationSalt } from "../../src/lab/subject/installation-salt"; +import { labRoot } from "../../src/lab/paths"; +import { getRoutingProfile, normalizeRoutingProfile, routingProfileIssues } from "../../src/routing/profile"; import { resetCompatibilityVersionCacheForTests, setCompatibilityVersionOverrideForTests, -} from "../src/routing/compatibility/version"; -import { normalizeRouteDecisionTrace } from "../src/routing/trace"; -import type { OcxConfig } from "../src/types"; -import type { CandidateCompatibilityEvidence } from "../src/routing/compatibility/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/routing/compatibility/version"; +import { normalizeRouteDecisionTrace } from "../../src/routing/trace"; +import type { OcxConfig } from "../../src/types"; +import type { CandidateCompatibilityEvidence } from "../../src/routing/compatibility/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const COMPAT_VERSION = "f".repeat(64); const SUBJECT_ID = "s".repeat(64); @@ -307,7 +307,7 @@ describe("CL-06 routing compatibility", () => { }); test("policy evaluation does not import live probe executors", async () => { - const mod = await import("../src/routing/compatibility/policy"); + const mod = await import("../../src/routing/compatibility/policy"); expect(Object.keys(mod)).not.toContain("runLiveScenario"); }); diff --git a/tests/routing-policy-fallback.test.ts b/tests/routing/routing-policy-fallback.test.ts similarity index 97% rename from tests/routing-policy-fallback.test.ts rename to tests/routing/routing-policy-fallback.test.ts index acfadb3744..205c70b872 100644 --- a/tests/routing-policy-fallback.test.ts +++ b/tests/routing/routing-policy-fallback.test.ts @@ -1,14 +1,14 @@ import { describe, expect, test } from "bun:test"; -import { formatErrorResponse } from "../src/bridge"; -import { RequestPacingQueueOverloadError } from "../src/providers/request-pacing"; -import type { OcxConfig } from "../src/types"; -import { beginRequestAttempt, type RequestLogContext } from "../src/server/request-log"; -import type { RouteDecisionTraceV1 } from "../src/routing/trace"; +import { formatErrorResponse } from "../../src/bridge"; +import { RequestPacingQueueOverloadError } from "../../src/providers/request-pacing"; +import type { OcxConfig } from "../../src/types"; +import { beginRequestAttempt, type RequestLogContext } from "../../src/server/request-log"; +import type { RouteDecisionTraceV1 } from "../../src/routing/trace"; import { handleResponsesWithPolicyFallback, rankPolicyFallbackCandidates, -} from "../src/server/responses/policy-fallback"; +} from "../../src/server/responses/policy-fallback"; function policyTrace(): RouteDecisionTraceV1 { return { diff --git a/tests/routing-policy-pool-quota.test.ts b/tests/routing/routing-policy-pool-quota.test.ts similarity index 97% rename from tests/routing-policy-pool-quota.test.ts rename to tests/routing/routing-policy-pool-quota.test.ts index 89f3ce1d75..006e21641f 100644 --- a/tests/routing-policy-pool-quota.test.ts +++ b/tests/routing/routing-policy-pool-quota.test.ts @@ -1,7 +1,7 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { clearAccountQuota, setAccountQuotaFromParsed } from "../src/codex/quota"; -import { codexPoolQuotaEvidence, quotaEvidenceForCandidate } from "../src/routing/quota"; +import { clearAccountQuota, setAccountQuotaFromParsed } from "../../src/codex/quota"; +import { codexPoolQuotaEvidence, quotaEvidenceForCandidate } from "../../src/routing/quota"; afterEach(() => clearAccountQuota()); diff --git a/tests/routing-policy-surface-parity.test.ts b/tests/routing/routing-policy-surface-parity.test.ts similarity index 94% rename from tests/routing-policy-surface-parity.test.ts rename to tests/routing/routing-policy-surface-parity.test.ts index 9b466b4dc2..71e4b136bd 100644 --- a/tests/routing-policy-surface-parity.test.ts +++ b/tests/routing/routing-policy-surface-parity.test.ts @@ -1,11 +1,11 @@ import { afterEach, describe, expect, mock, test } from "bun:test"; -import { chatCompletionsToResponsesBody } from "../src/chat/inbound"; -import { anthropicToResponsesTranslation } from "../src/claude/inbound"; -import { evidenceFromBody } from "../src/routing/request-evidence"; -import type { ProviderAdapter } from "../src/adapters/base"; -import type { AdapterEvent, OcxConfig, OcxProviderConfig } from "../src/types"; -import type { RequestLogContext } from "../src/server/request-log"; +import { chatCompletionsToResponsesBody } from "../../src/chat/inbound"; +import { anthropicToResponsesTranslation } from "../../src/claude/inbound"; +import { evidenceFromBody } from "../../src/routing/request-evidence"; +import type { ProviderAdapter } from "../../src/adapters/base"; +import type { AdapterEvent, OcxConfig, OcxProviderConfig } from "../../src/types"; +import type { RequestLogContext } from "../../src/server/request-log"; const MODEL = "policy/daily"; const EXPECTED_RICH_EVIDENCE = { @@ -107,19 +107,19 @@ describe("routing policy request evidence parity (translator-level coverage)", ( // ---- Handler-level parity tests (via dev handler entry points) ---- -const actualResolver = await import("../src/server/adapter-resolve"); +const actualResolver = await import("../../src/server/adapter-resolve"); let adapterFactory: ((provider: OcxProviderConfig) => ProviderAdapter) | undefined; -mock.module("../src/server/adapter-resolve", () => ({ +mock.module("../../src/server/adapter-resolve", () => ({ ...actualResolver, resolveAdapter(provider: OcxProviderConfig, cacheRetention?: "none" | "short" | "long") { return adapterFactory?.(provider) ?? actualResolver.resolveAdapter(provider, cacheRetention); }, })); -const { handleResponses } = await import("../src/server/responses"); -const { handleChatCompletions } = await import("../src/server/chat-completions"); -const { handleClaudeMessages } = await import("../src/server/claude-messages"); +const { handleResponses } = await import("../../src/server/responses"); +const { handleChatCompletions } = await import("../../src/server/chat-completions"); +const { handleClaudeMessages } = await import("../../src/server/claude-messages"); afterEach(() => { adapterFactory = undefined; diff --git a/tests/routing-profile-management-editor.test.ts b/tests/routing/routing-profile-management-editor.test.ts similarity index 98% rename from tests/routing-profile-management-editor.test.ts rename to tests/routing/routing-profile-management-editor.test.ts index 93eae2f944..9a680ec75d 100644 --- a/tests/routing-profile-management-editor.test.ts +++ b/tests/routing/routing-profile-management-editor.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 { fallbackCodexAccountLogLabel } from "../src/codex/account-label"; -import { handleManagementAPI } from "../src/server/management-api"; -import { ManagementRequest } from "./helpers/management-auth"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; -import type { OcxConfig } from "../src/types"; +import { fallbackCodexAccountLogLabel } from "../../src/codex/account-label"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { ManagementRequest } from "../helpers/management-auth"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import type { OcxConfig } from "../../src/types"; let testDir = ""; let previousHome: string | undefined; diff --git a/tests/routing-profile.test.ts b/tests/routing/routing-profile.test.ts similarity index 97% rename from tests/routing-profile.test.ts rename to tests/routing/routing-profile.test.ts index ea2c38e872..aafca468dd 100644 --- a/tests/routing-profile.test.ts +++ b/tests/routing/routing-profile.test.ts @@ -2,12 +2,12 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { validateConfigCandidate } from "../src/config"; -import { updateAccountQuota } from "../src/codex/quota"; -import { clearAccountQuotaCache } from "../src/providers/quota"; -import { handleManagementAPI } from "../src/server/management-api"; -import { ManagementRequest } from "./helpers/management-auth"; -import { closeRequestHistoryIndex } from "../src/routing/history/indexer"; +import { validateConfigCandidate } from "../../src/config"; +import { updateAccountQuota } from "../../src/codex/quota"; +import { clearAccountQuotaCache } from "../../src/providers/quota"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { ManagementRequest } from "../helpers/management-auth"; +import { closeRequestHistoryIndex } from "../../src/routing/history/indexer"; import { getRoutingProfile, listRoutingProfileIds, @@ -16,10 +16,10 @@ import { policyPublicModelId, resolvePolicyProfileId, routingProfileIssues, -} from "../src/routing/profile"; -import { evaluatePolicyProfile } from "../src/routing/evaluator"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/routing/profile"; +import { evaluatePolicyProfile } from "../../src/routing/evaluator"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testDir = ""; let previousHome: string | undefined; @@ -477,7 +477,7 @@ describe("routing profiles (RI-04)", () => { }); test("API dry-run mirrors live codex cooldown for openai candidates", async () => { - const { clearCodexUpstreamHealth, recordCodexUpstreamOutcome } = await import("../src/codex/routing"); + const { clearCodexUpstreamHealth, recordCodexUpstreamOutcome } = await import("../../src/codex/routing"); clearCodexUpstreamHealth(); const now = Date.now(); const config = baseConfig({ @@ -567,8 +567,8 @@ describe("routing profiles (RI-04)", () => { }); test("API dry-run leaves an unbound Anthropic candidate quota unknown despite an active account", async () => { - const { saveCredential, getAccountSet } = await import("../src/oauth/store"); - const { setCachedProviderAccountQuotaForTests } = await import("../src/providers/quota"); + const { saveCredential, getAccountSet } = await import("../../src/oauth/store"); + const { setCachedProviderAccountQuotaForTests } = await import("../../src/providers/quota"); await saveCredential("anthropic", { access: "access-a", refresh: "refresh-a", diff --git a/tests/subagent-context-staleness.test.ts b/tests/routing/subagent-context-staleness.test.ts similarity index 94% rename from tests/subagent-context-staleness.test.ts rename to tests/routing/subagent-context-staleness.test.ts index f4a644dcd5..068bc9374d 100644 --- a/tests/subagent-context-staleness.test.ts +++ b/tests/routing/subagent-context-staleness.test.ts @@ -2,12 +2,12 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync, writeFileSync, mkdirSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { resolveEffectiveSubagentRoster } from "../src/server/responses/collaboration"; +import { resolveEffectiveSubagentRoster } from "../../src/server/responses/collaboration"; import { NATIVE_GPT56_CONTEXT_WINDOW, NATIVE_GPT56_OPT_IN_CONTEXT_WINDOW, -} from "../src/codex/catalog"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/catalog"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * #2574: the subagent roster reads the persisted Codex catalog, which is only as fresh as the diff --git a/tests/subagent-defaults.test.ts b/tests/routing/subagent-defaults.test.ts similarity index 99% rename from tests/subagent-defaults.test.ts rename to tests/routing/subagent-defaults.test.ts index 96adcf2ae2..3e8eb16c21 100644 --- a/tests/subagent-defaults.test.ts +++ b/tests/routing/subagent-defaults.test.ts @@ -3,7 +3,7 @@ import { MANAGED_AGENTS_TABLE_MARKER, MANAGED_SUBAGENT_DEFAULT_MARKER, transformManagedSubagentDefaults, -} from "../src/codex/subagent-defaults"; +} from "../../src/codex/subagent-defaults"; function apply(content: string, model = "openai/gpt-5.6-sol", reasoningEffort?: string) { return transformManagedSubagentDefaults(content, { model, reasoningEffort }); diff --git a/tests/subagent-fallback-handle-responses.test.ts b/tests/routing/subagent-fallback-handle-responses.test.ts similarity index 96% rename from tests/subagent-fallback-handle-responses.test.ts rename to tests/routing/subagent-fallback-handle-responses.test.ts index 25401a42f1..83bdc0686b 100644 --- a/tests/subagent-fallback-handle-responses.test.ts +++ b/tests/routing/subagent-fallback-handle-responses.test.ts @@ -9,11 +9,11 @@ import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { fileURLToPath } from "node:url"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; import { clearAccountQuota, updateAccountQuota, -} from "../src/codex/quota"; +} from "../../src/codex/quota"; import { CODEX_QUOTA_PROBE_INTERVAL_MS, clearCodexUpstreamHealth, @@ -22,29 +22,29 @@ import { previewCodexAccountForRequest, recordCodexUpstreamOutcome, resolveCodexAccountForThreadDetailed, -} from "../src/codex/routing"; +} from "../../src/codex/routing"; import { DEFAULT_SUBAGENT_MODEL_FALLBACK_POLL_MS, isModelHealthBlocked, resetSubagentModelFallbackStateForTests, setSubagentQuotaPrimeForTests, -} from "../src/codex/subagent-model-fallback"; -import { resetCodexModelEntitlementCacheForTests } from "../src/codex/model-entitlements"; -import { getMainAccountPlan, setMainAccountPlan } from "../src/codex/main-account"; -import { resolveCodexAuthContext, type CodexAuthContext } from "../src/codex/auth-context"; -import { handleResponses } from "../src/server/responses"; -import { resetAgentTaskRecoveryState } from "../src/server/responses/agent-task-recovery"; -import { isEagerRelaySseResponse } from "../src/server/relay"; -import type { ActiveTurnLease } from "../src/server/lifecycle"; -import type { OcxConfig } from "../src/types"; -import type { RequestLogContext } from "../src/server/request-log"; -import type { ResponsesTerminalStatus } from "../src/bridge"; +} from "../../src/codex/subagent-model-fallback"; +import { resetCodexModelEntitlementCacheForTests } from "../../src/codex/model-entitlements"; +import { getMainAccountPlan, setMainAccountPlan } from "../../src/codex/main-account"; +import { resolveCodexAuthContext, type CodexAuthContext } from "../../src/codex/auth-context"; +import { handleResponses } from "../../src/server/responses"; +import { resetAgentTaskRecoveryState } from "../../src/server/responses/agent-task-recovery"; +import { isEagerRelaySseResponse } from "../../src/server/relay"; +import type { ActiveTurnLease } from "../../src/server/lifecycle"; +import type { OcxConfig } from "../../src/types"; +import type { RequestLogContext } from "../../src/server/request-log"; +import type { ResponsesTerminalStatus } from "../../src/bridge"; import { codexHeaders, encryptedInput as recoverableEncryptedInput, recoverySse, -} from "./helpers/agent-task-recovery"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../helpers/agent-task-recovery"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; setDefaultTimeout(30_000); @@ -419,7 +419,7 @@ describe("subagent fallback without primary auth cooldown failure", () => { updateAccountQuota("pool-a", 20, undefined, 20); const resetAt = Math.floor((now + 4 * 24 * 60 * 60_000) / 1000); recordCodexUpstreamOutcome(cfg, "pool-a", 429, { resetAt, now }); - const { noteSubagentModelFailure } = await import("../src/codex/subagent-model-fallback"); + const { noteSubagentModelFailure } = await import("../../src/codex/subagent-model-fallback"); noteSubagentModelFailure("gpt-5.5", "429", cfg, "pool-a"); const probeAt = now + CODEX_QUOTA_PROBE_INTERVAL_MS; @@ -481,7 +481,7 @@ describe("subagent fallback without primary auth cooldown failure", () => { updateAccountQuota("pool-a", 95, undefined, 20); const resetAt = Math.floor((now + 4 * 24 * 60 * 60_000) / 1000); recordCodexUpstreamOutcome(cfg, "pool-a", 429, { resetAt, now }); - const { noteSubagentModelFailure } = await import("../src/codex/subagent-model-fallback"); + const { noteSubagentModelFailure } = await import("../../src/codex/subagent-model-fallback"); noteSubagentModelFailure("xai/grok-4.5", "429", cfg); let fetchCalls = 0; @@ -535,7 +535,7 @@ describe("subagent fallback final-route normalization", () => { subagentModelFallback: ["openai-apikey/gpt-5.6-sol-pro"], fastMode: true, }); - const { noteSubagentModelFailure } = await import("../src/codex/subagent-model-fallback"); + const { noteSubagentModelFailure } = await import("../../src/codex/subagent-model-fallback"); noteSubagentModelFailure("gpt-5.6-sol", "429", cfg); const capture = { urls: [] as string[], bodies: [] as string[], auths: [] as Array }; @@ -591,7 +591,7 @@ describe("subagent fallback final-route normalization", () => { }, }, }); - const { noteSubagentModelFailure } = await import("../src/codex/subagent-model-fallback"); + const { noteSubagentModelFailure } = await import("../../src/codex/subagent-model-fallback"); noteSubagentModelFailure("xai/grok-4.5", "429", cfg); noteSubagentModelFailure("grok-4.5", "429", cfg); @@ -641,7 +641,7 @@ describe("subagent fallback final-route normalization", () => { }, }, }); - const { noteSubagentModelFailure } = await import("../src/codex/subagent-model-fallback"); + const { noteSubagentModelFailure } = await import("../../src/codex/subagent-model-fallback"); noteSubagentModelFailure("xai/grok-4.5", "429", cfg); noteSubagentModelFailure("grok-4.5", "429", cfg); @@ -678,7 +678,7 @@ describe("subagent fallback final-route normalization", () => { }, subagentModelFallback: ["xai/grok-4.5"], }); - const { noteSubagentModelFailure } = await import("../src/codex/subagent-model-fallback"); + const { noteSubagentModelFailure } = await import("../../src/codex/subagent-model-fallback"); noteSubagentModelFailure("gpt-5.5", "rate limit exceeded", cfg); const capture = { urls: [] as string[], bodies: [] as string[], auths: [] as Array }; @@ -755,7 +755,7 @@ describe("subagent fallback final-route normalization", () => { }, subagentModelFallback: ["xai/grok-4.5"], }); - const { noteSubagentModelFailure } = await import("../src/codex/subagent-model-fallback"); + const { noteSubagentModelFailure } = await import("../../src/codex/subagent-model-fallback"); noteSubagentModelFailure("gpt-5.5", "rate limit exceeded", cfg); const capture = { urls: [] as string[], bodies: [] as string[], auths: [] as Array }; @@ -789,7 +789,7 @@ describe("native fallback account preview", () => { { id: "pool-b", email: "b@example.test", isMain: false, chatgptAccountId: "pool_acc_b" }, ], }); - const { noteSubagentModelFailure } = await import("../src/codex/subagent-model-fallback"); + const { noteSubagentModelFailure } = await import("../../src/codex/subagent-model-fallback"); noteSubagentModelFailure("team/gpt-5.6-sol", "429", cfg, "pool-a", now); // Make a stale account choice observable at the fallback boundary: preview must // apply the first snapshot and move to pool-b before checking model health. @@ -1168,7 +1168,7 @@ describe("native fallback account preview", () => { activeCodexAccountId: "__main__", subagentModelFallback: ["gpt-5.5"], }); - const { noteSubagentModelFailure } = await import("../src/codex/subagent-model-fallback"); + const { noteSubagentModelFailure } = await import("../../src/codex/subagent-model-fallback"); noteSubagentModelFailure("xai/grok-4.5", "429", cfg); noteSubagentModelFailure("grok-4.5", "429", cfg); let selectionReleases = 0; @@ -1247,7 +1247,7 @@ describe("native fallback account preview", () => { // what the route-model scope derivation inside handleResponses prevents. expect(previewCodexAccountForRequest(bound.affinityKey ?? null, cfg, now, undefined)).not.toBe("pool-a"); - const { noteSubagentModelFailure } = await import("../src/codex/subagent-model-fallback"); + const { noteSubagentModelFailure } = await import("../../src/codex/subagent-model-fallback"); noteSubagentModelFailure("xai/grok-4.5", "429", cfg); noteSubagentModelFailure("grok-4.5", "429", cfg); @@ -1298,7 +1298,7 @@ describe("native fallback account preview", () => { }); expect(bound).toMatchObject({ kind: "pool", accountId: "pool-a" }); cfg.activeCodexAccountId = "pool-b"; - const { noteSubagentModelFailure } = await import("../src/codex/subagent-model-fallback"); + const { noteSubagentModelFailure } = await import("../../src/codex/subagent-model-fallback"); noteSubagentModelFailure("xai/grok-4.5", "429", cfg); noteSubagentModelFailure("grok-4.5", "429", cfg); @@ -1364,7 +1364,7 @@ describe("native fallback account preview", () => { now: cooldownAt, resetAt: Math.floor((cooldownAt + 60 * 60_000) / 1_000), }); - const { noteSubagentModelFailure } = await import("../src/codex/subagent-model-fallback"); + const { noteSubagentModelFailure } = await import("../../src/codex/subagent-model-fallback"); noteSubagentModelFailure("gpt-5.6-sol", "429", cfg, "pool-a", now); expect(previewCodexAccountForRequest(bound.affinityKey ?? null, cfg, now, "shared")).toBe("pool-a"); @@ -1433,7 +1433,7 @@ describe("native fallback account preview", () => { now, resetAt: Math.floor((now + 60 * 60_000) / 1_000), }); - const { noteSubagentModelFailure } = await import("../src/codex/subagent-model-fallback"); + const { noteSubagentModelFailure } = await import("../../src/codex/subagent-model-fallback"); noteSubagentModelFailure("gpt-5.3-codex-spark", "429", cfg, "pool-b", now); noteSubagentModelFailure( "gpt-5.3-codex-spark", @@ -1546,7 +1546,7 @@ describe("native fallback account preview", () => { */ test("both fallback preview sites pass the model-eligible account set (#2509)", async () => { const source = await Bun.file( - fileURLToPath(new URL("../src/server/responses/core.ts", import.meta.url)), + fileURLToPath(new URL("../../src/server/responses/core.ts", import.meta.url)), ).text(); const previews = source.match(/subagentFallbackAccountPreview = \([^)]*\)/g) ?? []; @@ -1599,7 +1599,7 @@ describe("native fallback account preview", () => { }); updateAccountQuota("pool-a", 95, undefined, 20); updateAccountQuota("pool-b", 10, undefined, 20); - const { noteSubagentModelFailure } = await import("../src/codex/subagent-model-fallback"); + const { noteSubagentModelFailure } = await import("../../src/codex/subagent-model-fallback"); noteSubagentModelFailure("xai/grok-4.5", "429", cfg); noteSubagentModelFailure("grok-4.5", "429", cfg); @@ -1663,7 +1663,7 @@ describe("native fallback account preview", () => { }); updateAccountQuota("pool-a", 95, undefined, 20); updateAccountQuota("pool-b", 90, undefined, 20); - const { noteSubagentModelFailure } = await import("../src/codex/subagent-model-fallback"); + const { noteSubagentModelFailure } = await import("../../src/codex/subagent-model-fallback"); noteSubagentModelFailure("xai/grok-4.5", "429", cfg); noteSubagentModelFailure("grok-4.5", "429", cfg); @@ -2029,7 +2029,7 @@ describe("encrypted child native-only fallback", () => { }, }, }); - const { noteSubagentModelFailure } = await import("../src/codex/subagent-model-fallback"); + const { noteSubagentModelFailure } = await import("../../src/codex/subagent-model-fallback"); noteSubagentModelFailure("gpt-5.6-terra", "429", cfg); const response = await postSpawn(cfg, { diff --git a/tests/subagent-model-fallback-api.test.ts b/tests/routing/subagent-model-fallback-api.test.ts similarity index 92% rename from tests/subagent-model-fallback-api.test.ts rename to tests/routing/subagent-model-fallback-api.test.ts index 68f1f52681..339c5ad76b 100644 --- a/tests/subagent-model-fallback-api.test.ts +++ b/tests/routing/subagent-model-fallback-api.test.ts @@ -6,9 +6,9 @@ import { afterEach, describe, expect, test } from "bun:test"; import { mkdtempSync} 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 { removeTreeWithRetry } from "./helpers/remove-tree"; +import { handleManagementAPI } from "../../src/server/management-api"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const savedHome = process.env.OPENCODEX_HOME; let tempHome: string | null = null; @@ -90,4 +90,4 @@ describe("/api/subagent-model-fallback atomic validation", () => { expect(config.subagentModelFallback).toEqual(next); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/subagent-model-fallback.test.ts b/tests/routing/subagent-model-fallback.test.ts similarity index 99% rename from tests/subagent-model-fallback.test.ts rename to tests/routing/subagent-model-fallback.test.ts index 6e1b2f1271..e3e2dd4551 100644 --- a/tests/subagent-model-fallback.test.ts +++ b/tests/routing/subagent-model-fallback.test.ts @@ -18,21 +18,21 @@ import { selectAvailableSubagentModel, setSubagentQuotaPrimeForTests, subagentFallbackGuidanceText, -} from "../src/codex/subagent-model-fallback"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { NATIVE_MAIN_DRAIN_SENTINEL_MODELS } from "../src/codex/catalog/native-models"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/main-account"; -import { clearAccountNeedsReauth, markAccountNeedsReauth } from "../src/codex/account-runtime-state"; -import { clearAccountQuota, setAccountQuotaFromParsed, updateAccountQuota } from "../src/codex/quota"; +} from "../../src/codex/subagent-model-fallback"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { NATIVE_MAIN_DRAIN_SENTINEL_MODELS } from "../../src/codex/catalog/native-models"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/main-account"; +import { clearAccountNeedsReauth, markAccountNeedsReauth } from "../../src/codex/account-runtime-state"; +import { clearAccountQuota, setAccountQuotaFromParsed, updateAccountQuota } from "../../src/codex/quota"; import { canAcquireCodexQuotaProbeLease, canAcquireCodexQuotaScopeProbeLease, clearCodexUpstreamHealthForAccount, CODEX_QUOTA_PROBE_INTERVAL_MS, recordCodexUpstreamOutcome, -} from "../src/codex/routing"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/routing"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; // beforeEach writes three Codex credentials (NTFS ACL harden on Windows). Under // `bun test --isolate` on a loaded windows-latest runner that can exceed the diff --git a/tests/subagent-roster-retention.test.ts b/tests/routing/subagent-roster-retention.test.ts similarity index 93% rename from tests/subagent-roster-retention.test.ts rename to tests/routing/subagent-roster-retention.test.ts index ad2245fc56..b710eeb58c 100644 --- a/tests/subagent-roster-retention.test.ts +++ b/tests/routing/subagent-roster-retention.test.ts @@ -9,9 +9,9 @@ * 5-model roster. */ import { describe, expect, test } from "bun:test"; -import { handleManagementAPI } from "../src/server/management-api"; -import { ManagementRequest as Request } from "./helpers/management-auth"; -import type { OcxConfig } from "../src/types"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { ManagementRequest as Request } from "../helpers/management-auth"; +import type { OcxConfig } from "../../src/types"; function makeConfig(overrides: Partial = {}): OcxConfig { return { port: 10100, providers: {}, defaultProvider: "openai", ...overrides } as OcxConfig;