A result you cannot reproduce is a rumour. So every node, whether you ran it, the AI Chat applied it or an external assistant proposed it, records what it did: the exact parameters, an honest determinism class and seed, and the package versions it ran under. The receipt sits on the node card, travels inside the AnnData, and is written into an open RO-Crate record every time you save.
The moment a node completes, the app attaches a compact record to its result. The same record is stamped into the AnnData as uns['_bioflow_provenance'], so it survives a Save H5AD and opens in Scanpy alongside your data.
node_id · node_typewhich node ran, and what kind it isparamsevery parameter value the node executed withparams_hasha fingerprint of those parameters for quick diffingdeterminismdeterministic · stochastic_seeded · stochasticrandom_state · seed_sourcethe seed actually used, and where it came frompkg_versionsscanpy, anndata, numpy and the packages the node type depends on, read from the running modulessourcemanual, ai_chat or mcp — who triggered the run (data-level stamp)session_id · timestampthe run this node belonged to, and when it executed (UTC)Illustrative values; the keys are the ones the app writes.
On the node card
Each completed node shows its class; hovering reveals the seed source and the first characters of the parameter hash.
The determinism class — one of three, decided per node type
deterministicNo randomness involved — Normalize, Log1p, Scale, DEG, Subset. Same input and parameters give the same numbers every time. Nodes not listed in the registry fall in this class.
stochastic_seededRandomness is involved and a seed governs it — PCA, Neighbors, UMAP, t-SNE, Leiden / Louvain / K-Means, Harmony, Draw Graph, LSI, Scrublet, scvelo, BANKSY domains, spatial permutation tests. The receipt stores the seed that was actually used.
stochasticNo seed can be captured — CellRank fate probabilities and lineage drivers, and Auto Annotation, which asks a language model. The receipt says so instead of pretending.
It never lies about a seed
A naive recorder would write random_state: 0 for every node. Oreumics keeps a registry of how each node type actually seeds itself and records that:
param:random_statethe node exposes a seed parameter; the value you set (default 0) is recordedfixed (hardcoded in node)the node pins its own seed — LSI, GSEA and transcript downsampling use 42 — and that real value is written, not a fabricated 0library default (not set by node)the library chose; random_state is recorded as null and the class stays honestn/adeterministic — there is no seed to recordIt never breaks a run
Provenance capture is passive. If a field cannot be recorded, the analysis still completes normally — the receipt is an observer, never a gatekeeper. Package versions are read from the loaded modules, so the packaged desktop build reports the same truth as a source checkout.
External databases and models — CellPhoneDB, CellTypist, OmniPath, JASPAR, methylation manifests — are installed through the Resource Center with a pinned version and checksum before a run, and that pin is recorded with the result. A computation never downloads anything mid-run.
The Methods tab under the canvas turns the current graph into a paragraph in execution order, one deterministic template sentence per node, filled from the parameters and citing the libraries used. It updates as you edit, has a Copy button, and involves no model — the output must be stable to be quotable. A node without a template is left out rather than invented.
Counts were normalized to 10,000 reads per cell. Normalized counts were log-transformed using log(1+x). The top 2,000 highly variable genes were selected using the seurat flavor. Principal component analysis was performed retaining the top 50 components. A k-nearest-neighbor graph was constructed using 15 neighbors over the top 30 principal components. Cells were clustered using the Leiden algorithm at resolution 1.0. Cells were embedded in two dimensions using UMAP.
Sentences are the app’s templates; the parameter values shown are an example. The real paragraph ends with the library citations and the Oreumics version.
It reports what actually ran
Since v0.25.0 Draw Graph names the layout it really used: when ForceAtlas2 is unavailable it falls back to Fruchterman–Reingold and says so in the Methods sentence and in the stored embedding key, instead of claiming a layout that never ran. K-Means clustering omits resolution, a parameter it does not use.
The chat can read the receipt
Ask “is this reproducible?” or “what seed produced this?” and the AI Chat calls get_provenance, which returns the receipt from the data itself. The same tool is available to an assistant connected over MCP, and it is what the agent loop reads to verify its own steps.
Every time a project is saved, Oreumics writes ro-crate-metadata.json next to the project, and every .bioflow export bundles it. It is an RO-Crate 1.1 document in JSON-LD, following a Workflow-Run-Crate-inspired profile: each node becomes an action with its parameters and receipt, each edge becomes lineage. Open, standards-based, readable without Oreumics.
JSON-LD, not a private log
Conforms to https://w3id.org/ro/crate/1.1. Any RO-Crate tool, or a text editor, can read the graph of nodes, parameters and receipts.
Per-node receipts inside
Determinism, parameter hash, seed and seed source, who triggered the run, the timestamp and the package versions — copied from each node’s receipt into the crate.
Written on save, bundled on export
No extra step. The sidecar is regenerated with each save so it never lags the project, and the .bioflow archive carries it along with the workflow and cached results.
The executor only re-runs what changed and keeps everything upstream cached, so a saved project reopens to the same numbers it was saved with. Re-running a deterministic or seeded node with the same data and parameters reproduces it. Where that promise does not hold, the app says so rather than rounding up.
Holds
Named exceptions
Behind the app, every change runs a layered validation suite — static consistency, visual regression on figures, loader-format tests, parameter coverage, template end-to-end runs against golden snapshots, a frozen-build smoke, and real-app Electron scenarios. That keeps the tool stable; it is not a claim about your data.
Receipt · Methods · RO-Crate
Receipts on every run, a Methods paragraph you can paste, and an RO-Crate in every saved project. See how the agent reads those receipts to verify its own work — and re-plans when a step falls short.