Skip to content

Check external evidence

An assertion in one archive cites an exact record in a different archive as evidence, and you want to check that citation offline, with the other archive opened only when you choose to open it.

Keep sample.core for evidence resolution; the claim whose evidence you are checking may have been recorded through sample.claim, and sample.claims reads its active head.

This guide assumes: you have finished the tutorial path, you can tell a checkpoint from a record after two kinds of identity, and you have met assertions in the scientific assertions workflow.

Suppose a colleague’s archive holds an ATR reference spectrum of a known polymer. Your archive for sample polymer-film-01 carries the claim “this film is polypropylene”, and that claim cites the colleague’s reference record as evidence. The citation is inert: loading and verifying your archive never opens the other file. When you want to check the citation, you decide which archives to hand over, and resolve_external_evidence does the rest. The example builds both archives in memory so it runs standalone.

import numpy as np
from mtrl import InstrumentRun, MaterialData, Mtrl
from mtrl.assertions import (
AssertionDraft,
EvidenceRef,
SubjectRef,
resolve_external_evidence,
)
reference = Mtrl(sample_id="reference-01")
reference_run = InstrumentRun(run_name="atr-check")
reference_checkpoint = MaterialData(
content=np.array([1.0, 2.0]),
type="raw",
checkpoint_name="atr",
)
reference_run.add_checkpoint(reference_checkpoint)
reference.add(reference_run)
reference_record = reference.get_active_record(reference_checkpoint.checkpoint_id)
study = Mtrl(sample_id="polymer-film-01")
study_uid = study.assign_sample_uid()
evidence = EvidenceRef.for_external_record(
reference.archive_id,
reference_record.checkpoint_id,
reference_record.record_id,
role="reference-identification",
)
draft = AssertionDraft(
subject=SubjectRef.sample(study_uid),
property_id="polymer.identity",
value="polypropylene",
evidence=(evidence,),
)
assertion = study.assert_properties([draft])[0]
print(f"evidence kind: {assertion.evidence[0].kind.value}")
reports = resolve_external_evidence(study, {reference.archive_id: reference})
print(f"report status: {reports[0].status.value}")
evidence kind: external-record
report status: verified

The first line prints evidence kind: external-record: the evidence is a citation into another archive, not a pointer to a local record. The second line prints report status: verified: you supplied the named archive, and the named record is in it.

EvidenceRef.for_external_record(...) stored an ArchiveRecordRef (importable from mtrl.domain) inside the assertion. It holds three identifiers — the identity of the other archive, the logical checkpoint identity, and the exact record identity — plus an optional expected payload digest. The reference is inert by design: loading and verifying your archive never opens the other archive, so a missing or changed file cannot break yours. The citation is a claim about another archive, not a live link into it.

resolve_external_evidence(study, {reference.archive_id: reference}) is where the check happens, and it stays offline. You pass the container that holds the assertions and a mapping of caller-supplied containers keyed by archive identity. MTRL opens no file and commits no revision: it reads only what you hand it. You receive one report per external evidence item, in assertion order and then evidence order. Each report carries the assertion and claim identities, the property, the external record reference, and a status.

The status is one of four values. verified means the archive was supplied, the record is present, and the expected digest — when one is recorded — matches the record’s content. unresolved means you did not supply the named archive, so nothing could be checked. missing-target means the archive is there but the record is not. digest-mismatch means the record is present but its content digests differently from the expected payload digest recorded in the evidence.

Pass expected_payload_digest= to EvidenceRef.for_external_record(...) when the claim must name the record’s exact content, not only its identity. From then on, a citation whose target holds different content reports digest-mismatch instead of passing silently. Pass as_of_revision= to resolve_external_evidence to check the claims as they stood at an earlier revision of your archive.

Tip — unresolved is an answer, not a failure. It means the check stayed honest: the archive was not in front of MTRL, so MTRL said so. Supply the archive and run the check again.

Caution — Resolution reports external-record evidence only. An assertion can also cite local records and local sources; those references are checked by the commit itself, so they never appear in these reports.

  • Record scientific assertions — the full assertion workflow: drafts, subjects, evidence, and the lifecycle calls.
  • Reference — the exact signatures of EvidenceRef, ArchiveRecordRef, EvidenceResolutionReport, and resolve_external_evidence.