docs: correct drifted documentation and compile the README in CI
Four README code blocks no longer compiled: `Player` was renamed `Rating`
in T2, the `Drift` trait gained a `T: Time` parameter and a second method,
and two blocks were missing imports outright. The `Rating` example needed
more than a rename — with the binding unused, `T` is ambiguous because
`ConstantDrift` implements `Drift<T>` for every `T`, so it now carries an
explicit annotation.
Nothing compiled those blocks. `src/lib.rs` gains a `cfg(doctest)` struct
carrying `#[doc = include_str!("../README.md")]`, which turns every `rust`
block into a doctest without displacing the curated crate docs as the
front page. Verified it bites: reintroducing `Player` fails the build with
E0432 rather than shipping. Illustrative blocks are fenced `text` — note
that a bare fence defaults to `rust` under rustdoc, which is how the
`variance_delta = elapsed * γ²` formula became a compile error.
Prose fixes: README claimed `Gaussian::forget` takes a square root (it
works in variance space) and pointed at a `.gamma()` builder method that
does not exist. CLAUDE.md's data-flow diagram spliced the public ingestion
shape into the internal one — `Team` is not in that chain — listed
`cdf()`/`erfc()` as public when they are `pub(crate)` and private, and
called `SkillStore` public when only `CompetitorStore` escapes the crate.
Rustdoc fixes: `EventBuilder::scores_with_sigma` claimed a debug-assert
that `Outcome::scores_with_sigma` never had and whose own docs contradict;
rejection happens at ingestion as `InvalidParameter`. `event.rs` described
`add_events_with_prior` as replaced when it is still the ingestion
chokepoint. `factors.rs` advertised `Game::custom` without noting it is
`#[doc(hidden)]`. Internal T2/T4 milestone labels are dropped from public
items; the ones in the private `time_slice` module are left alone.
Closes #35
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014b6wy2q8rnFK8U8GPJVQNU
This commit is contained in:
@@ -32,10 +32,19 @@ evidence both forward and backward across a history.
|
||||
|
||||
### Data flow
|
||||
|
||||
Ingestion (public types, `event.rs`):
|
||||
|
||||
```
|
||||
History → TimeSlice[] → Event[] → Team[] → Item[]
|
||||
↓
|
||||
Game (factor graph) → Schedule → BuiltinFactor[]
|
||||
Event<T, K> → Team<K>[] → Member<K>[]
|
||||
```
|
||||
|
||||
`History::add_events` flattens that into indices; teams survive only as
|
||||
grouping, not as a value. Inference then runs on the internal shapes:
|
||||
|
||||
```
|
||||
History → TimeSlice[] → Event[] → Item[]
|
||||
↓
|
||||
Game (factor graph) → Schedule → BuiltinFactor[]
|
||||
```
|
||||
|
||||
- **`History`** (`history.rs`) — top level. Interns keys, groups events into
|
||||
@@ -45,9 +54,12 @@ History → TimeSlice[] → Event[] → Team[] → Item[]
|
||||
- **`TimeSlice`** (`time_slice.rs`) — all events at one time. Owns a
|
||||
`SkillStore` and a `ScratchArena`; `iteration()` sweeps its events, using
|
||||
`ColorGroups` to partition independent ones.
|
||||
- **`Event`** (`time_slice.rs`) — one match. `compute()` runs inference reading
|
||||
skills immutably; `apply()` folds the result back. The split is what lets a
|
||||
color group run in parallel with no `unsafe`.
|
||||
- **`Event`** — two distinct types, do not confuse them. The *public* ingestion
|
||||
`Event<T, K>` is in `event.rs` (with `Team`/`Member`); the *internal*
|
||||
`pub(crate) Event` in `time_slice.rs` is one match during inference, where
|
||||
`compute()` runs inference reading skills immutably and `apply()` folds the
|
||||
result back. That split is what lets a color group run in parallel with no
|
||||
`unsafe`.
|
||||
- **`Game`** (`game.rs`) — a single match's factor graph. `run_chain` builds the
|
||||
diff chain between rank-adjacent teams and drives it to convergence.
|
||||
- **`Gaussian`** (`gaussian.rs`) — natural parameters (`pi = 1/sigma²`,
|
||||
@@ -61,14 +73,16 @@ History → TimeSlice[] → Event[] → Team[] → Item[]
|
||||
the only implementation.
|
||||
- **`Competitor`** (`competitor.rs`) — per-history temporal state (`message`,
|
||||
`last_time`). **`Rating`** (`rating.rs`) — static config (prior, `beta`, drift).
|
||||
- **`storage/`** — `SkillStore` (per slice) and `CompetitorStore` (per history),
|
||||
both dense `Vec`s indexed by `Index`.
|
||||
- **`storage/`** — `SkillStore` (per slice, `pub(crate)`) and `CompetitorStore`
|
||||
(per history, public), both indexed by `Index`. The module is `pub`, but only
|
||||
`CompetitorStore` is reachable from outside the crate.
|
||||
- **`KeyTable`** (`key_table.rs`) — user key ↔ `Index`, both directions O(1).
|
||||
- **`Drift`** (`drift.rs`) / **`Time`** (`time.rs`) — traits. `Time` is a *trait*
|
||||
(`i64`, `Untimed`), not an enum.
|
||||
- **`lib.rs`** — public exports, global defaults (`MU`, `SIGMA`, `BETA`,
|
||||
`GAMMA`, `P_DRAW`, `EPSILON`, `ITERATIONS`), and the standalone `quality()`,
|
||||
`cdf()`, `erfc()`.
|
||||
`GAMMA`, `P_DRAW`, `EPSILON`, `ITERATIONS`), and the standalone `quality()`.
|
||||
The `cdf()` / `erfc()` helpers live here too but are `pub(crate)` and private
|
||||
respectively — not public API.
|
||||
|
||||
### Invariants worth knowing
|
||||
|
||||
|
||||
Reference in New Issue
Block a user