rfgen.execution_evidence¶
rfgen.execution_evidence is the strict, immutable record format that links a
workstream’s implementation commit, acceptance evidence, scientific
validation, and chapter gate. It verifies submitted evidence against the
trusted plan and Git repository. It does not run the workflow that produced
that evidence.
All models are frozen Pydantic v2 models with unknown fields forbidden. Serialized timestamps are canonical UTC RFC 3339 values, SHA-256 fields are lower-case 64-character hex strings, and Git commits are 40-character IDs.
Library-backed primitives¶
The record boundary composes established, non-RF libraries rather than reimplementing serialization or schema machinery:
Pydantic v2 models own typed decoding, frozen model construction, and forbidden-extra-field checks.
jsonschema.Draft202012ValidatorandFormatCheckervalidate each persisted JSON instance against the packaged Draft 2020-12 schema before typed decoding.RFC 8785 supplies canonical JSON bytes for schema and self-digest identity; rfgen calls the
rfc8785package implementation rather than maintaining a canonicalizer.PyYAML
safe_loadparses the trusted plan frontmatter without constructing arbitrary Python objects.Git’s plumbing commands provide repository, tree, and ancestry observations used by the evidence records.
These dependency-backed checks establish typed, instance-schema, canonical
serialization, safe-plan parsing, and repository-observation boundaries. The
cross-record policy assembled by ExecutionEvidenceValidatorV1 is separate
framework behavior; its contract appears below rather than being attributed
to these libraries.
Canonical JSON means that equal JSON values have one deterministic byte representation, even if their source text differs in whitespace or object-key order. That stable representation makes a SHA-256 digest reproducible across processes and machines.
Each evidence record also carries a self-hash, its stored SHA-256 fingerprint over the record’s canonical payload fields rather than over the hash field itself. The validator recomputes the fingerprint before trusting a record; a mismatch means that its submitted contents changed after the fingerprint was created.
Module summary¶
from pathlib import Path
from rfgen.execution_evidence import ExecutionEvidenceValidatorV1, parse_evidence_record
record = parse_evidence_record(raw_json_object)
validator = ExecutionEvidenceValidatorV1(
Path.cwd(),
plan_path=Path(".agent-state/rfgen-build-plan/plan.md"),
chapter_guide_path=Path(".agent-state/rfgen-build-plan/chapters.md"),
)
report = validator.validate_bundle((record,))
assert report.overall == "PASS"
Use CLI / evidence validate when records are JSON files. Use this module when a service has typed records and needs the same in-process semantic decision.
Schema identity and record parsing¶
EXECUTION_EVIDENCE_SCHEMA_VERSION is 1.
EXECUTION_EVIDENCE_SCHEMA_RAW_SHA256 identifies packaged schema bytes and
EXECUTION_EVIDENCE_SCHEMA_CANONICAL_SHA256 identifies its RFC 8785 canonical
JSON value. These are public compatibility constants.
load_execution_evidence_schema()¶
def load_execution_evidence_schema() -> Mapping[str, object]
Loads the packaged Draft 2020-12 schema after verifying both public digests.
It raises EvidenceSchemaError for invalid package bytes, JSON, or schema
identity. Callers cannot replace this trust boundary with another schema.
parse_evidence_record(value)¶
def parse_evidence_record(value: Mapping[str, object]) -> EvidenceRecordV1
Parses exactly one object into the discriminated
EvidenceRecordV1 union.
The object must carry one of the six kind values, match the packaged schema,
and use canonical UTC timestamps. It raises ValueError for an unknown kind
or timestamp spelling, EvidenceSchemaError for schema-boundary failures,
and Pydantic or JSON-schema errors for invalid instances.
EvidenceRecordV1¶
The union comprises ModuleAcceptanceGateV1, ModuleStatusV1,
WorkstreamExecutionManifestV1, ChapterGateReportV1,
ScientificValidationHandoffV1, and ScientificValidationResultV1. A bundle
may be heterogeneous, but each member must contain its own kind.
Component and selector records¶
Model |
Fields |
Contract |
|---|---|---|
|
ID, kind, URI, SHA-256, size, producer command |
Immutable input, experiment, figure, report, gate, or regression artifact. |
|
module name, commit |
One direct plan dependency and accepted Git commit. |
|
ID, URI, digest, size, media type, non-mock flag, boundary |
Acceptance or chapter check evidence, with |
|
modules, repository, wave/base, branch/worktree/owner, scope, dependencies, tip/state/times/digest |
One owned worktree scope. State is |
|
wave, base, row digests, merge commit, time, digest |
One sealed integration wave. |
|
check ID, requirement, command/environment, times, exit/status/evidence/reason/digest |
One chapter check. Status is |
|
row ID, aggregate check, advertised/required/status/evidence IDs |
Report-side selector availability projection. |
GateCheckV1¶
One immutable chapter-gate observation. check_id identifies the gate,
required states whether that gate is mandatory, and command plus
environment_sha256 identify how it was evaluated. status is one of PASS,
FAIL, UNAVAILABLE, or SKIPPED; evidence holds the immutable artifacts
for the observation. reason_code is present when the result needs a
machine-readable explanation, and check_sha256 is the canonical self-hash.
DSSE_ROUNDTRIP is a trust-root check ID recorded by this model. Its
non-mock evidence demonstrates the real Sigstore DSSE verification boundary;
see SigstoreDSSEAdapter.
SelectorProvenanceV1 and SelectorInventoryV1¶
A selector is a named capability that a chapter can make available, for
example a plugin or configuration-defined backend. SelectorProvenanceV1(row_id, sources) records where that capability was discovered outside the submitted
evidence bundle.
The non-empty, sorted, unique sources are entry-point, installed Python
package registration metadata, and/or packaged-config, a configuration
declaration shipped with a package. SelectorInventoryV1(chapter_id, selectors) is the caller-owned, sorted inventory built from those deployment
inputs and supplied to the validator. Keeping it outside a chapter report
prevents the report from declaring a capability for itself.
def sources_by_row_id(self) -> Mapping[str, frozenset[str]]
Returns the immutable lookup used during chapter validation. It has no I/O and does not perform selector discovery.
Scientific-validation component records¶
Model |
Contract |
|---|---|
|
Original finding or deferred item with its evidence digest. |
|
One of six scientific lenses, severity counts, findings, artifacts, and result digest. |
|
Command, environment, input and output artifact digests, status, and result digest. |
|
Report output and render, audience, symmetry, claim-card, or banned-word gate evidence. |
|
Regression reproduction result or accepted deferral, including command/rationale and evidence. |
Every listed model is immutable and has the fields named by its row. The semantic validator enforces canonical ordering, self-hashes, and non-empty artifacts where their contract requires them.
Top-level records¶
ModuleAcceptanceGateV1¶
Carries module_name, implementation commit/tree/scope digests, manifest and
workstream-row digests, command/environment, evidence, status/exit code,
times, and gate_sha256. A passing gate has exit code zero and non-mock
evidence. It proves one module’s sealed implementation scope passed its
engineering acceptance boundary.
ModuleStatusV1¶
Carries module/layer/chapter/evidence class, implementation commit, status,
acceptance and engineering/scientific/release digests, optional frozen release
report projection, predecessor link, time, and status_sha256. Status is
planned, implemented, engineering-validated, optional
scientifically-validated, or release-qualified. Scientific modules require
a scientific result before their scientific or release-qualified status.
WorkstreamExecutionManifestV1¶
Carries repository/chapter identity, plan and chapter-guide digests, immutable
base, integration branch/worktree/owner, concurrency, workstream rows, wave
commits, active writers, timestamps, and manifest_sha256. Every acceptance
and chapter gate binds to this immutable plan-and-Git projection.
ChapterGateReportV1¶
Carries chapter, plan/guide/manifest/integration digests, module status
digests, checks, selector rows, times, outcome, failure IDs, and
report_sha256. A passing report needs the exact required check set, validated
module statuses and scientific results, plus a separately supplied inventory.
ScientificValidationHandoffV1 and ScientificValidationResultV1¶
The handoff binds planned module/component, implementation, plan/guide, acceptance artifacts and gate, regressions, deferrals, freeze time, and digest. The result binds the handoff to all lens results, experiments, report author, validation gates, regressions, deferrals, times, outcome, and digest. A result starts after the handoff and must match the exact planned scientific component.
Validation result models¶
EvidenceRecordKind is the stable integer ordering of the six kinds.
EvidenceRecordDigestV1(kind, self_sha256) is a normalized record identity.
EvidenceValidationFailureCode is INVOCATION, SCHEMA_BUNDLE,
INSTANCE_SCHEMA, SEMANTIC, GIT, or INTERNAL; its corresponding failure
model contains record index, code, path, and redacted detail ID.
ValidatedEvidenceV1 returns record kind, self digest, schema digest, and
validation time. ExecutionEvidenceValidationReportV1 returns ordered record
digests, bundle digest, seen/passed counts, failures, timestamps, outcome, and
report digest after a bundle call.
ExecutionEvidenceValidatorV1¶
class ExecutionEvidenceValidatorV1:
def __init__(
self,
repository: Path,
*,
plan_path: Path,
chapter_guide_path: Path,
selector_inventories: Sequence[SelectorInventoryV1] = (),
) -> None: ...
Custom logic: verify as follows¶
The cross-record linker is intentionally custom framework policy. No general-purpose library can decide whether this repository’s frozen plan, sealed integration waves, declared selector inventory, module-status history, and scientific handoff/result records satisfy rfgen’s release rules. The implementation is limited to binding those project-owned records and Git observations after the library-backed parsing and schema checks above; it does not replace a serializer, JSON-schema validator, canonicalizer, YAML parser, or Git implementation.
To verify a persisted bundle in the same boundary used by automation, run
rfgen evidence validate --bundle evidence.json --selector-inventory selectors.json --repository checkout --json. A PASS report means the exact
bundle passed its schema, digest, plan, Git, selector, status, and scientific
link checks; exit 5 or a FAIL report means it did not. The full invocation
and exit-code contract is in CLI / evidence validate.
The repository acceptance coverage is
tests/unit/test_layer11_public_evidence.py, which exercises both valid
bundles and tampered bindings.
repository is the checkout for Git ancestry and scope checks. plan_path
and chapter_guide_path are trusted planning artifacts. At most one explicit,
external selector inventory is allowed per chapter. Construction verifies the
packaged schema and safely parses plan frontmatter; it raises ValidationError
for duplicate inventory or bad trusted plan metadata and EvidenceSchemaError
for a schema identity failure.
Semantic methods¶
Method |
Inputs and return |
Validation boundary and failure |
|---|---|---|
|
Typed gate and manifest to |
Sealed-wave ancestry, scoped tree, status/exit relationship, and primary non-mock evidence. Raises |
|
Typed manifest to |
Self-hash, repository/plan/guide, wave partition, ownership scope, direct dependencies, ancestry, and chronology. Raises |
|
One module’s status tuple to |
Contiguous predecessor chain, gate/result/release binding. Empty, reordered, or mismatched histories raise |
|
Typed chapter inputs to |
Exact check order/evidence, status/science projection, and external inventory. A report that invents selectors raises |
|
Typed scientific pair to |
Planned component mapping, acceptance gate, timing, six lenses, experiments, report gates, regressions, and deferrals. Raises |
validate_bundle¶
def validate_bundle(
self, records: tuple[EvidenceRecordV1, ...]
) -> ExecutionEvidenceValidationReportV1
This public API deliberately accepts exactly one argument. It validates
self-hashes first and then all manifest, acceptance, science, chapter, and
status links. Ordinary semantic failures are returned in the report rather
than raised. It raises ValidationError only for unsupported nested bundle
invocation. Chapter reports require the constructor-supplied external selector
inventory; the validator never discovers selectors from evidence records.
Bundle-validation lifecycle¶
Callers parse persisted objects with parse_evidence_record(...) before this
method, then pass the resulting tuple once. A correct implementation follows
this ordered checklist:
Reject a nested call, initialize an empty manifest-validation cache scoped to this call, and clear that cache in
finally, including when validation fails. Git observations must not survive into a later bundle.Start the report clock, assign each input record its original tuple index, and validate every record’s self-digest. Append a
SELF_HASHsemantic failure at the original index for a bad digest, but continue so the report can collect independent failures.Partition the typed tuple into acceptance gates, module statuses, manifests, scientific handoffs, scientific results, and chapter reports. Build the manifest lookup by
manifest_sha256and preserve the original record-index lookup for failures.Validate each manifest against the frozen plan, chapter guide, repository, wave, scope, dependency, ancestry, and chronology rules. Convert a failed manifest binding into its record’s
GIT/MANIFESTfailure, then validate each gate against the manifest selected by its manifest digest. A missing selected manifest is aGATE_MANIFESTsemantic failure.For every scientific result, find the handoff by
handoff_sha256, derive its manifest from the handoff’s acceptance gate, and validate the pair. Missing handoff or manifest and a broken pair both yield the result record’sSCIENTIFIC_PAIRfailure.For every chapter report, select its manifest and only those status rows whose chapter and digest appear in the report. Obtain the matching constructor-supplied
SelectorInventoryV1; never derive it from the report. Validate the report with those statuses and all scientific results. A missing manifest, inventory, or invalid binding yieldsCHAPTER_GATE.Group statuses by module, sort each group by
recorded_at, and validate its history against all gates, scientific results, and the release-report projection on the release-qualified row. Track every engineering gate consumed by a valid history. Then add global failures for duplicate gates, an orphan gate, or duplicate normalized record identities.Normalize identities in
(kind, self_sha256)order, digest that ordered list into the bundle digest, sort failures by index, code, and path, and build the immutable report.records_passedis the input count minus the number of distinct failing indexes;overallisPASSonly when the failure list is empty. Digest the completed report last.
See Also¶
CLI: JSON invocation, inventory input, and exit codes.
Errors: framework error hierarchy.
Build and CI: checks that produce evidence.