WARDEN-WP-0033-T05: split the stale cadences, and record how a blocker was verified
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

The 90-day --stale-days default on `warden route gaps` was not a loose threshold,
it was an inert one: the delegation register was created 2026-08-15, so it could
not have fired before November. It was inherited from the catalog pointer cadence
and applied to a claim with a completely different half-life.

Two changes. DEFAULT_BLOCKER_STALE_DAYS = 14 now governs interim blockers, while
DEFAULT_STALE_DAYS = 90 keeps governing pointer freshness -- "is this the right
owner and page" is quarterly, "has the owner answered" is not. 14 is calibrated
on blockers that actually cost something: ten days for the secrets-engine lanes,
one for RISK-F-0001, roughly fifty for FLEX-WP-0007.

The second change matters more. `reviewed` records when someone touched an entry,
which is indistinguishable from re-checking it -- six lanes read as freshly
reviewed today because I typed in them. `verified:` now says how the claim was
established, and asked-and-waiting explicitly does NOT count: that is the state
the secrets-engine blocker sat in for ten days while looking current. A lane in
that state is stale at zero days old, and key-cape-oidc-login proves it works.

8 of 14 interim lanes are honestly marked unverified rather than given a fresh
date they did not earn.

--fail-on-stale exits 3 for a cron or gate. No CI test on age: a date-triggered
failure breaks the build for whoever commits next instead of whoever owns the
blocker. The CI test is structural -- every interim lane must record how it was
verified -- so it fails on the commit that introduces the omission.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-08-21 13:26:10 +02:00
parent a565e62b2f
commit 55f0f47a02
8 changed files with 335 additions and 24 deletions

View file

@ -184,7 +184,56 @@ owner repo's shipped path.
| **On canon change** | When net-kingdom security docs change, review affected `canon_ref` entries immediately |
| **On owner ship** | When an owning repo merges a new OpenBao path or playbook, promote `draft``active` and bump `reviewed` |
| **On agent confusion** | If `warden route find` misses a common query, add `need_keywords` or a playbook — do not restate owner procedure in the catalog |
| **On interim review** | Run `warden route gaps` — re-check each `blocked_on` against the intended owner; flip to `native` when their front door exists |
| **Fortnightly** (default 14 days) | Run `warden route gaps` — re-check each `blocked_on` against the intended owner; flip to `native` when their front door exists |
### Two cadences, because they are two different claims
A catalog pointer and an interim blocker both carry a `reviewed:` date, and for a
while they shared one 90-day threshold. They should not.
| Claim | Question | Default | Where |
| --- | --- | --- | --- |
| Pointer freshness | Is this still the right owner and page? | **90 days** | `warden route list --stale` |
| Interim blocker | Has the intended owner answered / can they front this yet? | **14 days** | `warden route gaps` |
A pointer genuinely is a quarterly question. A blocker is not: it is a claim
about another repo's state at a date, and this estate invalidates those in days.
`RISK-F-0001` invalidated an ops-warden blocker in one. The `secrets-engine`
lanes carried one for ten while it was answerable from that repo's source the
whole time. A `FLEX-WP-0007` blocker was repeated by two repos for about seven
weeks after that workplan read `finished`.
Sharing 90 days did not make the blocker check loose, it made it **inert**: the
delegation register was created 2026-08-15, so the threshold could not have fired
before November and never had.
### Reviewed is not verified
The more important half. A `reviewed:` date records when someone last *touched*
the entry, which looks identical to re-checking it. So every interim lane also
carries `verified:`, saying how the claim was established:
| Value | Meaning | Counts as verification |
| --- | --- | --- |
| `owner-confirmed` | the intended owner stated the blocker's status | **yes** |
| `source-read` | re-derived from the owner's code, canon, or a CCR | **yes** |
| `asked-and-waiting` | a question is outstanding | **no** |
| `unverified` | carried forward without a check | **no** |
`asked-and-waiting` deliberately does not reset the clock. A lane asked today
reads as reviewed today, and that is precisely how a blocker stays fresh-looking
while nobody answers it. `warden route gaps` flags such a lane as stale at zero
days old.
**Re-check the blocker; do not bump the date.** Bumping `reviewed` without
re-establishing the claim is the failure this section exists to prevent, and it
is cheap to avoid — most of these are answerable by reading the owner's repo.
```bash
warden route gaps # 14-day blocker cadence, plus unverified lanes
warden route gaps --stale-days 30 # looser threshold
warden route gaps --fail-on-stale # exit 3 — for a cron job or a gate
```
### Stale check (operators and agents)