Versioned evidence artifacts
The structured artifact is an opt-in JSONL stream produced from the same normalized evidence as the text renderer:
pytest --receptor=llm --receptor-events=.pytest-receptor/events.jsonl
The destination directory must already exist. The option requires the llm or
ci profile because human is a true passthrough and installs no collector.
No upload, network access, or automatic retention is performed.
The stream is bounded to 50 MiB by default. Set a different explicit ceiling (minimum 64 KiB) when required:
pytest --receptor=ci --receptor-events=events.jsonl \
--receptor-events-max-bytes=104857600
When the next event would consume the space reserved for finalization, the
writer emits evidence_limit, stops storing further event bodies, and still
writes session_finish. Its artifact_policy records the byte ceiling,
whether truncation occurred, and the exact number of dropped records. Thus a
bounded artifact remains integrity-valid but never silently claims full
evidence retention.
Completion and integrity
Every line is a UTF-8 JSON object with schema set to
pytest-receptor.events@1 and a type discriminator. A normal stream contains:
one
session_startrecord;phaseandwarningrecords as pytest emits them;one final
session_finishrecord.
The final record carries pytest’s exit status, normalized outcome, explicit
counts and completeness, plus a SHA-256 digest and count covering every earlier
record exactly as written. Each root_cause event gives a normalized cause a
stable sha256: fingerprint and lists its logical occurrences without growing
the finalization record.
A failed test run can still have a finalized artifact. Conversely, a file
without session_finish is an incomplete event stream even if its last
recorded test passed.
Evidence is streamed, so an interrupted process normally leaves useful partial
records. SIGKILL, host loss, storage failure, and buffered filesystem loss can
still prevent capture; the artifact does not claim otherwise.
Reader API
from pytest_receptor import read_artifact
artifact = read_artifact(".pytest-receptor/events.jsonl")
if not artifact.complete:
print(f"partial stream: {artifact.issue}")
else:
print(artifact.final.data["outcome"])
artifact.complete means that the stream has a validated final record. The
test run’s execution completeness is the separate
artifact.final.data["complete"] field.
The reader:
validates the SHA-256 digest of finalized streams;
rejects unsupported schema major versions;
preserves unknown record types as
ArtifactRecord(known=False)so a newer producer’s data is not silently discarded;classifies a missing or truncated final record as incomplete;
raises
ArtifactFormatErrorfor malformed interior records andArtifactIntegrityErrorfor altered finalized evidence.
Minor evolution within events@1 may add fields and record types. Consumers
must ignore unknown fields and retain unknown records when rewriting an
artifact. An incompatible change requires a new schema major.
Terminal message and captured-section budgets do not mutate the normalized
events. A compact omission marker states original and retained character counts
plus a SHA-256 prefix; .pytest_cache/d/receptor/last-run.txt retains the full
text projection, and JSONL retains the structured source event when enabled.
Security boundary
The file is created owner-only (0600) and symlinks are refused. Text fields
pass through the receptor’s control-character stripping and conservative
credential-pattern redaction before persistence. This catches common
token=..., password, secret, credential, Basic-auth, and bearer-token shapes;
it is not a guarantee that arbitrary sensitive test data cannot appear.
Choose the destination and retention period accordingly. The producer applies the configured hard size limit but deliberately does not delete artifacts; retention remains the responsibility of the local or CI system that owns the destination. Configurable project-specific redaction rules and external blobs may be added compatibly in a future 1.x release.