The proof ladder
From a stated requirement to fresh end-to-end evidence: the stages a requirement climbs to count as tested, and how strong its evidence is.
Consumer-facing reference for proofStatus, proofStages, proofGaps, and
proofAdvisories as reported by kibi coverage --by req and kb_coverage.
The authoritative implementation is packages/core/src/requirement_proof.pl
(proof version kibi.requirement-proof.v5); this document explains what each
stage means and what to do when it does not pass.
Applicability: is the requirement in scope at all?
The ladder only evaluates current requirements. A requirement is current
when its status is one of:
- Canonical:
open,in_progress,closed - Legacy (accepted for backwards compatibility):
active,approved
Everything else is out of scope by design. Three things can take a requirement out of scope:
- Supersession — a newer requirement links to it with
supersedes. - Retirement —
status: retiredwith aretired_reason: the behavior is gone and nothing replaces it. The applicability reason reads "requirement is retired: the behavior it stated no longer exists". - Status outside the vocabulary — e.g. the ADR vocabulary
accepted. Since that silently excludes the requirement from proof,kibi checkreports it as a blockingreq-status-vocabularyviolation instead of letting it hide.
Out-of-scope requirements report:
{
"proofStatus": "not_applicable",
"proofGaps": [],
"proofStages": {
"applicability": {
"status": "not_applicable",
"reason": "status 'accepted' is not a current requirement status"
}
}
}The typed reason is what not_applicable used to hide: superseded
requirements say so; status-vocabulary mismatches name the offending status.
Proof exemption: current but intentionally not E2E-provable
Some current requirements cannot be proven by end-to-end evidence — toolchain-currency gates, architectural boundaries, quality-gate policy. Parking them with an ADR status is exactly the trap above. Instead, mark them explicitly in the requirement document:
---
id: REQ-TOOLCHAIN-001
status: open
priority: must
proof_exempt: true
proof_exempt_reason: architectural boundary — verified by toolchain CI, not product E2E
---proof_exempt requires a non-empty proof_exempt_reason (upsert validation
enforces the pairing, and the ladder ignores an exemption without a reason).
Exempt requirements report not_applicable with the author's reason attached,
so coverage can distinguish "cannot be proven" from "not proven yet".
To re-enter the proof ladder, remove both properties.
The stages
For in-scope requirements the ladder evaluates the stages below, in order. Each
stage reports a status under its key in proofStages; productionSymbols
also carries a typed reason when it does not pass.
| # | Stage | Key in proofStages |
|---|---|---|
| 1 | Semantic inventory | semanticInventory |
| 2 | Logic grounding | logicGrounding |
| 3 | Contradictions | contradictions |
| 4 | Scenarios | scenarios |
| 5 | Scenario tests | scenarioTests |
| 5a | Failure side | negativePath |
| 5b | Quantified claims | dimension |
| 5c | Edge cases | cases |
| 6 | Passing E2E tests | passingE2e |
| 7 | Executable test symbols | executableSymbols |
| 8 | Production symbols | productionSymbols |
| 9 | Source coordinates | sourceCoordinates |
1. Semantic inventory
Checks: every assertive statement in the requirement's prose is listed in its semantic inventory and classified as modeled, unresolved, missing or nonlogical.
passed: the inventory is complete and nothing in it is unresolved.missing: there is no inventory, an entry is classified as missing, or an entry is malformed.unresolved: at least one statement is classified as unresolved.
2. Logic grounding
Checks: each modeled claim is grounded by a strict property, predicate or safe rule fact, one to one with the declared manifest.
passed: every modeled claim has exactly one grounding fact.missing: a claim has no grounding fact or no manifest entry.unresolved: the grounding exists but does not line up (an extra or duplicate manifest entry, claim text that differs, an invalid or undeclared fact, an unsafe rule).
3. Contradictions
Checks: no other current requirement contradicts this one over shared facts.
passed: no conflict was found and grounding is complete.blocked: a conflict was found;conflictsnames it.unresolved: the check could not finish, usually because logic grounding is incomplete, so the absence of a found conflict is not evidence of safety.
4. Scenarios
Checks: at least one scenario specifies the requirement (specified_by).
passed: one or more valid scenarios are linked.missing: no scenario is linked, or a link points at a scenario that does not exist.blocked: a linked success scenario is infeasible;infeasibleScenariosnames it.
5. Scenario tests
Checks: each linked scenario is validated by at least one test
(verified_by or validates).
passed: every scenario has a test.missing: a scenario has no test, or links a test that does not exist.
5a. Failure side
Checks: a requirement that grounds a claim (a requires_property,
requires_predicate or requires_rule fact) is not tested through its happy
path alone. At least one linked scenario must expect rejection or error
and assume a value or situation the requirement forbids: either the
scenario-feasibility analysis finds a witness naming the requirement, or one
of its assumes facts opposes one of the requirement's claim facts directly
(a conflicting value or polarity on the same subject and property, the
opposite polarity of the same predicate, or, for a rule over predicates, a
predicate fact instantiating one of the rule's atoms). For a guarantee rather
than an input constraint, the assumed fact describes the attempt to break the
guarantee, and rejection means the system refuses or contains it.
passed:negativeScenarioslists the linked scenarios that do this.missing: none does; the requirement gets thehappy_path_onlygap, andsuggestedNegativesgives, per open claim, a fact that opposes it (the value just past a numeric bound, the other boolean, a different string, a set missing a required member, the opposite polarity of a predicate).not_required: the requirement grounds no claim, or a fresh certificate proves every claim at code scope (certifiedClaims): a certificate decides both sides of the claim already. When every open claim is proved by a certificate test whose receipt is only older than the code (pendingReproofClaims), the evidence floor reportspending_reproofrather thanbelow, as for any other stale receipt.waived: the requirement has no failure side to test. Its claims state a capability or an output shape, so there is no input or attempt to refuse. The requirement records why infailure_side_waiverand who accepted it infailure_side_waiver_approved_by, andwaivershows both. A reason without an approver staysmissing, andkibi proof explainreports the waiver as awaiting approval.
The negative scenario needs a test like any other linked scenario, so the
failure side is proven by the same passing E2E receipts. The canonical
scenario-outcome-mismatch check rule reports a scenario that expects
rejection or error while current requirements govern and permit everything it
assumes.
5b. Quantified claims
Checks: a claim that quantifies over a collection (each, every,
all) or bounds a cardinality (exactly, at least, at most, no more than) is grounded on what varies, not only on its verdict. When every fact
grounding such a claim is a boolean property_value or a ground predicate,
the claim states that the behavior holds without naming the dimension it
holds over, and a scenario with one item can pass where several items break.
Ground it on an integer count or bound, a set of members, a rule over a
variable, or a state machine instead. only, any and some are not
counted: they mostly scope a condition ("only when", "before any write")
rather than range over one.
missing:claimslists each such claim with itsquantifier, the groundingfactIds, andrewrites, the typed groundings that would represent it, likeliest first (boundfor a cardinality;rule,countorsetfor a collection). The requirement gets thedimension_unrepresentedgap.not_required: no grounded claim is quantified this way, or a fresh certificate proves the claim at code scope. Stale certificate receipts are reported aspendingReproofClaims, as in the failure-side stage.waived: every such claim has an approved waiver. When the quantifier word ranges over nothing ("start without all network access"), the grounding fact records why indimension_waiverand who accepted it indimension_waiver_approved_by;waivedClaimslists them. A reason without an approver keeps the claim inclaims, andkibi proof explainreports it as awaiting approval.
kb_semantic_advisor marks the same clauses: each normative proposition
with such a quantifier carries dimension with its quantifier and
rewrites, so the grounding can be chosen before the fact is written.
5c. Edge cases
Checks: every value class a typed property claim predicts is refused has
a scenario that reaches it. Kibi derives the cases from each property_value
fact the requirement grounds a claim on with requires_property:
- a numeric bound yields the bound itself (or the nearest value inside a
strict bound) and the class past it:
files_per_batch lte 5giveseq 5(success) andgt 5(rejection); - an integer bounded at one or more also yields zero, one and many
(
eq 0,eq 1,gte 2), keeping only the classes that fall wholly on one side of the bound; - a set yields each member (success) and the value outside it: rejection
for
eqandsubset_of,unspecifiedforincludes; each member of anexcludesset is a rejection case.
A case is dropped when an earlier one already names its class with the same
outcome, and one fact yields at most 12 (limitReached says when the cap
cut). Each case has a stable caseId (CASE- and 12 hex characters) and the
assumption a scenario would state to land in it.
A case is covered by a scenario of the requirement that is not a draft,
whose expects matches the prediction (rejection also accepts error),
and whose assumes fact on the same subject and property entails the case:
files_per_batch eq 6 covers gt 5. Success cases are reported but do not
block; the requirement's success scenarios already exercise them.
missing: a rejection case is uncovered;uncoveredCaseslists them and the requirement gets theuncovered_casegap. The repair plan'scase_scenariosphase carriescaseSkeletons, an upsert-ready draft scenario and assumed fact per case: fill in any placeholder value, verify the scenario by a test and make it active.passed: every rejection case is covered.not_required: no grounded claim predicts a rejection case, or a fresh certificate proves the claim at code scope. Stale certificate receipts are reported aspendingReproofClaims.waived: the uncovered rejection cases all belong to facts with an approved waiver. When the cases are covered another way (a unit suite that walks every value, a class the system cannot produce), the grounding fact records why incase_waiverand who accepted it incase_waiver_approved_by. A reason without an approver keeps the gap.
kibi coverage --cases lists every requirement's cases with their coverage,
and kibi proof explain prints the assumption each uncovered case needs.
kb_semantic_advisor previews the cases of each strict-property suggestion
in casesPreview, so the scenario debt shows before the fact is written.
6. Passing E2E tests
Checks: every linked scenario has at least one end-to-end test, and every
linked E2E test that bears proof carries a valid, fresh, passing
kibi.proof-receipt.v1 receipt bound to the current snapshot, contract hash
and fingerprint.
passed: every scenario obligation passed.missing: a scenario has no qualifying E2E test or receipt.unresolved: the evidence exists but does not qualify (for example a stale, failed or invalid receipt).
Per-scenario results are in scenarioObligations, each with the
acceptedScopes it allows. Unit and integration tests linked alongside the
E2E tests do not block. A UI pattern scenario also accepts component tests;
see Component-scope proof.
7. Executable test symbols
Checks: each qualifying E2E test is linked to executable test code with
executable_for.
passed: every qualifying test has executable code linked.missing: a test has noexecutable_forlink;missingTestslists it.blocked: there are no passing E2E tests to check.
8. Production symbols
Checks: the production symbols that implement the requirement are covered
by the passing E2E tests (covered_by).
passed: every production symbol is covered.missing: no production symbol implements the requirement, or some lackcovered_bylinks;uncoveredSymbolslists them.blocked: there is no passing E2E evidence in the current snapshot (usually stale or missing receipts), so coverage cannot be evaluated.reasonsays so and points atkibi prove.
Type-shape symbols (interfaces, type aliases, enums) are listed under
structuralSymbols instead. One counts as covered when it is covered_by a
passing E2E test or a unit test with a current passing receipt; an authored
status: passing on the unit test is not enough. Without that receipt the
symbol is in uncoveredSymbols with the reason
structural_unit_receipt_not_current, and kibi prove on the unit test (or
kibi prove --stale) clears it.
explanations[] gives each symbol a rollup reason and, for each rejected
covered_by candidate, a primary rejection code plus optional secondary codes.
See Stage statuses, precisely.
9. Source coordinates
Checks: the requirement source and every linked test and production symbol carry exact published coordinates.
passed: all coordinates are present.missing: the requirement has no source, or a symbol has no coordinates;missingSymbolslists them.blocked: there are no linked symbols to check.
Component-scope proof for UI patterns
A scenario whose specifying requirements are all grounded only in the built-in UI pattern
predicates (ui_pattern, same_pattern, pattern_marker, each linked with
requires_predicate, and no requires_property or requires_rule) accepts tests with
verification_scope unit or integration as well as end_to_end. Such a test still
needs a valid, fresh, passing receipt, executable_for code, and covered_by links for the
production symbols it proves. Its obligation reports
acceptedScopes: [unit, integration, end_to_end]; every other scenario reports
[end_to_end].
The reason is cost, not leniency: a pattern ("this list is a line-and-dots timeline in
both variants") is fully observable by rendering one component in isolation, so demanding a
browser test per pattern would make E2E suites heavy for no extra evidence. The moment the
requirement also carries a layout fact such as ui_container, a strict property or a logic
rule, the scenario goes back to end-to-end proof. See ui-requirements.md.
Stage statuses, precisely
passed: the stage's obligations hold.missing: the evidence is absent. The stage names what is missing (missingTests,missingReceiptTests,uncoveredSymbols,missingSymbols, ...), andproofGapscarries the blocking gap code.unresolved: evidence exists but is not conclusive (for example unresolved statements in the inventory, or a stale receipt).blocked: the stage found a hard stop or has nothing to evaluate:contradictions: a conflicting requirement was found.scenarios: a linked success scenario is infeasible.executableSymbolsandproductionSymbols: there is no passing E2E evidence in the current snapshot (typically stale or missing receipts).productionSymbolssays so inreason;uncoveredSymbolsstill lists every remaining production symbol, and each explanation usesstage_blocked_no_passing_e2erather than implying the symbol itself lackscovered_by.sourceCoordinates: there are no linked symbols to check.
explanations[] on productionSymbols never changes status, reason,
uncoveredSymbols or proofStatus. A rejected covered_by candidate carries
the earliest disqualifying reason and optional secondaryReasons already
known from cheaper checks. Tests outside the scenario chain do not have their
receipts read.
A blocked stage never silently counts as passing. A blocked
contradictions stage makes proofStatus unresolved; any other blocked
stage does the same unless another stage is missing, in which case
proofStatus is missing.
Gaps, advisories, and status
proofGaps[]— blocking only. Every entry carries a code (e.g.missing_proof_receipt,missing_production_symbol_coverage), a priority, a stage name, and a suggested repair action.proofAdvisories[]— explicitly non-blocking context. Receipt-completeness codes (missing_proof_receipt,stale_proof_receipt,failed_proof_receipt,invalid_proof_receipt, andproof_contract_mismatch) remain blocking for every linked E2E obligation; they are never downgraded because another scenario has a passing receipt.proofStatus— the headline:tested— all stages passed (proofGapsis empty by invariant). Untilkibi.requirement-proof.v4this value wasproven; it was renamed because passing end-to-end tests are evidence, not proof.missing— at least one stage ismissing(evidence absent).unresolved— evidence is inconclusive or a stage isblocked.not_applicable— out of scope; see applicability above.
proofRepairs[]— ranked concrete recovery actions derived from blocking gaps.
Evidence levels
proofStatus says how far a requirement climbed the ladder. evidenceLevel
says how strong the evidence behind it is, and is never stronger than what
backs it:
| Level | Meaning | What earns it |
|---|---|---|
proved |
A checker established every claim of the requirement for every case and left certificates a second program can re-check | proofStatus: tested, and every applicable claim has a derived, code-scope binding: a fresh kibi.proof-receipt.v2 of a certificate-kind contract (exhaustive, typecheck, arithmetic, smt, rule, state_machine, regex, source) that names the claim in proves, whose certificate re-checks now against the obligation Kibi derives from the claim's fact (see Binding a certificate to claims) |
tested |
Passing runs on sampled cases, bound to the current code snapshot | proofStatus: tested |
asserted |
A person stands behind the statement, but nothing current checks it | origin.approved_by, or firm: firmness: firm, or no firmness and an origin other than agent |
unverified |
Stated, not approved, no evidence | Nothing: an agent wrote it and no person approved it |
Each row's evidence[] lists the entries that earned the level, each with
kind (certificate, e2e, human_intent), scope (code for what the tests exercised,
intent for what a person stated) and level; an e2e entry names its
passing tests, a certificate entry its proved tests and their proof
kinds, a human_intent entry its basis (approved or firm)
and, when there is one, the ref to the person's words. The coverage
summary counts rows per level under evidenceLevels.
From kibi.requirement-proof.v5 each row also judges its claims one by one.
claimEvidence[] has an entry per inventory claim with its claimKey,
status, whether it is applicable (a nonlogical context span is not), the
level it reaches and the certificate bindings behind it (derived,
attested or rejected, with the test, kind, scope and reason);
claimSummary counts the applicable claims per level (proved, attested,
tested, unresolved) and unprovedClaims lists those below proved. A
claim is proved only through a derived binding with scope code; an
attested binding (the fact has no derivation) and an intent-scope one (an
arithmetic claim decided from the facts alone) count as tested. The coverage
summary adds the claim totals under proofClaims.
Firmness and evidence level are separate axes. Firmness says how sure the
person is; the level says how strong the evidence is. A firm requirement at
asserted is the gap to close before relying on it.
Evidence floors
Each current requirement also has a floor: the weakest evidence level it
accepts. The evidence-floor rule of kibi check fails while a
requirement's level is below its floor, so a regression is caught on the
requirement itself and no shared snapshot file has to be kept in step.
| Floor | Where it comes from |
|---|---|
required_evidence: proved | tested | asserted | unverified |
Set on the requirement by its author |
tested |
No required_evidence and the requirement is firm (firmness: firm, or no firmness and an origin other than agent) |
tested |
No required_evidence, no firmness, and a person approved the requirement (origin.approved_by), from KB schema 15 |
unverified (no floor) |
No required_evidence, not firm and not approved, or approved with an explicit firmness: default or exploratory |
Coverage rows carry the floor as evidenceFloor with required, source
(explicit, firmness or approval) and status: met, below, or pending_reproof
when the floor is tested and every gap only says the receipts are older
than the code. A plain kibi check lets pending_reproof pass, so a local
check catches grounding, contradiction and link regressions without
re-proving first. kibi check --fresh-evidence judges receipts as they are
and also needs a clean proof snapshot; run it right after kibi prove, as CI
does. The coverage summary counts current requirements with a floor under
evidenceFloors (met, below, pendingReproof), the coverage table has a
Floor column, and kibi report and kibi signoff show each requirement's
floor and whether it is met.
Requirements outside proof scope (proof_exempt, superseded or not current)
have no floor. Lowering a floor is a visible edit to the requirement, so
reviewers see it; give the reason in the requirement when you lower one.
The schema 11 upgrade (kibi migrate --yes) records required_evidence: asserted on each current firm requirement that has no scenario verified by
an end-to-end test with a proof contract and a passing receipt, since it has
not reached tested; raise it once the requirement has an end-to-end proof.
Firm requirements whose proof has passed keep the tested floor, and the
migration lists them. Their proof can still have gaps it does not read, such
as a stale receipt or a production symbol without covered_by, so run
kibi check --rules evidence-floor after migrating and fix what it reports.
The schema 15 upgrade does the same for approved requirements: an agent's
requirement that a person approved and that states no firmness now needs
tested, so kibi migrate --yes records required_evidence: asserted on
each current one without a passing proof path and lists the ones that keep
the tested floor. Remove the pin once the requirement has an end-to-end
proof.
One more rule reads the same requirement proofs:
agent-requirement-unapproved-implemented (canonical, KB schema 15) blocks a
current priority: must requirement whose origin.kind is agent, that
production symbols implement, and that nobody has approved
(origin.approved_by) more than 14 days after it was written: shipped
behavior must not rest on a requirement no person confirmed. The age comes
from authored data only: origin.recorded_at (every kb_upsert write
records it), else a created_at the requirement's front matter states; a
requirement with neither counts as older. So does one whose date is not an
ISO 8601 date (yesterday, 2026-13-45) or lies more than a day in the
future: the finding names the unusable date, and its evidence carries
sinceProblem: not-a-date or future. kb_upsert refuses such a
created_at or origin.recorded_at on a requirement, so an agent cannot
keep its own requirement out of review with a date. The stored created_at
is not read, because sync fills a missing one with the sync time. The schema 15
upgrade (kibi migrate) lists the agent's must requirements this rule can
fail right away.
The schema 12 upgrade binds certificates to claims. kibi migrate --yes pins
proves on each certificate-kind contract whose test reaches exactly one
claim its kind can prove and lists the other contracts for review. Until a
contract names its claims, the blocking proof-contract-claims rule reports
it and its certificate proves nothing, so a requirement that reported
proved before reports tested until its claims are bound and re-proved with
kibi prove.
Knowledge-base certificates
Evidence levels describe requirements. The kb-consistency rule of
kibi check (and kb_check) covers the knowledge base itself: it states a few theorems about the facts current requirements
name, finds a certificate for each, and re-checks every certificate with a
separate checker (certificate_check.pl) that never searches and never loads
the code that found the certificate.
| Theorem | Certificate when it holds | Certificate when it fails |
|---|---|---|
properties_consistent |
A model per subject, property and scope: one value that satisfies every fact (a forbid fact counts as its negation) |
An irreducible core: facts that admit no value together, with one model per dropped fact to show each is needed |
predicates_consistent |
A truth value per ground atom that every fact agrees with | Two facts that assert and deny the same atom |
decisions_consistent |
One allow or deny per decision key | Two facts with opposite effective decisions |
rules_stratified |
A stratum number per rule predicate: a head is at least its body's stratum, and above it across not |
A negation cycle: a closed path of rule dependencies with a negated edge |
The property theorem is joint: facts that contradict only together, where
every pair still admits a value (for example int >= 0, <= 1, != 0,
!= 1), are a contradiction here even though the pairwise
domain-contradictions rule is silent. A core whose facts are never valid at
the same time is reported as property_unresolved, not as a contradiction.
A context the checker cannot compare (mixed value types or units, an
operator other than eq/neq on a non-numeric value, an unknown polarity)
is unresolved and needs no certificate; it never counts as consistent.
A re-verified contradiction (a core, two disagreeing facts or a negation
cycle) is a blocking kb-consistency violation, and so is a certificate the
checker rejects. An unresolved context is a non-blocking
kb-consistency-unresolved diagnostic. kibi check --staged runs the rule
too, so a commit that introduces a joint contradiction is blocked. Opposing
rule pairs and scenario feasibility are not certified yet; their own
kibi check rules still decide them. Certificates are regenerated on each
run and are not committed: kibi check --write-certificates <file> saves the
bundle, and kibi check --certificates <file> re-checks a saved one and
prints each theorem's verdict (proved, disproved or unresolved).
The numeric decision procedure, proved
Numeric contradictions, the arithmetic certificate kind and the property
theorem above all rest on intervals.pl, which folds every comparison on a
variable into an interval (open or closed ends, excluded points) or, for an
integer variable, an integer range, and asks whether it is empty. The Lean 4
project in proof/lean defines the same folds and
proves:
| Theorem | Statement |
|---|---|
realFeasible_iff |
The real fold is true exactly when some value satisfies every constraint |
intFeasible_iff |
The integer fold is true exactly when some integer satisfies every constraint, whatever (fractional) values they compare with |
satisfiable_iff |
numeric_constraints_satisfiable/2 is true exactly when one assignment, integral on the integer variables, satisfies every constraint |
entailed_iff |
numeric_constraint_entailed/3 is true exactly when every such assignment that satisfies the premises satisfies the claim |
The proofs hold for any dense linear order without endpoints that embeds the
integers with a floor and a ceiling, so for the rationals and the reals, and
rest on Lean's standard axioms only (CI fails on sorry). The rationals the
model's executable computes with are proved to be such an order, so the
theorems cover the executable itself. A proof about a
model says nothing about the shipped code unless the two compute the same
thing, so scripts/intervals-differential.ts decides 200000 generated cases
(rationals, integers and floats) with intervals.pl on the bundled
SWI-Prolog, with the Lean model's executable and with an independent
CLP(Q)/CLP(FD) oracle, and fails on any disagreement. intervals.pl rejects
a NaN or infinite bound with a domain error. Both run in CI (lean-intervals-proof) and as the proof of
REQ-kibi-intervals-verified.
Common failure patterns
| Symptom | Usual cause | Fix |
|---|---|---|
productionSymbols: blocked |
No passing E2E receipts in the current snapshot at all | Run kibi prove to refresh receipts, then re-check |
missing_symbol_coordinates gap |
Symbol has no coordinate entry; often granularity_reason missing so the coarse fallback was gated off |
kibi sync --refresh-symbol-coordinates reports failed ids and reasons; add symbol_role/granularity_reason where the reason says to |
| Requirement missing from proof reports entirely | Non-current status or supersession | Coverage --status not_applicable --by req lists it with the typed applicability reason |
passingE2e.scenarioObligations has a non-passed status |
A linked scenario has no E2E test or one of its E2E proof-bearing tests lacks qualifying evidence | Inspect the scenario's gaps, repair every listed receipt, and run kibi prove |
Related surfaces
kibi coverage --by req --status missing(also:tested,unresolved,not_applicable) — enumerate exactly one proof-status slice; N/A rows include their applicability reason. The summary always reflects the whole KB.kibi proof inspect— detect test infrastructure, propose a proof integration, and return the reviewed plan that writes.kb/proof/integrations.jsonthroughkb_apply_plan.kibi proof explain REQ-*/kibi proof explain SYM-*— project the same Proof, labelingrequired_proofs,executable_for, andcovered_byseparately.kibi check --rules evidence-floor— fail every current requirement whose evidence level is below its floor (see Evidence floors). Without--fresh-evidence, gaps that only reflect stale evidence (stale_proof_receipt,proof_contract_mismatch, and production coverage whose symbols all have a qualifying candidate or a scenario-backed E2E candidate rejected solely for stale evidence) count as pending re-proof, so a local run catches semantic regressions without re-proving. Unit or integration scope, missing receipts, invalid evidence, and scenario-chain failures stay blocking.bun run proof:gate(this repository) — the integrity rules plusevidence-floor, as the pre-push hook and the KB merge workflow run them; CI runs it again with--fresh-evidenceafterkibi prove --all.bun run proof:replay(this repository) — replay the CI proof job's gate steps from.github/workflows/proof.ymlin a clean clone of the committed HEAD, outside the repository tree, and stop at the first failing step.kibi proof compact— one-off: drop receipts that can no longer decide proof from a store written beforekibi provecompacted histories on ingest. Coverage decisions are unchanged.kibi proof prune --keep 1— keep only the newest receipt per test, whether or not older ones still decide proof.kibi proof migrate-legacy— remove legacyverification_receiptsblocks from tests that already carry aproof_contract.docs/proving-requirements.md— the runner-neutral proof pipeline: contracts, integrations, artifacts, and howkibi proveproduces receipts.
Before pushing, run kibi sync with the project-local CLI (it keeps the
gitignored symbol coordinates current), commit, and run bun run proof:prepush.
If committing leaves the KB stale, sync it again before the check. This checks the
committed manifests, publish metadata (including exact GitHub owner casing),
and evidence floors (scripts/proof-gate.sh) using the project-local CLI. When
proof contracts, coverage links, or proof tooling change, also run
bun run proof:replay to reproduce the full CI gate on committed HEAD.
The repository's pre-commit framework configuration includes a pre-push stage
for the fast gate. Maintainers using that framework enable it with
pre-commit install --hook-type pre-push; tracking the configuration alone does
not install the hook. The fast gate checks the current clean checkout; use the
corresponding checkout when pushing another branch or an explicit ref.