lightcone.engine.crate¶
The publication view: the repository described as a Workflow Run
RO-Crate. The project is the crate — ro-crate-metadata.json sits at
the root, describes what the repository already holds, and a deposit is
git archive, not an export step. lc's manifests stay the canonical
record; the crate is the same facts in schema.org vocabulary for
archives and viewers that will never run lc.
Source: src/lightcone/engine/crate.py (converged by
materialize._converge_crate).
Key symbols¶
| Symbol | Role |
|---|---|
render(root, graph, *, license, dsid, writer) |
The document, as bytes. A pure function of repository state — git comes in as the writer callable, the dataset id as a value. |
license_of(root) |
[project].license from pyproject.toml; empty means no crate is maintained. Presence is publication intent. |
CRATE_FILENAME |
ro-crate-metadata.json. |
What must stay true¶
- The clock never enters the render.
datePublishedis the newest manifestfinished_at(the spec file's last-commit date for a never-materialized project) and must override rocrate's construction-time default. Entities build in sorted order, serialization issort_keys— render-twice-identical is the one byte-level claim, and it is what makes convergence sound. The serialization also compacts every one-element array to its value, as RO-Crate 1.1 recommends: which properties hold one value depends on the project, so the rule lives in one place, not in each builder. - Maintenance is derived, never configured. RO-Crate requires a license; materialize must not refuse to run science over a missing key, and inventing one asserts terms over someone's data. Absent ⇒ one report line; removed later ⇒ the file is left, and the line says it is no longer maintained.
- Run identity comes free from
git_sha— the driver reads HEAD once per run, so grouping manifests by it is grouping by run: oneOrganizeActionper materialize, aControlActionper execution, aHowToStepper output id (deduped across universes — a step is spec structure, an action is one execution). - The
Personis the author of the output's saving commit (viawriter), never the manifest'sgit_sha— that is the commit the run started at and can be someone else's. - An output is a
File, not aDatasetof parts. It is one file, so there is one annex key to look up and onesha256to publish — the same number its manifest records asdata_version, and the onesha256sumprints. - The manifest is not transliterated.
env_version,definition_versionandhermeticityget no invented schema.org spelling — the manifest itself is in the crate as aFile,subjectOfits output. Real vocabulary comes from the workflow-run@context, without whichcontainerImageandsha256are undefined terms JSON-LD silently drops — the pre-rebuild exporter's failure mode. - The rerun entry point does not regenerate the crate — it is one task's executor, so the crate lags until the next materialize. Recorded residue, not a bug.
Tests¶
tests/test_crate.py — pure: fixture manifests, a hand-built graph, a
stub writer, no git anywhere; structure and ordering assertions plus
the single render-twice byte check. tests/test_crate_smoke.py — the
official rocrate-validator against Provenance Run Crate 0.5:
REQUIRED clean, RECOMMENDED pinned to the recorded _FLOOR set (a new
failure is a regression, a disappearing one is the floor to shrink),
required in CI via LC_CRATE_TESTS_REQUIRED=1.