# Wave 16 Reconnaissance Audit Audit of `docs/research/*RECONNAISSANCE.md` and `*LANDSCAPE.md` against repo state at sha `e5add150ab06aeef3adda726c0fcae05aa270500`. Wave 16d charter: check 7 recon/landscape docs against current code, produce this audit table, and apply only **unambiguous** inline fixes. Ambiguous claims are tagged with `` HTML comments inline and recorded here for orchestrator follow-up. ## Summary - Total claims checked: ~36 across 7 docs - KEEP: 24 - FIX (unambiguous, applied inline): 2 - FLAG (ambiguous; HTML comment + entry below): 5 - DELETE: 0 The framework deliberately ships proposal-shaped recon docs alongside built code. Wave 16d's posture has been "do not rewrite proposals; flag where the realised code diverged so future readers know which sections are pre-impl sketch vs. accurate-as-of-build documentation." ## Per-doc findings ### DILOCO_RECONNAISSANCE.md External-only doc (about `meta-pytorch/torchft`); no in-repo symbol or path references. Nothing to audit against current code. | Claim | Status | Action | | --- | --- | --- | | All references are to `torchft.local_sgd.DiLoCo`, `torchft/local_sgd.py:324`, `torchft/manager.py`, etc. | external library, not our concern | KEEP | | Recommends `pip install torchft-nightly`; `composer_replication/diloco/__init__.py` later adopted that | confirmed in code | KEEP | ### DILOCO_SERVERLESS_RECONNAISSANCE.md Doc is a pre-implementation proposal for ADR-005. The realised package layout under `composer_replication/diloco/serverless/` is flatter and uses different module names than the proposal. | Claim | Status | Action | | --- | --- | --- | | `composer_replication.diloco.serverless` namespace exists | matches reality | KEEP | | Code blocks use file headers `_modal_adapter.py`, `_hf_jobs_adapter.py`, `_protocol.py`, `_rendezvous.py`, `_base.py` | actual modules are `modal.py`, `hf_jobs.py`, `executor.py`, `allreduce.py` (no leading underscore, no _protocol/_base/_rendezvous split) | FLAG (`stale_serverless_layout` HTML comment added before §3.4) | | §3.4 proposed `modal/`, `hfjobs/`, `runpod/` subpackages | actual ships flat `modal.py`, `hf_jobs.py` modules | FLAG (covered by same comment) | | `make_diloco_outer_loop` lives in `composer_replication/diloco/__init__.py` lines 64–125 | line numbers verified (def at 64, body ends ~125) | KEEP | | `python -m composer_replication.diloco.serverless.replica_entrypoint` | module exists with `main()` at line 38 | KEEP | | `MockManager` exists in serverless package | confirmed at `composer_replication/diloco/serverless/allreduce.py:215` | KEEP | | `ObjectStoreAllReduce` exists | confirmed at `composer_replication/diloco/serverless/allreduce.py:30` | KEEP | | §3.5 user-facing API `from composer_replication.diloco.serverless import ModalExecutor, HFJobsExecutor, ReplicaSpec` | partial: `ModalExecutor` and `HFJobsExecutor` exist as classes, but `serverless/__init__.py` does NOT re-export them (only `LocalProcessExecutor`, `MockManager`, `ObjectStoreAllReduce`, `ReplicaHandle`, `ServerlessExecutor`) and `ReplicaSpec` is not implemented | covered by `stale_serverless_layout` flag | ### MODAL_RECONNAISSANCE.md Doc anchors all loss-shape claims to `spikes/005-integrated-trainer-skeleton/`, which is unchanged since Wave 15. All checked references resolve. | Claim | Status | Action | | --- | --- | --- | | `spikes/005-integrated-trainer-skeleton/trl_path/composer_trainer.py` exists | confirmed | KEEP | | `spikes/005-integrated-trainer-skeleton/opsd_loss.py` exists | confirmed | KEEP | | `_compute_sdpo_loss` student/teacher forwards at `composer_trainer.py L138–143` | confirmed (L138-143 are student/teacher logits) | KEEP | | `_compute_trace_replay_loss` chosen/rejected forwards at `L191–198` | confirmed (L191-198 are `_sequence_logprobs` calls) | KEEP | | Zero-tensor short-circuit at `L136` and `L155` | confirmed (both lines `return torch.tensor(0.0, ..., requires_grad=True)`) | KEEP | | `opsd_loss.py L54` references `top_k` arg | confirmed | KEEP | | Trainer defaults `alpha_sdpo=0.1`, `beta_replay=0.05` | match `composer_replication/loss.py:75-76` | KEEP | ### REPLAYSIM_NORMALIZATION_RECONNAISSANCE.md Pre-spike proposal for ADR-004. The library was adopted (data-juicer) and `DJNormalizer` exists, but the adapter shape and recipe path differ from the proposal. | Claim | Status | Action | | --- | --- | --- | | `composer_replication.replaysim` package exists with `DJNormalizer` | confirmed at `composer_replication/replaysim/normalize.py:145` | KEEP | | `replay_trace`, `extract_dpo_pairs` re-exported from replaysim | confirmed in `__init__.py` | KEEP | | §4.3 sketch shows DPOPair with `{prompt, chosen, rejected, state, meta}` and `_to_dj`/`_from_dj` round-trip | actual `DPOPair` is `{state_id, state_messages, chosen: str, rejected: str, n_teachers_agreeing}` (TypedDict in `composer_replication/teacher_replay.py:99`) | FLAG (`stale_replaysim_paths_and_dpo_shape` added before §4.3) | | Recipe path `composer_replication/replaysim/recipes/dpo_normalize.yaml` (line 344) | actual is `composer_replication/recipes/replaysim/default.yaml` | FLAG (covered by same comment) | | `composer_replication/replaysim/ops/preference_validator.py` (line 431) | not created — no `ops/` subpackage exists | FLAG (covered by same comment) | | §4.5 hook into `composer_replication/replaysim/teacher_replay.py` | actual integration path is `replay_and_normalize_trace_sync` in `composer_replication/replaysim/normalize.py:301` (no separate replaysim/teacher_replay.py — teacher_replay lives at top-level `composer_replication/teacher_replay.py`) | FLAG (covered by same comment) | ### RL_FRAMEWORKS_LANDSCAPE.md Wave 14b parity rewrite changed the public surface for the PRIME-RL recipe. Most file/symbol references in the doc are unambiguously fixable. | Claim | Status | Action | | --- | --- | --- | | PRIME-RL `LossInputs` / `LossOutputs` interface, fields `trainer_logprobs, inference_logprobs, teacher_logprobs, advantages, loss_mask` | matches `composer_replication/recipes/prime_rl/composer_loss.py:17-28` | KEEP | | `import_path = "composer_replication.losses.composer_three_channel_loss"` (line 318) | actual is `composer_replication.recipes.prime_rl.composer_loss:loss_fn` | FIX (applied inline) | | `composer_replication/losses.py` (~120 LOC) (line 333) | actual file is `composer_replication/recipes/prime_rl/composer_loss.py`; function is `loss_fn` not `composer_three_channel_loss`; signature is `(inputs, **kwargs)` not `(li, *, hint_weight, replay_weight, replay_logits)` | FIX (filename + AUDIT comment noting signature drift; sketch retained as-is) | | Recipe in `recipes/composer_v0_prime_rl.toml` with kwargs `hint_weight`, `replay_weight`, `replay_logits_path` | actual recipe is `composer_replication/recipes/prime_rl/prime_rl_config.yaml` (YAML not TOML) and kwargs are `alpha_sdpo, beta_dpo, dppo_mask_high, dppo_mask_low, adv_tau, kl_tau` | FLAG (`stale_recipe_format` HTML comment added at the recipe block) | | Monarch sketch `composer_replication/orchestrator/monarch_runner.py` | not in code; treated as v0.2 sketch (and §6.2 already labels it "Monarch wrap-up sketch (v0.2)") | KEEP (clearly v0.2 forward-looking; no AUDIT needed) | | Note that `composer_replication/recipes/monarch/actors.py` exists, providing the monarch actor surface | matches `composer_replication/recipes/monarch/actors.py` | KEEP | ### SELF_DISTILLATION_LANDSCAPE.md Audit doc for ADR-007. Three losses (SimPO, TAID, Entropy-Aware OPD) were adopted, but the package layout proposed in §"Recommended follow-up wiring" is not what was built. | Claim | Status | Action | | --- | --- | --- | | References `composer_replication/__init__.py` and existing `composer_replication.opsd.generalized_jsd_loss` | confirmed | KEEP | | Audited candidate verdicts (SimPO/TAID/EA-OPD recommended) | matches what shipped under `composer_replication/distillation/` | KEEP | | Proposed package layout: `composer_replication/distillation/{targets.py, losses.py}` + `composer_replication/preference/{simpo.py, dpo.py}` | actual: flat `composer_replication/distillation/{simpo.py, taid.py, entropy_aware_opd.py}` — no targets/losses split, no top-level `preference/` package | FLAG (`stale_distillation_layout` HTML comment added before the proposal block) | | Function names `taid_target`, `entropy_aware_kl_loss`, `fixed_target` | actual exports: `taid_loss` + `TAIDScheduler`, `entropy_aware_opd_loss`, `simpo_loss` | FLAG (covered by same comment) | | Composition rule sketch `L_distill = entropy_aware_kl_loss(target = taid_target(...), ...)` | not realised as a single composed function — actual API is per-loss with `compose_loss` mixing channels via `sdpo_wrapper`/`dpo_variant` switches | FLAG (covered by same comment) | ### TRACE_SOURCE_RECONNAISSANCE.md Pre-spike audit feeding ADR-002 and Spike 007. Doc cites the actual `TraceState`/`DPOPair` TypedDicts correctly (matches current `composer_replication/teacher_replay.py:81-104`). The sketch in §6 uses spike-shape names that do not match what shipped. | Claim | Status | Action | | --- | --- | --- | | `TraceState` and `DPOPair` field lists in §1 | match `composer_replication/teacher_replay.py` (TypedDicts at lines 81-104) | KEEP | | `spikes/005-integrated-trainer-skeleton/teacher_replay.py` exists | confirmed | KEEP | | §6 sketch path `spikes/007-trace-ingester/trace_ingester.py` and class `TraceIngester` | actual spike path is `spikes/007-real-trace-ingestion/claude_code_ingester.py` and the production class is `composer_replication.ingestion.claude_code.ClaudeCodeIngester` | FLAG (`stale_ingester_paths_and_naming` HTML comment added before §6) | | Direct inspection of `~/.claude/projects/` JSONL files | not testable from CI; user-machine claim | KEEP | | Re-use of `TraceState` from spike-005 `teacher_replay.py` | spike still has it; production also has it | KEEP | ## Open items for Wave 17+ > **Wave 17 closeout (2026-05-26):** All 5 FLAGs below were resolved > by adding "Realised in v0.1" companion sections to the affected > proposal docs that document the shipped surface inline above the > historical sketch. Wave 17 also fixed the underlying code bug from > FLAG #1 — `serverless/__init__.py` now re-exports `ModalExecutor` > and `HFJobsExecutor` (verified by > `composer_replication/diloco/serverless/tests/test_serverless_local.py::test_public_reexports_include_all_executors`). > The original FLAG-list below is preserved as historical record of > what the audit found. These are the FLAGged ambiguous claims that need orchestrator decision before a confident rewrite: 1. **DILOCO_SERVERLESS_RECONNAISSANCE.md §3.4** — proposed serverless package layout (`_modal_adapter.py`, `_protocol.py`, etc.) does not match shipped layout (`modal.py`, `executor.py`, etc.). Decide: rewrite §3.4 to document shipped layout, or keep as historical proposal. Note also: §3.5 references `ModalExecutor` and `HFJobsExecutor` as `from … serverless import …` but `serverless/__init__.py` only re-exports `LocalProcessExecutor`. Either the public re-export should be added (code change, out of Wave 16d scope) or §3.5 needs to use the longer module path. 2. **REPLAYSIM_NORMALIZATION_RECONNAISSANCE.md §4** — Adapter sketch assumes a `DPOPair` shape (`{prompt, chosen, rejected, state, meta}`) that does not match the realised TypedDict (`{state_id, state_messages, chosen: str, rejected: str, n_teachers_agreeing}`). The §4.3 `_to_dj`/`_from_dj` functions in the sketch will not work as written. Decide: rewrite §4 to match `replay_and_normalize_trace_sync` in `composer_replication/replaysim/normalize.py:301`, or keep as proposal- shaped historical context. 3. **RL_FRAMEWORKS_LANDSCAPE.md §6.1** — recipe sketch is `.toml` with `hint_weight`/`replay_weight` kwargs; reality is `.yaml` with `alpha_sdpo`/`beta_dpo`/`dppo_mask_high`/`dppo_mask_low`/`adv_tau`/`kl_tau`. The `loss_fn(inputs, **kwargs)` signature also differs from the `composer_three_channel_loss(li, *, hint_weight, replay_weight, replay_logits)` sketch. Decide: rewrite §6.1 to match shipped recipe, or keep as the original landscape proposal. 4. **SELF_DISTILLATION_LANDSCAPE.md §"Recommended follow-up wiring"** — the `distillation/{targets.py, losses.py}` + `preference/{simpo.py, dpo.py}` layout is not what shipped. Actual is flat `composer_replication/distillation/{simpo.py, taid.py, entropy_aware_opd.py}` with function names `simpo_loss`, `taid_loss` + `TAIDScheduler`, `entropy_aware_opd_loss`. Decide: rewrite the wiring sketch or leave as proposal-shaped record of pre-ADR thinking. 5. **TRACE_SOURCE_RECONNAISSANCE.md §6** — `TraceIngester` sketch differs from shipped `ClaudeCodeIngester`. Decide: rewrite §6 to point at the realised ingester (would also require updating spike path from `007-trace-ingester` to `007-real-trace-ingestion`), or keep as pre-spike proposal. ## What was NOT changed - `WAVE_*_FINAL_REVIEW.md` files — explicitly out of scope for Wave 16d. - Any code under `composer_replication/`, `examples/`, `tests/` — code-side fixes (e.g. adding `ModalExecutor`/`HFJobsExecutor` to `serverless/__init__.py` re-exports) belong to a code wave, not a doc audit. - Whole-section rewrites of any doc — Wave 16d's mandate is "audit + safe inline fixes only". Each FLAG above is a candidate for a future targeted rewrite wave.