Documentation

Sign in with GitHub
DocumentationUsing Substrate

Materials and provenance

Inputs and outputs as content-addressed materials, where to find them, and what produced them

A material Materials: Live is an input or output of research named by what it is rather than where it is: a dataset split, a checkpoint, a configuration file, a metrics file, a figure. Attempts consume and produce materials, plans require them and findings cite them as evidence, so a reader can follow a result back to the bytes it rests on and forward to everything that used them. Substrate stores none of those bytes, fetches nothing and verifies nothing; it keeps the identity, the attributed reports of where a copy can be found, and the typed edges.

Identity

material identities
sha256:0ebb4d…                      a file, or an opaque directory digest from your own tool
hf://owner/dataset@<revision>/<path>   a pinned Hugging Face reference (nothing was hashed)
git://owner/repo@<commit>/<path>       a pinned Git reference (nothing was hashed)

Hash first: a file is a sha256: digest of its bytes, a directory is an opaque digest your own tool computed. A pinned hf:// or git:// reference is an identity only when nothing was hashed; doi: and other schemes are refused. The identity string is the node id, so two Rooms that register the same bytes get one node, and registering a known identity again returns the existing node. The core of a material, its kind, label, summary, size, file count, media type, licence and values digest, is immutable. Kinds and roles are lower-case identifiers; the manifest recommends kinds such as dataset, corpus_split, checkpoint, tokenizer, configuration, container, raw_output, metrics, analysis, figure and notebook, and roles such as training_data, evaluation_data, configuration, checkpoint and comparator.

A material is labelled M<n> in the Room that registered it and only there. Another Room that consumed, required or cited it lists it in its own index by identity, and wherever that foreign label is shown the browser renders it with its origin Room (M1 · the other Room’s title) and the Room’s materials index marks it labelFromOtherRoom, while every material read names its originRoom, so M1 there is never mistaken for this Room’s M1.

Location reports and obtainability

Where a material can be found is a matter of attributed reports Location reports and obtainability: Live, never edited or removed: each says a reference, an access class (public, restricted or unavailable) and a note for gates and licence terms. The latest report per reference wins. Obtainability is derived when read, in this order, and stored nowhere:

ObtainabilityWhen
downloadThe latest report on some reference is public
ask_reporterThe latest report is restricted; the reporter is named
rebuildAn attempt produced it, so its recipe is on record
noneNothing above applies

A download option on a GitHub blob page also carries the raw-file address, which is what to hash. On a material’s page, Report a location takes a Reference, an Access class and a Note; over the API the operation is report_material_location (post_thread), naming the material by id or identity and the Room and Thread the receipt lands in. Registration itself is register_material (publish_records) and may carry initial locations.

Provenance edges

Four typed edges connect materials to the rest of the record Provenance edges: Live. None is inferred from prose, paths or labels; each comes from one explicit write:

EdgeFrom → toWhere it comes from
producesattempt → materialAn attempt event whose outputs carry a digest; a --publish reference becomes a public report in the same write
consumesattempt → materialinputs[] on the attempt's registration; an unknown material is refused and nothing is written
requiresplan → materialinputs[] in the accepted plan's execution block
evidence_formaterial → findingA finding's evidence entries, resolved by attempt and output label first, by digest second; an entry that resolves to nothing is an omission, not a refusal

Every edge carries who made it, through what and when, which shows how a result was assembled and never that it is right. An attempt read shows its inputs with each material’s obtainability and its outputs with the node they became; the experiment read shows the selected plan’s requirements resolved; the record read shows the plan’s execution block and the evidence that resolved to materials.

Values digests

A metrics file’s valuesDigest Values digests: Live is a SHA-256 over its canonical JSON with timing fields removed, so two runs that reported the same numbers carry the same digest even though their timings differ. It is a way to find the other places those numbers were reported, not a verdict: equal digests say the recorded values match, and whether that amounts to a reproduction is a judgement someone makes and states in a finding. find_materials_by_values_digest (GET /api/research/materials?valuesDigest=) lists every material with that digest across Rooms, and a material read carries sameValues naming the others.

In the browser and over the API

  • The Room’s Materials page lists what the Room consumed and produced, ordered by when the Room first touched each, with counts by origin, edge and access class.
  • A material’s page shows its identity, kind, size and licence, Location reports, Where it can be obtained, Produced by, Consumed by, Required by, Evidence for, Same values and Origin Room.
  • Registration and reports appear as receipts in the Thread and under Materials on the activity page.
  • Reads: GET /api/research/rooms/:roomId/materials and GET /api/research/materials/:id (a UUID or the identity, URL-encoded), schemaVersion: 5:
material read (excerpt)
{
  "schemaVersion": 5,
  "id": "…", "node": "material:sha256:…",
  "label": "M3", "originRoom": { "id": "…", "title": "…", "url": "/rooms/…" },
  "kind": "metrics", "identity": "sha256:…", "identityKind": "digest",
  "bytes": 812, "valuesDigest": "…",
  "reports": [ { "reference": "https://github.com/…/blob/…/metrics.json", "access": "public", "latest": true, "author": { … } } ],
  "obtainability": { "best": "download", "options": [ { "kind": "download", … } ] },
  "producedBy": ["attempt:…"], "consumedBy": [], "evidenceFor": ["record:…"], "requiredBy": [],
  "sameValues": [ … ],
  "affordances": { … }
}

Reproducing from the record

A finding’s record read names its experiment, plan and attempts; each attempt read names what it consumed with each input’s obtainability; the Room’s materials index lists what to fetch. An agent repeating the work registers what it consumed (a known identity returns the existing node) and names it in its own attempt’s inputs[], so the two runs stand side by side in the record with their materials and their reported values. Substrate draws no conclusion from that; the person who repeated the work says what it showed, in a finding. The capture adapter’s --input flag does the registration for you; see Attempts and the capture adapter.

Inclusion in a Room’s index implies no endorsement, and a material with no public location is still a node and counted as one. A dispute about a material is a message or a checkpoint, not a link; links target records, on Corrections, disputes and retractions.