Skip to main content

gam_runtime/warm_start/
mod.rs

1//! On-disk warm-start store.
2//!
3//! Persists periodic checkpoints of in-progress fits so a subsequent run
4//! (possibly after a SIGKILL or weeks later) auto-resumes from the
5//! best-known iterate. Keyed on a SHA-256 fingerprint of the data + fit
6//! spec, so re-fitting the same model on the same data reuses the matching
7//! persisted warm-start entry.
8//!
9//! The store does not choose its own root — [`WarmStartStore::open`] takes one.
10//! High-level fitting accepts an explicit root and carries it through
11//! [`ConfiguredWarmStartStore`]. There is no ambient temp/cache-directory
12//! lookup and no implicit cross-process persistence: omitting the root keeps a
13//! fit disk-silent.
14//!
15//! Layout under that root:
16//!
17//! ```text
18//! <keyhex>/
19//!   <runid>.json    metadata (objective, iter, checksum, kind)
20//!   <runid>.bin     opaque payload bytes
21//! ```
22//!
23//! All writes are tmp-file + fsync + rename, so a hard crash leaves either
24//! the pre-write state or a fully-written entry on disk — never half-written.
25//! Per-entry SHA-256 checksums catch any residual corruption.
26//!
27//! Multiple entries can coexist for one key (concurrent fits, prior aborted
28//! runs). `lookup` prefers a completed fit's [`EntryKind::Final`] write over
29//! any [`EntryKind::Checkpoint`], takes the LATEST of several terminal writes
30//! (which completed fit a resume carries is a provenance question, not a
31//! quality one), and orders checkpoints by lowest objective.
32//!
33//! # The key identifies the problem; the entry identifies its producer
34//!
35//! The fingerprint is over `(data, spec)` and deliberately absorbs nothing
36//! version-like, so a library upgrade that does not change the on-disk layout
37//! keeps every user's warm start. That is right for a *seed* — a seed only has
38//! to be close — but [`EntryKind::Final`] claims more than closeness: it claims
39//! a converged optimization ended there, judged against the criterion the
40//! writing code implements. Since the key cannot see that code, two builds
41//! fitting the same model shared entries, and one build could resume the
42//! other's terminus and ship it at zero outer iterations (#2625).
43//!
44//! Each entry therefore records the identity of the binary that wrote it, and
45//! every read compares it: **a terminal certificate from a different build (or
46//! from an unknown one) is returned as a [`EntryKind::Checkpoint`] instead.**
47//! Reuse is untouched — the payload, objective and timestamps all survive, and
48//! the iterate is still the best available seed. What is withdrawn is the right
49//! to be shipped as a fit that this build's outer search never ran. The
50//! comparison lives at the single point where metadata is deserialized, so
51//! lookup, ranking and eviction cannot observe a foreign terminus and none of
52//! them has to remember to ask.
53//!
54//! Consequently a warm hit may cost outer iterations it did not cost before,
55//! and that is the intended price: SPEC-20 allows work to survive walls via
56//! checkpoint/resume, and a resumed *seed* still has to converge here.
57//!
58//! Disk is bounded by [`StoreOptions::size_budget_bytes`] (default ~1 GiB);
59//! oldest entries are evicted to fit. Entries older than
60//! [`StoreOptions::ttl`] (default 30 days) are dropped on every save.
61
62mod configured;
63pub mod key;
64pub mod session;
65pub mod store;
66
67pub use configured::ConfiguredWarmStartStore;
68pub use key::{Fingerprint, Fingerprinter};
69pub use session::{LoadSource, LoadedEntry, Session};
70pub use store::{EntryKind, StoreError, StoreOptions, WarmStartEntry, WarmStartStore};