RFC-0010 — Checkpoint & Artifact Format¶
| RFC | 0010 |
| Title | Checkpoint & Artifact Format |
| Slug | artifact-checkpoint-format |
| Status | Accepted |
| Track | Standards |
| Authors | @AbdelStark |
| Created | 2026-06-02 |
| Target milestone | v0.1 (Stage A) |
| Area | artifacts |
| Requires | RFC-0001 |
| Informs | RFC-0003, RFC-0006, RFC-0009, RFC-0013, RFC-0014, RFC-0015 |
Summary¶
This RFC specifies the on-disk format of a Lensemble model artifact: the bundle that holds the shared,
federated parameters $(\theta_t, \phi_t)$ — encoder $f_\theta$ and predictor $g_\phi$ — at a given
round $t$. The format is two files: a safetensors weight payload (tensors only, no pickle) plus a
sidecar JSON header validated by a pydantic v2 model carrying an integer schema_version and a
SHA-256 content_hash over a canonical byte serialization of the weights. The content_hash is the
single value that flows through the federated protocol — it is committed in RoundClose
(RFC-0003 §8) and is what INV-CHECKPOINT-HASH binds. A
parent_hash field chains each round's artifact to the previous one, giving the auditable model-version
history that the Phase-2 verifiable layer (RFC-0006 §5) recomputes
over. Action heads $h_\psi^{(c)}$ are never serialized into a shared artifact (INV-ACTIONHEAD-LOCAL).
The stable data-model schema for this artifact (CheckpointHeader) is at
03-data-model.md §10; this RFC owns the byte-level format, the canonicalization, the hashing
procedure, and the load/verify lifecycle. The artifact module is lensemble.artifacts
(checkpoint.py, schema.py, hashing.py), public surface per conventions §1.
Motivation¶
The artifact is the unit of trust in the federation. Three forces converge on its format:
-
Aggregation reproducibility and proof-readiness. The outer step is bitwise-deterministic (
INV-AGG-DETERMINISM, RFC-0001 §6). A verifier — public recomputation in Phase 1, a STARK circuit in Phase 2 — must be able to load the exact bytes the coordinator committed, recompute their hash, and get an identical value on a different OS, CPU architecture, and torch build. This forces a canonical, platform-stable byte serialization with no implementation freedom, and rules out any format whose bytes depend on object identity, dict ordering, or pickle protocol. -
Tamper-evidence and supply-chain safety. A checkpoint crossing a boundary or sitting in shared storage must be detectably modified. A content hash recomputed on every load gives this for free, provided the serialization is deterministic. The same property forbids
pickle/torch.save: loading a pickle executes arbitrary code, and the byte stream is non-deterministic, so it is unfit both as a security boundary and as a hash input. -
Schema evolution without breakage. The header schema will change pre-1.0 (conventions §10). Readers must accept older artifacts via registered migrations and fail closed — not guess — on versions newer than they understand.
No existing torch checkpoint convention satisfies all three (the default torch.save fails 1 and 2),
so the format is specified here. The latent gauge result (RFC-0002)
keeps aggregation a near-linear weighted average, which is what makes a single committed hash per round
a meaningful and cheap proving target (RFC-0006 §3); the artifact
format is the substrate that carries that commitment.
Goals¶
- Specify the two-file artifact: a
safetensorsweight payload + a JSONCheckpointHeadersidecar, with every header field typed (the schema mirrors 03-data-model.md §10). - Specify a canonical byte serialization and the SHA-256 hashing procedure over it such that the
content_hashis identical across OS, CPU architecture, and torch build (INV-CHECKPOINT-HASH). - Define the hash chain (
parent_hash) that links round artifacts into an auditable model history, serving the proof-ready requirement of committed model versions (RFC-0006 §3). - Define schema versioning + migration (forward-compatible readers, ordered migration chain) and the
two distinct failure errors:
SchemaVersionMismatchandCheckpointIntegrityError(conventions §6). - Enforce
INV-ACTIONHEAD-LOCALat the serialization boundary: per-embodiment action heads are never in a shared artifact; an attempt is aResidencyViolation. - Provide the
save/load/verifyAPI and its determinism, error-propagation, and fail-closed-on-tamper contract.
Non-Goals¶
- This RFC does not specify episode/dataset commitments or Merkle construction (that is RFC-0014); it only reuses the same canonical commitment hash (SHA-256, conventions §11) so the two commitment surfaces agree.
- It does not specify the federated message wire format (
RoundOpen/Update/Commitment/RoundCloseare RFC-0003 §8); it specifies only the artifact whose hash theRoundClosemessage carries. - It does not specify the
RunManifest(RFC-0009) or the config-hash procedure; the artifact header merely referencesconfig_hashby value. - It does not specify the STARK proof circuit or TEE attestation (Phase 2, RFC-0006); it specifies the proof-ready artifact disciplines that land in v0.1.
- Action-head local persistence (a participant saving its own $h_\psi^{(c)}$ to its private store) is a participant-runtime concern (RFC-0013); this RFC only forbids action heads from entering a shared artifact.
Proposed Design¶
1. Artifact layout on disk¶
A model artifact is a directory (or a tar of one) containing exactly:
<artifact>/
weights.safetensors # tensors only; encoder + predictor param groups
header.json # CheckpointHeader (pydantic v2), schema-versioned
Large models MAY shard weights across weights-00000-of-000NN.safetensors files plus a
weights.index.json (the standard safetensors shard index mapping tensor name → shard file). When
sharded, the canonical hash (§4) is computed over the concatenation of shards in ascending shard index,
so a sharded and an unsharded artifact of the same weights produce the same content_hash. The
header is always a single header.json; it is the entry point a loader reads first.
Weights store only the federated, shared parameter groups — encoder ($\theta$) and predictor
($\phi$). Per-embodiment action heads $h_\psi^{(c)}$ are excluded by construction
(INV-ACTIONHEAD-LOCAL, §6). Master weights are fp32 (conventions §9); the artifact stores the fp32 master
copy, not the bf16 compute view, so a reload is exact.
2. The CheckpointHeader schema¶
The header is the pydantic v2 model below (the canonical data-model definition is
03-data-model.md §10; reproduced here as the format owner). It is JSON, UTF-8, with an integer
schema_version as the first-validated field.
from datetime import datetime
from pydantic import BaseModel, ConfigDict
class CheckpointHeader(BaseModel):
model_config = ConfigDict(frozen=True, extra="forbid")
schema_version: int # on-disk schema version ([conventions §10](../spec/conventions.md#10-versioning-and-schema-policy)); validated before body
content_hash: str # SHA-256 (lowercase hex, 64 chars) over canonical weight bytes
parent_hash: str | None # previous round's content_hash; None at round 0
wmcp_version: str # pinned latent-contract version (INV-WMCP)
round_index: int # the round t these params belong to (>= 0)
config_hash: str # the RunManifest config content hash that produced them
param_groups: tuple[str, ...] # e.g. ("encoder", "predictor"); action heads NEVER included
tensor_manifest: tuple["TensorEntry", ...] # per-tensor name/dtype/shape/group, sorted by name
weight_files: tuple[str, ...] # ("weights.safetensors",) or ordered shard list
created_at: datetime # UTC, RFC 3339
class TensorEntry(BaseModel):
model_config = ConfigDict(frozen=True, extra="forbid")
name: str # fully-qualified parameter name
group: str # one of param_groups
dtype: str # canonical dtype token, e.g. "float32", "bfloat16"
shape: tuple[int, ...] # tensor shape
| Field | Type | Domain | Meaning |
|---|---|---|---|
schema_version |
int, >= 1 |
version | header schema version; checked first (§7) |
content_hash |
str (64 hex) |
hash | canonical SHA-256 of the weight bytes; the committed value |
parent_hash |
str \| None |
hash | prior checkpoint's content_hash; None only at round 0 |
wmcp_version |
str |
tag | pinned latent contract these params target (INV-WMCP) |
round_index |
int, >= 0 |
count | round $t$; 0 for the warm-start / Stage-A start |
config_hash |
str |
hash | binds the artifact to the RunManifest that produced it |
param_groups |
tuple[str,…] |
labels | shared groups stored: encoder/predictor only |
tensor_manifest |
tuple[TensorEntry,…] |
— | every stored tensor's name/group/dtype/shape, name-sorted |
weight_files |
tuple[str,…] |
filenames | one entry, or the ordered shard list |
created_at |
datetime |
UTC RFC 3339 | artifact creation time (informational; not hashed) |
tensor_manifest is redundant with the safetensors file metadata by design: it lets a verifier check
the param-group disposition (and thus INV-ACTIONHEAD-LOCAL) and the dtype/shape contract without
loading tensor data, and it is part of the canonical hash input (§4) so the structural shape of the
artifact is itself tamper-evident.
3. Module responsibilities¶
lensemble.artifacts.schema— theCheckpointHeader/TensorEntrypydantic models, theSCHEMA_VERSIONconstant, and the ordered migration chain (migrate_vN_to_vN1).lensemble.artifacts.hashing— the canonical byte serialization (§4) andcontent_hash(...)/verify_hash(...). This is whereINV-CHECKPOINT-HASHis enforced; it depends on nothing above L3 (conventions §1 / RFC-0001 §3).lensemble.artifacts.checkpoint— the publicsave/load/verifyAPI (§5), gluing weights + header, calling hashing, and raising the typed errors of conventions §6.
4. Canonical byte serialization and hashing (INV-CHECKPOINT-HASH)¶
The content_hash MUST be a deterministic function of the model parameters and the structural header
fields, independent of the host OS, CPU endianness/architecture, torch build, number of shards, and
Python dict iteration order. The procedure:
- Tensor normalization. Each tensor is moved to CPU, made contiguous, and serialized as its raw
element bytes in little-endian with its declared on-disk dtype (fp32 master weights; the dtype is
recorded in
TensorEntry.dtype). No device/layout/stride metadata enters the byte stream — only element bytes. - Deterministic ordering. Tensors are concatenated in ascending order of fully-qualified
TensorEntry.name(byte-wise UTF-8 comparison), which is the same ordertensor_manifestis sorted in. Sharding does not affect ordering: the manifest order, not the file layout, defines the hash input. - Per-tensor framing. Each tensor contributes a domain-separated frame:
len(name)‖name‖dtype_token‖rank‖shape_dims‖element_bytes, all integers little-endian fixed-width, so that a rename or reshape changes the hash even if the raw bytes coincide. - Structural header bind. A trailing canonical frame binds the structural header fields that define
which parameters these are:
schema_version,wmcp_version,round_index,parent_hash(empty string whenNone),param_groups(sorted), and the orderedweight_files.content_hash,config_hash, andcreated_atare excluded from the hash input —content_hashbecause it is the output,config_hash/created_atbecause they are provenance pointers carried alongside, not part of the weight identity. - Digest.
content_hash = SHA-256(stream)rendered as 64 lowercase hex characters.
The canonical commitment hash is SHA-256 (conventions §11: conservative, interoperable, the same primitive RFC-0014 uses for episode/Merkle leaves, so artifact and dataset commitments share one algorithm). Domain separation distinguishes an artifact hash from a Merkle leaf hash so the two surfaces never collide.
def content_hash(weights: Mapping[str, "Tensor"], header_fields: "StructuralFields") -> str: ...
# deterministic across OS/arch/torch build/shard count (INV-CHECKPOINT-HASH)
def verify_hash(artifact_dir: Path) -> None: # raises CheckpointIntegrityError on mismatch
...
INV-CHECKPOINT-HASH is enforced here: the value returned by content_hash over the loaded weights and
structural fields MUST equal the header's content_hash, which MUST equal the hash committed in
Commitment/RoundClose (RFC-0003 §8). A divergence at any of these
three equalities is a tamper/corruption signal and raises CheckpointIntegrityError (§7).
RISK: step 1/2/3 fix endianness, ordering, framing, and contiguity, but a residual risk is a torch or
safetensors version that changes the default storage layout of an exotic dtype (e.g. a sub-byte or
complex dtype) such that "raw element bytes" is ambiguous. Resolution plan: the artifact restricts stored
dtypes to {float32, bfloat16, float16} for v0.1 (the only dtypes the model uses, conventions §9) and a
cross-platform hash-stability test (Testing Strategy) is a release gate; a new dtype requires extending
the canonical-dtype-token table and re-pinning the test fixtures. Tracked in the Open Question on
canonical-byte ordering.
5. Save / load / verify lifecycle¶
# lensemble.artifacts.checkpoint
def save_checkpoint(
artifact_dir: Path,
weights: Mapping[str, "Tensor"], # encoder + predictor only
*,
wmcp_version: str,
round_index: int,
config_hash: str,
parent_hash: str | None,
param_groups: tuple[str, ...] = ("encoder", "predictor"),
shard_size_bytes: int | None = None,
) -> str: ... # returns the content_hash (the value to commit)
def load_checkpoint(artifact_dir: Path) -> tuple[dict[str, "Tensor"], CheckpointHeader]: ...
# validates schema_version, migrates if older, verifies hash, then loads tensors
def verify(artifact_dir: Path, expected_hash: str | None = None) -> CheckpointHeader: ...
# header-only + hash check; if expected_hash is given it must equal header.content_hash
Save (coordinator on COMMITTING, RFC-0013; single-site on a
checkpoint cadence): validate that weights contains only param_groups tensors and no action-head
parameters (INV-ACTIONHEAD-LOCAL, §6) — a violation raises ResidencyViolation (security-critical,
never swallowed) before any bytes are written. Write safetensors (optionally sharded), build the
tensor_manifest, compute content_hash (§4), write header.json, and return the hash. The returned
hash is exactly what the coordinator puts in RoundClose.
Load (any consumer — evaluate, the outer step reading the prior global model, the public verifier):
read header.json first; validate schema_version and migrate if older, fail closed if too new (§7);
recompute the canonical hash over the weight bytes and assert it equals header.content_hash
(INV-CHECKPOINT-HASH) — mismatch raises CheckpointIntegrityError and no tensors are loaded into
memory; only then deserialize the safetensors tensors. safetensors deserialization is mmap-able and
never executes code; a pickle/torch.save payload presented at this path is rejected (§7,
CheckpointIntegrityError with a "not a safetensors artifact" remediation) — the loader never falls back
to torch.load.
Verify is the header-and-hash-only path used by public recomputation
(RFC-0006 §4, lensemble.verify.recompute) and by ingress checks:
it confirms integrity and, if given, that the artifact matches a committed expected_hash, without
materializing tensors for downstream compute.
6. INV-ACTIONHEAD-LOCAL at the serialization boundary¶
Per-embodiment action heads $h_\psi^{(c)}$ are local and never aggregated
(RFC-0001 §4). The artifact format makes this a serialization invariant,
not only a federation-path invariant: save_checkpoint rejects any tensor whose param group is not in
the allowed shared set {encoder, predictor}. Because action-head parameters are private model state of
private embodiments, emitting one into a shared artifact is treated as a residency breach
(ResidencyViolation, fail-closed) — consistent with INV-RESIDENCY and the data-model rule that
param_groups never contains an action head (03-data-model.md §10). A participant persisting its
own action head to its own private store uses a separate, unshared local-state path
(RFC-0013) that this RFC does not govern.
7. Failure modes and error propagation¶
All errors derive from LensembleError and carry .code (a LensembleErrorCode) and .remediation
(conventions §6). The artifact errors are the ArtifactError subtree (SchemaVersionMismatch,
CheckpointIntegrityError) plus ResidencyViolation on the save path.
| Failure | Trigger | Detection | Error (conventions §6) | System response |
|---|---|---|---|---|
| Schema too new / unknown | header schema_version exceeds reader max |
pydantic reads schema_version before the body |
SchemaVersionMismatch (SCHEMA_VERSION_MISMATCH), carries file_schema_version, reader_max_version |
fail-closed; load aborts; remediation names the upgrade path. Never silently coerces (04-error-model.md §5.7) |
| Schema older (known) | header schema_version < reader max |
version compare on read | none (handled) | run the ordered migration chain migrate_v(k)…→v(m), then proceed |
| Hash mismatch / tamper | recomputed canonical hash ≠ header.content_hash (or ≠ committed RoundClose hash) |
hash recomputation on every load | CheckpointIntegrityError (CHECKPOINT_INTEGRITY), carries expected_hash, got_hash |
fail-closed; tensors are not loaded; enforces INV-CHECKPOINT-HASH; never swallowed |
| Not a safetensors artifact | a pickle/torch.save/npz payload presented at the weight path |
format sniff before deserialize | CheckpointIntegrityError (CHECKPOINT_INTEGRITY) with a "safetensors-only" remediation |
fail-closed; the loader never executes a pickle; refuses load |
| Action head in shared artifact | a tensor outside {encoder,predictor} passed to save_checkpoint |
param-group check before any write | ResidencyViolation (RESIDENCY_VIOLATION) |
fail-closed; nothing written; security-critical, never caught-and-ignored (INV-ACTIONHEAD-LOCAL, INV-RESIDENCY) |
| Malformed header | header JSON fails pydantic validation (missing/extra field, bad hex length) | pydantic extra="forbid", field validators |
ArtifactError (ARTIFACT_INVALID) |
fail-closed; load aborts with the validation detail |
| Shard/index inconsistency | weight_files / weights.index.json disagree with present files |
manifest vs filesystem check on load | CheckpointIntegrityError (CHECKPOINT_INTEGRITY) |
fail-closed; refuse load |
SchemaVersionMismatch (a version problem) and CheckpointIntegrityError (a bytes problem) are
deliberately distinct: the first is recoverable by upgrading the reader or migrating; the second is a
tamper/corruption signal with no in-band recovery. Validation happens at the load boundary, before any
tensor materialization, so a corrupt artifact never enters compute.
8. Determinism and concurrency¶
- Determinism.
content_hashis a pure function of weights + structural fields (§4) and is required to be bitwise-reproducible across hosts; this is the artifact-side leg ofINV-AGG-DETERMINISM(RFC-0001 §6) and the proof-readiness requirement on committed model versions (RFC-0006 §3).created_atand any non-hashed field do not affect the hash, so two coordinators committing the same weights at different wall-clock times produce the samecontent_hash. - Concurrency. Save is single-writer per
artifact_dir(the coordinator owns commitment, RFC-0013); the directory is written to a temporary path and atomically renamed so a reader never observes a half-written artifact. Loads are concurrent and read-only (mmap), and the hash check makes a partially-written or truncated artifact aCheckpointIntegrityErrorrather than a silent partial read.
9. Proof-ready tie-in¶
This format satisfies two of the five Phase-1 proof-ready requirements (RFC-0006 §3) directly:
- Committed model versions: every $(\theta_t,\phi_t)$ is a hash-committed artifact; the
content_hashis the commitment carried inRoundClose. - Reproducible / recomputable inputs: the canonical hash lets a verifier load the exact
committed bytes and recompute alignment on the public probe
(RFC-0002 §5) — the "free" public-recomputation row of the
provable surface (RFC-0006 §3).
parent_hashchains the artifacts into the model-version history a Phase-2 aggregation STARK proves over. No format change is needed to add the Phase-2 proofs.
Alternatives Considered¶
safetensors (chosen) vs pickle / torch.save. torch.save is the default torch checkpoint
container and is convenient — it round-trips arbitrary Python objects and optimizer state. Rejected as the
artifact format because loading a pickle executes arbitrary code (a supply-chain and untrusted-artifact
hazard for a system whose whole point is exchanging artifacts across mutually-distrusting boundaries) and
because its byte stream is non-deterministic (object identity, protocol version, dict ordering), which
breaks INV-CHECKPOINT-HASH and the proof-ready determinism requirement. safetensors stores only
tensors with a small JSON header, is mmap-able, never executes code, and has a stable byte layout — it is
the format conventions §11 pins for exactly these reasons.
safetensors vs npz. numpy's .npz is also pickle-free for plain arrays and zip-packaged.
Rejected because it forces a tensor → numpy round-trip (losing bfloat16, which numpy lacks natively),
its zip container adds compression and timestamp non-determinism that would have to be canonicalized away,
and it is not mmap-friendly for large models. safetensors is purpose-built for tensor weights at scale.
Metadata in the safetensors header vs a sidecar header.json. safetensors permits a small
string-keyed metadata map inside its own header. Considered for keeping the artifact a single file.
Rejected as the primary metadata home because the structured CheckpointHeader (nested tensor_manifest,
typed fields, schema_version + migrations) is awkward to express as a flat string map, and validating it
with pydantic v2 (conventions §8) is cleaner as standalone JSON. The sidecar is canonical; a small subset
(content_hash, schema_version) MAY be mirrored into the safetensors metadata as a convenience, but
the sidecar is authoritative and is what load_checkpoint reads first.
Hashing the header file bytes vs hashing canonical weight bytes + structural fields (chosen). A
simpler scheme hashes the literal header.json and weights.safetensors file bytes. Rejected because
file bytes depend on JSON key ordering, whitespace, shard count, and safetensors library version —
none of which change the model — so the hash would be unstable across platforms and library versions and
would not survive re-sharding. The canonical procedure (§4) hashes the model identity, not the file
encoding, which is what a cross-platform verifier needs.
SHA-256 (chosen for Phase 1) vs a STARK-friendly hash (e.g. Poseidon2). A Poseidon2-style hash would
make the Phase-2 aggregation/commitment circuit far cheaper to prove. Not adopted in Phase 1 because
SHA-256 is conservative, ubiquitous, hardware-accelerated, and interoperable, and Phase-1 verification is
public recomputation (no circuit). The migration is the shared Open Question with
RFC-0006 and RFC-0014; the
hash_algorithm is a versioned choice so the change is a forward-compatible schema bump, not a rewrite.
Drawbacks¶
safetensorsstores only tensors, so structured metadata needs a sidecar — two artifacts to keep in sync. This is also the safety win: the tensor payload cannot smuggle executable state, and the metadata is validated independently. The atomic-rename write (§8) keeps the pair consistent.- A custom canonical hash is a maintenance surface. The byte procedure (§4) must be re-validated
whenever a stored dtype or the
safetensors/torch storage layout changes; the cross-platform hash-stability test is therefore a release gate, not an optional check. - No optimizer state in the shared artifact. Inner-loop optimizer state (AdamW moments) and outer Nesterov momentum are not part of the shared artifact (they are local/coordinator state), so a shared artifact alone does not resume an inner training run; that is intentional (only $(\theta,\phi)$ cross), but it means a participant rejoiner reconstructs optimizer state locally (RFC-0013).
Migration / Rollout¶
- The format ships in v0.1 (Stage A):
save/load/verify, SHA-256 canonical hashing, the header schema, and the round-0 warm-start artifact whosecontent_hashequals the pinned warm-start hash (INV-WARMSTART-T0, RFC-0001 §4). - Hash chaining via
parent_hashis used from v0.2 (Stage B) when the federated round loop produces a sequence of committed global models. - Schema migration: readers handle
schema_version <= SCHEMA_VERSION; each bump adds onemigrate_vN_to_vN1to the ordered chain and a round-trip migration test (07-testing-strategy.md §210). Pre-1.0 the schema may change with a bump and a migration; there is no removal of an old reader path within a major line (09-release-and-versioning.md §4.1). Aschema_versionbump is a Keep-a-ChangelogChangedentry with thearea:artifactslabel. - Hash-algorithm migration (SHA-256 → STARK-friendly) is a Stage-D / Phase-2 change carried by a
versioned
hash_algorithmfield, coordinated with RFC-0014 so artifact and dataset commitments migrate together.
Testing Strategy¶
The full pyramid is at (07-testing-strategy.md); the artifact-owned tests:
- Round-trip equality.
save_checkpointthenload_checkpointreturns tensors bitwise-equal to the inputs (fp32 master weights) and a header that re-validates; the returnedcontent_hashequals the header's. Runs on the CPU fallback (conventions §9). - Hash determinism across processes/platforms (release gate). The same weights + structural fields
produce an identical
content_hashacross two processes, and (in CI's matrix) across OS/arch, across a sharded vs unsharded layout, and across the pinned torch/safetensorsbuilds — directly exercisingINV-CHECKPOINT-HASHand the §4RISK. Tiny synthetic weights only; no large downloads. - Tamper detection. Flipping a byte in a weight file, reordering tensors, or editing the header's
content_hashcausesload_checkpoint/verifyto raiseCheckpointIntegrityErrorand to load no tensors (fail-closed). A mismatch against a suppliedexpected_hash(the committedRoundClosehash) also raises. - No-pickle assertion. A
pickle/torch.savepayload presented at the weight path is rejected withCheckpointIntegrityError(safetensors-only remediation); the loader is asserted never to calltorch.load/pickle.load(a property test over crafted payloads). - Action-head exclusion.
save_checkpointgiven a tensor outside{encoder,predictor}raisesResidencyViolationbefore any write (INV-ACTIONHEAD-LOCAL), and the test asserts the error is not caught-and-ignored anywhere on the path. - Schema migration + round-trip. A
schema_version = kheader loads into a version-mreader (k < m) via the migration chain and re-validates; a too-new version raisesSchemaVersionMismatchwithfile_schema_version/reader_max_versionpopulated. - Hash agreement with the commitment hash. A property test asserts the artifact
content_hashalgorithm matches the SHA-256 primitive RFC-0014 uses, with distinct domain separation so an artifact hash can never equal a Merkle-leaf hash of the same bytes.
Numerical-tolerance policy (07-testing-strategy.md): the hash and the fp32 master-weight round-trip require exact equality (no atol/rtol); approximate tolerances apply only to compute paths, not to the artifact bytes.
Open Questions¶
OPEN QUESTION: The exact canonical-byte ordering and framing for guaranteed cross-platform hash
stability across all stored dtypes (the §4 RISK). The v0.1 scheme is little-endian element bytes,
name-sorted, domain-separated per-tensor framing, restricted to {float32, bfloat16, float16}. Owner
@AbdelStark; resolution path: the cross-platform hash-stability test is a v0.1 release gate, and any new
stored dtype extends the canonical-dtype-token table behind a schema_version bump (Stage A, hardened
through v1.0).
OPEN QUESTION: Migrating the commitment hash from SHA-256 to a STARK-friendly hash (e.g. Poseidon2)
to keep the Phase-2 proof circuit cheap. Shared with
RFC-0006 and RFC-0014. Owner
@AbdelStark; resolution path: Stage D — carried by the versioned hash_algorithm field so the change is
a forward-compatible schema bump applied to artifact and dataset commitments together.
OPEN QUESTION: Whether a subset of header fields (content_hash, schema_version) should be mirrored
into the safetensors internal metadata map as a redundancy/self-description convenience, or kept solely
in the sidecar. Owner @AbdelStark; resolution path: decide during Stage A based on operator ergonomics;
the sidecar remains authoritative either way, so this does not affect the contract.
References¶
- RFC-0001 — Architecture & System Overview: §4 federation map and
INV-ACTIONHEAD-LOCAL; §6 trust boundaries andINV-AGG-DETERMINISM; §7 data-flow lifecycles (dataset commit). - RFC-0002 — The Latent Gauge & Frame-Anchored Aggregation: §5 the participant-side Procrustes backstop and the distinct committed-model alignment diagnostic that a verifier can recompute from public artifacts.
- RFC-0003 — Federated Training Protocol: §8 the message table —
RoundClosecarries the artifactcontent_hash,Commitmentcarries the dataset root. - RFC-0006 — Verifiable Contribution: §2 the provable surface; §3 the Phase-1 proof-ready requirements (committed model versions, reproducible outer step) this format satisfies.
- RFC-0009 — Configuration, Run Manifest & Reproducibility:
the
config_hashandRunManifestthe header references. - RFC-0013 — Coordinator & Participant Runtime: the
COMMITTINGstate that callssave_checkpoint; rejoiner local-state recovery. - RFC-0014 — Provenance Commitments & Merkle Scheme: the shared SHA-256 commitment primitive and the STARK-friendly-hash migration.
- RFC-0015 — Observability, Diagnostics & Telemetry: logging of
artifact hashes/sizes (hashes and norms are permitted; raw tensors are not —
INV-RESIDENCY). - Spec: 03-data-model.md §10 (
CheckpointHeader); 04-error-model.md §5.7 (artifact failure modes); 09-release-and-versioning.md §4.1 (artifactschema_versionpolicy); 06-security.md (no-pickle, supply-chain); 07-testing-strategy.md. safetensors(>=0.4, conventions §11) — safe, mmap-able, pickle-free tensor serialization.pydantic(>=2,<3, conventions §11) — typed validation of the JSON header with an explicitschema_version.hashlibSHA-256 (stdlib, conventions §11) — the Phase-1 canonical commitment hash.- Stwo — the Circle-STARK prover that, in Phase 2, proves over the committed-artifact hash chain.