Reproducibility, run_id and caching¶
Every feature run is tagged with a run identifier:
The hash covers the feature's parameters, its inputs, and the frame range. Identical
inputs and parameters give an identical run_id. That single fact produces most of
mosaic's useful behavior.
What it buys you¶
- Re-running costs nothing. The run is already there, so a script you run twice does the work once.
- Parameter sweeps organize themselves. Each setting lands in
features/<name>/<run_id>/, with no naming scheme to invent and no chance of two settings overwriting each other. - A result cannot be silently applied to the wrong input. Change an upstream feature and everything downstream re-addresses, because the upstream identity is one of the terms.
Throughput knobs — worker counts, batch sizes — are deliberately excluded from the hash. Retuning them for a bigger machine does not invalidate a cache, because they change how fast a result is produced and not what it is.
Version is a decision, not an accident¶
The <version> segment is declared by the feature, and moving it re-addresses every
run of that feature. That is what a version bump is for: it says the meaning of the
output changed, so previous results should not be reused as if they were the same
thing.
Adding a parameter with a default does not need a bump — the hash covers it. Changing what an existing parameter means does.
Status is derived, never stored¶
mosaic inventory reports what a dataset holds, and its answers are computed at read
time from what is on disk: absent, partial, complete, complete-but-drifted,
inconsistent.
There is no inventory database and no filesystem watcher. Every view is a cache thrown away rather than reconciled, which is why a stale answer is impossible rather than merely unlikely — and why you can delete a run directory by hand and have the next inventory simply tell you the truth.
Coverage is which entries exist, never a boolean. "Complete" means every entry in scope
has an artifact, and complete-but-drifted means they all exist but a source they were
made from has changed since.
That change is detected by comparison, not by the identifier. A run_id covers the
recipe of each input, not its content, so re-converting tracks from changed source files
or re-transcoding media leaves every downstream identifier as it was. What each run read
is recorded beside it and compared with the present. The next run_feature recomputes
the entries whose tracks changed, and a tracker run over re-transcoded media reports
complete-but-drifted.
A trained model can say what it saw¶
A model's identifier covers its training data by content, so it is reproducible in the usual sense. It is also traceable, because each step records the one before it:
the model records the prepared dataset it was trained on
the prepared dataset records each annotation set, revision and content digest it merged,
and the pose it narrowed them to
the revision records what was noted when it was saved -- a database commit, say
mosaic models provenance <run_id> walks that chain and prints it. Nothing stores the
chain as a whole, for the same reason status is not stored: a summary is a second thing
to keep agreeing with the records it summarizes. When a link is missing the answer
says where it stopped, for instance a model trained from a folder of labels that no
preparation run wrote, or a revision in a dataset that has since been archived.
Only the revision's content enters an identifier. Its number is a label, so asking for "the latest" and asking for the number that resolves to are the same run, and annotations restored to an earlier state reuse what was computed for that state.
What this does not promise¶
Determinism is a property of the code, and the identifier only records inputs. A
feature that used unseeded randomness or depended on filesystem ordering would produce
a different answer under the same run_id, and nothing would notice. mosaic's own
features avoid that; a feature you write must too.