Source: U24 (#24) ce-code-review — cross-model Codex adversarial peer, P1@conf75. Disposition: DEFER to the #28/#29 concurrent-config-write cluster (below the merge bar; see reachability).
Mechanism (real)
installCodex reads config.toml twice with no lock between:
src/install/codex.ts:220 — const existingConfig = readToml(configTomlPath(home)) (pre-flight), then :228 const token = extractCodexToken(existingConfig) ?? randomUUID() captures token A.
- The authoritative write re-reads the file inside
mergeConfig (src/configwrite/engine.ts:~229) but applies a static patch built from A, and replaceSubtrees:['mcp_servers.agent-os'] replaces the whole entry.
If the embedded credential changes A→B between those two reads, the write puts A back. Since the gate reads config.toml live, revoked A then authenticates while B is rejected.
Why deferred (reachability)
If we ever fix it
Derive+reuse the token inside mergeConfig's callback form from that callback's current value (eliminating the separate snapshot), or add compare-and-swap/lock on publish. Both belong with the engine-level #28 fix, not a point patch here.
Not a blocker for #24 — normal single-user macOS flow never hits it.
Source: U24 (#24) ce-code-review — cross-model Codex adversarial peer, P1@conf75. Disposition: DEFER to the #28/#29 concurrent-config-write cluster (below the merge bar; see reachability).
Mechanism (real)
installCodexreads config.toml twice with no lock between:src/install/codex.ts:220—const existingConfig = readToml(configTomlPath(home))(pre-flight), then:228const token = extractCodexToken(existingConfig) ?? randomUUID()captures token A.mergeConfig(src/configwrite/engine.ts:~229) but applies a static patch built from A, andreplaceSubtrees:['mcp_servers.agent-os']replaces the whole entry.If the embedded credential changes A→B between those two reads, the write puts A back. Since the gate reads config.toml live, revoked A then authenticates while B is rejected.
Why deferred (reachability)
installCodexwrites our token, and it reuses rather than rotates. Getting from A to B requires a concurrent uninstall+reinstall cycle interleaving a running install's ~ms window: concurrent invocation of a manual, single-user CLI.If we ever fix it
Derive+reuse the token inside
mergeConfig's callback form from that callback's current value (eliminating the separate snapshot), or add compare-and-swap/lock on publish. Both belong with the engine-level #28 fix, not a point patch here.Not a blocker for #24 — normal single-user macOS flow never hits it.