Nodes/BrainDead Nodes/BD Provenance
ComfyUI Node

BD Provenance

The run receipt your PNG was never carrying

By BizaNator·Created 8 months ago·Updated about 3 hours ago· 15
BD Provenance
  • anchor
  • anchor
  • provenance
title
creator
studio
website
reference
license
notes
include_modelstrue
include_addonstrue
hash_modelsfalse

A ComfyUI PNG already tells a story: the whole graph is in its text chunks, so you can drag the file back onto the canvas and rebuild the pipeline. What it doesn't tell you is which seed actually ran, which checkpoint that loader resolved to on this machine, or which node packs were involved at which commits. Nor who made it. BD Provenance collects both halves of that and writes it into the workflow itself.

Half is knowledge only the run has. Half is knowledge only you have. This node is where they meet.

How it works

It reads the API prompt for the run - the flattened execution format, not your widget values - so a seed the frontend randomised before submitting is the one recorded. It walks every node's inputs for seed, noise_seed, rand_seed and random_seed, filing each with the node that used it.

Models are found the same lazy way: any string input ending in .safetensors, .ckpt, .pt, .gguf or one of a few other weight extensions counts as a model file, which is why this keeps working for loaders from packs the node has never heard of. Each is resolved through ComfyUI's own folder_paths to the real file on disk, with its size. Then every class_type is mapped back to its custom_nodes directory, whose git remote and short HEAD commit get read.

Everything lands in workflow.extra.bd_provenance, and that location is the clever part. extra is a real LiteGraph field, so it round-trips through a load, an edit and a save in the UI. The record isn't a parallel JSON file that drifts - it is the workflow, and any save node that writes a sidecar or a PNG text chunk carries it without knowing it exists.

Execution order is the one thing that can go wrong

This node and the save node read the same extra_pnginfo dict for the run, which this one mutates in place. So it has to run first. Wire anchor - a wildcard pass-through - into the chain ahead of the save and the dependency guarantees it. Leave it unwired and the node still runs and still shows you the record, but ComfyUI is free to schedule it after the save. The provenance output says so, rather than letting a file that looks fine quietly lie to you.

The inputs worth setting

  • anchor - the pass-through above. Do this.
  • title / creator / studio / website / reference / license - your half of the record. reference is where a likeness or source came from: a URL, a character, a shoot.
  • notes - multiline, freeform.
  • hash_models - off by default. Exact, slow the first time, cached per path/size/mtime, so a moved file re-hashes.

Two outputs: anchor to keep the chain alive, and provenance - a readable summary of everything captured, the same text printed to the console.

One thing that isn't obvious: model links. A filename can't be turned into a URL by guessing, so url is only filled for files listed in config/model_sources.json - as shipped, one commented-out example. Expect paths, sizes and hashes, no links, until you add entries.

Install

ComfyUI Manager → search "BrainDead" → install, or:

cd ComfyUI/custom_nodes
git clone https://github.com/BizaNator/ComfyUI-BrainDead
cd ComfyUI-BrainDead
pip install -r requirements.txt

Restart afterwards. Nothing in requirements.txt is needed here - the git-pinned moge/utils3d/pipeline and natten are for the Pixal3D nodes and are imported defensively, so the pack loads without them. Manager installs them anyway. This is a V3-API pack, so use a current ComfyUI. The node lives under 🧠BrainDead/Cache - newer than the README's node tables, so searching the README won't help.

Where people get burned

The files don't carry the record. Almost always anchor left unwired, so it ran after the save.

Nothing is stamped at all. No UI graph in extra_pnginfo means there's nothing to stamp, and ComfyUI only fills that field for frontend submissions - a headless caller has to send the graph in extra_data. Same trap as API-generated PNGs that carry a prompt chunk and no workflow chunk.

It caches nothing. The name says cache; it just records.

What this is, and what it isn't

A paper trail, not proof. These are ancillary PNG chunks and sidecars, and any re-encode deletes them with no way back - post the file somewhere that recompresses and the record dies with the workflow. Even a perfect hash proves the identity of a model file, not that you made the image.

So treat it as internal bookkeeping: the archive copy that can still answer "how did we build this, out of which exact files, on which box" in eighteen months, when the paths point at models you've long since reorganised. The EU AI Act's Article 50 transparency obligations started applying on 2 August 2026, and "who made this, under what licence" is the sort of field people want recorded - but a strippable text chunk is not a compliance story. One node for a real record is a good trade. Just don't call it proof.

Category🧠BrainDead/Cache

Inputs (11)

NameTypeDefaultDescription
anchoropt*Pass anything through on its way to the save node. This is what guarantees this node runs BEFORE the save, so the files carry the record. Unwired, ordering is not guaranteed.
titleoptSTRINGWhat this run produced.
creatoroptSTRING
studiooptSTRING
websiteoptSTRING
referenceoptSTRINGWhere the source or the likeness came from — a URL, a character name, a shoot, a ticket.
licenseoptSTRING
notesoptSTRING
include_modelsoptBOOLEANtrue
include_addonsoptBOOLEANtrue
hash_modelsoptBOOLEANfalsesha256 every resolved model file. Exact, and slow the first time — results are cached per (path, size, mtime).

Outputs (2)

NameTypeDescription
anchor*
provenanceSTRING