I2348 — A gate's result is reused only for the exact inputs it judged, and a skipped gate carries the proof that nothing it reads changed
Join the path-class gates and their implications with the affected closure, a cache key, a proof for each skipped gate, integrity of a remote against a local cache, concurrency and precise invalidation, so that a stale verification is never reused.
BLOCKED wave 1 · p2 · implementation profile · parallel safe
Blocked. This issue cannot start until I2350 is done. The status is derived from that, not declared.
Objective
Join the path-class gates and their implications with the affected closure, a cache key, a proof for each skipped gate, integrity of a remote against a local cache, concurrency and precise invalidation, so that a stale verification is never reused.
Why
The plan already skips gates a change cannot affect, by pattern. It keeps no record that would let a later reader, or a merge commit, check that the skip was right, and every refresh of a branch runs the whole selected suite again for inputs it judged an hour before. Source: autopilot prompts/05-performance.md Issue 3 'Reusable CI selection'. Revived on 2026-10-18 from the delivery-packs rescue sweep into ci-critical-path, because its milestone derive-does-only-what-a-change-requires never landed; its dependency on I2324 was dropped, because no record of I2324 exists on master.
Current state
scripts/ci-plan selects gates from path classes in .ai/repo/ci/gates.yaml, escalates an unmatched path to the full plan, and the verdict accepts a skipped gate the plan left out (scripts/ci/verdict). Caches for the toolchain and the built executable are keyed in the workflow (docs/CI.md). No gate result is keyed by its inputs.
Desired state
A gate declares what it reads, as the derive's nodes do. A result is recorded with the digest of those inputs and the gate's own version, as evidence. The plan may substitute a recorded pass only when the digest matches exactly, and it records the substitution with the run it reuses. A skipped gate's row in the verdict names the unchanged digest. The required status and the branch rules are obeyed as before.
Scope
- scripts/ci-plan
- scripts/ci/run-plan
- scripts/ci/verdict
- .ai/repo/ci/gates.yaml
- .github/workflows/validate.yml
- scripts/ci/evidence-collect
- docs/CI.md
Out of scope
- Skipping a gate the branch rules require to report.
- Reusing a result across a changed gate script.
Dependencies
What waits on this
Acceptance criteria
- A gate whose declared inputs are unchanged is satisfied by its recorded pass, and the verdict shows which run it reused
- Changing one declared input, or the gate's own script, makes the gate run
- A recorded failure is never reused as a pass, and a result older than its inputs is refused
- A gate with no declaration of what it reads is never reused
Validation
- bin/majordomus plan validate
- scripts/ci-plan --check
- MJ_TEST_JOBS=4 bash test/run.sh 26_ci_wiring 94_ci_plan <the cases this issue adds>
Evidence required
- gate_result_reuse_case
- stale_result_refused_case
Evidence
None recorded. Every token above needs a command or an artifact behind it before this issue can be completed; narrative is refused.
Timeline
- started
- —
- verified
- —
- completed
- —
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/I2348.yaml. Read it back with majordomus plan show I2348.