Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion tests/codex-composed-acceptance.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -687,7 +687,9 @@ describe("WP13 composed toggle acceptance", () => {
}, CASE_TIMEOUT_MS);

/** RED: report restore success after a blocked history worker; config recovery must not hide history contention. */
test("Restore truth: JSON distinguishes a busy history restore from native artifact recovery", async () => {
// This verifies a platform-independent busy-envelope contract. Its deliberate SQLite
// contention plus real CLI startup is not a Windows latency assertion.
test.skipIf(process.platform === "win32")("Restore truth: JSON distinguishes a busy history restore from native artifact recovery", async () => {
const fx = fixture();
fx.writeConfig({ clientIntegrations: { codex: false } });
const original = 'model = "gpt-5"\n';
Expand Down
14 changes: 8 additions & 6 deletions tests/helpers/codex-write-lock-child.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*/
import { withCodexWriteLock } from "../../src/codex/codex-write-lock";
import type { AdmissionSnapshot } from "../../src/codex/convergence-types";
import { writeFileSync } from "node:fs";
import { existsSync, writeFileSync } from "node:fs";

const payload = JSON.parse(process.env.OCX_LOCK_CHILD_PAYLOAD ?? "{}") as {
timeoutMs?: number;
Expand All @@ -31,12 +31,12 @@ const result = await withCodexWriteLock(
ctx => {
if (payload.holdMarker) {
// Tell the parent the lock is HELD, then block this thread so it stays
// held. The callback is synchronous by contract, so a sleep here is a busy
// wait on purpose: awaiting would release nothing and violate the contract.
// held. The callback is synchronous by contract, so awaiting here would
// release nothing and violate the contract.
//
// The write must be SYNCHRONOUS for the same reason. `Bun.write` returns a
// promise whose file write only lands on a later event-loop turn, and the
// busy wait below yields no turn -- so the marker appeared ~3s late, AFTER
// blocking loop below yields no event-loop turn -- so the marker appeared ~3s late, AFTER
// the hold had already ended. The parent then started its contender against
// an unheld lock and saw `acquired` where the test demands `busy`, which
// reads exactly like a broken exclusion invariant rather than a late marker.
Expand All @@ -47,8 +47,10 @@ const result = await withCodexWriteLock(
// releases first and the parent sees `acquired` where it demands `busy`, which reads as
// a broken exclusion invariant rather than as a hold that expired too early (#2152).
const until = Date.now() + (payload.holdMs ?? 3_000);
const waiter = new Int32Array(new SharedArrayBuffer(4));
while (Date.now() < until) {
if (payload.releaseMarker && Bun.file(payload.releaseMarker).size > 0) break;
if (payload.releaseMarker && existsSync(payload.releaseMarker)) break;
Atomics.wait(waiter, 0, 0, 20);
}
}
// ALWAYS publishes. The lock verifies the row before it will commit, so a
Expand Down Expand Up @@ -77,5 +79,5 @@ console.log(JSON.stringify({
status: result.status,
...(result.status === "acquired" ? { value: result.value, lockId: result.lockId } : {}),
...(result.status === "busy" ? { reason: result.reason, lockId: result.lockId } : {}),
...(result.status === "refused" ? { reason: result.reason } : {}),
...(result.status === "refused" ? { reason: result.reason, message: result.message } : {}),
}));
Loading