한 줄 요약X가 콜드스타트 실험에서 control과 treatment 두 arm이 똑같은 bucket 관측 기록을 남기도록 고쳤다. treatment arm의 콜드스타트 후보는 Phoenix MoE 후보로 좁혔다.
1콜드스타트 실험의 두 arm이 같은 관측 기록을 남기게 됐다 — X
자료xai-org/x-algorithm@902a06f — GitHub, 2026-09-04 21:03 UTC, 코드. Open-source X Recommendation Algorithm 정기 크론 미러이고, 바뀐 파일은 25개(+472/−179)다. 이 노트들은 4세대 공개 뒤의 X 커밋에 차례로 번호를 붙여 부르며, 이 커밋은 4세대+16이다.
배경 X의 오픈소스 미러는 크론이 프로덕션 캐넌을 정기적으로 흘려보내는 커밋으로, 어제(2026-09-05) 판에는 4세대+15(9b0dc31)까지 반영됐고 이 커밋(902a06f)이 그다음 판이다. Phoenix는 X For You 피드의 트랜스포머 랭킹 모델이고, Phoenix MoE(Mixture of Experts)는 검색·랭킹 백본을 서로 다른 전문가 서브네트워크에 배분해 서빙하는 아키텍처다. VF는 포스트마다 이 뷰어에게 보여도 되는지를 판정하는 visibility-filtering 서비스다. 이번 커밋은 Phoenix MoE의 A/B 인프라를 다시 손본 것이 중심이고, 부수적으로 Phoenix serving 요청 계약과 VF dark-traffic 연결이 바뀌었으며 예정된 muted-keyword VF rule의 실마리도 드러났다.
새로 알게 된 것
A. 콜드스타트 실험의 두 arm이 같은 bucket 관측 기록을 남기도록 실행 순서를 바꿨다
이제 control과 treatment 두 arm이 똑같은 실험 bucket 관측 기록(impression)을 남긴다 확인. codivert는 X 내부 용어로 보인다 추정. 뜻은 bucket 관측 시점을 두 arm에서 똑같이 맞춰 A/B 분석에 편향이 들지 않게 하는 패턴이고, "co-divert"는 두 arm이 같은 시점에서 각자 분기한다는 의미다 추정. 이번 커밋은 이 패턴을 코드로 구체화했다.
viewer_arm(query)를 호출한다. experiment bucket을 실제로 조회하며, 이때 첫 impression이 남는다.
author_corpus(...)를 호출한다. author bucket을 실제로 조회하며, 이때 author-side impression이 남는다.
cold-start 로직을 실행한다.
문제는 2단계의 조기 반환이었다. EnableViewerColdStart=false인 control arm은 3·4단계를 아예 거치지 않는다. 그러면 실험 분석에서 두 arm의 impression 로그 형태 자체가 달라진다. treatment는 viewer bucket과 author bucket을 모두 관측한 사용자만 세고, control에는 관측이 아예 없다. 이렇게 되면 triggered-analysis와 intent-to-treat 사이의 정의가 어긋나고, 파이프라인 진입 편향이 lift 추정을 오염시킨다. triggered-analysis는 파이프라인에 실제로 진입한 사용자만 비교하고, intent-to-treat는 할당된 모든 사용자를 비교한다.
이번 커밋은 순서를 이렇게 바꿨다.
ColdStartParams::read(query)가 모든 param을 한 번에 읽고 params.arm으로 저장한다. 이때 viewer_arm도 함께 호출돼 viewer bucket impression이 남는다.
관측 횟수가 arm과 상관없이 같아야 한다는 대칭성을 assertion으로 고정한 것이다.
의미 이번 커밋은 처음으로 콜드스타트의 A/B 관측 방법론 자체를 코드로 고정한다. 정본(서비스별 현재 이해를 담는 이 저장소의 노트)의 이전 판은 4세대+1(2026-08-14)의 Thompson sampling 연결과 4세대+3(2026-08-18)의 count_tracked_ids 단순화까지 알았고, 이 두 흐름은 콜드스타트 로직의 진화였다. SpyingBucketImpressor라는 테스트 유틸(experiment SDK가 노출한 impression 계측 스파이)이 있다는 사실까지 드러난다. X가 A/B 실험에서 bucket 관측 대칭성을 회귀 테스트로 강제한다는 문화 관찰이 정본에 더해진다.
B. treatment 뷰어의 콜드스타트 후보가 Phoenix MoE 후보로 좁혀졌다
treatment 뷰어의 cold-start 후보는 이제 Phoenix MoE 소스에서 온 후보로 한정된다 확인. treatment corpus author의 포스트라도 Phoenix MoE 소스에서 온 것이 아니면 cold-start boost 대상에서 빠진다.
fixture가 cold_start_candidate(...)에서 moe_candidate(...)로 바뀐 것도 같은 뜻이다.
의미 이 변경은 Phoenix MoE와 cold-start를 하나의 codivert 실험 안에 묶어, 둘이 서로 confounded되지 않게 하려는 연결이다. treatment 뷰어에서는 MoE 연결을 활성화하고 cold-start도 MoE 후보에만 적용해, "MoE의 효과"와 "cold-start 부스트의 효과"가 겹치지 않게 격리한다. YAML에서 enable_viewer_cold_start_boost가 treatment에서는 true, control에서는 false로 고정된 것도 같은 방향이다. cold-start는 이제 Phoenix MoE의 실 트래픽 실험 옆칸으로 재배치됐다.
C. engagement counts hydration이 cold-start 스위치에서 분리됐다
engagement counts hydration을 켜는 조건에서 cold-start 스위치와 캐시 조건이 빠졌다 확인. cold-start와 engagement counts hydration은 이제 서로 독립된 정책 축이다.
!query.has_cached_posts 게이팅이 없어져, 캐시가 있어도 항상 갱신한다.
정책 축이 순수 hydration flag와 shadow traffic으로 좁혀졌다.
의미 이번 분리로 두 파이프라인의 rollout이 서로 걸림 없이 진행된다. 이전 연결은 "cold-start가 켜지면 반드시 engagement counts를 hydrate한다"는 강결합이었다. cold-start Thompson sampling이 view_count_on_home·fav_count에 의존하는 4세대+1 초기 연결의 유물로 보인다. 특히 codivert 대칭성(A절)과 결합하면 "Treatment는 cold-start 켜짐 + engagement counts 켜짐, Control은 cold-start 꺼짐 + engagement counts는 자기 flag대로"라는 명확한 실험 축 분리가 가능해진다.
D. Phoenix 서빙 요청에 실험 파라미터 오버라이드 필드와 slate 지표 두 개가 생겼다
Phoenix 서빙 요청 계약에 필드 세 개가 새로 생겼다 확인. 하나는 요청마다 experiment 파라미터를 오버라이드하는 map이고, 나머지 둘은 slate(함께 노출되는 후보 묶음) 문맥에 붙는 metric이다. 새 필드는 experiment_overrides와 exact_k·exact_gap이다.
SlateContext struct와 From<xai_recsys_proto::SlateContext> 변환 impl 양쪽에 exact_k: Option<u32>, exact_gap: Option<u32> 두 필드가 추가됐다.
의미 Phoenix serving이 slate context에 관측 metric을 계속 추가하는 흐름이 이어진다. SID 계열(4세대+3)에서 시작해 recon 계열(4세대+9~+11)로 넓어졌고, 이번에는 exact 계열이 붙었다. 소비 경로(RankingScorer 폴백)는 이미 4세대+5의 UseServedSlateContext 게이트에 연결돼 있으니, 새 metric이 붙어도 자동으로 흡수된다. experiment_overrides는 upstream과 downstream의 experiment 스코프 일관성 문제에 대한 계약 차원의 대응이고, codivert 연결(A절)과 시점이 겹치는 것은 우연이 아니다.
의미 VF 재작성의 검증 인프라에 PR 단위 검증까지 붙었다. 이 인프라는 4세대+4 dark_traffic → 4세대+6 shadow→staging 리네임 → 4세대+7 reference_compare까지 이어진 감사 스택이다. 개발자가 VF 규칙 변경 PR을 올리면 그 PR용 devel 배포에 프로덕션 트래픽 미러가 흘러 들어와, 실제 프로덕션 규모에서 verdict 차이를 미리 검증할 수 있다. VF는 fail-closed(정본 x.md의 주의 목록 #1)라 규칙 변경 리스크가 크므로, 미러링 스택이 staging 배포에서 PR 배포까지 넓어지는 것이 자연스러운 진화 경로다.
F. VF가 예정된 muted-keyword rule에 쓸 포스트 텍스트 필드를 미리 남겨 뒀다
VF가 지금은 어떤 rule도 쓰지 않는 포스트 텍스트 필드를, 앞으로 붙을 muted-keyword rule을 위해 남겨 뒀다 확인.
CoreFeature.text에 dead-code 경고를 억제하는 어트리뷰트가 붙었고, 이 어트리뷰트가 명시적으로 "upcoming muted-keyword rule에 쓰기 위해 남겨 둔다"고 밝힌다 확인 — visibility-filtering/models/tweet.rs.
SlateContext.exact_k/exact_gap을 SlateContext 진화 계열에, experiment_overrides map을 PredictNextActionsRequest 필드 계열에 추가했다.
새 절 "### 4세대+16 (2026-09-04, 902a06f)"을 4세대+15와 정본 주의 목록 사이에 만들었다.
의미 이번 커밋에서 얻은 문화 관찰은 X가 지금 Phoenix MoE 롤아웃의 A/B 인프라를 재정비하는 국면이라는 것이다. 근거는 다음 세 축이 정합적으로 얽혀 함께 움직였다는 사실이다.
A/B 관측 방법론의 코드화: codivert impression 대칭성이 회귀 테스트로 고정됐다.
experiment 스코프의 수직 전달: experiment_overrides map으로 upstream 배정이 downstream까지 일관되게 흐른다.
cold-start의 Phoenix MoE 실험 축 병합: treatment 뷰어의 cold-start 후보가 MoE 후보에만 걸린다.
VF 스택은 검증 인프라(dark_traffic)를 PR 배포까지 넓히는 방향으로 자체적으로 진화하는 중이고, 예정된 muted-keyword rule의 실마리가 dead-code 어트리뷰트에 명시됐다. Phoenix 학습 스택에서는 4세대+13~+15에서 새로 생긴 envelope encryption·StableHLO bundle·H100 remat 등의 안정화 후속이 이어진다.
검증에서 뒤집힌 것
뒤집힌 것은 없다. 이번 커밋은 정본의 방향과 맞는다. 다만 4세대+3에서 관찰됐던 "count_tracked_ids 로직 단순화 이후 record_tracked_ids 호출자와 param의 실 배선"이 이번 커밋에서 명확해진다.
record_tracked_ids는 ColdStartTrackedIds param을 그대로 소비한다.
EnableViewerColdStart 게이팅과 상관없이 항상 호출된다(A절 재정렬의 결과).
tracked ID 관측 훅이 A/B와 무관한 상시 관측 채널이 됐다는 사실이 확정된다.
레이더
레이더에 올린 자료는 없다. arXiv cs.IR 30건을 파싱했고, 산업 블로그는 일요일이라 건너뛰었다. 30건을 triage한 결과 통과한 것은 0건이다.
추천·CTR·reranker 관련 9건은 모두 학술 기관 저자 위주이고, 프로덕션 배포나 A/B 주장이 없다. 이 9건은 탈락했다.
CORE(MLLM 임베딩 compositional)
EPIC(SID diffusion recommendation)
LLM4AIGQ(e-commerce guidance query)
HypRQ-VAE(hyperbolic long-tail generative rec)
SelfDR(LLM 기반 rec reasoning distillation)
DoPR(LLM reranker 압축 문서 프리픽스)
UniCon(CTR unified context)
Recommender System as Slow and Fast Thinkers
Training seeds and model-selection stability 등
나머지 21건도 탈락했다. 성격은 세 갈래다.
benchmark·평가 방법론: SHELF, MultiGhostBench, Incremental Pooled Eval
도메인 제한: POI·법률·의료·과학·야구·music·finance QA
RAG·private retrieval·essay grading 등 LLM 응용 방법론
다음에 볼 것
이번 커밋에 나온 codivert 실험과 새 필드, 예고만 된 VF muted-keyword rule, PR 배포 미러링이 실제로 어떻게 쓰이는지가 남은 질문이다.
moe_codivert_viewer 실험의 초기 트래픽 비율과 활성 시점 — 이번 diff에서는 YAML rule과 param default(false)만 고정됐고, 실 트래픽이 언제 붙는지가 다음 관측 포인트다.