4.0 KiB
4.0 KiB
T4.4 — Retention ordering guard
| Field | Value |
|---|---|
| Phase | P4 — Verification |
| Size | S — under 1 day |
| Status | Not started |
| Flags | — |
| Spec | inlined below |
| Blocks | — |
Goal
Reduction must not outrun verification or grading. Eligibility is grading has terminated, not grading succeeded.
Facts (inlined — no spec read needed)
- Eligible states for reduction:
Graded,Ungraded, orArchived. - Never a step-level finish timestamp. A step can finish, be reduced, and then run-level verification finds nothing left to check.
Ungradedbelongs in that set, and the tighter-lookingGraded-only rule is the one that gets written. A run that never gets a score — a novelTaskIdwith no reference, a tournament group that closed without it, a tenant over its grading ceiling — is finished. Gating onGradedalone leaves it irreducible forever.- The tenants that hit this are the low-volume ones and the cost-capped ones: the two populations least able to absorb unbounded storage, and the two least likely to have anyone watching for it.
Graded-only passes every other test in this phase and strands storage only in production. So theUngraded-is-reducible case must be asserted directly.
Steps
- Write
fn is_reducible(run_state) -> boolmatching exactlyGraded | Ungraded | Archived. Exhaustive match, no_arm. - Make reduction (T8.4) call it as a precondition and reject — a typed error naming the current state — rather than skipping silently. A silent skip is indistinguishable from success and leaves no trace to investigate.
- Delete any path that reads a step-level finish time for retention decisions.
- Wire the rejection into metrics so refusals are countable.
- Test both halves: a run resting in
Gradingis rejected; a run terminal inUngradedis reduced.
Acceptance
- A run still resting in
Gradingis not reducible, and attempting it is a rejected operation rather than a silent skip. - A run that reached terminal
Ungradedis reducible — asserted directly.
Verify
Harness: runs parked in each lifecycle state, plus the reduction entry point from T8.4 (or a stub of it that calls the same guard).
Integration test — tests/it_retention_guard.rs:
- Table-driven over every run state. For each, call reduce and assert:
Graded,Ungraded,Archived→ permitted;- every other state, including
GradingandVerifying→ rejected with a typed error naming the current state.
- Assert the rejection is an
Err, notOk(()). A silent skip is indistinguishable from success and leaves nothing to investigate. - Assert
Ungradedis reducible directly, with a run that reachedUngraded { NoReference }. This is the case aGraded-only implementation fails, and it is the only assertion that catches it. - Assert no code path reads a step-level finish timestamp for retention —
grep, plus a test where a step finished long ago while the run is still
Verifying: reduction must be refused. - Assert refusals increment a metric, so a stuck reducer is visible.
Command: cargo test -p retention guard
False pass:
- Testing only the
Grading-is-refused half.if state == Gradedpasses that, passes every other test in P4, and strands storage in production for exactly the low-volume and cost-capped tenants least able to absorb it. Step 3 is the whole point of this task's acceptance criterion. - A table covering only the states someone remembered. Enumerate the run-state
enum exhaustively with no
_arm so a new state forces a decision.
Traps
if state == Graded— passes this phase, strands storage in production.- Returning
Ok(())on ineligible runs "because there is nothing to do". Then a stuck reducer looks healthy.
Background (not required to do this task): rust-agentic-sys.md §5.2, §10.3 · rust-agentic-task.md