George Sarris (0xcircuitbreaker) · · 5 min read
Content Addressing in OpenTine 0.8: Files, Repositories, and Limits
OpenTine 0.8 uses full SHA-256 identities for recorded agent content, with different guarantees for portable v2 artifacts and v3 repositories.
In this article
Audit note: this article changed with the product
The original version of this article described OpenTine 0.1.0: a small saved-trace CLI whose step IDs were 12 hexadecimal characters derived from a step kind, encoded inputs, and one parent ID. That description was accurate for the April release, but it is no longer an accurate description of the current product.
This revision is pinned to the tagged OpenTine 0.8.0 release, published August 23, 2026 UTC. The authoritative format boundary is the tagged TINE_FORMAT specification.
OpenTine now has two storage forms with related, but intentionally different, identity rules.
| Portable artifact | Repository | |
|---|---|---|
| On disk | One *.tine file, format v2 | A .tine/ directory containing v3 objects |
| Scope | One run graph | Many runs, objects, refs, reflogs, and packs |
| Node name | Step | Event |
| Verification | tine verify and optional artifact signature | tine fsck plus attestations |
| Typical use | Attach a run to a bug, archive it, or send it to someone | Maintain shared history, branches, evaluations, and release gates |
Treating those surfaces as interchangeable leads to incorrect claims about deduplication, signing, and fork identity.
What a v2 step ID commits to
A portable v2 run is a graph of steps. In 0.8.0 a step ID is the full 64-character SHA-256 digest of a canonical immutable payload containing:
- the step kind;
- its parent links;
- inputs and outputs;
- model and tool metadata; and
- any recorded error.
Timestamps, duration, cost, and token usage are recorded, but are not part of that step identity. Two otherwise identical steps whose providers reported different accounting data can therefore share a step ID while appearing as a changed pair in tine diff.
This is much stronger than the old 48-bit display prefix. It also has a specific boundary: the ID commits to what OpenTine recorded, not to every fact about the environment that produced it. If a caller omits a system package version, a remote API revision, or an external database snapshot, the hash cannot recover that missing context later.
There is one retained compatibility limitation. Portable v2 identity rules were released before the v3 object model. A step can be identified from its in-memory fields before save-time redaction, while the serialized artifact contains the redacted value. The artifact-level integrity digest still checks the serialized canonical artifact body, excluding metadata under the documented v2 boundary, but the individual v2 step ID may not identify the exact serialized step bytes. The current format specification documents this rather than overstating the guarantee.
What a v3 object ID commits to
The repository model fixes that boundary for newly recorded repository data. It stores five immutable object types:
blob;event;run;attestation; andannotation.
Each object ID includes its type, schema version, and SHA-256 digest. JSON bodies use RFC 8785 JSON Canonicalization Scheme rules. Typed links are validated: event parents must point to events, a run's roots and tips must belong to its event set, and referenced objects must exist locally or be declared as a shallow boundary.
Redaction runs before canonicalization and hashing. The stored redacted value is therefore the value the v3 object ID commits to. Identical v3 objects deduplicate naturally, and branches can share ancestor objects rather than copying an entire prefix into every file.
That does not mean two executions of the same prompt deduplicate automatically. Outputs, model information, tool records, and causal links are recorded content. If any of those differ, the object differs. Content addressing removes duplicate recorded objects; it does not declare semantically similar model answers identical.
Verify, authenticate, and inspect structure are different operations
OpenTine uses three checks for three different questions:
tine verify run.tinerecomputes a portable artifact's integrity digest. It detects corruption and many edits, but an editor who can rewrite the file can also recompute an unkeyed checksum.tine verifywith an HMAC key or Ed25519 public key checks authenticity against the signed view. This is the check that can distinguish an authorized signer from an arbitrary file editor.tine fsck --repo .recomputes repository object IDs and validates canonical encoding, typed links, refs, shallow boundaries, and event cycles.
An artifact can be internally consistent without being signed. A signature can establish which key signed recorded bytes without proving that the model's answer was true. A structurally valid repository can faithfully preserve a bad tool decision. Provenance makes those distinctions inspectable; it is not a substitute for evaluation.
Fork and replay semantics in 0.8.0
The current release has working file and repository branching:
tine fork run.tine --from-step 3 --save retry.tine
tine diff run.tine retry.tine --exit-code
tine repo-fork heads/main \
--from-event event:sha256:... \
--ref experiments/retry \
--repo .
A v2 fork ID names the fork act, including the retained slice, branch, declared intent, and a recorded nonce. A v3 run ID is a content hash, so two repository forks with identical recorded content resolve to the same immutable object.
Replay has two modes:
--mode cachederives a run from recorded steps without calling a live model or tool;--mode reruninvokes the configured model or external harness again.
tine replay <run> --verify is a checkable structural gate. In cache mode it round-trips and re-derives the recorded artifact, then exits 0 when the expected structure reproduces and 1 on drift. With a harness it executes twice and compares the resulting artifacts.
The word deterministic must remain scoped to that procedure. A cached derivation from fixed recorded inputs can be deterministic. A fresh call to a hosted model can change because of sampling, provider upgrades, serving kernels, hidden prompts, or mutable tools. OpenTine reports that drift; it cannot prevent the outside world from changing.
What content addressing helps with
The practical gains are concrete:
- Tamper detection. Recompute a name instead of trusting a stored label.
- Shared history. Repository branches reuse immutable ancestors.
- Precise comparison. A semantic diff can name common and divergent recorded events.
- Portable evidence. A
.tinefile can travel with a bug report or evaluation result. - Release gates. Evaluations, attestations, and promotions can point at immutable runs.
- Trace exchange. Imported OpenTelemetry or framework events enter the same identity model.
It does not, by itself, solve:
- missing environmental context;
- nondeterministic models or tools;
- false or low-quality outputs;
- leaked secrets that were placed outside the configured redaction boundary; or
- authenticity when no trusted signature or attestation is checked.
Migrating old files honestly
OpenTine 0.8.0 can best-effort import the legacy 0.1.0 linear shape and reads released v1/v2 artifacts. Moving a portable artifact into a v3 repository is explicit:
tine init history
tine migrate-v3 old-run.tine --repo history --ref heads/main
tine fsck --repo history
Migration preserves the original artifact as a byte-exact legacy blob, records its original verification result, and produces an old-to-new identity map. A signature over the old file remains a signature over that legacy blob; it is not silently promoted into an attestation over newly generated v3 objects.
That explicit boundary is the right pattern for an evolving provenance system: keep old evidence readable, label the transformation, and avoid claiming that a new identity scheme was present before it existed.
Current source of truth
For implementation-level decisions, use the tagged 0.8.0 concepts guide, format policy, and changelog. The OpenTine project page summarizes the release surface; the tagged documents own the exact guarantees.