# Critic: FIDELITY-TO-SOURCES **Reviewer:** fidelity critic (critical-review pipeline) **Date:** 2026-06-10 **Primary sources re-verified this pass:** Composer 2.5 blog full body (vault note `introducing-composer-25-cursor`, re-read verbatim), deep-reads `00-grounding.md` and `01`–`08` (all read in full), plus direct re-reads of `docs/COMPOSER_RECIPE_MAPPING.md`, `research/01-composer-2.5.md`, `research/06-feature-deletion-datagen.md`, `docs/adrs/ADR-010`, `composer_replication/opsd.py`, `composer_replication/teacher_replay.py`, `composer_replication/trainer/kl_in_reward.py`, `composer_replication/diloco/__init__.py`, `framework/composer-replication-framework.md`, `docs/VISION_VALIDATION.md`. Severity scale: **P0** = claim must be corrected (factually wrong vs primary source); **P1** = needs a caveat/qualifier (true-ish but overclaims or hides scope); **P2** = wording/precision fix. --- ## P0 — claims that must be corrected **1. [P0] Benchmark numbers (69.3%, Terminal-Bench 2.0 parity) presented as Cursor-stated — they appear in NO primary source.** - *Source fact:* The Composer 2.5 blog (re-fetched, full body) contains **zero benchmark numbers**. The only numerics are pricing ($0.50/$2.50, $3.00/$15.00), "25x more synthetic tasks," "10x more total compute," "0.2s" optimizer step, CP=2/EP=8. The Composer 2 tech report's Table 1 has 61.3/73.7/61.7 for Composer **2** (deep-read 01, FINDING-1). - *Repo claim:* `research/01-composer-2.5.md:63-64`: "Composer 2.5 scored 69.3% … On public agentic benchmarks like *Terminal-Bench 2.0*, it hit 69.3%. On *SWE-bench Multilingual*, it achieved parity with or slightly surpassed OpenAI's GPT-5.5." - *Problem:* The file's own audit notice (line 8) flags this, but the body still asserts the numbers as fact, and the audit note says only "not in the 2.5 blog" — it does not say the numbers are unverified in ANY primary source. Anyone citing §Performance gets fabricated/secondary numbers. - *Correction:* Strike or rewrite §"Performance Characteristics" to: "Neither the 2.5 blog nor the Composer 2 technical report publishes Composer 2.5 benchmark numbers. Figures like 69.3% circulate in secondary commentary (e.g., the Lushbinary developer-guide blog in the vault) and must not be used as replication targets." **2. [P0] "Feature Deletion + 24 other (unnamed) generators" — the count 24 is invented.** - *Source fact (blog, verbatim):* "We use a **range of approaches** for creating synthetic tasks that are grounded in real codebases. For example, **one** synthetic approach is feature deletion." No count, no other names, anywhere. - *Repo claim:* `docs/COMPOSER_RECIPE_MAPPING.md:75` (mapping row b): "Feature Deletion + 24 other (unnamed) generators"; `research/06-feature-deletion-datagen.md:330`: "The other ~24 generators"; propagated into `research/09` line 23 ("captured 'Feature Deletion + 24 unnamed generators'"). - *Problem:* "24" appears to be a back-formation from "25x" — but 25x is a **task-count multiplier vs Composer 2**, not a generator count. Two unrelated quantities have been conflated. - *Correction:* "Feature deletion is the only named generator. The blog says 'a range of approaches'; the number, names, and weighting of other generators are unknown. The '25x' figure counts synthetic *tasks* relative to Composer 2 (whose baseline count is also unstated), not generators." **3. [P0] SDPO declared "mathematically the same" as Composer 2.5's mechanism — the equivalence is asserted nowhere by Cursor, and SDPO's published mechanics materially differ.** - *Source facts:* (a) The blog cites the three self-distillation papers only as "For more **background** on this approach see…" (footnote 1, verbatim). (b) SDPO (arXiv:2601.20802, Eq. 1) applies the KL **over the full rollout response** with feedback in the **conditioning prefix**; it has **no error-turn detection, no hint intercalated into the response, and requires a regularized (EMA/trust-region) teacher** (deep-read 03 §1.1, §3.1–3.2). The blog's mechanism is turn-localized ("For that turn only, we then update the student weights…") — closer to the repo's implementation than to SDPO. - *Repo claims:* `docs/COMPOSER_RECIPE_MAPPING.md:25`: "This is **mathematically the same** as Composer's targeted-textual-feedback method"; same doc §Citations: SDPO is "The direct formalization of Composer's hint-distill"; `composer_replication/opsd.py:13-14`: "arXiv:2601.20802 (formalizes the same loss as Composer 2.5's 'Targeted RL with Textual Feedback')". - *Problem:* This is the load-bearing identification the whole Channel-2 architecture rests on ("Lift the OPSD/SDPO loss directly… exact same mechanism Cursor uses" — mapping doc §Implementation handles). Cursor never says SDPO is its mechanism; and the repo's actual implementation (error-turn masking + hint spliced into the teacher's response sequence + ADR-011 alignment indices) is **neither** SDPO **nor** confirmed Composer — it is a blog-inspired original design (deep-read 03 verdicts: "FALSE — SDPO applies loss to full rollout"; "FALSE — feedback is in prefix, not intercalated"). - *Correction:* "Cursor cites SDPO/OPSD as *background*. SDPO is the closest published formalization of a hint-conditioned same-weights teacher with an on-policy distillation KL, but it differs from the blog's described mechanism in localization (full-rollout vs per-turn) and from our implementation in teacher-context construction (feedback-in-prefix vs hint-at-error-turn). Our SDPO channel is a blog-faithful, SDPO-*inspired* design — not a port of SDPO and not a confirmed match to Cursor's internal method." **4. [P0] Streaming DiLoCo misattributed: wrong authors AND wrong title attached to arXiv:2501.18512.** - *Source fact:* arXiv:2501.18512 is "Streaming DiLoCo with overlapping communication: Towards a Distributed Free Lunch," **Douillard et al. 2025**. "Eager Updates for Overlapped Communication and Computation in DiLoCo" is a *different* paper (arXiv:2502.12996, Kale/Douillard/Donchev). "Liu et al." is the Async Local-SGD paper (arXiv:2401.09135) (deep-read 05, F4). - *Repo claims:* `composer_replication/diloco/__init__.py:8`: "Streaming DiLoCo (Liu et al. 2025)"; `research/design-F4-decoupled-diloco-s3.md:109`: "Liu et al. 2025, 'Eager Updates for Overlapped Communication in DiLoCo', arXiv:2501.18512". - *Correction:* Fix both files to "Streaming DiLoCo (Douillard et al. 2025, arXiv:2501.18512)"; cite Eager Updates separately as Kale et al. 2025, arXiv:2502.12996. **5. [P0] CWM cited as licensing "train-on-all for the world-model aux head during RL" — CWM does this in a separate mid-training stage, not as an aux head riding policy gradients.** - *Source fact (CWM, arXiv:2510.02387 §2.2, verbatim):* "Because our goal with the ForagerAgent data is to learn a comprehensive world model … **we do not filter trajectories based on whether they succeed**." That is a **mid-training data decision** for a dedicated pre-RL stage; the world-modeling capability is in the base weights before RL begins (deep-read 06, Finding 2.1, 4.4). - *Repo claim:* `research/notes/final_report_socratic-mcts-swe-worldmodel-8f6dea.md` §2: CWM "crucially training *on all* trajectories **for the world-model head**, reserving success-filtering only for the RL reward"; §4 re-uses it as the justification that the aux head "makes train-on-all *safe* for the policy." - *Problem:* This is the single load-bearing citation for the two-harvest design (failed branches → world-model head). The cited architecture is structurally different; the simultaneous-gradient configuration the repo proposes is exactly the one the also-cited interference paper (2602.00994) warns about. - *Correction:* "CWM mid-trains on unfiltered trajectories in a dedicated pre-RL stage; it provides an existence proof for train-on-all *dynamics learning*, not for an auxiliary next-state head trained simultaneously with RL. No published work tests our exact configuration." --- ## P1 — claims needing caveats / qualifiers **6. [P1] CWM's "65.8% on SWE-bench Verified" cited without the test-time-scaling qualifier.** - *Source:* CWM abstract: "pass@1 scores of 65.8% on SWE-bench Verified **(with test-time scaling)**"; the single-attempt base score is lower (deep-read 06, Finding 2.1). - *Correction:* Always cite as "65.8% with test-time scaling" or give the base score alongside. **7. [P1] Chain-of-World (arXiv:2603.03195) used as evidence for SWE world-modeling — it is a robotics VLA paper.** - *Source:* CoWVLA: latent-motion world model for robot manipulation, CVPR 2026, cs.CV (deep-read 06, Finding 2.2). No SWE/code content. - *Repo claim:* final report §2 deploys it for "predict the consequential terminal state" in the SWE design. - *Correction:* Keep only as explicitly-flagged robotics analogy or remove. **8. [P1] "85% of total compute is post-training" still stated as fact in the research/01 body.** - *Source:* Neither blog nor tech report contains any compute-budget ratio (deep-read 01, FINDING-6). - *Repo claim:* `research/01-composer-2.5.md:14`: "roughly 85% of the total compute budget for Composer 2.5 was spent on Cursor's proprietary post-training…". The header audit note flags it, but the body asserts it unhedged. - *Correction:* Inline-tag the sentence: "[community speculation — not in any Cursor source]". **9. [P1] The repo's implemented "feature deletion" is gold-patch reversion over pre-labeled SWE datasets — not the blog's mechanism — yet downstream docs say it "matches the recipe."** - *Source fact (blog, verbatim):* "the agent is given a codebase with a large set of tests, and **asked to delete code and files** in such a way that the codebase remains functional while specific testable features are removed." The published mechanism is (likely agentic) *deletion from a functional, test-covered codebase*. The repo's `SweBenchAdapter` instead reverts human PR gold patches of pre-packaged instances — the analogue of SWE-smith's **PR Mirror** strategy, a *third* construction the blog never describes (deep-reads 00 Claim 1, 02 §6.1). - *Repo claims:* ADR-010 is honest about Option A vs B, but its Consequences section says the subsystem delivers the recipe; `docs/COMPOSER_RECIPE_MAPPING.md:42` paraphrases the blog as "take a repo with passing tests, delete some code" (passive — drops the agentic deleter and the "remains functional" constraint); the project framing ("point-at-a-repo feature-deletion task synthesis") attributes to the blog a phrase ("point at a repo") that appears nowhere in it. - *Correction:* "We implement the *inversion analogue* of feature deletion (revert gold patch of an existing SWE instance — SWE-smith's PR-Mirror shape, which SWE-smith's ablations show yields the best training data). The blog's actual generator — deleting code/files from a live, functional codebase so that targeted tests fail — is unbuilt (Option B / Path B). 'Point at a repo' is our reconstruction, not blog language." **10. [P1] ADR-010: "Online difficulty gate matches the actual recipe" — only half the recipe, and with a different signal.** - *Source facts:* Blog: "we both **select for and create** harder tasks dynamically throughout the run" — two operations. The only Cursor-stated difficulty signal is Composer 2's "number of turns and thinking tokens of rollouts—to upsample increasingly harder data points" (tech report §4) — and that is a Composer-2 mechanism mapped onto 2.5 (deep-read 01, FINDING-12). - *Repo state:* `DifficultyCurriculum` implements only the SELECT half, primarily on a pass-rate frontier (extrapolated, not Cursor-stated); the CREATE half (minting harder tasks mid-run) is 0% built; `granularity` is hardcoded `"feature"` (grounding doc, Claim 3). Wave 20's effort tilt on turns/think-tokens partially aligns with the stated heuristic. - *Correction:* "The select-for half is built (pass-rate frontier [EXTRAPOLATED] + turns/think-token effort tilt [Composer-2-sourced]); the create-harder half of the published recipe is not implemented." **11. [P1] ADR-010 decision driver: substrates "already guarantee test-exercises-the-code via FAIL_TO_PASS."** - *Source fact:* SWE-smith (§2.1) shows the F2P property is the *output of running validation* (overall yield ~50.1%; candidates lacking test coverage are filtered out by execution), not a schema-inherited guarantee; no surveyed dataset verifies *reachability* of the deleted code from the failing tests (deep-read 02, §6.2 item 6; ADR-010's own OPEN item concedes Gate 2 doesn't verify reachability). - *Correction:* "F2P labels are trustworthy because the upstream pipelines *executed* the tests; any new inversion we mint must re-run gates 1–3 to re-establish the property, and reachability remains unverified across the field." **12. [P1] Mapping doc states the KL direction as `KL(teacher || student)` — unsupported by the blog and opposite to the paper the doc equates it to.** - *Source facts:* Blog: "an on-policy distillation KL loss that moves the student's token probabilities toward the teacher's" — direction unspecified. SDPO Eq. 1: `KL(π_θ ‖ stopgrad(q_θ))` — **student first** (deep-read 03 §1.1). - *Repo claim:* `docs/COMPOSER_RECIPE_MAPPING.md:20`: "Loss = on-policy KL divergence: `KL( teacher_logits_at_turn_t || student_logits_at_turn_t )`". - *Correction:* "Direction unspecified in the blog; SDPO uses KL(student‖teacher) (adopting JSD for stability); our implementation uses the OPSD generalized JSD." **13. [P1] `opsd.py` β-convention docstring is inverted vs the upstream it claims byte-parity with.** - *Source:* OPSD README: "Beta=0 means forward KL and 1 means reverse KL." Repo docstring labels β=0 "reverse KL" / β=1 "forward KL." Code is numerically correct; the labels would misconfigure anyone choosing β by docstring (deep-read 03 §2.2). - *Correction:* Swap the labels to match upstream. **14. [P1] SDPO-fidelity claim without SDPO's teacher regularization.** - *Source:* SDPO Table 4: non-regularized live-weights teacher **diverges** (36.1% vs 50.6% with trust-region teacher); EMA/trust-region regularization is a core stability component (deep-read 03 §1.1, rec. 4). Also §4.5: SDPO underperforms GRPO on weak models; λ=0.9 GRPO + 0.1 SDPO hybrid recommended. - *Repo state:* teacher = live weights each step, no EMA/trust-region; no usage guidance on the weak-model failure mode. - *Correction:* Document both gaps wherever the SDPO channel is described as paper-faithful; implement or explicitly defer teacher regularization. **15. [P1] `SiblingBootstrapGenerator` framed as following from SDPO's "successful rollouts as implicit feedback" — it is an extrapolation.** - *Source:* SDPO's sibling mechanism puts the successful sibling rollout **into the teacher's conditioning prefix** and applies the KL over the *entire* original response. It does not generate a "Reminder: a working approach looks like…" hint string, insert text into the response, or detect error turns (deep-read 03 §6). - *Repo claim:* `research/07` + `hint_generator.py` sketch present the sibling-hint design as the natural SDPO-supported fallback. - *Correction:* "SDPO supports sibling-as-conditioning-context; our hint-string splice at error turns is our own Composer-blog-inspired variant. The paper-faithful alternative (sibling in prefix, full-response KL) is simpler and should be the ablation baseline." **16. [P1] "$0.98 mean per-trace cost ungated — verified economic floor" hides the trace definition; real sessions cost ~2 orders of magnitude more.** - *Source:* Spike 001 measured 50 hand-crafted synthetic states at N=3 teachers. Real Claude Code sessions have 125–2,830 tool-use messages (ADR-002); at DEFAULT_TEACHERS pricing a ~1,400-step session is ~$70–80 flat (deep-read 07, FR-R5). - *Repo claims:* `teacher_replay.py` docstring ("Verified economic floor … $0.98 mean per-trace cost ungated"); `docs/VISION_VALIDATION.md` ("$0.98/trace verified … economic floor is established"). - *Correction:* "Verified floor for 50-step synthetic-state benchmark traces; full-session flat replay is ~$70–80 ungated; $0.30/trace VOI-gated figure is a projection, not a measurement." **17. [P1] "$64 ungated tree" is mislabeled — it is a flat N=8, T=1000 extrapolation, not a tree and not a codebase config.** - *Source:* research/05 constructs $0.008 × 1000 × 8 = $64 flat; DEFAULT_TEACHERS is N=3; a true branching tree is O(N^D), strictly worse (deep-read 07, 05-R6/FR-R6). - *Correction:* Label it "flat 8-teacher × 1000-step extrapolation (unmeasured)" everywhere; never "tree." **18. [P1] `kl_in_reward.py`: "verl adopted k1-in-reward as its *only* reverse-KL option" — overclaim.** - *Source:* verl supports `kl_penalty="kl"` (k1) **and** `kl_penalty="low_var_kl"` (k3-family) (deep-read 04 §4.3). - *Correction:* "verl defaults to / recommends k1-in-reward" — drop "only." **19. [P1] Comedy of Estimators (arXiv:2512.21852) used as "k1-in-reward improves OOD; k3-in-reward can collapse" — full text never read, and the 7B/8B-math→1T-MoE-agentic extrapolation is unflagged.** - *Source:* Only the abstract was obtainable (HTML 404); it supports "biased gradients → instability; unbiased → better OOD" but does not state the specific estimator-placement ranking the repo asserts (deep-read 04 §2, §4.4). - *Correction:* Soften to "consistent with the abstract's biased-vs-unbiased finding; specific k1/k3-placement ranking unverified (full text unavailable); empirical scope is 7B/8B reasoning models." **20. [P1] GSPO preset claims to implement GSPO but inherits GRPO-scale clipping — two orders of magnitude off the paper's settings.** - *Source:* GSPO paper §5.1: clipping ranges 3e-4/4e-4, "a difference of two orders of magnitude in the fractions of clipped tokens between GSPO and GRPO." The repo preset sets no epsilon → TRL defaults (~0.2) → effectively unclipped sequence-level REINFORCE (deep-read 04, ISSUE 1). - *Correction:* Add `epsilon=3e-4, epsilon_high=4e-4` to the preset or annotate it "architecture-only; not operationally GSPO without GSPO-scale epsilons." (Companion: CISPO preset should set `beta=0.0` explicitly per MiniMax-M1, and document its deliberate `scale_rewards="none"` deviation from the paper's std-norm.) **21. [P1] research/05's novelty framing: rStar named "closest precedent" (misread) while the actually-closest works are uncited.** - *Source facts:* rStar's discriminator verifies **full trajectories**, not per-step states ("acts as a discriminator to verify each trajectory" — abstract). Tree-GRPO (arXiv:2509.21240) proves intra-tree group-relative advantage ≡ step-level DPO — the formal version of `extract_dpo_pairs`; SWE-Search (arXiv:2410.20285) is MCTS on SWE-bench itself. Neither is cited in research/05; `framework/composer-replication-framework.md:17` still says "Closest precedent: rStar-Math … Multi-teacher *frozen-trace replay* is open territory" (deep-read 07, 05-R1/R2/R3). - *Correction:* The novelty claim (frozen-trace × N heterogeneous teachers × disagreement-DPO) survives, but the provenance section must cite Tree-GRPO and SWE-Search as the nearest neighbors and correct the rStar granularity description. **22. [P1] "Roughly nine-tenths of it is reuse" (final report §6) conflates design-reuse with build status.** - *Source:* Exhaustive grep confirms tree controller, SiblingBootstrapGenerator, world-model head, `` token, pipeline/, infra/, broken-image builder are **0% built** (grounding doc §3, Claim 5). - *Correction:* "Nine-tenths of the *recipe-replication* layer reuses existing code; the framework's own additions (tree, world-model head, AWS datagen pipeline) are entirely design-stage." **23. [P1] World-model aux-head design presented with citation support that is wholly analogical; "parameter isolation eliminates the interference risk" overclaims DART.** - *Source facts:* No paper in the cluster tests a next-state aux loss on a policy LLM during code RL — the evidentiary gap for the exact proposed configuration is total (deep-read 06, Missing 1). DART (2602.00994) shows separate LoRA modules *reduce* interference but do not reach the 2-Agent upper bound (Finding 3.1); its domain is RAG-QA/NL2SQL, not SWE. - *Correction:* Add an explicit null-evidence flag to §2 of the final report and to any ADR that inherits it; change "eliminates" → "substantially reduces"; the P4 ablation is a research hypothesis test, not a validation of established results. **24. [P1] VeRL "first-class agentic RL support" — the async path is experimental.** - *Source:* verl README: `fully_async_policy`, `transfer_queue` live under `verl/experimental`; `uni-agent` (May 2026) is a separate layer (deep-read 08 §7.1). - *Correction:* "VeRL's agentic/async path exists but is experimental; evaluate `uni-agent` before committing to a custom AgentLoop." --- ## P2 — wording / precision **25. [P2] research/01 §5: "During **post-training**, Cursor employs Sharded Muon and Dual Mesh HSDP."** Blog (verbatim): "For **continued pretraining**, we use Muon…". Fix the stage attribution (the mapping doc already has it right). Also do not conflate with Composer 2's FSDP+CP/AdamW system (deep-read 01, FINDING-7). **26. [P2] research/06's "two-agent / two-phase structure the blog implies."** The blog's grammar has one "the agent … asked to delete"; whether the deleter is a model, program, or pipeline is unstated. research/06 already lists this as an open question (line 329) — align the §1 framing with it: "deleter unknown; blog grammar suggests an agent" (deep-read 01, FINDING-3). **27. [P2] research/06 "~50k–60k tasks" as the "25×-spirit" pool.** No Composer-2 baseline count exists, so 25x is not convertible to an absolute. The "spirit" hedge is present; add "[EXTRAPOLATED — no primary-source baseline]" at the number (deep-read 01, FINDING-2). **28. [P2] Grounding doc Claim 1 presents a paraphrase as a blog quote.** `research/deepread/00-grounding.md` Claim 1: "What the blog says (COMPOSER_RECIPE_MAPPING.md): 'take a repo with passing tests, delete some code, ask the agent to reimplement to pass tests.'" — that sentence is the mapping doc's paraphrase, not blog text. Use the real blog sentence when quoting "what the blog says." **29. [P2] research/02 DiLoCo compression details.** "FP16 outer state" → Streaming DiLoCo quantizes **outer gradients to FP4 (E3M0)**, FP32 accumulation; bandwidth claim "~100×" → measured ≈400× total-bits reduction (Table 1) (deep-read 05, F6/F7). **30. [P2] DiLoCo H default source attribution.** `diloco/__init__.py` docstring credits "DiLoCo paper §3.2" for defaults, but §3.2's main-experiment H is 500; the repo's `sync_every=100` matches the Streaming/OpenDiLoCo range. Also note Streaming's outer_lr=0.4 vs the vanilla 0.7 default (deep-read 05, F2/F3). **31. [P2] "Foresight@k" cited as if sourced.** The metric is coined by the final report; citations [11][2] do not define it. Mark "(we define this metric)" at first use (deep-read 06, Finding 3.2). **32. [P2] SWE-rebench "21,336 tasks" count never verified against the SWE-rebench paper** (only the Nebius infra blog was fetched); and the 59k-row figure is ambiguous between SWE-smith-on-HF and Nemotron-SWE-v1 (deep-read 02, §6.2 items 3 and unverified item 3). Tag both counts "[UNVERIFIED-COUNT]" until arXiv:2505.20411 is read. **33. [P2] `_normalize_action` whitespace-only normalization is acknowledged in code but absent from every risk list.** On real tool-call traces, Channel-3 pair extraction will be mostly noise; the final report's §10 failure modes and ADR-002 consequences should both name it (deep-read 07, FR-R8). (Fidelity angle: the "DPO-pair extractor, 7 unit tests" line in VISION_VALIDATION implies more readiness than the known-stub normalizer supports.) --- ## Confirmed faithful (for balance — no action) - The verbatim 25x sentence, feature-deletion paragraph, reward-hacking anecdotes (Python type-check cache, Java bytecode), and "agentic monitoring tools" are quoted accurately in `research/06`, `research/09`, ADR-010, and COMPOSER_RECIPE_MAPPING — re-verified against the fetched blog body this pass. - Dr.GRPO claims in `research/10` (length-norm removal, no std-norm, k1 estimator, DAPO overlong masking tried-and-rejected, Adam, single-epoch) — all verified verbatim against the Composer 2 report (deep-read 04 §4.1–4.2). - The k1-in-reward fold-then-baseline algebra and its Dr.GRPO-regime precondition are mathematically sound (deep-read 04 §3.2); one latent `num_iterations>1` guard is missing (engineering, not fidelity). - Channel 3's depth-1/flat and teacher-plurality-not-execution self-descriptions in the final report are accurate (deep-read 07, FR-R1/R2). - Channel-3 and tree-of-work provenance is honestly labeled "NOVEL — our addition, not part of Cursor's recipe" in `framework/composer-replication-framework.md`, VISION_VALIDATION, and the spike layer — the provenance boundary between "Composer's recipe" and "our additions" is consistently drawn. The residual issue is nearest-neighbor citation completeness (finding 21), not provenance dishonesty. - ADR-010's OPEN items (Gate-2 reachability, deleted_symbols emptiness) are honest self-flags that match what the sources show is an unsolved field-wide gap. - TRL claims (default `loss_type="dapo"`, `scale_rewards` handling, drift assertions in `make_dr_grpo_config`) verified against live docs (deep-read 08 §1). --- ## Severity totals - **P0: 5** (findings 1–5) - **P1: 19** (findings 6–24) - **P2: 9** (findings 25–33)