Files
poimen/tasks/T4.4-retention-ordering-guard.md
T

92 lines
4.0 KiB
Markdown
Raw Normal View History

2026-08-17 23:05:20 -07:00
# 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`, or `Archived`**.
- **Never a step-level finish timestamp.** A step can finish, be reduced, and
then run-level verification finds nothing left to check.
- `Ungraded` belongs in that set, and the tighter-looking `Graded`-only rule is
the one that gets written. A run that never gets a score — a novel `TaskId`
with no reference, a tournament group that closed without it, a tenant over its
grading ceiling — is **finished**. Gating on `Graded` alone 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 the `Ungraded`-is-reducible case must be asserted directly.
## Steps
1. Write `fn is_reducible(run_state) -> bool` matching exactly
`Graded | Ungraded | Archived`. Exhaustive match, no `_` arm.
2. 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.
3. Delete any path that reads a step-level finish time for retention decisions.
4. Wire the rejection into metrics so refusals are countable.
5. Test both halves: a run resting in `Grading` is rejected; a run terminal in
`Ungraded` is reduced.
## Acceptance
- A run still resting in `Grading` is **not reducible**, and attempting it is a
**rejected operation** rather than a silent skip.
- A run that reached terminal `Ungraded` **is** 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`:
1. Table-driven over **every** run state. For each, call reduce and assert:
- `Graded`, `Ungraded`, `Archived`**permitted**;
- every other state, including `Grading` and `Verifying` → **rejected with a
typed error naming the current state**.
2. Assert the rejection is an `Err`, not `Ok(())`. A silent skip is
indistinguishable from success and leaves nothing to investigate.
3. **Assert `Ungraded` is reducible directly**, with a run that reached
`Ungraded { NoReference }`. This is the case a `Graded`-only implementation
fails, and it is the only assertion that catches it.
4. 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.
5. 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 == Graded` passes 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](../../../rust-agentic-sys.md) §5.2, §10.3 ·
[rust-agentic-task.md](../../../rust-agentic-task.md)