把上下文治理寫進 code review
上一章把往上下文裏塞東西收成類型。類型過了,這段文字仍然可以合法地又長、又勤、又無界。擋這些後果的,是倉庫根十行禁令,外加一份會把同一節再讀一遍的評審 skill。
ContextualUserFragment 的改動,編譯器仍會放行一份會打掉 cache、撐滿窗口或讓舊會話恢復失敗的 PR;以及六條禁令裏,哪幾條落在程式碼裏,哪幾條只能靠人和 skill 守。
- 注入有沒有登記成 ContextualUserFragmentAGENTS.md L100
- 這一條有沒有硬上限AGENTS.md L97 · protocol.rs L3112
- 單條是否可能超過 10K tokenAGENTS.md L98 · model_info.rs L167
- 新種類若可能過 1K,標 P0 另審AGENTS.md L99 · additional_context.rs L5
- 會不會每輪改已經發出去的前綴AGENTS.md L96 · client.rs L272
- 是追加新行,還是改歷史裏的舊行AGENTS.md L95 · session/mod.rs L3383
- 改舊行會不會讓已有 rollout 恢復失敗AGENTS.md L110
想像四份看起來很負責的 PR。甲給 environment 上下文加一個 git_status 字段,每輪寫入完整工作區狀態。乙在 turn.rs 裏 format 一句 hint,提醒模型跑測試。丙新建一個 fragment,把整個源檔案塞進模型可見文本,不寫截斷。丁在 AGENTS.md 一改時,就地改寫歷史裏那一條説明。
四份都能寫出乾淨的 struct、乾淨的測試。類型系統會放行。下一輪推理的 cache 前綴會被打掉,token 帳單會按輪翻倍,從舊 rollout 恢復時會讀到被改過的歷史。
ContextualUserFragment 是往模型上下文裏塞一段帶標記文字的登記口。上一章用它把注入收成類型。編譯器從此只接受實現了這個 trait 的 struct。形狀對了,成本還可以不合法:又長、又勤、又無界。
Codex 把成本寫成六條禁令,放在倉庫根 AGENTS.md,標題就叫 Model visible context。同一段原文被抄進 .codex/skills/code-review-context/SKILL.md。評審機器人讀到的就是這六條,沒有第二套解釋。
### Model visible context
Codex maintains a context (history of messages) that is sent to the model in inference requests.
1. No history rewrite - the context must be built up incrementally.
2. Avoid frequent changes to context that cause cache misses.
3. No unbounded items - everything injected in the model context must have a bounded size and a hard cap.
4. No items larger than 10K tokens.
5. Highlight new individual items that can cross >1k tokens as P0. These need an additional manual review.
6. All injected fragments must be defined as structs in `core/context` and implement ContextualUserFragment trait
openai/codex,核對文件 AGENTS.md,commit 4f39251a01,核對日期 2026-08-22。程式碼塊保留源碼原文。同一段六條還出現在 .codex/skills/code-review-context/SKILL.md 第 7 到 13 行。第 6 條和第 3、4 條先問入口和上界。沒走 trait,handler 裏直接 format! 一段 Message,編譯能過,評審打回。走了 trait 但沒寫硬 cap,同樣打回。工具輸出側預設按字節 10_000 截斷,超了從中間砍,前面加一行警告,告訴模型原 token 數和總行數。出處:codex-rs/protocol/src/protocol.rs 第 3112 行;codex-rs/models-manager/src/model_info.rs 第 167 行;codex-rs/utils/output-truncation/src/lib.rs 第 12 至 24 行
通用附加上下文另卡在 1_000 token。1K 正好是第 5 條的門檻:已有種類被程式碼截到 1K,新的可能超過 1K 的種類才需要人看。源碼裏沒有 P0 枚舉,也沒有 lint 去估一個新 struct 的 body() 會不會超過 1K。出處:codex-rs/context-fragments/src/additional_context.rs 第 5 行
第 2 條盯的是時機。能追加就追加。每輪重寫環境 XML、每輪換工具清單,前綴對不上,cache 從第一層作廢。會話級客户端把跨 turn 穩定和 turn 內粘滯拆開,sticky token 不準跨 turn 重放。Guardian 審查會話故意複用同一條 trunk,好保住 prompt_cache_key。集成測試 prompt_caching.rs 盯的就是連續兩輪 instructions 和 tools 必須一致。出處:codex-rs/core/src/client.rs 第 262 至 274 行;codex-rs/core/src/guardian/review.rs 第 932 至 934 行
類型系統證明的是形狀。它證明不了這條文字會不會每輪變、有沒有上界、會不會改已經發出去的前綴。這些是過程屬性,換語言重寫也得另開一扇門。
日常命令也補不上這扇門。just fmt 和 just test 擋住格式、鎖文件漂移和一部分 API 破壞。它們讀不懂你是不是每輪注入了 git status。六條裏零條有專用 lint。第 1、2 條有集成測試影子,第 3、4 條靠局部 cap,第 5 條純靠人。第 6 條攔得住沒實現 trait 就走 render_full 的路,攔不住在 handler 裏直接拼一段 Message。skill 存在,説明執行主體是評審。
AGENTS.md 改了,最省事的做法是找到歷史裏那一條 UserInstructions,把正文換掉。當前輪少佔一條消息,token 看起來還降了。從舊 rollout 恢復時,讀到的是被改過的文本,會話對不上。
壓縮看起來也像在改歷史:舊窗口從 live history 裏消失。若有人把壓縮做成打開歷史文件改一行,第 1 條和 breaking changes 第五項會一起被踩中。第五項點名的就是從已有 rollout 恢復會話。
replace_compacted_history 把新表整表裝進 live history,舊內容以帶 replacement_history 的 CompactedItem 追加到 rollout,不回改舊行。註釋寫明 「Compaction starts a new history window」。第 1 條和壓縮能共存,因為壓縮被定義成開新窗口。生產路徑裏那條就地換表的函式叫 replace_history,上面標了 #[cfg(test)]。出處:codex-rs/core/src/session/mod.rs 第 3373 至 3418 行;AGENTS.md 第 95 行、第 110 行
遠端壓縮還有一層濾網。服務端送回來的 transcript 不可信,developer 消息直接丟掉,再由本地按當前 world state 把帶 marker 的 fragment 重新渲染進去。歷史繼續增量構建,壓縮繼續換窗口。出處:codex-rs/core/src/compact_remote.rs 第 354 至 372 行
追加寫、用快照換窗口,是日誌系統的通用形狀。事件溯源換的是投影,LSM 樹換的是 SSTable,都不回改已經寫下的舊行。禁止就地更新,恢復才有得對。
總量誰來管,六條沒寫數字。程式碼用兩層補上:模型窗口的 full_context_window_limit 是硬頂,會話樹的 RolloutBudget 按加權 token 記帳,用盡對整棵 thread 停寫。40 條都合法且每條 9K,總量仍會被滿窗或會話預算攔住。出處:codex-rs/core/src/session/context_window.rs 第 53 至 54 行、第 74 至 79 行;codex-rs/core/src/rollout_budget.rs 第 45 至 65 行
DeepSeek Harness:原則加筆記,少寫禁令
DSH 倉庫根 AGENTS.md 第 107 行寫的是 「Model-visible ⟺ logged」:送到模型請求裏的東西,必須能從會話日誌重建;新的模型可見輸入,必須對應一條 session 事件。它管的是可見與落盤對齊,不管這一條是不是無界、是不是每輪改、單條是不是超過 10K。
否決過的路會立檔。一篇討論要不要把 compaction 的定義包和唯一實現折在一起的筆記,Status 寫明 rejected,還單獨留下 Alternatives considered:將來可能有遠端或 recall 後端,不夠成為現在就拆包的理由。Codex 這一側沒有 rejected/ 目錄告訴後來者,某次每輪注入 git status 為何撤回。後來者只能從 prompt_caching.rs 和 Guardian 註釋反推。
Claude Code:產品審查和運行時紅綫不是一回事
用 Model visible context、ContextualUserFragment、unbounded context 檢索還原源碼,找不到公開的上下文注入評審規範。REVIEW.md 是給審查模型看的產品化 PR 規則,用來標記該不該在審查裏指出某類問題,和運行時往模型上下文塞東西的工程紅綫不是同一層。
這一格空着。後續如果有新的還原源碼,可以按這幾個詞複查。
已檢索 · 未找到對應規範 · 2026-08-22這句 format 能留嗎
有人要在 session/turn.rs 裏 format 一段 <workspace_map>,把當前目錄樹塞進去,聲稱只有除錯時才開。按六條逐條過:哪幾條亮紅,改成什麼樣才能留。
進階一問:若目錄樹最壞超過 1K token,PR 標題要不要標 P0,源碼裏有沒有對應的屬性宏替你標。