새 기능은 먼저 crate를 찾아요. core는 마지막 칸.
저장소를 열면 첫 반응은 core에 넣는 거예요. 저장소는 그걸 금지로 적어 둡니다. 기존 non-core crate를 먼저 보고, 없으면 새로 만드세요. 의존 방향이 리프 타입을 핵심 밖으로 막습니다.
codex-core에 들어가면 안 되는지. 의존 방향이 어떻게 한 층 밖으로 막는지, 막힌 뒤 올바른 착지점은 어디인지. 이 금지에는 기계 빨간불이 없는데, 무엇으로 아직 돌아가고 있는지.
- workspace members는 명시 배열, 지금은 135개Cargo.toml L3
- 디렉터리는 core, crate 이름은 codex-coreAGENTS.md L4
- 금지: resist adding code to codex-coreAGENTS.md L76
- 기존 non-core crate에 살 수 있는지 먼저 묻기AGENTS.md L80
- 아니면 workspace crate를 새로 만들고 옛 코드 리팩터를 허용AGENTS.md L81
- 리뷰는 불필요하게 core로 가는 PR을 적극 막음AGENTS.md L83
- core는 이미 빼낸 context-fragments를 의존함core/Cargo.toml L35
- 비기계적 변경은 한 번에 800줄 이하AGENTS.md L127
이 agent에 작은 기능을 넣고 싶어요. 매 턴 시작에 현재 git 브랜치 이름을 모델 컨텍스트에 쓰는 것. 저장소를 열면 첫 반응은 codex-core에 넣는 겁니다. session, context, guardian, tools가 다 거기 있어요. 새 파일을 넣는 게 제일 싸죠. 의존 표도 안 고치고, 호출 사슬도 crate를 넘지 않아요.
일주일이 지나면 같은 이유로 세 개가 더 들어와요. 도구 출력을 자르는 helper, 모델 공급자 어댑터, 세션 복구의 구석. core/src/lib.rs 꼭대기에 mod가 또 셋. 하류는 use codex_core만 쓰면 되고, 컴파일 그래프는 넓어집니다. 누군가 컨텍스트 조각 타입만 재사용하려다 core에 용접된 걸 봐요. 재사용하려면 core 전부, 샌드박스·MCP·Guardian까지 끌어와야 해요.
저장소는 이걸 금지로 적어요. AGENTS.md는 굵은 영어로 resist adding code to codex-core라고 씁니다. 새 개념은 기존 non-core crate에 살 수 있는지 먼저 물어요. 그다음 workspace crate를 새로 만들지, 그리고 그걸 위해 옛 코드를 리팩터해도 되는지. core는 마지막 칸. 리뷰는 core에 기능을 쌓는 PR을 적극 되돌리라고 요구받아요.
출처: AGENTS.md 72–83행
금지가 파일에 적힌 날은 2026-03-26. 그때 이미 core가 가장 큰 crate였어요. 세운 뒤 workspace 멤버는 75에서 135로 늘었고, core 생산 코드도 여전히 늘었습니다. 막는 것은 기본으로 핵심에 던지는 습관이지, 핵심이 계속 크는 것은 못 막아요.
명단은 명시 배열이에요. codex-rs/Cargo.toml의 members를 세면 135. 디렉터리 이름과 crate 이름은 따로 보세요. 디렉터리는 core, 패키지 이름은 codex-core, use할 때는 codex_core.
출처: codex-rs/Cargo.toml 1–20행; AGENTS.md 1–5행; codex-rs/core/Cargo.toml 1–9행
.rs 줄 수로 보면 소수 crate가 부피 대부분을 먹어요. core 33만, tui 27만, app-server 14.8만. 1만 줄 이상이 24개, 2천 미만이 77개. 테스트를 빼면 core는 약 10.3만 줄. workspace 멤버 25개가 직접 의존합니다. tui의 Cargo.toml에는 그 줄이 없어요. codex-app-server-client를 의존하고, client가 core를 끌어옵니다. core에 한 줄 넣으면 직접 하류 25개가 재컴파일되고, tui도 끌려와요.
출처: codex-rs/cli/Cargo.toml 41–42행; codex-rs/tui/Cargo.toml 30–31행
신 패키지의 실패 모드는 “이번엔 작으니까 핵심에 먼저”예요. 기본 착지점을 평범한 글로 적어 리뷰가 막을 권한을 갖게 하세요. 언어에 기대지 않습니다. 다른 언어로 다시 써도 최소 형태는 이 세 질문이에요. 기존 패키지에 살 수 있나, 새 패키지를 만들어야 하나, 핵심에 들어간다면 왜 못 빼내나.
의존 방향이 뒤집히면 컴파일 그래프가 양쪽에서 부풀어요. core는 이미 codex-* crate 61개를 의존하고, 빼낸 context-fragments와 features도 포함됩니다. 새 컨텍스트 타입을 다시 core에 쓰면, 재사용하려는 사람은 샌드박스와 Guardian까지 같이 끌어와야 해요. 리프가 핵심을 의존하고 핵심이 다시 리프를 의존하면, 경계는 사라집니다.
빼낸 crate는 자기에게 필요한 것만 가져요. context-fragments 패키지 목록에는 비즈니스 의존이 거의 없고, protocol과 문자열 유틸만 만지며, 조각 타입 둘과 trait 하나를 re-export합니다. core는 그걸 의존할 수 있고, 그건 core를 의존하지 않아요. git 브랜치 이름 같은 조각은 이 길로 갑니다. 타입은 fragments에 두고, core는 호출 쪽. 모델 공급자 어댑터는 이미 codex-model-provider로 빠졌어요. session 내부를 꼭 만져야 하는 것만 마지막 칸으로 가고, 리뷰는 그래도 왜 못 빼내는지 묻습니다.
출처: codex-rs/context-fragments/src/lib.rs 1–6행; codex-rs/core/Cargo.toml 26–42행
옆에 자가 두 개 더 있어요. 파일 목표는 500줄, 대략 800을 넘으면 새 모듈. 비기계적 변경은 한 번에 800줄 이하, 복잡한 로직은 500까지. 세 층을 같이 보면 같은 일을 겨냥해요. 사람과 AI 모두 이미 큰 파일에 변경을 크게 쓰려 합니다.
출처: AGENTS.md 49–61행; AGENTS.md 125–131행
이 금지 자체에는 lint도 CI job도 없어요. 저장소에서 resist adding code to codex-core를 찾으면 AGENTS.md 한곳뿐입니다. 실제로 막는 것은 옆의 조항들이에요. Bazel lock을 안 갱신하면 CI가 빨개지고, include_str!인데 BUILD.bazel을 안 고치면 Bazel이 빨개집니다. core 금지는 습관을 막고, 이유 있는 예외와 놓친 눈은 못 막아요.
출처: AGENTS.md 37–43행
컴파일 그래프의 방향은 물리 제약이에요. 리프는 혼자 컴파일되고 여러 중심이 재사용할 수 있습니다. 중심이 리프 타입을 삼키면, 재사용 비용이 중심 전부 끌어오기가 돼요. 이 모양은 언어를 바꿔도 성립합니다.
DSH: 능력은 전부 플러그인, 특권 커널은 없어요
DSH 루트 AGENTS.md는 원칙을 굵은 영어로 적어요. everything is a plugin. Cordis는 서비스·타입화된 이벤트·되돌릴 수 있는 부작용만 받습니다. 모델 어댑터, 도구 레지스트리, 세션 로그, agent loop가 전부 플러그인이에요. 패치해야 하는 특권 커널은 없습니다. 새 패키지가 기존 그룹에 들어가면 루트 package.json은 안 고치고, glob이 찾아요.
Codex는 그 착탈기를 컴파일기 crate로 바꿨어요. 새 능력은 members 배열을 고치고 BUILD.bazel을 쓰고 다시 컴파일해야 합니다. 손댈 자리는 리뷰와 CI뿐이에요. 리뷰는 core에 들어가도 되는지, CI는 잠금 두 개를 같이 고쳤는지 봅니다.
Grok Build: 명단은 자동 생성, 계층은 디렉터리
Grok 루트 Cargo.toml 첫 줄은 이 workspace가 생성된 것이라고 밝히고, 사람은 각 crate 자기 명단을 고치라고 해요. 같은 기준으로 members를 세면 79. 조직은 루트 README에 있습니다. pager는 TUI, shell은 런타임, tools와 workspace는 도메인 능력, common / build는 리프.
리뷰가 읽으라고 쓴 core 금지는 없어요. 분할 자체가 지도입니다. 팽창은 조합 입구와 crate 추출로 소화해요. Codex가 더 내는 것은 리뷰 텍스트와 이중 빌드 잠금이에요.
양쪽 모두 소스 대조 완료 · 2026-08-22 · Grok · workspace 멤버 79개도구 출력을 자른다면, 어디에 둘까요
작은 기능이 또 와요. 도구 반환이 너무 길면 먼저 자르고 모델에 넘기는 것. helper처럼 보이니 core의 tools 옆에 두는 게 제일 싸죠. 방금 세 질문으로 밀어 보세요. 기존 non-core crate에 더 맞는 집이 있는지, 문자열 유틸만 담는 작은 패키지를 만들어야 하는지, core에 넣으면 어느 의존 변이 막히는지.
어느 변을 막을지, 막은 뒤 올바른 착지점을 적으세요. 마지막 칸을 고르면 리뷰가 무엇을 물을지 한 줄 보태세요.