starplast.searches
A search you can put down and pick up: every configuration it tried, and everything each found.
A climb is expensive and its result is not one map -- it is a hundred of them, with their scores, their metrics and their claims. Keeping only the winner throws away the two things that make a search evaluable afterwards: the runner-up, and how far behind it came. A single best configuration with nothing to compare it against cannot be told apart from a lucky one.
What is written, and what is left to be rebuilt
Written: the manifest (what was asked, of which table, by which version), one row per configuration with its score and every metric, every finding from every configuration, and the cluster labels each configuration produced.
Not written: the coordinates. They are the largest thing by an order of magnitude and the one thing that is exactly reproducible -- a recipe plus a seed rebuilds the same map, which is a promise this project makes everywhere else and may as well keep here. Labels ARE written, because kmeans and HDBSCAN are not seeded identically across versions of their libraries and a clustering that came back different on reload would silently change every claim built on it.
The fingerprint, which is the point of the manifest
A search is a set of statements about genes identified by their POSITION in a node table. Reloaded against a different table -- a rebuilt cache, a newer release, a filtered subset -- those positions address different genes, and every finding in the run quietly becomes a claim about the wrong ones. So the table is fingerprinted when the search is saved, checked when it is loaded, and a mismatch is reported rather than papered over. It is not fatal: the configurations and scores remain readable and comparable. What stops is the mapping from a label to a gene.
What table this search was about, in enough detail to notice it is a different one.
The gene identifiers hashed in order, not merely counted: a table with the same number of rows in a different order is the commonest way for this to go wrong, and a count would not see it.
One climb, complete: what was asked, what was tried, and what each attempt found.
(row, its findings, its labels) for one configuration, by position in configs.
By position in the saved table, which is sorted by score -- so 0 is the winner and 1 is the runner-up, which is the comparison this exists to make possible.
Split a climb's return into the part that is a table and the part that is artefacts.
Saved searches on disk, one directory each.
A directory rather than a single file because the pieces have different natural formats and very different sizes -- a manifest that should stay readable in a text editor, two tables, and a block of integer arrays -- and because a half-written search should be identifiable as one.
Where a search of this name lives, with anything awkward taken out of the name.