Raised by the PR review bot on #77 (P2) and deferred there to keep that PR's scope to the change it declares.
Problem
_codex_rollout_window() reads backward in chunks but joins the entire window before returning, and the caller then applies splitlines() to it. For a transcript at or above _CODEX_ROLLOUT_SCAN_LIMIT (64 MiB) that is two large allocations per resolution, even though the qualifying record is normally within the last few KiB.
The coordinator resolves the host profile during both startup_preflight() and issue_policy_envelope(), so a long-running session can pay this cost twice per routed request.
Why it was deferred rather than fixed in #77
_codex_rollout_window is shared with the Codex rollout path. Changing its scan strategy alters behaviour for a second, already-shipped consumer, which is outside what #77 declares and would need its own regression coverage for the Codex side. #77 reuses the helper unchanged precisely so it inherits the existing hardening.
Suggested approach
Scan backward chunk by chunk and stop as soon as the newest qualifying record validates, instead of materializing the full window. Both consumers select the NEWEST matching record, so neither needs the whole window in memory.
Constraints to preserve:
- the incomplete-tail rule (a snapshot whose final record is not newline-terminated must still fail closed);
- the leading partial-line discard when the window is truncated;
- the per-line size cap and strict JSON decoding;
- the post-read
fstat identity and size re-check.
A chunk boundary must not be allowed to split a record such that a partial line parses as valid.
Note
Performance only. No correctness or security consequence is claimed, and the current behaviour is bounded — it is a fixed 64 MiB ceiling, not unbounded growth.
Raised by the PR review bot on #77 (P2) and deferred there to keep that PR's scope to the change it declares.
Problem
_codex_rollout_window()reads backward in chunks but joins the entire window before returning, and the caller then appliessplitlines()to it. For a transcript at or above_CODEX_ROLLOUT_SCAN_LIMIT(64 MiB) that is two large allocations per resolution, even though the qualifying record is normally within the last few KiB.The coordinator resolves the host profile during both
startup_preflight()andissue_policy_envelope(), so a long-running session can pay this cost twice per routed request.Why it was deferred rather than fixed in #77
_codex_rollout_windowis shared with the Codex rollout path. Changing its scan strategy alters behaviour for a second, already-shipped consumer, which is outside what #77 declares and would need its own regression coverage for the Codex side. #77 reuses the helper unchanged precisely so it inherits the existing hardening.Suggested approach
Scan backward chunk by chunk and stop as soon as the newest qualifying record validates, instead of materializing the full window. Both consumers select the NEWEST matching record, so neither needs the whole window in memory.
Constraints to preserve:
fstatidentity and size re-check.A chunk boundary must not be allowed to split a record such that a partial line parses as valid.
Note
Performance only. No correctness or security consequence is claimed, and the current behaviour is bounded — it is a fixed 64 MiB ceiling, not unbounded growth.