sei.lock — drift state
✅ Stable
sei.lock is the freshness anchor file the engine writes to the repository root after every sei run. It holds the digests of pipeline inputs at the time of the last recompute. sei status reads it without running any script to determine which sections have become stale.
What sei.lock anchors
Section titled “What sei.lock anchors”The core of the file is the anchored triple (triple), which deterministically identifies the state of the repository at the time of recompute:
triple field | What it measures | How it is computed |
|---|---|---|
code | Code version | SHA-1 of HEAD (via gix, in-process) |
model | (reserved) | Empty in GitDvcVersionResolver (model: String::new()); the model version is anchored indirectly via pipeline_lock_digest (dvc.lock/metrics) |
dataset | Dataset version | Composed SHA-256 of DVC hashes from data/*.dvc |
In addition to the triple, the pipeline_lock_digest field anchors the state of the reproducible pipeline:
- DVC backend (cat. 1): SHA-256 of
dvc.lockafterdvc repro— anchors deps + params + outs of the recompute. - MLflow (cat. 2): Canonical SHA-256 of the run metrics (content-addressed).
- Dagster (cat. 3): SHA-256 of the metrics file after asset materialisation.
The pipeline_lock_digest is included in the signed evidence bundle (EvidenceBundle.pipeline_lock_digest) as provenance of the recompute (Annex IV §1).
File structure
Section titled “File structure”The schema lives in seigarrena-core/src/lock.rs. The following is an illustrative shape of a real sei.lock (hash values are fictitious):
{ "schema_version": "seigarrena.dev/v1alpha1", "program_uid": "550e8400-e29b-41d4-a716-446655440000", "triple": { "code": "4280c0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7", "model": "", "dataset": "dvc:a1b2c3d4e5f6..." }, "sections": { "classification": { "status": "valid", "input_hash": "sha256:abc123...", "edge_type": "scope" }, "measurement_data": { "status": "valid", "input_hash": "sha256:def456...", "edge_type": "data" }, "measurement_model": { "status": "valid", "input_hash": "sha256:789abc...", "edge_type": "impl" } }, "signed_bundle_digest": "sha256:deadbeef..."}Top-level fields
Section titled “Top-level fields”| Field | Type | Description |
|---|---|---|
schema_version | string | Lock schema version (seigarrena.dev/v1alpha1). |
program_uid | string | UUID of the risk programme (the risk section of sei.yaml) at run time, derived from the system name (anchors the normative context). |
triple | object | Anchored triple (code, model, dataset) — see table above. |
sections | map | Typed dependency graph: each section has its input_hash, status, and edge_type. |
signed_bundle_digest | string | SHA-256 of the signed evidence bundle emitted by this run (None on the pipeline-less path). |
sections entries (LockEntry)
Section titled “sections entries (LockEntry)”Each entry in the sections map has three fields:
| Field | Type | Values | Description |
|---|---|---|---|
status | string | "valid" | Section status at run time. |
input_hash | string | sha256:… | Hash of this section’s inputs. When it changes, the section becomes stale. |
edge_type | string | "scope", "impl", "data" | Edge type in the dependency graph (see below). |
Edge types (EdgeType)
Section titled “Edge types (EdgeType)”The edge_type field determines which changes trigger recomputation of each section:
edge_type | Rust value | What triggers recomputation |
|---|---|---|
scope | EdgeType::Scope | Change to system purpose or risk triage (Drift A). Risk classification must be redone. |
impl | EdgeType::Impl | Change to the evaluation script or model (Drift B). Re-measure only; no re-triage if purpose is unchanged. |
data | EdgeType::Data | Change to the dataset (Drift C, EU AI Act Art. 10). Only data-dependent measurements are recomputed. |
This typology maps directly to drift classes A, B and C. See Typed drift for the full model description.
How sei status detects drift without recomputing
Section titled “How sei status detects drift without recomputing”sei status compares current hashes against those stored in sei.lock without running any script:
- Resolves the current repository triple (git HEAD + DVC hashes; the
modelfield stays reserved/empty — the model version is reflected inpipeline_lock_digest). - Compares each
input_hashinsectionsagainst the current hash of the corresponding input. - Sections whose hash has changed are marked
Stale { reason, change_class }with the corresponding drift class. - Unchanged sections are marked
Reused.
The result is a per-section drift report with its class (A, B or C) and the reason for the change. sei status returns exit ≠ 0 if any section is stale (freshness gate) or if any blocking control in the last bundle fails (risk gate).
# Detect drift without recomputing — useful in CI/CD as a fast gatesei statusStaleness is selective: if only the dataset changes (edge_type: data), only data-measurement sections are recomputed on the next sei run; system classification and dataset-independent measurements are reused.
Canonical serialisation
Section titled “Canonical serialisation”sei.lock uses an ordered BTreeMap and deterministic serialisation: the same repository state always produces the same bytes. This ensures that signed digests are reproducible across machines.
Relationship with the evidence bundle
Section titled “Relationship with the evidence bundle”sei.lock and .sei/bundle.json are complementary:
sei.lockis the freshness anchor: it tells you when to re-run..sei/bundle.jsonis the signed evidence: it contains the results of the last run, control verdicts, and thepipeline_lock_digest.
The signed_bundle_digest field in sei.lock links the two artefacts: it is the SHA-256 of the bundle written during the same sei run.
See also: sei CLI Reference, The .sei/* artefacts.