Skip to main content

Module contract_walk

Module contract_walk 

Source
Expand description

Shared recursive contract directory walker.

Multiple pv subcommands need to load every YAML contract under a directory tree (including subdirectories like contracts/aprender/, contracts/trueno/, contracts/patterns/). This module provides the canonical walker so commands agree on what counts as a contract and which sidecar files to skip.

PVL-1 (PMAT-1099): a corpus with ZERO contracts is REFUSED, never reported. Measured before this change (PV-LEAN-AUDIT-001, 2026-09-10): pv lint /nonexistent-path exited 0 with Result: PASS over 0 contracts, and pv proof-status <empty dir> printed Proof Status (0 contracts) at exit 0 — a gate that measures nothing and reports PASS. collect_corpus is the entry point every reporting subcommand uses: it returns ZeroContracts (exit ZERO_CONTRACTS_EXIT) for an empty or missing directory, and treats a single .yaml file as a one-contract corpus so pv <cmd> <file> reports that file instead of walking nothing.

ONE definition of “empty”. The set of contract files is the one pv lint walks — provable_contracts::lint::collect_yaml_files (the is_contract_yaml rule plus the skipped sidecar directories) — so no two commands can disagree on what is there. A contract file that fails to parse is NOT “no contract”: it was measured, and it failed (ParseErrors, exit 1, every file named). The second review quorum on #3093 measured proof-status and lint --diff refusing an unparsable-only directory as “0 contracts” (exit 2) while lint failed the same directory with contracts: 1, errors: 1 (exit 1); this walker’s old private rule also skipped every *playbook* stem, and the corpus holds real contracts named that way.

Structs§

LintDeclined
pv lint’s armed meet is Unknown(reason) (ONT-001 §3.4): nothing armed was measured to a verdict. Exit 2; the line is exactly Verdict::decline_line.
LintRejected
pv lint’s armed meet is Fail: measured, and failed. Exit 1.
ParseErrors
Contract files under path that failed to parse: measured, and failed (exit 1) — never a silent skip, never “0 contracts”.
ReleaseArgsRefused
aprender#3715: a --shape / --release-* flag set that cannot name a release (a partial subject, a short sha, a flag outside --gate shapes). The CALLER’s error, exit 3 — never a verdict about the evidence.
SigmaMalformed
pv lint --gate sigma found Σ itself malformed (ONT-001 §5 ONT-2b): the DECLARATION is wrong, not the corpus, so it is error: at exit 3 and never reject:.
UnknownGate
--gate <name> named a gate this build does not compute alone.
ZeroContracts
The corpus under path holds no contract (after filter, when set).

Constants§

ARMED_GATES_SHRANK_EXIT
Exit status of an armed_gates list that dropped a gate its comparand armed (ONT-001 §3.9).
ZERO_CONTRACTS_EXIT
Exit status of a refused empty corpus.

Functions§

collect_contracts
Walk dir and collect every PARSEABLE contract, dropping the rest.
collect_corpus
Load the corpus at path and refuse an empty one.
exit_code_for
Exit status for a dispatch error: ZERO_CONTRACTS_EXIT for a refused empty corpus or a declined lint meet, ARMED_GATES_SHRANK_EXIT for a shrunk armed set, 1 for everything else (a parse failure and a rejected meet included).
has_contract_files
Is there at least one contract file under path? The one definition of a non-empty corpus, answered WITHOUT parsing (diff mode asks this before it says “nothing changed”). A file path is a one-contract corpus.
require_contracts
Refuse an empty corpus: Err(ZeroContracts) when corpus is empty.
verdict_for
The verdict class pv prints before an error, in PVL-001 §0’s vocabulary: decline (exit 2, nothing measured), reject (exit 1, measured and failed), error (anything else, the shrunk armed set at exit 3 included). One definition, so the word and the exit code cannot drift apart — ONT-001 §5 ONT-1 asserts both halves of the line.
walk_contracts
Walk dir recursively with pv lint’s file rule: every contract file is parsed into out as (stem, contract), or recorded in errors as (file, error). Nothing is dropped.