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:
parent
8b204d0411
commit
42bbf5d2dc
17 changed files with 429 additions and 148 deletions
|
|
@ -22,14 +22,19 @@ def date(value) -> dt.date | None:
|
|||
return None
|
||||
|
||||
|
||||
def review_cell(f: dict) -> str:
|
||||
due = date(f.get("review_by"))
|
||||
if due is None:
|
||||
def check_cell(f: dict) -> str:
|
||||
when = lib.moment(f.get("next_check"))
|
||||
if when is None:
|
||||
return "—"
|
||||
late = (TODAY - due).days
|
||||
if late > 0:
|
||||
return f"**{due} (overdue {late}d)**"
|
||||
return str(due)
|
||||
if lib.now() >= when:
|
||||
return "**due**"
|
||||
return when.strftime("%Y-%m-%d %H:%MZ")
|
||||
|
||||
|
||||
def cadence_cell(f: dict) -> str:
|
||||
rung = f.get("cadence", "instant")
|
||||
streak = f.get("clean_streak", 0)
|
||||
return f"{rung} ({streak})"
|
||||
|
||||
|
||||
def sev_cell(f: dict) -> str:
|
||||
|
|
@ -50,23 +55,23 @@ def esc_cell(f: dict) -> str:
|
|||
def render() -> str:
|
||||
fs = lib.findings()
|
||||
ns = lib.notes()
|
||||
open_fs = [f for f in fs if f.get("status") == "open"]
|
||||
open_fs = [f for f in fs if lib.watched(f.get("status"))]
|
||||
|
||||
out = [
|
||||
"# Register",
|
||||
"",
|
||||
f"Generated by `tools/register_index.py` from `findings/`. Do not edit by hand. Last built {TODAY}.",
|
||||
"",
|
||||
f"{len(open_fs)} open of {len(fs)} findings; {len(ns)} notes below the floor.",
|
||||
f"{len(open_fs)} live of {len(fs)} findings; {len(ns)} notes below the floor.",
|
||||
"",
|
||||
"## Findings",
|
||||
"",
|
||||
"| ID | Finding | System | Severity | Disclosure | Escalation | Fix owner | Status | Review by |",
|
||||
"| --- | --- | --- | --- | --- | --- | --- | --- | --- |",
|
||||
"| ID | Finding | System | Severity | Disclosure | Escalation | Fix owner | Status | Cadence | Next check |",
|
||||
"| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |",
|
||||
]
|
||||
for f in fs:
|
||||
out.append(
|
||||
"| [{id}]({path}) | {title} | {system} | {sev} | {disc} | {esc} | {owner} | {status} | {review} |".format(
|
||||
"| [{id}]({path}) | {title} | {system} | {sev} | {disc} | {esc} | {owner} | {status} | {cadence} | {check} |".format(
|
||||
id=f["id"],
|
||||
path=f["_path"].relative_to(lib.REPO),
|
||||
title=str(f.get("title", "")).strip('"'),
|
||||
|
|
@ -76,7 +81,8 @@ def render() -> str:
|
|||
esc=esc_cell(f),
|
||||
owner=f.get("fix_owner", "—"),
|
||||
status=f.get("status", "—"),
|
||||
review=review_cell(f),
|
||||
cadence=cadence_cell(f),
|
||||
check=check_cell(f),
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -112,7 +118,9 @@ def render() -> str:
|
|||
|
||||
out += ["", "## How to read this", "",
|
||||
"Severity is `docs/method/severity.md`; disclosure `docs/method/disclosure.md`;",
|
||||
"escalation `docs/method/escalation.md`; review dates `docs/method/review.md`.",
|
||||
"escalation `docs/method/escalation.md`; the check cadence `docs/method/review.md`.",
|
||||
"Cadence is the ladder rung and the count of consecutive clean checks — a finding at `1q (9)`",
|
||||
"has held still for a long time; one at `instant (0)` moved recently. Anything wrong resets it.",
|
||||
"A constraint may be graded higher than the finding that carries it — read both.",
|
||||
""]
|
||||
return "\n".join(out)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue