Trajectories¶
H05: local, single-host recording
A scripted harness run can record a verifiable trajectory beside its result. Nothing is stored in the database or streamed to a controller; Harness Evaluation measures recorded runs. Liveness, publication proof and reconciliation hold on one host only. The decisions are in ADR-021, accepted on 2026-10-12.
A trajectory is evidence of an execution, not proof that it can be reproduced. It records what happened, and declares how much of it was captured and how much is still available.
Recording a run¶
Recording is opt-in. Without it, the compiler emits the H03 spec byte for byte, with the same fingerprint and request digest.
from xaytune.core.trajectory import TrajectoryRecordingSpec
from xaytune.harness import HarnessCompilationContext, ScriptedHarnessRunner
from xaytune.trajectory import WRITER
context = HarnessCompilationContext(
...,
output_uri="/runs/r1",
trajectory=TrajectoryRecordingSpec(writer=WRITER), # bounds, replay level, tiers, retention
)
spec = compiler.compile(harness, context) # outputs: the result, then the trajectory
result = ScriptedHarnessRunner().run(
spec, model=model, toolbox=toolbox, authorized_tools=tools,
trajectory_secrets={"sk-..."}, # frozen when the attempt opens
)
/runs/r1/agent-run.json the result: the same inode as one attempt's result.json
/runs/r1/trajectory/attempts/<ainst_...>/ one directory per attempt instance, owner-only
open.json tail.jsonl progress.json chunks/ blobs/{ordinary,restricted}/
result.json manifest.staged.json manifest.json expiry.jsonl
Each execution is its own attempt instance. Its id is minted and persisted before any call. A retry or a crash starts a new one.
Every start is durable before its call. A crash leaves a started call with no finish.
The commit point. The final chunk, result.json and a staged manifest
are written and verified first. Only then is the result hard-linked to its
declared location, and the staged manifest linked into place.
- Before the commit point, a failure publishes nothing.
- After it, reconciliation completes the seal, or reports the result as unattested.
Replay is checked. A recording-enabled run returns a published result
only when the attempt that published it is sealed complete and verifies.
Otherwise it raises UnattestedResultError, and never runs again.
Verifying¶
from xaytune.core.trajectory import validate_manifest
from xaytune.trajectory import (
check_availability, reconcile_trajectories, verify_publication, verify_trajectory,
)
validate_manifest(data) # the manifest alone: structure, bindings, chain
verify_trajectory(store, paths, manifest) # evidence: chunks, events, blobs, result
verify_publication(paths, manifest, location) # this attempt's link (st_dev, st_ino)
check_availability(store, paths, manifest) # available, expired, missing or corrupt
reconcile_trajectories(store, location) # seal what dead writers left
| Capture disposition (sealed, fingerprinted) | Availability (observed, never written back) |
|---|---|
captured, captured-restricted, redacted, not-provided |
available, expired, missing, corrupt |
Expiry. expire_blob removes a blob only after its tier's retention,
and records the removal first. The sealed manifest and its fingerprint never
change.
Retention is measured from the seal time of the manifest stored in the attempt. A supplied manifest must be that manifest, field for field. The seal time is not part of the fingerprint, so a copy with an earlier seal time would otherwise still validate.
Missing or corrupt content. A blob that is absent without an authorized
expiry record is missing; one whose bytes changed is corrupt. Both are
integrity incidents. A record authorizes an expiry only if it names the
sealed fingerprint, the tier's declared retention and the deadline that
retention gives, and a removal at or after that deadline.
Replay¶
from xaytune.harness import verify_replay
verify_replay(store, paths, manifest, spec, verifier=my_verifier)
# equivalent | diverged (sequence, field) | prefix-equivalent | ineligible (reasons)
A re-drive serves the recorded model replies and tool outputs, and calls no
model and no host tool. It shows that the harness logic makes the same
decisions, under xaytune.trajectory-replay-projection/v1. It never shows
that a provider or a tool would answer the same again.
recorded-responses is the minimum level eligible for replay. A trajectory's
writer can't verify its own replay.
Only the manifest sealed at the attempt's manifest.json is re-driven, never
a staged one. A complete trajectory also needs its result published by this
attempt at the spec's location. A partial one is checked as a prefix.
Secrets¶
Frozen set. The registered-secret set is frozen when the attempt opens. A value from it is never written, and neither is a digest of one.
Detection. If a frozen-set value would be written, the run stops before
the commit point, and the attempt is sealed as a sanitized partial.
Late discovery. contain_attempt quarantines the whole attempt, blobs
included, and restricts a published result. It makes no claim about what was
written before.