I1948 — Evidence is judged at the presented revision, by one freshness function
Write the freshness table, the presented revision, containment and aggregation of ADR 0087 once each (decisions 4, 5, 7 and 8), so that evidence show can judge the checked-out commit by the ledger committed in it and every verdict comes from one derivation.
DONE wave 0 · p1 · implementation profile · runs alone
Objective
Write the freshness table, the presented revision, containment and aggregation of ADR 0087 once each (decisions 4, 5, 7 and 8), so that evidence show can judge the checked-out commit by the ledger committed in it and every verdict comes from one derivation.
Why
The rules module holds a second copy of the freshness derivation, a skip reads failing, a plain maximum hides a failure behind an absence, and the corpus verdict proposed in PR #597 says proven over rules whose inputs are merely unchanged. No command judges a commit rather than the working tree.
Current state
evidence/mod.rs and rules/mod.rs each derive freshness; containment lives privately in the delivery module of PR #600; PR #597 adds RulesVerdict, which accepts inputs_unchanged as proven. This slice is stacked on PR #597 (fix/a-verdict-says-what-was-proven), with its pull request into that branch.
Desired state
evidence::freshness implements ADR 0087's freshness table and one aggregate() with failure precedence; `evidence show --presented <rev> --presented-tree <state>` judges the checked-out commit by its committed ledger and reads the working ledger's uncommitted executions through the monotone rule; containment lives in git/mod.rs; the rules module's copy is gone while evidence::changed_since stays byte-for-byte; RulesVerdict is proven only when every blocking rule is proven; ProofState::token() maps each wire word to its design token.
Scope
- apps/majordomus-cli/src/git/mod.rs
- apps/majordomus-cli/src/evidence/mod.rs
- apps/majordomus-cli/src/evidence/freshness.rs
- apps/majordomus-cli/src/evidence/ledger.rs
- apps/majordomus-cli/src/rules/mod.rs
- apps/majordomus-cli/src/rules/tests.rs
- apps/majordomus-cli/src/capability/builtin/evidence.rs
- apps/majordomus-cli/src/cli.rs
- apps/majordomus-cli/src/commands/evidence.rs
- docs/EVIDENCE.md
- docs/DOCTRINE.md
- docs/HOW_IT_WORKS.md
- docs/CONCEPTS.md
- docs/CLAIMS.yaml
- docs/claims
- .ai/repo/features/evidence.md
- test/cases/502_evidence_is_judged_at_the_presented_revision.sh
- test/cases/133_rule_graph.sh
Out of scope
- apps/majordomus-cli/src/environment: the entry preflight is I1965's
- Changing evidence::changed_since, which PR #578 calls from the preflight
- Adding a field to Execution or RunRef
- A version bump
Dependencies
None. This issue is a root of the graph.
What waits on this
- I1951READY Evidence runs are typed, and a recording carries what its run measured
- I1952DONE Evidence subjects are derived once, in Rust
- I1965READY The entry preflight reads the one verdict
Acceptance criteria
- Each row of ADR 0087's freshness table is reached by a case assertion, and only row 10 yields proven
- evidence show --presented refuses a revision that is not the checked-out commit, reads the ledger committed in it, and caps proven at stale over a clean failing run the working ledger holds uncommitted
- A skip reads not_run with its reason, never failing and never proven
- aggregate() returns failing whenever any part fails, before any absence
- RulesVerdict is proven only when every blocking rule is proven
- The rules module's own freshness derivation is removed, and evidence::changed_since is unchanged byte-for-byte
- Merging with PR #578 in either order produces no conflict
Validation
- bash test/run.sh 502_evidence_is_judged_at_the_presented_revision
- bash test/run.sh 133_rule_graph
- bash test/run.sh 124_evidence
- cargo test --workspace --all-features
Evidence required
- one_freshness_function
- presented_revision_judged
- failure_precedes_absence
Evidence
| covers | type | command | result | at commit |
|---|---|---|---|---|
| presented_revision_judged | test | bash test/run.sh 502_evidence_is_judged_at_the_presented_revision | ok at 4090b2b8ae: evidence show --presented HEAD judges from the committed ledger, is capped at stale by an uncommitted clean failure, and refuses another revision with exit 13 | 4090b2b |
| failure_precedes_absence | test | bash test/run.sh 502_evidence_is_judged_at_the_presented_revision | ok at 4090b2b8ae: a blocking rule with one failing and one skipped test reads failing in rules show, rules report and the corpus verdict | 4090b2b |
| one_freshness_function | test | bash test/run.sh 133_rule_graph && bash test/run.sh 124_evidence | both ok at 4090b2b8ae: rules and claims are judged by evidence::freshness, and the corpus verdict reads unproven over an inputs_unchanged rule and proven only over proven ones; the workspace tests were not run locally: CI validate run 37744906831 on a tree identical to 4090b2b8ae passed lib (2448) and doc tests (1872) | 4090b2b |
Risk
Stacked on PR #597, it lands with #597: merged into it, or retargeted to master after #597 lands. If scripts/ci/version-matches-surface asks for a bump, the slice stops and reports; it never bumps.
Timeline
- started
- 2026-10-08T10:50:08Z
- verified
- 2026-10-08T10:52:39Z
- completed
- 2026-10-08T10:52:43Z
Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.
Canonical record: .ai/repo/project/issues/I1948.yaml. Read it back with majordomus plan show I1948.