Adaptive check cadence: the interval is earned, not assigned

Operator ruling 2026-08-20. Severity no longer sets the review interval.
A check that comes back clean climbs one rung — instant, 1h, 8h, 24h,
48h, 96h, 7d, 14d, 1mo, 1q — and anything wrong drops straight back to
instant. A quarter is the ceiling. The operator may defer an instant
finding to a stated date; that is the only other way off the bottom rung.

The rung is the point: it says how stable the estate has been on that
matter, which is information severity does not carry. Volatile things get
attention automatically; quiet things stop consuming it; neither
judgement has to be made by a person who might be busy.

Escalation trigger 5 rebased onto the ladder — fourteen days at the
bottom rung, whether that is failing checks or no checks.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-08-20 07:43:51 +02:00
parent 8b204d0411
commit 42bbf5d2dc
17 changed files with 429 additions and 148 deletions

View file

@ -14,20 +14,75 @@ review_interval: 180d
`INTENT.md`: a finding that has sat untouched past its review date is itself a
finding. Silence is not resolution. This document makes that operable.
## Intervals
## The cadence ladder
Set from the headline severity at grading time, and reset at each review.
Operator ruling, 2026-08-20. **Intervals are not set by severity. They are
earned by outcomes.**
| Severity | Interval | Stale (2×, escalation trigger 5) |
| --- | --- | --- |
| `critical` | 7 days | 14 days |
| `high` | 30 days | 60 days |
| `medium` | 90 days | 180 days |
| `low` | 180 days | — (ages out through review) |
A finding is checked, and the check comes back clean or it does not. Clean
climbs one rung. Anything wrong drops straight back to the bottom.
A finding graded `critical` is being looked at weekly or it is not being
managed. If weekly is unbearable, the honest response is to re-grade it, not
to let the date slide.
| Rung | Wait before the next check |
| --- | --- |
| `instant` | now, and again immediately until a check comes back clean |
| `1h` | one hour |
| `8h` | eight hours |
| `24h` | one day |
| `48h` | two days |
| `96h` | four days |
| `7d` | one week |
| `14d` | two weeks |
| `1mo` | one month |
| `1q` | one quarter — **the ceiling; nothing is ever checked less often than this** |
Two rules and one escape:
- **Climb on clean.** One rung per clean check, never two.
- **Reset on anything wrong.** Not a slide down one rung — straight to
`instant`. A matter that has just moved has no track record, whatever it had
before.
- **The operator may defer.** An `instant` finding can be deferred to a stated
future date by explicit operator decision, recorded as `deferred_to`. That is
the only way out of the bottom rung other than a clean check, and it is a
decision with a name on it rather than a check quietly not happening.
### The rung is the signal
This is the point of the design, not a side effect. **The cadence a finding
sits on is a statement about how stable the estate has been on that matter.**
`RISK-F-0002` at `1q (9)` says the signing gate has been examined ten times
over three months and nothing has moved. `RISK-F-0002` at `instant (0)` says
something changed within the day. The number carries information that no
severity does — severity says how bad it would be, the rung says how settled
it is — and the two are independent. A `low` finding that keeps resetting is
telling you something a `critical` one at the ceiling is not.
It is also self-correcting in the direction that matters. Anything volatile
gets attention often, automatically, without anyone deciding it deserves it;
anything genuinely quiet stops consuming attention, without anyone deciding to
stop looking. Neither of those judgements has to be made by a person who might
be wrong or busy.
### What "clean" means
A check is **clean** when nothing about the assessment moved: the grade still
holds, every stated blocker is still true, the fix state is unchanged, the
disclosure state is still right, and no new fact has arrived.
A check is **not clean** when any of those moved — including when they moved in
a good direction. `RISK-F-0001` being fixed is not a clean check; it is a large
change, and the next check comes immediately. Good news resets the ladder
exactly like bad news, because the ladder measures stillness, not health.
### Starting position
Every finding starts at `instant`. A register with no check history has no
grounds to wait, and the first clean check is what buys the first hour.
The whole register sat at `instant (0)` on 2026-08-20, which is correct and
temporary: everything in it had been graded, re-graded or ruled on within the
preceding day.
## What a review is
@ -58,18 +113,19 @@ and `review_by` is pushed by one interval. A review that changes nothing still
writes the line — "checked, nothing moved" is the evidence that the silence was
observed rather than accidental.
## When a review is missed
## When a check is missed
Overdue is not a status change on the finding. It is a fact about *this repo*,
and it surfaces in three places:
- `make check` reports it (`tools/register_check.py`), always, unconditionally.
- `REGISTER.md` shows the finding as overdue with the day count.
- At **twice** the interval, escalation trigger 5 fires for `critical`,
`high` and `medium`. That is the point at which the register's own silence
reaches the operator.
- `make check` lists it under "Checks due", with how late it is and which rung
it is on.
- `REGISTER.md` shows the next check as **due**.
- A finding sitting at the bottom rung for more than fourteen days with no
movement fires escalation trigger 5. Bottom rung means it keeps failing or
keeps being skipped; fourteen days of that is a stall whichever it is.
The register does not auto-escalate severity for lateness, and it does not
The register does not auto-escalate severity for lateness and does not
auto-close anything. Both would be the register lying about its own state to
make a number look better.
@ -90,13 +146,17 @@ obligation is visible rather than discovered on the day.
## Front-matter this adds
```yaml
last_reviewed: "2026-08-19"
review_by: "2026-08-26"
last_checked: "2026-08-20T05:40:00Z"
next_check: "2026-08-20T06:40:00Z"
cadence: 1h
clean_streak: 1
production_rescore: true
deferred_to: "" # only by explicit operator decision
```
`review_by` is what the nag reads. It is a date, never a duration, so that
nothing has to recompute an interval to know whether a finding is late.
`next_check` is what the nag reads, and it is an absolute moment rather than a
duration, so nothing has to recompute an interval to know whether a check is
late. The rungs run in hours as well as days, so it carries a time.
## Closing a finding
@ -106,10 +166,20 @@ A finding leaves `open` for exactly one of:
something concrete rather than been told. Publication follows if the
disclosure state was `embargoed`.
- `accepted` — the estate is deliberately carrying it. Requires who accepted
it, why, and a re-review date. `accepted` is not `closed`; it keeps a review
interval forever.
it, why, and what ends the acceptance. `accepted` is not closed: it stays on
the ladder forever, and it climbs like anything else.
- `mitigated` — the live gap is closed but the finding is not. `RISK-F-0003` is
the case: the boundary now fires, and the omission that let it not fire is
still there. Stays watched.
- `withdrawn` — the finding was wrong, or the defect never existed. Say which.
**Any status the tooling does not recognise keeps the finding watched, and the
unrecognised word is reported.** `RISK-F-0003` arrived as `mitigated` on
2026-08-20, before that word existed here, and dropped silently out of
`make check` — a finding vanishing from the nag because someone used an
unfamiliar word is precisely the failure this register exists to prevent. The
tooling now fails loud instead of quiet.
There is no `stale`, no `wontfix` and no silent expiry. A finding that nobody
will fix and nobody will accept stays `open` and keeps arriving in the nag,
because that is the true state.