Codex Compaction Recovery Turns a Stuck Preflight Into a Bounded Restart
Codex compaction is not a feature most users think about until it starts breaking the part they do care about: the next answer. That is why OpenClaw PR #85500 is more interesting than its small diff suggests. It turns a stuck native compaction preflight from an ambient runtime failure into a bounded recovery path: close the shared Codex app-server client, retry once, and report whether recovery happened.
That sounds like maintenance plumbing because it is. But agent infrastructure is mostly maintenance plumbing with a model attached. Long-running coding agents have to keep enough context to remain useful without carrying so much context that every turn becomes slow, expensive, or impossible to replay. Compaction is the garbage collector for conversation state. When it wedges, the user does not see “compaction subsystem failed.” They see an agent that suddenly cannot dispatch, cannot continue, or keeps failing before the model ever has a chance to be smart.
A retry is boring. A bounded retry is architecture.
The patch adds a new constant, MAX_CODEX_NATIVE_COMPACTION_ATTEMPTS = 2, and a typed CodexNativeCompactionTimeoutError. If waiting for thread/compact/start completion times out on the first attempt, OpenClaw logs that Codex app-server compaction timed out, closes the client, and retries with a fresh one. If the second attempt also times out, it closes again and returns a failed compaction result rather than pretending the preflight succeeded.
The regression test is nicely specific. It sets OPENCLAW_CODEX_COMPACTION_WAIT_TIMEOUT_MS to 100, simulates a first client that hangs, verifies first.close() is called once, then uses a second client that emits thread/tokenUsage/updated and item/completed. The expected recovery result records tokensAfter as 12_345, itemId as compact-2, signal as item/completed, compactionAttempts as 2, and recoveredAfterAppServerRestart as true.
That metadata matters. Silent recovery is better than silent failure, but observable recovery is better than both. If an operator sees compaction succeeding only after app-server restarts, that is a health signal. It tells you the steady-state path may still be sick even if users are no longer completely blocked. In production agent systems, “it eventually worked” is not enough; you need to know whether the runtime had to kick itself in the shins first.
The shared-client blast radius is the real review comment
ClawSweeper’s critique on the PR is the right one: closing the cached shared app-server client can interrupt concurrent Codex requests or cause a transient runtime restart. That is not a theoretical purity concern. It is the operational tradeoff at the center of this fix. The patch does not cancel one stuck compaction task with surgical precision; it restarts the shared client because the system has decided a wedged preflight is worse than a temporary blast radius.
For a single-user local setup, that is probably the right call. The user would rather the runtime recover than sit behind a failed compaction forever. For a multi-session deployment, it is more complicated. If several Codex-backed sessions share the app-server client, one stuck compaction can now cause collateral interruption for unrelated work. That may still be preferable, but it should be treated as an availability decision, not a free fix.
This is where agent platforms need to mature past “does the model answer?” reliability. Coding agents increasingly look like small distributed systems: a gateway, an app-server, session stores, compaction, replay, tool policies, auth refresh, channel delivery, and a model provider or three. Restarting one component to recover another is a normal systems move, but normal systems moves need scope, metrics, and eventually isolation boundaries. Today the boundary is the shared client. Tomorrow, the better design may be per-thread cancellation, app-server health probes, or a circuit breaker that marks a compaction lane unhealthy without disturbing unrelated sessions.
Why this matters in Codex-vs-Cursor-vs-Claude comparisons
Most public comparisons of coding agents still over-index on model output: which one writes the cleaner diff, explains the bug better, or guesses the test command. That is useful, but incomplete. A daily-driver coding assistant wins by surviving the unglamorous paths: session replay, long-context cleanup, failed tool calls, auth expiry, stuck subprocesses, and partial restarts. The model can be excellent and the product can still be unreliable if the runtime strands requests behind a wedged preflight.
PR #85500 is a concrete example of that reliability layer becoming visible. It was opened on May 22 by steipete, merged about an hour later, and changed only three files in its first commit: the changelog, compact.ts, and compact.test.ts. The label set tells the story too: extensions: codex, P1, and merge-risk: availability. This is not a headline feature. It is a patch to keep the machine from getting stuck behind its own maintenance step.
Practitioners should take two things from it. First, if you run OpenClaw with Codex in workflows that depend on long-lived sessions, watch compaction telemetry. Timeouts, retries, and recovery-after-restart should be treated as health signals, not curiosities in a log file. Second, if you are evaluating coding-agent platforms, ask about failure recovery paths as much as benchmark scores. Can the runtime recover from a stuck preflight? Does it expose that recovery? Does the fix disrupt other users? Those questions are boring until they decide whether your agent can be left alone for an afternoon.
The editorial read is simple: OpenClaw is slowly converting hidden agent-runtime failure modes into bounded, observable recovery paths. That is what infrastructure does. It does not make the demo prettier; it makes the thing safe enough to keep using after the demo ends.
Sources: OpenClaw PR #85500, PR patch, related compaction work