docs: record that the event log is the source of truth, and why
#45 asked whether a fitted `History` can be persisted, and noted that the absence of `serde` "reads as an omission rather than a decision, which invites exactly this issue from every consumer in turn". Fair. Documents the decision on `History` along with the reasoning that makes it one: `converge` reaches a fixed point determined by the events, ratings and configuration alone, so a snapshot would carry no information the event log does not — it would cache the computation, never the answer. It also bounds what a snapshot could buy, since that is the question a consumer actually has. Re-converging an unchanged history costs one iteration, measured at 0.91 ms against 365 ms cold on 2 000 events, so it would make a cold restart cheap and do nothing for appends. Appending one event moves its participants more than a sigma across their whole history, so that re-convergence is real work rather than repeated work. Closes #45 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011hcFjNDmHXZF8URGLku5zZ
This commit is contained in:
@@ -189,6 +189,32 @@ impl CompetitorConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A fitted history: competitors, their skills over time, and the events that
|
||||||
|
/// produced them.
|
||||||
|
///
|
||||||
|
/// # Persistence
|
||||||
|
///
|
||||||
|
/// `History` is deliberately not serializable, and the event log is the
|
||||||
|
/// intended source of truth. This is a decision rather than an omission.
|
||||||
|
///
|
||||||
|
/// [`converge`](History::converge) reaches a fixed point determined by the
|
||||||
|
/// events, ratings and configuration alone — not by the message state it
|
||||||
|
/// started from, which ingestion resets anyway. So a snapshot of a fitted
|
||||||
|
/// history would carry no information the event log does not; it would be a
|
||||||
|
/// cache of the *computation*, never of the answer.
|
||||||
|
///
|
||||||
|
/// That also bounds what one could buy. Re-converging an unchanged history
|
||||||
|
/// costs a single iteration — measured at 0.91 ms against 365 ms cold on 2 000
|
||||||
|
/// events — so a snapshot would make a cold restart cheap. It would do nothing
|
||||||
|
/// for appends: adding one event moves its participants by more than a sigma
|
||||||
|
/// across their whole history, back to their first appearance, so the
|
||||||
|
/// re-convergence is real work rather than repeated work. Cost per append is
|
||||||
|
/// inherently O(history). A design that made appends cheap would be computing a
|
||||||
|
/// filtering estimate — see [`History::filtered_learning_curve`] — rather than
|
||||||
|
/// Through Time.
|
||||||
|
///
|
||||||
|
/// `tests/reconvergence_equivalence.rs` pins the path-independence this rests
|
||||||
|
/// on.
|
||||||
pub struct History<
|
pub struct History<
|
||||||
T: Time = i64,
|
T: Time = i64,
|
||||||
D: Drift<T> = ConstantDrift,
|
D: Drift<T> = ConstantDrift,
|
||||||
|
|||||||
Reference in New Issue
Block a user