From e7d9829e6a4aac9199056ccc952f36c4503f5838 Mon Sep 17 00:00:00 2001 From: luvs01 <27862058+luvs01@users.noreply.github.com> Date: Mon, 14 Sep 2026 10:48:21 +0900 Subject: [PATCH 1/2] test(codex): compare the injected catalog path as a decoded TOML value The paginated-home regression test asserted that config.toml literally contains the catalog path. A Windows path is written as a TOML basic string with escaped separators, so the raw file text holds C:\\Users\\... while the assertion looked for C:\Users\... . The test failed on every Windows shard and passed everywhere else, which took the whole windows job down for unrelated pull requests. What the picker actually reads is the decoded value, so the assertion now decodes the model_catalog_json basic string and compares that. POSIX behavior is unchanged, since a path with no backslash decodes to itself. --- .../codex-inject-integration.test.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/codex-integration/codex-inject-integration.test.ts b/tests/codex-integration/codex-inject-integration.test.ts index d0dda14d01..18b26970ad 100644 --- a/tests/codex-integration/codex-inject-integration.test.ts +++ b/tests/codex-integration/codex-inject-integration.test.ts @@ -16,6 +16,16 @@ const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta setDefaultTimeout(SPAWN_BUDGET_MS); +// Reads back what a TOML consumer would see for a top-level basic-string key. A Windows path +// is stored with escaped separators, so the raw file text never contains the unescaped path. +function decodeTomlBasicString(toml: string, key: string): string | undefined { + const line = toml.split(/\r?\n/u).find(candidate => candidate.trimStart().startsWith(`${key} =`)); + if (!line) return undefined; + const value = line.slice(line.indexOf("=") + 1).trim(); + if (!value.startsWith(String.fromCharCode(34))) return undefined; + return JSON.parse(value) as string; +} + // Full injectCodexConfig runs in a subprocess with isolated CODEX_HOME/OPENCODEX_HOME so // module-level path constants bind to the temp dirs (same pattern as codex-journal.test.ts). function runInject(codexHome: string, ocxHome: string, configJson = "{}"): { stdout: string; status: number } { @@ -438,7 +448,10 @@ describe("injectCodexConfig integration (Design B)", () => { }); const written = readFileSync(configPath, "utf8"); expect(written).toContain("model_catalog_json"); - expect(written).toContain(catalogPath); + // What the picker reads is the decoded TOML value, not the raw file text. A Windows path + // is written as a basic string with escaped separators, so asserting on the raw text + // compared an unescaped path against escaped bytes and failed on Windows only. + expect(decodeTomlBasicString(written, "model_catalog_json")).toBe(catalogPath); expect(readFileSync(rollout, "utf8")).toBe(bytes); }); From 3de5e91c4018902bf2c968226f1172467a459b75 Mon Sep 17 00:00:00 2001 From: luvs01 <27862058+luvs01@users.noreply.github.com> Date: Mon, 14 Sep 2026 16:41:40 +0900 Subject: [PATCH 2/2] test(codex): require root catalog path readback --- .../codex-inject-integration.test.ts | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/tests/codex-integration/codex-inject-integration.test.ts b/tests/codex-integration/codex-inject-integration.test.ts index 18b26970ad..5ffbc54f99 100644 --- a/tests/codex-integration/codex-inject-integration.test.ts +++ b/tests/codex-integration/codex-inject-integration.test.ts @@ -16,16 +16,21 @@ const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta setDefaultTimeout(SPAWN_BUDGET_MS); -// Reads back what a TOML consumer would see for a top-level basic-string key. A Windows path +// Reads back what a TOML consumer would see for a top-level string key. A Windows path // is stored with escaped separators, so the raw file text never contains the unescaped path. -function decodeTomlBasicString(toml: string, key: string): string | undefined { - const line = toml.split(/\r?\n/u).find(candidate => candidate.trimStart().startsWith(`${key} =`)); - if (!line) return undefined; - const value = line.slice(line.indexOf("=") + 1).trim(); - if (!value.startsWith(String.fromCharCode(34))) return undefined; - return JSON.parse(value) as string; +function readRootTomlString(toml: string, key: string): string | undefined { + const value = Bun.TOML.parse(toml)[key]; + return typeof value === "string" ? value : undefined; } +test("catalog readback requires a root string rather than a nested namesake", () => { + const key = "model_catalog_json"; + const catalog = String.raw`C:\Codex\catalog.json`; + expect(readRootTomlString(`${key} = ${JSON.stringify(catalog)}\n[profile]\n${key} = "nested"\n`, key)).toBe(catalog); + expect(readRootTomlString(`[profile]\n${key} = ${JSON.stringify(catalog)}\n`, key)).toBeUndefined(); + expect(readRootTomlString(`[[profiles]]\n${key} = ${JSON.stringify(catalog)}\n`, key)).toBeUndefined(); +}); + // Full injectCodexConfig runs in a subprocess with isolated CODEX_HOME/OPENCODEX_HOME so // module-level path constants bind to the temp dirs (same pattern as codex-journal.test.ts). function runInject(codexHome: string, ocxHome: string, configJson = "{}"): { stdout: string; status: number } { @@ -451,7 +456,7 @@ describe("injectCodexConfig integration (Design B)", () => { // What the picker reads is the decoded TOML value, not the raw file text. A Windows path // is written as a basic string with escaped separators, so asserting on the raw text // compared an unescaped path against escaped bytes and failed on Windows only. - expect(decodeTomlBasicString(written, "model_catalog_json")).toBe(catalogPath); + expect(readRootTomlString(written, "model_catalog_json")).toBe(catalogPath); expect(readFileSync(rollout, "utf8")).toBe(bytes); });