agent replay --ci reads each recorded response from <data_dir>/recordings/<upstream>.ndjson and diffs it against its frozen baseline family, entirely offline. No network, no provider account, no running agent.
What it compares
Each JSON recording is matched to its(method, template, status class) family and diffed the same way live traffic is: fields added or removed, types changed, values outside the known set, a field arriving null, a status code moving within its class. Findings are deduplicated per method, template, kind, field and detail, and each carries the fingerprint pikopod agent accept takes.
Risk tiers
A provider adding a field should not block a release. A type flip onamount must. Every finding is graded by what breaks consumers, and --fail-on sets the lowest tier that fails the build:
A finding the provider’s new spec version documents drops one tier. The default is
medium, so additive fields are accepted and everything else fails. Findings below the threshold are printed under accepted and never fail the gate:
--fail-on low fails on everything, --fail-on high only on removals, retypes and status changes:
pikopod agent accept <fingerprint> is honoured here too: it is listed in its own accepted block, whatever its tier, and does not fail the gate. See ack, accept, baseline.
What it skips
- Recordings whose family is not frozen yet. They are counted as pre-warmup skipped.
- Non-JSON recordings.
- New values on fields listed in
volatile_fields. Presence, type and nullability of those fields are still checked.
Exit codes
In CI
The gate needs thedata_dir the agent wrote, or a copy of it. Ship the baselines/ and recordings/ directories as an artifact, or mount the volume read-only:
{"source":"replay-ci","records":n,"fail_on":"medium","findings":[…],"accepted":[…]}; each finding carries risk and fingerprint, each accepted entry also because. pr comment renders the findings. See CI integration.