-
Notifications
You must be signed in to change notification settings - Fork 759
docs(agents): document the five-model spawn_agent window and its V1/V2 difference #1815
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
88 changes: 88 additions & 0 deletions
88
...260816_codexrs_multiagent_v2_and_history_perf/012_c1_implementation_evidence.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| # 012 — C1-D: 구현 완료와 검증 증거 | ||
|
|
||
| 브랜치 `codex/compat-multiagent-v2-catalog` @ `d7bac3476` (origin/dev `8a0de6c44` 위). | ||
| 상류 codex-rs `49db349ff`. 계획: `011` 4판. | ||
|
|
||
| ## 구현한 것 | ||
|
|
||
| ### 1. 로스터 자격 (G1a) — `src/codex/catalog/sync.ts:105-108` | ||
|
|
||
| ```ts | ||
| // before | ||
| return pinned === "v2" || pinned === null || pinned === undefined; | ||
| // after | ||
| return entry.multi_agent_version !== "disabled"; | ||
| ``` | ||
|
|
||
| 상류 `6d4d9442c` 와 정합. `v1` 핀은 이제 **자격 있는 리프 워커**이며, 이것이 upstream이 | ||
| `gpt-5.6-luna` 에 붙인 핀이다. 주석에 3분류(eligible-recursive / eligible-LEAF / excluded)와 | ||
| `keepNativeChatGptOnV1`(#1728) 정책과의 관계를 명시했다. | ||
|
|
||
| ### 2. `gpt-daybreak-blue-latest` 전역 편입 — `src/codex/catalog/native-models.ts` | ||
|
|
||
| 소유자 결정. `NATIVE_OPENAI_MODELS` 에 추가. 선언부 주석에 **수용된 트레이드오프**를 기록: | ||
| 권한 없는 계정도 행을 보게 되며, 선택 시 백엔드 400이 릴레이된다(bare 풀 라우트는 인식된 | ||
| 400 본문에 한해 다른 계정 1회 재시도; 셀렉터 한정 라우트는 고정 계정이라 즉시 릴레이). | ||
| `disabledModels` 는 가시성 hatch이지 런타임 거부가 아니다. | ||
|
|
||
| `NATIVE_OPENAI_CAPABILITY_ALIAS_MODELS` 주석도 정정 — 두 목록 겸속이 이제 정상이며, | ||
| 소비 맵이 `Map` 이라 중복이 접힌다는 점을 명시. | ||
|
|
||
| ## 검증 (lidge, Ubuntu 16-core, `~/ocx-c1-test` @ `d7bac3476`) | ||
|
|
||
| | 게이트 | 결과 | | ||
| | --- | --- | | ||
| | `bun x tsc --noEmit` | **exit 0** | | ||
| | `OCX_TEST_NO_QUEUE=1 bun scripts/test.ts` | **12561 pass / 13 skip / 0 fail**, `TEST_EXIT=0` | | ||
| | 규모 | `Ran 12574 tests across 813 files. [453.83s]` | | ||
|
|
||
| SHA 일치 확인: 로컬 `d7bac347604bbd2cafcc7653a030f4aa506e577b` = 원격 | ||
| `refs/heads/codex/compat-multiagent-v2-catalog` = lidge 체크아웃. | ||
|
|
||
| 첫 실행에서 12 fail / 7 errors 였다. 7 errors는 `gui/` 의존성 미설치(환경)였고, | ||
| `cd gui && bun install` 후 사라졌다. 12 fail은 전부 **의미가 뒤집힌 픽스처**로, 감사가 | ||
| 사전에 지목한 목록과 일치했다. | ||
|
|
||
| ## 뒤집힌 테스트와 처리 | ||
|
|
||
| | 테스트 | 낡은 전제 | 새 단언 | | ||
| | --- | --- | --- | | ||
| | `multi-agent-compat` (3건) | `v1` 핀은 로스터에서 제외 | Luna가 `candidates`/`advertised` 에 등장; `disabled` 가 `surface_incompatible` 역할 | | ||
| | `native-model-toggle` (2건) | daybreak = 미지의 관측 id | `gpt-future-unlisted` 로 교체 + **관측 없이 전역 행 존재 + sol의 `v2` 상속** 신규 케이스 | | ||
| | `codex-catalog` | bare 행 없음 | bare 1개 + 셀렉터당 1개 (**중복 없음** 증명) | | ||
| | `codex-models-cache-invalidate` | daybreak = 미지 관측 | `gpt-future-unlisted` 로 교체 | | ||
| | `codex-convergence-account-selectors` | 셀렉터 1개만 투영 | **모든 가시 셀렉터** + bare, 각 정확히 1개 | | ||
| | `codex-catalog-sync-hardening` (2건) | bare 행 없음 | bare 정확히 1개; 명시적 Codex-forward 커스텀 행은 별개 정체성 유지; API-key alias는 여전히 Codex 표면에 없음 | | ||
| | `claude-models-discovery` | 계정한정 행으로 발견 | 관리 API는 **전역 bare 정체성**; Anthropic 표면에는 둘 다 없음(전역 행이 `hide` 로 합성됨) — **실측으로 확인 후** 단언 | | ||
|
|
||
| 모든 변경 단언은 `some(...)` 가 아니라 **`toHaveLength(1)`** 로 바꿔, 중복 행 회귀가 여기서 | ||
| 잡히도록 했다. | ||
|
|
||
| ## 예상 밖 발견 | ||
|
|
||
| Anthropic 디스커버리에서 daybreak가 **양쪽 정체성 모두 사라졌다.** 전역 합성 행은 | ||
| `visibility: "hide"` 이고, 계정한정 투영은 전역 편입으로 더는 생성되지 않기 때문이다. | ||
| 추측으로 단언하지 않고 실제 응답을 출력해 확인했다(필터된 id 목록에 `gpt-5.5` 만 존재). | ||
| 이는 **의도된 결과는 아니지만 무해**하다 — Claude 표면은 Codex 카탈로그에서 가시적인 행만 | ||
| 광고하며, daybreak는 네이티브 OpenAI 경로로 라우팅되기 때문이다. 별도 노출이 필요하면 | ||
| 후속 사이클에서 `visibility` 정책을 다뤄야 한다. | ||
|
|
||
| ## 열린 채로 남은 것 | ||
|
|
||
| | 갭 | 사이클 | | ||
| | --- | --- | | ||
| | G1b — `default` 모드 blanket `v2` 스탬프 (`parsing.ts:409+`, `8a0de6c44` 가 안 고침) | C2 | | ||
| | G2 — capability creation path / bridge | C3 | | ||
| | G12 — fallback capability class (암호화 NEW_TASK fallback과 얽힘) | C3 | | ||
| | G14 — `model_messages.multi_agent` (#38619) | 별도 | | ||
|
|
||
| ## 프로세스 기록 | ||
|
|
||
| A 게이트: 리뷰어1과 3라운드(블로커 4+4+5, 전부 소스로 검증 후 반영, 반박 0), | ||
| 이후 신선한 리뷰어 2명(NEAR-PASS → **PASS**). 리뷰어1이 잡은 결정적 두 건: | ||
| (1) `origin/dev` 가 4커밋 앞서 있었고 `8a0de6c44` 가 이 범위와 겹친다는 것 — 리베이스로 해결, | ||
| (2) 2판의 "`8a0de6c44` 가 default 스탬프를 재정의했다"는 **내 사실 오류**. | ||
|
|
||
| `cxc review-round` 판정 훅은 이 환경에서 리뷰어 종료 시 기록되지 않았다(직전 사이클과 동일). | ||
| 감사는 실제로 수행되었고 판정 원문은 `orchestrate` attest와 이 문서에 보존한다. | ||
|
|
97 changes: 97 additions & 0 deletions
97
...og/_plan/260816_codexrs_multiagent_v2_and_history_perf/013_five_cap_v1_vs_v2.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| # 013 — "다섯 개가 v2에서도 동일하게 노출되는가" 확정 답변 | ||
|
|
||
| 사용자 질문에 대한 P-단계 조사. 상류 `49db349ff`, opencodex `bf97f4bd0` 기준. | ||
| 원자료: `.tmp/research3/J_five_cap_v2.md` (gitignored). 서브에이전트 조사 + 메인 직접 검증. | ||
|
|
||
| ## 한 줄 답 | ||
|
|
||
| **상한 숫자 5는 V1/V2 동일하지만, 그 5개를 고르는 창(window)의 내용은 다르다.** | ||
|
|
||
| ## 왜 다른가 — 필터가 cap보다 먼저 적용된다 | ||
|
|
||
| `spawn_agent_models_description` (`multi_agents_spec.rs:785-790`) 순서: | ||
| `show_in_picker` 필터 → `model_supports_multi_agent_backend` 필터 → `.take(5)`. | ||
|
|
||
| 두 번째 필터가 표면에 따라 다르게 동작한다 (`multi_agents_common.rs:36-42`): | ||
|
|
||
| ```rust | ||
| multi_agent_version != MultiAgentVersion::V2 | ||
| || model.multi_agent_version != Some(MultiAgentVersion::Disabled) | ||
| ``` | ||
|
|
||
| - **V1 호출**: 좌변이 참이라 **모든 행이 통과**한다 — `Disabled` 조차 포함된다. | ||
| - **V2 호출**: `Some(Disabled)` 만 제외된다. | ||
|
|
||
| 제외된 행이 있으면 **뒤 행이 5칸 안으로 밀려 들어온다.** 그래서 같은 카탈로그가 두 표면에서 | ||
| 다른 목록을 만든다. | ||
|
|
||
| ### 구체 예 (모두 picker-visible, 이 순서) | ||
|
|
||
| | # | 모델 | `multi_agent_version` | | ||
| | ---: | --- | --- | | ||
| | 1 | `v2-a` | `V2` | | ||
| | 2 | `disabled-a` | `Disabled` | | ||
| | 3 | `v1-a` | `V1` | | ||
| | 4 | `null-a` | `None` | | ||
| | 5 | `v2-b` | `V2` | | ||
| | 6 | `disabled-b` | `Disabled` | | ||
| | 7 | `null-b` | `None` | | ||
|
|
||
| - **V1 광고**: `v2-a, disabled-a, v1-a, null-a, v2-b` | ||
| - **V2 광고**: `v2-a, v1-a, null-a, v2-b, null-b` | ||
|
|
||
| ## 그 외 V1/V2 차이 | ||
|
|
||
| | 항목 | V1 | V2 | 근거 | | ||
| | --- | --- | --- | --- | | ||
| | 목록 게이트 | `hide_agent_type_model_reasoning` — 실제 등록이 `false` 로 고정하므로 **항상 광고** | `expose_spawn_agent_model_overrides` — 이것이 진짜 게이트 | `multi_agents_spec.rs:67-70` / `:102-105`; `spec_plan.rs:1200-1207` / `:1150-1160` | | ||
| | 그 플래그 기본값 | (V1에선 불활성) | **`true`** (`MultiAgentV2Config` 기본) | `config/mod.rs:1229-1255`, `:2650-2655` | | ||
| | 게이트 off일 때 | 해당 없음 | 목록 생략 + `model`/`reasoning_effort` 스키마에서 제거 | `multi_agents_spec.rs:103-119` | | ||
| | `service_tier` | 노출 | `hide_spawn_agent_metadata` 기본 true → 제거 | `config/mod.rs:1242-1243` | | ||
| | 성공 경로 검증 | 전체 카탈로그, cap/visibility 없음 | 동일 + `Disabled` 만 거부 | `multi_agents_common.rs:431-442` | | ||
|
|
||
| **5는 여전히 "광고 + 실패 에러 메시지"에만 쓰인다** (`multi_agents_spec.rs:789`, | ||
| `multi_agents_common.rs:448`). 5위 밖 모델도 이름만 맞으면 수락된다. 동시 실행 수(V1 6, | ||
| V2 총 4 → 자식 3)와는 **무관**하다. | ||
|
|
||
| ## opencodex 패리티: 이미 맞다 | ||
|
|
||
| `effectiveSubagentRoster` (`src/codex/catalog/sync.ts:157-188`)의 필터가 | ||
| `surface !== "v2" || isEligibleV2SubagentEntry(entry)` 이므로 **V1은 자격 필터를 건너뛴다** — | ||
| 상류 V1이 모든 행을 통과시키는 것과 정확히 같다. C1에서 `isEligibleV2SubagentEntry` 를 | ||
| `!== "disabled"` 로 고친 결과, V2 쪽도 상류와 일치한다. | ||
|
|
||
| 또한 opencodex는 **V1 표면에 로스터를 주입하지 않는다** (`collaboration.ts:368-372` — 최상위 | ||
| effort에서 proactive 텍스트만). 즉 V1 목록의 권위는 상류 툴 설명문이고, 우리가 개입하지 않는다. | ||
|
|
||
| ## 기각한 주장: `modelPickerOrder` "실버그" | ||
|
|
||
| 서브에이전트가 `effectiveSubagentRoster` 가 `SPAWN_PRIORITY_FIELD`(자연 우선순위)로 정렬해 | ||
| 상류의 재작성된 `priority` 창과 달라진다며 **실버그**라고 보고했다. **기각한다.** | ||
|
|
||
| 이는 **이슈 #1649의 의도된 설계**다: | ||
|
|
||
| - `sync.ts:70`: "modelPickerOrder is a **DISPLAY-ONLY**" | ||
| - `sync.ts:622-624`: "modelPickerOrder is a DISPLAY-ONLY override. Record the natural priority | ||
| spawn_agent must keep using" | ||
| - `sync.ts:174-176`: "so a modelPickerOrder display reorder (#1649) **can never change candidate | ||
| membership**" | ||
| - `sync.ts:477`: "Independent of the 5-slot spawn_agent cap" | ||
|
|
||
| 그리고 **기존 테스트가 이 동작을 계약으로 고정**하고 있다 | ||
| (`tests/codex-catalog-model-picker-order.test.ts`): | ||
| `"picker-order-only rows do not displace default-tier spawn_agent candidates"` (`:113`), | ||
| `"candidate set is unchanged when all routed rows are listed in reverse order"` (`:176`). | ||
|
|
||
| 서브에이전트가 관찰한 "발산"은 실재하지만 **그것이 이 기능의 목적**이다: 사용자가 피커 표시 | ||
| 순서를 바꿔도 스폰 후보 집합은 흔들리지 않게 하는 것. 상류 창과 다른 것은 알려진 트레이드오프이지 | ||
| 회귀가 아니다. 커밋 `088997364` 참조. | ||
|
|
||
| **교훈:** 상류 대조만으로 "버그"를 판정하면 안 된다. 로컬 설계 의도(주석·이슈·테스트)를 먼저 | ||
| 확인해야 한다. | ||
|
|
||
| ## 결론: 코드 변경 없음 (문서화 레이어) | ||
|
|
||
| 이 질문에 대해 opencodex가 고칠 것은 **없다.** V1/V2 창 차이는 상류 의미이며 opencodex는 이미 | ||
| 표면별로 올바르게 동작한다. 산출물은 `structure/03_catalog-and-subagents.md` 문서화다. | ||
|
|
68 changes: 68 additions & 0 deletions
68
.../_plan/260816_codexrs_multiagent_v2_and_history_perf/014_stacked_pr_evidence.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| # 014 — 스택 PR 개설과 레이어별 검증 증거 | ||
|
|
||
| `origin/dev` 위에 4층 스택을 구성하고 PR 4개를 열었다. DEV-STACK-01/02/03 준수. | ||
|
|
||
| ## 스택 구조 (bottom-up 병합) | ||
|
|
||
| | # | PR | 브랜치 | base | 커밋 | 논지 | | ||
| | ---: | --- | --- | --- | ---: | --- | | ||
| | 4 | [#1815](https://github.com/lidge-jun/opencodex/pull/1815) | `codex/compat-v2-five-cap` | `codex/compat-v2-daybreak` | 5 | 5-모델 창의 V1/V2 차이 문서화 + SoT 동기화 | | ||
| | 3 | [#1814](https://github.com/lidge-jun/opencodex/pull/1814) | `codex/compat-v2-daybreak` | `codex/compat-v2-roster` | 4 | daybreak 전역 네이티브 행 (소유자 결정) | | ||
| | 2 | [#1813](https://github.com/lidge-jun/opencodex/pull/1813) | `codex/compat-v2-roster` | `codex/compat-v2-docs` | 3 | 로스터 술어: `v1` 핀 = 자격 있는 리프 | | ||
| | 1 | [#1812](https://github.com/lidge-jun/opencodex/pull/1812) | `codex/compat-v2-docs` | **`dev`** | 2 | 상류 분석 문서만, 코드 없음 | | ||
|
|
||
| 각 레이어가 자기 커밋만 담는지 확인 (`git log <lower>..<upper>`): | ||
|
|
||
| ``` | ||
| L2 over L1: df83829cd feat(agents): treat a v1 pin as an eligible leaf subagent | ||
| L3 over L2: 926ca6cdd feat(catalog): ship gpt-daybreak-blue-latest as a global native row | ||
| L4 over L3: 9a75124c1 docs(agents): document the five-model spawn_agent window... | ||
| ``` | ||
|
|
||
| base ref는 `gh pr list --json baseRefName` 로 되읽어 확인했다. | ||
|
|
||
| ## 레이어별 독립 검증 (ssh lidge, Ubuntu 16-core) | ||
|
|
||
| DEV-STACK-03 "각 레이어는 자기 tip에서 빌드·테스트를 통과해야 한다"를 만족한다. | ||
| 레이어마다 체크아웃 → `tsc` → 전체 스위트를 각각 돌렸다: | ||
|
|
||
| | 레이어 | SHA | `tsc --noEmit` | 전체 스위트 | | ||
| | --- | --- | --- | --- | | ||
| | L1 docs | `bba4b9669` | **0** | **12575 pass / 0 fail** | | ||
| | L2 roster | `df83829cd` | **0** | **12575 pass / 0 fail** | | ||
| | L3 daybreak | `926ca6cdd` | **0** | **12576 pass / 0 fail** | | ||
| | L4 five-cap | `9a75124c1` | **0** | **12576 pass / 0 fail** | | ||
|
|
||
| L3에서 pass가 1 늘어난 것은 daybreak 전역 행을 증명하는 신규 테스트 | ||
| ("ships as a global native row without an observation")가 추가되었기 때문이다. | ||
|
|
||
| L2 단독 포커스 검증도 별도로 수행: `multi-agent-compat` + `multi-agent-keep-native-v1` + | ||
| `codex-catalog-model-picker-order` = **69 pass / 0 fail**. | ||
|
|
||
| ## 분할 방식 | ||
|
|
||
| `729e2e4a2` 는 로스터 변경과 daybreak 변경을 한 커밋에 담고 있었으므로 파일 단위로 갈랐다: | ||
|
|
||
| - L2 ← `src/codex/catalog/sync.ts`, `tests/multi-agent-compat.test.ts`, 관련 devlog | ||
| - L3 ← `src/codex/catalog/native-models.ts`, daybreak 픽스처 4개 + `codex-catalog`/`native-model-toggle` | ||
|
|
||
| L4 tip을 원래 검증된 브랜치(`codex/compat-multiagent-v2-catalog`)와 diff한 결과, 차이는 | ||
| `013_five_cap_v1_vs_v2.md` 와 `structure/03` 신규 섹션뿐이다 — 즉 **분할 과정에서 코드가 | ||
| 유실되거나 변형되지 않았다.** | ||
|
|
||
| ## 주의: `main` 푸시 관찰 | ||
|
|
||
| `git push` 중 `6abcd2631..e664647de main -> main` 이 함께 실행되었다. 확인 결과 로컬 | ||
| `main` 에 이미 있던 **기존 유지보수 커밋**(`bitkyc08-arch` 작성, "Merge dev into main: bind | ||
| the retained usage window")이 fast-forward된 것으로, **이번 작업 커밋은 포함되지 않았다.** | ||
| 그럼에도 의도치 않은 원격 상태 변경이므로 기록해 둔다. 이후 push는 전부 | ||
| `refs/heads/<branch>:refs/heads/<branch>` 형태로 명시했다. | ||
|
|
||
| ## 다음 | ||
|
|
||
| 병합은 bottom-up: #1812 → #1813 → #1814 → #1815. 하위 레이어가 수정되면 상위를 | ||
| `git rebase --update-refs` 로 캐스케이드하고 `--force-with-lease` 로 재푸시해야 한다 | ||
| (DEV-STACK-02). 병합은 사용자 결정 사항이며 이 작업에서는 수행하지 않았다. | ||
|
|
||
| 여전히 열린 갭: G1b(default 모드 blanket 스탬프), G2, G12, G14 — `000_plan.md` 의 C2/C3 참조. | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When
modelPickerOrderis configured for enough routed rows, this statement conflates OpenCodex's injected roster with Codex's native five-model tool-description window.buildCatalogEntriesFromObservedStaterewrites the Codex-visiblepriority, and Codex sorts the catalog by that field before taking five; the privateSPAWN_PRIORITY_FIELDis ignored by Codex and is consumed only byeffectiveSubagentRoster. Consequently, picker ordering can change the models advertised by the nativespawn_agentdescription even though the injected roster retains natural membership. Please distinguish those two windows instead of stating that the override cannot affect this one.Useful? React with 👍 / 👎.