fix(codex): bound aggregate rollout inspection during startup - #5703
konstantinosbotonakis wants to merge 1 commit into
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
✅ Deterministic PR hygiene checks passed. |
⏳ DRAFT
What to do
Review readiness checklist
0/4 boxes ticked. This PR stays in draft until every box above is ticked. |
리뷰 · 우선순위 66 / 80이 PR은 Codex를 켜기 전에 하는 기록 검사를, 한 번 호출할 때 롤아웃 내용 64 MiB까지만 읽게 막습니다. 검사 결과는 세 가지입니다. clean이면 코디네이터를 만들 수 있습니다. residue이면 이미 라우팅된 홈을 입양(adopt)합니다. indeterminate이면 옛 경로(legacy-uncoordinated)로 쓰고, 코디네이터 행은 만들지 않습니다. 쓰기는 막지 않습니다. 이번 패치는 히스토리 데이터베이스와 백업 목록이 예산 하나를 같이 쓰게 합니다. 호출할 때마다 64 MiB로 다시 채웁니다. 다음 파일이 남은 예산을 넘으면 그 파일은 읽지 않고 indeterminate를 돌려줍니다. 끝까지 못 본 기록을 clean으로 두지 않습니다. 첫 indeterminate에서 뒤 검사는 멈춥니다. residue는 기억했다가, 끝까지 indeterminate가 없으면 처음 residue를 돌려줍니다. 베이스는 src/codex/native-residue.ts:465 - 파일을 읽기 전에 파일 크기 전체를 예산에서 뺍니다. 가운데서 residue나 깨진 줄을 만나 멈춰도, 안 읽은 뒷부분은 이미 쓴 예산입니다. 그다음 백업 검사가 남은 예산으로 돌아갑니다. src/codex/native-residue.ts:703 - PR 본문은 뒤 표면을 다 분류할 수 있을 때만 처음 residue를 유지한다고 적습니다. 이 줄이 그 코드입니다. indeterminate가 나오면 그 자리에서 끝이고, 앞에서 기억한 residue는 버려집니다. 히스토리에서 residue를 본 뒤 백업이 예산에 걸리면 결과는 indeterminate입니다. 입양 대신 옛 경로로 갑니다. src/codex/native-residue.ts:590 - 히스토리는 model_provider가 opencodex인 줄의 롤아웃을 읽지 않습니다. 그 파일은 백업 목록에서 다시 크기를 뺍니다. 경로가 같아도 두 번 셉니다. 테스트 1037행이 이 동작을 고정합니다. 파일을 한 번만 세면 64 MiB 안이어도, 히스토리와 백업이 각각 빼면 indeterminate가 됩니다. src/codex/native-residue.ts:86 - 총량 한도가 파일당 한도와 같은 64 MiB입니다. 파일 하나가 한도를 꽉 채우면, 다음 파일은 크기가 1바이트여도 총량에서 걸립니다. tests/codex-integration/codex-native-residue.test.ts:1007 - 새 테스트는 세 개입니다. 네이티브 파일 두 개가 총량을 넘는 경우, 예산이 호출마다 다시 채워지는 경우, 같은 파일을 히스토리와 백업이 같이 세는 경우입니다. 먼저 residue를 찾고 나중 파일이 예산을 넘는 경우, opencodex 줄만 있는 큰 백업이 residue 대신 indeterminate가 되는 경우는 없습니다. 메인테이너의 판단이 필요한 지점 64 MiB가 기가바이트 읽기를 막는 상한인지, 입양과 coordinated를 포기하는 상한인지 정해야 합니다. 총량을 파일당 한도와 같게 두면, 긴 대화가 두 개만 되어도 매번 옛 경로로 갑니다. 예산은 실제 읽은 바이트만 뺄지, 같은 경로는 한 번만 뺄지, 이미 본 residue를 나중 indeterminate가 지워도 되는지도 정해야 합니다. 준비 체크는 0/4입니다. 너의 추천 총량 상한은 두세요. 못 본 기록은 clean으로 두지 마세요. 상한은 64 MiB보다 크게, 이번 맥 관측 872 MiB보다는 작게 두는 편이 이 버그에 맞습니다. 465행은 실제로 읽은 만큼만 빼거나, 이미 센 경로는 다시 빼지 마세요. 703행에서 앞 residue를 지울지는 입양을 남길지와 같이 정하세요. residue를 남기면 그 경우를 1007행 옆에 테스트로 두세요. opencodex 줄만 있고 백업이 총량을 넘는 경우도 같이 두세요. 드래프트와 준비 체크는 그 다음에 채우면 됩니다. 닫을 중복 PR은 없습니다. 이 댓글은 grok-bot이 작성했습니다 |
The native-residue classifier limited each referenced rollout to 64 MiB but not the total, so the read-only startup preflight could parse gigabytes of conversation history on every Codex launch (#5701). One observation now reads at most 64 MiB of rollout content across the history database and backup manifest together; a file that would exceed the remaining budget is reported indeterminate before it is read, and classification stops at the first indeterminate surface. Exhausting the budget never reports clean. Carries #5703. Closes #5701. Co-authored-by: Konstantinos <37538071+konstantinosbotonakis@users.noreply.github.com>
The native-residue classifier limited each referenced rollout to 64 MiB but not the total, so the read-only startup preflight could parse gigabytes of conversation history on every Codex launch (#5701). One observation now reads at most 64 MiB of rollout content across the history database and backup manifest together; a file that would exceed the remaining budget is reported indeterminate before it is read, and classification stops at the first indeterminate surface. Exhausting the budget never reports clean. Carries #5703. Closes #5701. Co-authored-by: Konstantinos <37538071+konstantinosbotonakis@users.noreply.github.com>
…, sub-agent identity, agent-message recovery, 98% main lock (#5743) * docs(devlog): plan lane L4 Codex integration, CLI and service bundle * fix(service): preserve connected client key on uninstall (#5713) ocx service uninstall unconditionally deleted service-api-token, which on a remote-hub client is the per-client data-plane key issued by the hub (#5699). Uninstall now deletes the token only under the client lifecycle and config mutation locks, and only when persisted client state is disconnected and no pending connect marker owns the current key's fingerprint. Connect publishes that fingerprint marker before writing the key and clears it on commit or rollback. Lock, state-read and unlink failures report cleanup as unverified. On top of #5713: rollback checks the pending marker against its own fingerprint, so a valid marker for a different key is left alone instead of adding a spurious rollback failure. Carries #5713. Closes #5699. Co-authored-by: 정우철 <oocheol@naver.com> * fix(codex): bound aggregate rollout inspection during startup (#5703) The native-residue classifier limited each referenced rollout to 64 MiB but not the total, so the read-only startup preflight could parse gigabytes of conversation history on every Codex launch (#5701). One observation now reads at most 64 MiB of rollout content across the history database and backup manifest together; a file that would exceed the remaining budget is reported indeterminate before it is read, and classification stops at the first indeterminate surface. Exhausting the budget never reports clean. Carries #5703. Closes #5701. Co-authored-by: Konstantinos <37538071+konstantinosbotonakis@users.noreply.github.com> * fix(codex-home): import path expansion without the config facade (#5548) src/codex/home.ts imported expandUserPath from the ../config barrel, which re-enters the config facade before the Codex home resolver has initialized. On a fresh WSL process that import cycle could fail before the home was resolved. The resolver now imports expandUserPath from src/config/paths.ts directly, and a fresh-process regression test loads the resolver first with a tilde CODEX_HOME. Only the import fix, its structure note and the fresh-process test are carried; the PR's cli-help, service and docker expectation edits target the documented container-only failures and stay out. Carries #5548 (partial). Co-authored-by: Vadevious <Vadevious@users.noreply.github.com> * docs(remote-hub): translate the service uninstall key-retention note Adds the #5713 uninstall paragraph to the fr, ja, ru, tr, zh-cn and zh-tw remote hub guides so no locale describes the old unconditional token deletion. Co-authored-by: 정우철 <oocheol@naver.com> * fix(identity): name the worker's own model when a sub-agent is spawned (#5221) Codex stores a session's instruction block once and replays it verbatim into a sub-agent spawned on a different model, so a worker inherited the parent's identity sentence and answered identity questions with the parent's model id (#5217). The catalog no longer bakes a model id into base_instructions; it writes the model-neutral line. The destination is named at request time: the request parser names the neutral line or a stale routed sentence in the top-level instructions and developer items, adapters that call identifyRoutedModel still settle on the wire model id, and the Responses passthrough renames on a routed destination and drops the sentence on a native/forward one. Only sentences this proxy generated are matched. Rebuilt on current dev. On top of #5221: the parser also covers instructions, so adapters that build their own system text (devin, ollama-native, cursor, qoder, codebuddy, mimo-free) keep a named identity; a forward strip that empties instructions or a developer item removes it instead of sending it blank; catalog cases live in a sibling test file because codex-catalog.test.ts is at its size cap; slug-codec and configured-native-models expectations follow the neutral catalog. Carries #5221. Closes #5217. Co-authored-by: sbc1-code <207095575+sbc1-code@users.noreply.github.com> * fix(responses): recover FOLLOWUP_TASK and FINAL_ANSWER agent messages (#5009) Opt-in encrypted agent-task recovery handled only NEW_TASK and MESSAGE, so an unreadable FOLLOWUP_TASK or FINAL_ANSWER item either failed without recovery or, for an unrecognised envelope shape, measured as readable and was forwarded as raw ciphertext. Recovery and the unreadable-ciphertext guard now recognise all four codex-rs agent-message types, including a FINAL_ANSWER without a Task name line. Sender and admission checks are unchanged: credential admission still runs before any cache access, the structured author must equal the header sender, and the recipient is cross-checked whenever the header names one. The cache key is a JSON-encoded fixed-order tuple that binds the structured recipient, and a recovered assignment that echoes the other routing family is rejected. agentTaskRecovery stays default-off. Carries #5009. Co-authored-by: Zhaofeng Li <lzfxxx@gmail.com> * docs(subagents): describe four-type agent-task recovery in every locale The localized sub-agent guides still said agentTaskRecovery loses message-type follow-ups, which contradicts the #5009 recovery of FOLLOWUP_TASK and FINAL_ANSWER. Co-authored-by: Zhaofeng Li <lzfxxx@gmail.com> * feat(codex): lock the main account at 98% by default (#5694) Codex Desktop disables its send button once the ChatGPT account window reads 0% remaining, even when the user routes every request to another provider. The main-account hard lock already stops ocx from admitting new identity-matched main-account requests at a usage threshold, but it was opt-in at 99%. The lock is now on by default at 98%: an absent or true codexMainAccountHardLock enables it, and only an explicit false opts out. Every gate reads one resolver (isMainAccountHardLockEnabled); the settings route persists false and deletes the key for true, like fastRows; a malformed hand edit falls back to the default; the blocked-request message derives its percent from the constant. Trade-offs: while blocked, the main account's Luna Reserve cannot activate; switching the setting off lets the main account run to exhaustion. The old switch deleted the key when turned off, so an earlier opt-out now reads as on and has to be switched off once more. GUI copy (all locales), the English and Korean accounts reference, and structure/providers/openai-tiers.md describe the new default. Refs #5694. * docs(devlog): record L4 publish plan * test(gui): expect the 98% hard-lock blocked label The main-card blocked label follows the #5694 threshold change. * fix(identity): drop the neutral catalog line on native destinations After #5221 the catalog stores the model-neutral identity line, so a native worker spawned from a routed parent received "Do not claim to be GPT-5 or to be made by OpenAI", contradicting Codex's own model_switch identity. The forward strip now removes the neutral line as well as a routed sentence; an instructions value that becomes empty is still removed. Co-authored-by: sbc1-code <207095575+sbc1-code@users.noreply.github.com> * fix(gui): use the Turkish locative -de after %98 Ninety-eight ends in a front vowel, so the hard-lock title reads %98’de. * fix(identity): name the final wire model and system-role items Two review findings on the #5221 carry. The request parser names the identity sentence from the client selector, which can be an alias, a namespaced slug or a combo name, and adapters that never call identifyRoutedModel (devin, ollama-native, cursor, qoder, codebuddy, coding-agent) shipped that name. The final route normalization now renames our sentence to route.modelId, where the dispatched id is known and every dispatch path reads the context afterwards. The parser also names system-role input items, not only developer items. Co-authored-by: sbc1-code <207095575+sbc1-code@users.noreply.github.com> --------- Co-authored-by: 정우철 <oocheol@naver.com> Co-authored-by: Konstantinos <37538071+konstantinosbotonakis@users.noreply.github.com> Co-authored-by: Vadevious <Vadevious@users.noreply.github.com> Co-authored-by: sbc1-code <207095575+sbc1-code@users.noreply.github.com> Co-authored-by: Zhaofeng Li <lzfxxx@gmail.com>
Summary
Bound native Codex residue inspection during startup to 64 MiB of rollout content per observation.
ocx ensurecan invoke this path before starting Codex; the existing per-file limit still allowed it to parse gigabytes across many files.indeterminatebefore reading a file that would exceed the budget. Keep existing refusal and legacy compatibility behavior; never treat an incomplete scan as clean.structure/config.md.On the same live macOS history, the read-only preflight improved from 5.732–6.397 s / 872–885 MiB peak RSS to 0.934 s / 232 MiB after applying the patch to 2.64.0. These are local observations, not a controlled benchmark or proof that every machine freeze is fixed.
Large histories that exceed the new total budget now remain indeterminate instead of completing an unbounded inspection. History is not deleted or rewritten. Provider, authentication, and routing settings are unchanged.
Closes #5701.
Verification
bun test tests/codex-integration/codex-native-residue.test.ts: 87 passed, 0 failed.bun run typecheck: passed.bun run privacy:scan: passed.bun run structure:check: passed.bun run test:changed --parallel=2: intentionally stopped after more than six minutes when the two test workers exceeded 10 GiB combined resident memory. Incomplete, not a passing result. Focused regression coverage was used under the repository's resource-cost exception; broader coverage remains for maintainer-triggered CI.The full cross-platform suite and repository CI have not been run. This is a draft contributor PR; no merge or release is requested by this operation.
Checklist
Review readiness checklist
This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:
Required local validation passed; commands, results, and any full-suite exception are documented.
I pushed my PR to a recent dev commit (at most 10 behind; a maintainer may still ask for the exact tip before merge).
I resolved all correct Codex and CodeRabbit findings.
My PR is ready for review.