fix: read verified canonical Codex rollouts

Merged
KH
8h ago
+297-46

Summary

Codex hook binding verifies a canonical rollout path, but the reader previously reopened the original path. An alias retargeted between verification and reading could therefore select a different file. Pass the verified canonical path into the callback and use it in the actual rollout reader.

Add second-snapshot refusal tests for a released parent lock, a closed rollout and changed captured birth evidence, while retaining the constant two-snapshot scaling check. Document that multi-chat app-server/IDE sessions and CLI roots with live subagents skip the SessionStart preamble and early activation; those actions are not deferred or replayed. Missing turn IDs, unavailable birth evidence and a rollout outside the core's configured Codex homes leave hook work pending.

This is a separate follow-up to merged #2090. These are local context-binding checks, not authentication against a malicious process running as the same user. The installed Codex0.166 turn-ID assumption was checked against its pinned submission UUID7 implementation; custom harness versions may differ. No UUID-only restriction is added.

Test Plan

  • Three targeted tests pass: canonical reader with a retargeted alias; second-snapshot lock/rollout/birth mutations deny; 2 and 12 held rollouts both use exactly two snapshots.
  • Seven affected actual hook route and registration-guidance tests pass.
  • Exact merged-base/head proof: 29f4017e5f8d2ae83d96c9f976c62aefcd98063a fails the canonical-read regression; 00fec7ebdc585c50ed1c75a4ad6e9ab1ddb09c1e passes it. Both arms compile and execute the actual binding helper and reader.
  • Cargo fmt, pinned Prettier, quality comparison (105 inherited findings on both sides; none new) and final Veto code/security/secrets review pass.
  • Current-head CI and independent review.

RelayFlow Proof

  • Change type: bugfix
  • RelayFlow case: codex-hook-canonical-read

The runner applies the same canonical-read test to both exact clean revisions. It transparently adapts only the base fixture's callback ABI: the old FnOnce() captures the original alias, matching the old reader; the new FnOnce(&Path) receives the verified canonical path. The test retargets the alias after verification and confirms the alternate file differs. Neither arm changes production code. Dirty revisions, compile failures or a skipped test do not count as a reproduced bug; fixture overlays are restored afterward.


Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.