OpenAI Codex · Code Mode

컨텍스트 거버넌스를 code review에 쓰세요

지난 레슨은 컨텍스트에 넣는 글을 타입으로 묶었습니다. 타입이 통과해도 그 글은 여전히 합법적으로 길고, 자주 바뀌고, 끝이 없을 수 있어요. 그 비용을 막는 것은 저장소 루트의 열 줄 금령과, 같은 절을 다시 읽는 리뷰 skill입니다.

강의 목표읽고 나면 두 가지를 말할 수 있어요. ContextualUserFragment를 구현한 변경이 왜 cache를 깨고, 창을 채우고, 옛 세션 복원을 실패시키는 PR을 컴파일러가 그대로 통과시키는지. 그리고 여섯 금령 중 어떤 것이 코드에 떨어지고, 어떤 것은 사람과 skill만 지킬 수 있는지요.
먼저 해보기 · 변경 하나를 여섯 금령에 넣기
책임져 보이는 PR 네 건을, 조항마다 리뷰
변경
왼쪽은 구체적인 변경 네 건이에요. 아래에서 증분 plus 하드 cap으로 바꿔, 어떤 등이 꺼지는지 보세요.
쓰기
필드를 더하거나 초장 모듈은 고치면 통과할 수 있어요. 한 줄을 더하거나 옛 행을 고치면, 쓰기를 바꿔도 각자의 조항을 못 넘습니다.
이 PR심사 대기
environment에 git_status 필드를 더하기
매 턴마다 온전한 git status를 쓰면, 모델이 작업 공간이 더러운지 추측하지 않아요.
타입 시스템은 아직 입을 열지 않았어요.
통과하면 모델이 보는 것접힘
6등록된 타입을 타야 함
3주입마다 하드 상한이 필요
4한 건은 10K를 넘으면 안 됨
51K를 넘을 수 있으면 P0
2매 턴 접두사를 바꾸지 말 것
1추가만, 옛 행은 고치지 말 것
시작을 기다려요. 변경 하나를 골라, 어떤 금령이 막는지 보세요.
논리 궤적 · 애니메이션 한 걸음이 소스의 어느 구간에 대응하는지
  1. 주입이 ContextualUserFragment로 등록됐는가AGENTS.md L100
  2. 이 항목에 하드 상한이 있는가AGENTS.md L97 · protocol.rs L3112
  3. 한 건이 10K token을 넘을 수 있는가AGENTS.md L98 · model_info.rs L167
  4. 새 종류가 1K를 넘을 수 있으면 P0으로 따로 심사AGENTS.md L99 · additional_context.rs L5
  5. 이미 보낸 접두사를 매 턴 바꾸는가AGENTS.md L96 · client.rs L272
  6. 새 행을 추가하는가, 기록의 옛 행을 고치는가AGENTS.md L95 · session/mod.rs L3383
  7. 옛 행을 고치면 기존 rollout 복원이 실패하는가AGENTS.md L110
재생을 눌러, 타입이 통과한 변경이 어떤 금령에 아직 부딪히는지 보세요.
타입이 통과시킨 것PR 네 건은 모두 컴파일돼요. 컴파일러는 struct와 marker만 보고, 이 글이 매 턴 바뀌는지, 얼마나 긴지, 옛 세션을 고치는지 보지 않습니다.
금령이 막는 것필드 추가는 2조, 한 줄 추가는 6조, 초장 모듈은 3·4조, 옛 행 수정은 1조와 breaking change 다섯 번째 항에 부딪혀요.
쓰기를 바꾼 뒤필드 추가와 초장 모듈을 증분 plus 하드 cap으로 바꾸면 빨간 등이 꺼지고, 1K를 넘을 수 있는 것은 여전히 P0이에요. 한 줄 추가는 타입을 타지 않았고, 옛 행 수정은 여전히 옛 메시지를 patch합니다. 쓰기를 바꿔도 못 넘어요.
수업용 스케치: PR 네 건과 쓰기 전환은 수업용 설정으로, 여섯 금령이 각각 어떤 비용을 보는지 보여 줍니다. 논리 궤적 오른쪽 행 번호는 openai/codex 저장소 commit 4f39251a01에 대응해요.
아이디어 1 · 타입은 입구, 리뷰는 문지기
어떤 문제를 푸는가

책임져 보이는 PR 네 건을 떠올려 보세요. 갑은 environment 컨텍스트에 git_status 필드를 더해 매 턴 작업 공간 전체를 씁니다. 을은 turn.rs에서 hint 한 줄을 format해 테스트를 돌리라고 일깨웁니다. 병은 fragment를 새로 만들어 소스 파일 전체를 모델이 보는 글에 넣고 자르지 않습니다. 정은 AGENTS.md가 바뀌면 기록의 그 한 줄을 그 자리에서 고칩니다.

네 건 모두 깨끗한 struct와 깨끗한 테스트를 쓸 수 있어요. 타입 시스템은 통과시킵니다. 다음 추론의 cache 접두사는 깨지고, token 청구는 턴마다 두 배가 되며, 옛 rollout에서 복원하면 고쳐진 기록을 읽어요.

아이디어는 무엇인가

ContextualUserFragment는 표시가 달린 글을 모델 컨텍스트에 넣는 등록구예요. 지난 레슨은 이것으로 주입을 타입으로 묶었습니다. 이후 컴파일러는 이 trait를 구현한 struct만 받아요. 모양은 맞아도 비용은 여전히 불법일 수 있습니다. 길고, 자주 바뀌고, 끝이 없어요.

Codex는 비용을 여섯 금령으로 써 저장소 루트 AGENTS.md에 두고, 제목은 Model visible context예요. 같은 원문이 .codex/skills/code-review-context/SKILL.md에 옮겨집니다. 리뷰 봇이 읽는 것은 이 여섯 줄뿐이고, 두 번째 설명은 없어요.

AGENTS.md91–100행
### 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에서 Message를 format!하면 컴파일은 되고 리뷰가 돌려보냅니다. 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 열거가 없고, 새 struct의 body()가 1K를 넘을지 짐작하는 lint도 없습니다.출처: codex-rs/context-fragments/src/additional_context.rs 5행

2조가 보는 것은 타이밍이에요. 추가할 수 있으면 추가합니다. 매 턴 환경 XML을 다시 쓰고 도구 목록을 바꾸면 접두사가 안 맞고, cache는 첫 층부터 폐기돼요. 세션 클라이언트는 턴을 넘는 안정과 턴 안의 점성을 나누고, sticky token은 턴을 넘어 재생하면 안 됩니다. 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행

제안된 주입 PR 한 건 타입 입구 struct가 있어야 컴파일 여섯 리뷰 금령 6 trait를 타야 함 3 / 4 하드 cap과 10K 5 1K 넘으면 P0 2 매 턴 접두사 금지 1 추가만, 옛 행 금지 사람이 타이밍과 최악 길이를 봄 머지 가능 모양은 맞고 비용도 괜찮음
수업용 구조도: 타입은 입구예요. 입구를 지나도 여섯 금령을 더 넘어야 머지를 말할 수 있습니다.
왜 오래가는가

타입 시스템이 증명하는 것은 모양이에요. 이 글이 매 턴 바뀌는지, 상한이 있는지, 이미 보낸 접두사를 고치는지 증명하지 못합니다. 과정 속성이라, 언어를 바꿔 다시 써도 문을 하나 더 열어야 해요.

일상 명령도 이 문을 메우지 못해요. just fmtjust test는 포맷, lock 파일 드리프트, 일부 API 파괴를 막습니다. 매 턴 git status를 넣었는지는 읽지 못해요. 여섯 조 중 전용 lint는 하나도 없습니다. 1·2조는 통합 테스트 그림자가 있고, 3·4조는 국소 cap에 기대며, 5조는 순전히 사람입니다. 6조는 trait 없이 render_full로 가는 길은 막지만, handler에서 Message를 직접 이어 붙이는 것은 못 막아요. skill이 있다는 것은 실행 주체가 리뷰라는 뜻입니다.

아이디어 2 · 압축은 창을 바꾸고 기록을 남긴다
어떤 문제를 푸는가

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행

그 자리에서 옛 행을 고침 live 3번째 같은 id, 본문만 바뀜 옛 rollout이 안 맞아 복원 실패 압축이 창을 바꿈 새 창을 live에 넣음 옛 행이 현재 보기에서 사라짐 rollout에 CompactedItem 추가 replacement_history를 달고 다음 턴은 차이만 추가 복원하면 같은 창으로
수업용 대조: 위는 옛 행 자체를 고치고, 아래는 다시 재생할 수 있는 창 교체 기록을 남깁니다.
타입은 모양을, 리뷰는 비용을 봅니다. 압축은 창을 바꾸고 기록을 남겨요.
왜 오래가는가

추가 쓰기와 스냅샷으로 창을 바꾸는 것은 로그 시스템의 흔한 모양이에요. 이벤트 소싱은 투영을 바꾸고, 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의 정의 crate와 유일한 구현을 접을지 논한 메모는 Status를 rejected로 적고, Alternatives considered를 따로 남깁니다. 나중에 원격이나 recall 백엔드가 있을 수 있다는 것은 지금 패키지를 쪼갤 이유가 못 돼요. Codex 쪽에는 나중에 읽는 이에게 매 턴 git status 주입이 왜 철회됐는지 말해 주는 rejected/ 디렉터리가 없습니다. 나중 사람은 prompt_caching.rs와 Guardian 주석에서 거꾸로 짚어야 해요.

양쪽 소스 모두 확인 · 2026-08-22 · DSH · Agent Notes와 AGENTS.md

Claude Code: 제품 심사와 런타임 빨간선은 다른 층

복원 소스에서 Model visible context, ContextualUserFragment, unbounded context를 찾아도, 공개된 컨텍스트 주입 리뷰 규범은 없어요. REVIEW.md는 심사 모델이 보는 제품화된 PR 규칙으로, 어떤 문제를 심사에서 짚을지 표시합니다. 런타임에 모델 컨텍스트에 글을 넣는 공학 빨간선과는 층이 다릅니다.

이 칸은 비어 있어요. 나중에 새 복원 소스가 있으면 이 단어들로 다시 보면 됩니다.

검색함 · 대응 규범 없음 · 2026-08-22
수업 실습
01

이 format을 남겨도 될까요

누군가 session/turn.rs에서 <workspace_map>를 format해 현재 디렉터리 나무를 넣고, 디버그일 때만 켠다고 말해요. 여섯 조를 하나씩 지나 보세요. 어떤 등이 빨개지고, 어떻게 고쳐야 남을 수 있는지요.

한 단계 더: 디렉터리 나무의 최악이 1K token을 넘으면 PR 제목에 P0을 달아야 할까요. 소스에 대신 달아 주는 속성 매크로가 있는지도요.

Takeaway:타입은 모양을, 리뷰는 비용을 봅니다. 주입은 타입으로 등록돼야 하고, 하드 cap이 있어야 하며, 추가만 하고 옛 행은 고치지 않아요. 압축은 창을 바꾸고 CompactedItem을 남깁니다. just가 못 보는 조항은 사람과, 같은 원문 절을 다시 읽는 skill이 지킵니다.