How long Runs are kept
A self-hosted server keeps every Run until its operator sets a window. With
RUN_RETENTION_DAYS set (or, on a hosted plan, the plan’s window), a nightly
sweep deletes the Runs of every Batch whose newest Run is older than the
window. A Batch is kept or deleted as a whole, so a late shard keeps it young;
a Run’s own execution time never changes its age. A Run with a calibration label
is never deleted.
Compaction. With RUN_COMPACTION_DAYS set (or the plan’s compaction age), a
Batch older than that but still inside the window keeps only each Scenario’s
representative Run (the Run a comparison reads as that Scenario’s row), plus any
labelled Run and any Run with a Violation that a comparison reads (the latest Run of
its repeat index; an older retry’s Violation goes with it). A comparison against a compacted Batch
gives the same verdict and rows as before; it carries compacted_at for that side,
its run-set report says the run-set evidence was discarded on that date, and a gate
tier that needs every Run of the run set stays unverified with a reason naming the
compaction.
Retired Batches. A compacted or expired Batch keeps its row. Pushing results
into it again is refused with 409 batch_retired (so a CI retry cannot bring
deleted Runs back; push to a new batch id), and comparing against an expired
Batch is refused with 410 batch_expired and the date. Drift history outlives
expired Runs: its nights stand on their own stored results. Any member can read
the terms in force, where they come from (plan, default or off) and the last
complete sweep with GET /team/run-retention; the dashboard shows the same under
Team > Run retention, and the compare page labels a compacted side in its batch
header and names an expired Batch with the date and what to do instead.