docs: audit everything, consolidate 18 skills into 2, resync the mdBook - #32
Merged
Conversation
Audited every `.claude/skills/` package (9,371 lines), all 32 `docs/` files, README.md, `.claude/references/`, and CLAUDE.md by verifying each concrete claim against source rather than assessing plausibility. Findings (full report: docs/2026-07-30-docs-and-skills-audit.md): - `kan_head.disaggregation.use_precip` does not exist. It is documented in CLAUDE.md, src/config.rs:113's comment, and config/sources/conus-hourly.yaml. Removed in 334f0fe; the head now always consumes precip. - `ddrs init` (exit 2) and `ddrs run --workflow eval` (`--from-run` unimplemented) are documented as working in README.md, docs/, and CLAUDE.md. Both hard-error. - The baseline `0.689 / 0.723` propagated into 13 of 18 skills as the CONUS bar. It is a global-MERIT 5,224-gauge number. The CONUS bar is 0.6781 / 0.7172 on 2,365 gauges, making the widely-quoted +0.026 delta a cross-population subtraction (correct: +0.037). - The 07-07 and 07-16 findings docs compare 3,211-gauge baselines against 2,365-gauge trained medians. Population-matched, hourly-lstm's "+0.022 NSE gain from routing" reverses to -0.051. - One superseding doc (2026-07-06 leakance NO-GO) invalidated the same "Phase B is required" paragraph in six skills; none were updated. Three still carried executable instructions for the closed campaign. - Test counts were wrong (leakance_gradcheck 16 not 8, zeta_accum 8 not 6), and two gate commands in CLAUDE.md/docs run zero tests and exit 0. - `.claude/references/` is a strict subset of `docs/`; its newer mtime is a 2026-06-10 back-port of corrections `docs/` received on 2026-06-08. Consolidation: 18 skills -> 2, 9,371 -> 2,359 lines (75% reduction). - `ddrs-dev` (build/code/run/debug): SKILL.md + references/{build-and-env, config, testing, traps, research-status}.md - `ddrs-eval-plots` (evaluate output): rewritten around `.ddrs/runs/<id>/`; the dead `output/saved_models_*/` layout is gone. Two dead-campaign references (H5 parameter_swap, H6 loss_landscape) removed since both plot instruments the v2 audit refuted; two orphaned parity_* files merged into parity.md and wired into the routing table. Editorial rules applied: do not duplicate CLAUDE.md (in context every turn); lead with the discriminating test, not the narrative; one authoritative numbers table with gauge-set definitions and a do-not-use list, replacing five copies of H1-H7; assert "all pass" instead of brittle test counts. Every rewritten eval-plots template was executed end-to-end against a real run, reproducing the committed parameter_convergence_stats.json values exactly. docs/ and README.md fixes are enumerated as prioritized follow-ups in the report, not applied here. Co-Authored-By: Claude <noreply@anthropic.com>
Table of contents: - ddrs-dev/SKILL.md gains a §Contents indexing each reference file's sections, so an agent can jump to the right file+section without opening all five. - ddrs-eval-plots/SKILL.md likewise. - Added §Contents to the four reference files that lacked one: config.md, research-status.md, parameter_map.md (455 lines), metrics.md. traps.md and parity.md already open with functional index tables. CLAUDE.md corrections (verified against source): - `kan_head.disaggregation.use_precip` does not exist — removed in 334f0fe. The disagg block's presence is what makes `aorc_precip` mandatory. - `ddrs run --workflow eval` is not implemented (`--from-run` does not exist); `ddrs init` exits 2. Both were listed as working commands. - `src/sparse.rs` -> `src/sparse/` (3 sites). - `cargo test --test mmc mc_routes_linear_chain` names a test that does not exist -> `forward_reproducible`. - Baseline cache key hashes BASELINE_ALGO_VERSION first; documented the headwater gauge filter and why it exists (513/3211 phantom zeros). - Data-source table no longer marks netcdf/icechunk readers (TODO) — both are implemented. - Added `kge` and `nse-batch` to the loss-kind list. - `conus-hourly` is not `conus` plus one key; the groups target different hosts. - Repointed `.claude/references/*` links at their `docs/` counterparts. - Added a pointer to the two surviving skills. README.md corrections: - Same `--workflow eval` / `ddrs init` caveat. - Workspace table was missing config.yaml, baseline/, plot/kan_parameters.nc, and the baselines cache; checkpoint contents now spelled out. - Leakance formula was missing the losing-only clamp, which is ON by default, plus the impervious mask. - Documented the disaggregation head (previously in no user-facing doc) and `experiment.loss.kind`. - Documented `--backend cpu` and the six other `ddrs run` flags, and the `--workspace`-beside-config trap. Co-Authored-By: Claude <noreply@anthropic.com>
The book was a 2026-06-08 snapshot. Everything landed since was invisible to it: leakance, the precip disaggregation head, the nnse-kge/kge objectives, `ddrs sources`/`import`/`status`/`gc`, managed adjacency, the global data stores, and `--backend cpu`. Two documented entry-point commands hard-errored. Fixed across 13 chapters, each claim re-verified against source: Commands that did not work - `ddrs init` (exits 2) removed from the getting-started path in setup.md and running.md; documented as a dead stub. - `ddrs run --workflow eval` documented as unimplemented (`--from-run` does not exist); `train-and-test` and the legacy `eval` binary are the working paths. - `cargo test --test sp8_gradcheck -- --ignored` ran zero tests and exited 0 — a gate that could not fail. Same for `--lib training::checkpoint` and `--lib data::store::zarr::tests::…`. `mc_routes_linear_chain` never existed. Claims that were inverted or wrong - outputs.md opened with "there is no global results directory"; everything lands under `.ddrs/runs/<id>/`. Rewritten around the real tree. - setup.md claimed the CPU path needs no CUDA; burn-cuda and cudarc are non-optional, so a CPU-only reader fails at `cargo build`, not at runtime. Reframed as CPU *execution* via `--backend cpu`. - Seven "MLP head" mentions in algorithm.md and intro.md violated invariant 5. - algorithm.md called `p_spatial` an exponent; it is the coefficient. - perf.md had the Rust defaults inverted (`Cpu`/`false`, not cuda/true), `PersistentScratch` at 33 handles (39 — a group of 6 backward handles was missing, understating memory ~18%), and a wrong K1 output list. - `DDRS_FORCE_GRAPHS=1` does not exercise graph capture — it only selects the backend. Corrected in ddr-comparison.md and the dependent V9 claim in perf.md. - baseline.md's cache key omitted the BASELINE_ALGO_VERSION salt and its gauge filter predated the headwater skip. - burn-autograd.md knew two custom Backward ops; there are three (widths 2/5/8). - inputs-formatting.md described `tau` as a substep count; it is the UTC→local trim-window phase offset and nothing in src/routing/ reads it. - inputs-reading.md said five data sources; there are eleven store modules. - architecture.md described a two-way timestep dispatch; it is three-way. Coverage added - The disaggregation head and leakance math, previously in no chapter. - `experiment.loss`, `state_cache`, `kan_head.disaggregation`, the leakance params, and the four missing `parameter_ranges` keys. - Managed adjacency in the reader chapters; the format-sniffing store enums. - All `ddrs run`/`plan` flags, the global `--config`/`--workspace` pair and the workspace-beside-config trap, and the stale-binary trap. - architecture.md's module map went from 9 of 15 top-level modules to all of them, with sub-tables for src/data/store/ and src/training/. - nh-qprime-store-contract.md added to SUMMARY.md — README and CLAUDE.md both cite it, but it was not published. Also caveated `nse-batch`/`adadelta` in CLAUDE.md and README.md: they arrive with PR #31 and do not exist on master. `mdbook build` is clean. Verified: zero MLP references outside the documented `mlp:` serde alias, and every remaining `ddrs init` mention is in a "this is dead" context. Co-Authored-By: Claude <noreply@anthropic.com>
…9 claim
Two source-side defects surfaced by the documentation audit.
1. `src/cuda_graph/scratch.rs` module docstring (comment-only).
Claimed "32 Handles total" and "All buffers are `[n × f32]`". Counted
against the struct: 39 handles — 3 forward I/O, 6 static-input mirrors,
1 pattern diag_mask, 23 saved-state, 1 backward input, 5 backward
outputs. Two of them (`state_a_values`, `pattern_diag_mask`) are
nnz-sized, not n-sized, so 37 are `[n_segments]`.
The memory figures were understated ~18%: ~525 KB / ~44 MB become
~740 KB / ~51 MB, plus `2 × nnz × 4` bytes. An inline comment also said
"24 saved-state outputs" where the group holds 23; it is now tied
explicitly to `mmc_op::NUM_SAVED_STATE` so the two stay in lockstep.
`docs/reference/perf.md` already carries the corrected numbers.
2. The V9 "graph vs no-graph bit-match: GREEN" verdict is retracted as
UNVERIFIED in `.claude/ARCHITECTURE.md` and `docs/architecture.md`.
The recorded evidence is `DDRS_FORCE_GRAPHS=1 compare_ddr_sandbox`, but
that env var only selects the CUDA backend (and is read with `.is_ok()`,
so `=0` triggers it too). Capture requires all three of
`use_cuda_graphs && sparse_solver == Cuda && backend_is_cuda`
(`src/routing/mmc.rs:289-294`); the sandbox builds from
`Config::default()` (`src/sandbox.rs:88-89`) = `use_cuda_graphs: false`
+ `SparseSolver::Cpu`, and `fixtures/sandbox/config.csv` sets neither
toggle — it carries only geometry, ranges, and dt. So the run exercised
the CUDA backend with the CPU sparse solver and no capture.
Corroborating: today's run reports max abs 1.525879e-5 m³/s, matching
the 1.5e-5 in the historical V9 entry to the digit — that entry's run
was this same CPU-solver path. The ABSOLUTE MATCH is real and still
certifies the backend; it does not certify the property V9 names. The
CUDA-graph capture path currently has no gate. Closing it needs a
sandbox config that sets both toggles.
Tier C gate (comment-only src/ change, but run in full):
cargo check --lib clean
cargo test --lib 243 passed, 0 failed
cargo test all binaries ok, 0 failed
cargo run --release --example compare_ddr_sandbox
ABSOLUTE MATCH, max abs 1.525879e-5 m³/s
Co-Authored-By: Claude <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Audits every
.claude/skills/package (9,371 lines), all 32docs/files,README.md,.claude/references/, andCLAUDE.md— then acts on what it found. Full report:docs/2026-07-30-docs-and-skills-audit.md.Method: five parallel auditors, each required to verify every concrete claim against the repo rather than assess plausibility. Every path
ls'd, every config key checked againstsrc/config.rs, everycargo test --test Xchecked againsttests/, every CLI flag grepped, every#[test]counted, every number cross-checked against the dated findings doc that owns it. Where docs disagreed, metrics were recomputed from.ddrs/runs/*/rather than picking a side.What was wrong
A config key that does not exist.
kan_head.disaggregation.use_precipwas documented in CLAUDE.md,src/config.rs's own comment, andconfig/sources/conus-hourly.yaml. It was removed in334f0fe. Because CLAUDE.md is in context on every turn, this propagated faster than any one doc could be corrected.Two documented entry-point commands hard-error.
ddrs initexits 2;ddrs run --workflow evaldemands a--from-runflag that exists nowhere insrc/. Both were the documented first step indocs/setup.mdand README.The baseline number came from the wrong network.
0.689 / 0.723appeared in 13 of 18 skills as the CONUS bar. It is a global MERIT number over 5,224 gauges; the CONUS bar is0.6781 / 0.7172on 2,365. That makes the widely-quoted+0.026delta a cross-population subtraction (correct:+0.037). A separate population error in the 07-07/07-16 findings docs flips a verdict — hourly-lstm's "+0.022 NSE gain from routing" becomes −0.051 when the baseline is scored on the same gauges.One doc invalidated six skills at once. The 2026-07-06 leakance NO-GO retired the "Phase B is required" framing; all six research skills still asserted it, three still carried executable instructions for the closed campaign. That duplication is why the staleness was uniform.
Gates that cannot fail.
cargo test --test sp8_gradcheck -- --ignoredruns zero tests and exits 0 (nothing in that file is#[ignore]). Same for--lib training::checkpointand--lib data::store::zarr::tests::….mc_routes_linear_chainnever existed. Test counts were also wrong — 16 not 8, 8 not 6.What changed
Skills: 18 → 2. 9,371 → 2,359 lines.
ddrs-dev— build/code/run/debug, withreferences/{build-and-env, config, testing, traps, research-status}.mdddrs-eval-plots— evaluate output, rewritten around.ddrs/runs/<id>/; the deadoutput/saved_models_*/layout is goneDropped the H5/H6 plot references (both plot instruments the v2 audit refuted) and rescued two orphaned parity files. Editorial rules: don't duplicate CLAUDE.md; lead with the discriminating test, not the narrative; one authoritative numbers table with a do-not-use list; assert "all pass" instead of brittle counts. Each
SKILL.mdopens with a TOC indexing into its references.The mdBook, 13 chapters. It was a 2026-06-08 snapshot — leakance, the disaggregation head,
nnse-kge/kge,ddrs sources/import/status/gc, managed adjacency, the global stores, and--backend cpuwere all invisible to it. Beyond the dead commands:outputs.mdopened with "there is no global results directory" (everything lands under.ddrs/runs/<id>/);setup.mdclaimed the CPU path needs no CUDA (burn-cuda/cudarcare non-optional, so a CPU-only reader fails atcargo build); seven "MLP head" mentions violated invariant 5;p_spatialwas called an exponent;perf.mdhad the Rust defaults inverted andPersistentScratchat 33 handles instead of 39, understating memory ~18%;DDRS_FORCE_GRAPHS=1does not actually exercise graph capture.CLAUDE.md and README.md corrected for all of the above, plus the disaggregation head and
experiment.loss.kind— neither of which appeared in any user-facing doc.Verification
mdbook buildis clean. Zero MLP references outside the documentedmlp:serde alias. Every remainingddrs initmention is in a "this is dead" context. Every rewrittenddrs-eval-plotstemplate was executed end-to-end against a real run, reproducing the committedparameter_convergence_stats.jsonvalues exactly.Notes for review
src/change, comment-only (src/cuda_graph/scratch.rsdocstring). Tier C gate run in full anyway:cargo check --libclean,cargo test --lib243 passed / 0 failed,cargo testall binaries ok,compare_ddr_sandboxABSOLUTE MATCH (max abs 1.525879e-5 m³/s).nse-batch/optimizer: adadeltaare documented with an explicit "arrives with PR feat(training): optimizer micro-batching (gradient accumulation) with exact valid-count weighting #31" caveat; they do not exist onmaster..claude/references/is left in place. It is a strict subset ofdocs/and its newer mtime is a 2026-06-10 back-port, not newer knowledge — but deleting it means updating ~25 inbound links including one insrc/sparse/mod.rs. Recommended as a follow-up in the report.The V9 verdict is retracted
The last commit fixes the two source-side defects the audit found, and the second one is worth a reviewer's attention.
.claude/ARCHITECTURE.mdrecorded "V9 (graph vs no-graph bit-match): GREEN", evidenced byDDRS_FORCE_GRAPHS=1 compare_ddr_sandbox. That env var only selects the CUDA backend — and is read with.is_ok(), soDDRS_FORCE_GRAPHS=0triggers it too. Capture requires all three ofuse_cuda_graphs && sparse_solver == Cuda && backend_is_cuda(src/routing/mmc.rs:289-294). The sandbox builds fromConfig::default()(src/sandbox.rs:88-89) =use_cuda_graphs: false+SparseSolver::Cpu, andfixtures/sandbox/config.csvsets neither toggle — it carries only geometry, ranges, and dt.So the run that certified V9 exercised the CUDA backend with the CPU sparse solver and no capture. Corroborating: this PR's verification run reports max abs
1.525879e-5m³/s, matching the1.5e-5in the historical V9 entry to the digit — that entry's run was this same CPU-solver path.The ABSOLUTE MATCH is real and still certifies the backend. It does not certify the property V9 names. The CUDA-graph capture path currently has no gate. Both architecture docs now say UNVERIFIED with the reason; closing it needs a sandbox config that sets both toggles.
Also fixed:
scratch.rs's docstring claimed 32 handles and all-n-sized buffers. Actual is 39 handles, of which 37 are n-sized and 2 nnz-sized — understating memory ~18% (~525 KB / ~44 MB → ~740 KB / ~51 MB). The inline "24 saved-state" is 23, now tied explicitly tommc_op::NUM_SAVED_STATE.🤖 Generated with Claude Code