Windows apply_patch can commit the target mutation but never return completion, making retry unsafe
Summary
On Windows with @openai/codex 0.144.5, an apply_patch invocation created the intended scratch file with the exact expected SHA-256, but the tool call never returned a successful completion and was terminated after nonreturn.
This is a committed_without_completion state. Retrying automatically would be unsafe because the requested mutation is already durable even though no completion receipt exists.
Observed evidence
- Platform: Windows x64.
- Package:
@openai/codex0.144.5. - Component:
codex.exe --codex-run-as-apply-patch. - Intended target: a non-sensitive scratch text file in a local test workspace.
- Expected SHA-256:
e27a32267b34b6ee0b9814b94569412f3c5366642c1ca4add23a899f74d2f0bf. - Actual SHA-256 after read-only reconciliation:
e27a32267b34b6ee0b9814b94569412f3c5366642c1ca4add23a899f74d2f0bf. - Target visible and readable: yes.
- Tool returned a successful completion: no.
- A completion timeout/nonreturn was observed: yes.
- Tool was terminated after nonreturn: yes.
- Automatic retry performed: no.
- Original attempt ID: not available.
- Exact timeout duration: not recorded and intentionally not inferred.
- No host completion/cancellation receipt was available after termination.
No private absolute paths, credentials, source contents, or repository data are included in this report.
Safety impact
The caller cannot distinguish a mutation that never happened from one that committed but lost its completion signal. A generic retry policy can therefore duplicate or conflict with an already-durable mutation.
The safe local response is to reconcile the exact target and expected hash read-only, classify the state as committed_without_completion, and prohibit automatic retry.
Requested host contract
- Allocate and expose a stable attempt ID before mutation begins.
- Return an explicit terminal state within a bounded caller-visible deadline.
- On timeout, expose exact-target read-only reconciliation fields: intended target/marker, expected hash, actual hash, visibility, and reconciliation time.
- Return
committed_without_completionwhen expected bytes are present without a successful completion receipt. - Return a cancellation/termination receipt and whether the child/tool remains alive.
- Mark timeout or ambiguous completion as non-retryable by default; require explicit operator action for another attempt.
- Correlate tool return, timeout, termination, and reconciliation events under the same attempt ID.
Related issues
- #21117 covers duplicate approval and an app-server hang during an apply_patch sandbox retry path.
- #20874 covers Windows command output loss and hanging after redirected output was written.
This report is related but distinct: the target mutation itself was durably committed with the expected hash while no successful apply_patch completion was delivered.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗