opentine v0.6.0: provenance engines at the CLI
opentine 0.6.0 is the Surface Release: the v3 provenance engines that were already available through MCP now have first-class CLI commands for operators and CI.
The release also turns deterministic replay into a checkable gate, makes diffs scriptable, and adds cross-run statistics. It does not change storage formats: portable *.tine artifacts remain v2 and repository objects remain v3.
Operate v3 repositories from the terminal
The repository layer now has commands for reading runs, following causal context, comparing histories, and searching recorded work:
tine repo-show heads/main
tine repo-log --repo . --json
tine context event:sha256:... --depth 8
tine repo-diff heads/main heads/experiment --exit-code --json
tine repo-search "regression" --model claude-sonnet-5 --json
The write side is available too:
tine attest heads/main --signer release-bot --claim-file claim.json
tine evaluate heads/main --evaluator qa --score accuracy=0.96
tine promote heads/main --name candidate
tine repo-fork heads/main --from-event event:sha256:... --ref experiments/fix
tine repo-resume heads/main --ref experiments/resumed
These commands use the same underlying engines as their MCP counterparts, with parity tests guarding the shared behavior. A few differences are intentional. The CLI acts with operator authority, so it is not confined to experiments/*; MCP keeps that restriction because its inputs can be model-controlled. Promotion is also an explicit operator command, while MCP promotion remains opt-in.
Mutating commands emit JSON only after a successful write. Promotion preserves compare-and-swap behavior: creating a promotion expects the ref to be absent, moving an existing one requires --expected-old, and there is no force flag.
Verify deterministic replay
tine replay --verify makes replay reproducibility usable as a CI result rather than an informal expectation.
tine replay result.tine --verify --json
tine replay result.tine --verify --ignore-cost-drift
Cache-mode verification does not merely compare an in-memory copy. It writes the replay to a temporary path, loads it back, derives the replay again from the source bytes, and checks the retained slice, run ID, integrity digest, and structural fields. The command exits 0 when the replay reproduces and 1 when it drifts or cannot be loaded.
Accounting-only drift can be downgraded with --ignore-cost-drift; structural drift still fails. Unless --save is supplied, verification leaves nothing in .tine_runs/.
With --harness, verification re-executes the external agent twice over the same retained context and compares the two recorded artifacts. That is the nondeterminism check for a live runtime; cache mode remains the default gate that launches nothing.
Script diffs and summarize local history
The portable-artifact diff command now has the same automation-friendly exit convention:
tine diff baseline.tine candidate.tine --json --exit-code
Exit 0 means identical and exit 1 means different. The JSON drift object is shared with replay --verify, separating structural drift from accounting drift.
tine stats aggregates the local .tine_runs index:
tine stats --group-by model --json
tine stats --group-by tag --deep
Without --deep, it reports only fields present in the index, including run and step counts, cost aggregates, models, tags, statuses, and format versions. Token and duration totals are absent rather than misleadingly reported as zero. --deep opts into loading each bounded run to collect those additional fields. Version 0.6 statistics cover the legacy local index, not v3 repositories.
A more direct Python and JSON surface
Diff, query, graph, signing, format, and budget types that were already public through narrower modules are now available directly from opentine, including RunDiff, StepChange, FieldDelta, Graph, Query, parse_query, sign_artifact, verify_artifact, FORMAT_VERSION, and BudgetBreach.
tine import and the read-only forms of tine tag also gain --json, joining the commands introduced in 0.5. A mutating tag operation refuses --json rather than accepting a flag it cannot honor.
Compatibility and the context fix
Version 0.6 includes two related replay fixes. replay --inspect and --dry-run now preview the ancestor closure that a replay actually retains, not the discarded descendant path. Harness fork and replay context uses that same retained history, preventing a child run from citing future steps it does not contain.
There is no artifact or repository migration. The compatibility gate exercises portable artifacts and repositories written by the published 0.3.0, 0.4.0, and 0.5.0 releases.
Install opentine 0.6.0 from PyPI, read the official v0.6.0 changelog, and inspect the tagged source for the full release.