risk-nexus/tools/register_check.py
tegwick d5a3953f2e RISK-WP-0001 T01-T06,T08: the four instruments, the index, and the first grading
Severity (impact x likelihood, fidelity modifier for controls that lie,
headline-vs-constraint, build-mode double grade, the floor), disclosure
(publish/embargoed/restricted, and the build-mode deferral re-taken and
narrowed with RISK-F-0001 in hand), escalation (the five INTENT triggers
settled plus an ordering-hazard trigger the RISK-F-0002 case forced;
proposed, awaiting the custodian), review (intervals, what a review is,
what missing one produces, the production re-score).

Then applied: RISK-F-0001 critical/embargoed/escalated, RISK-F-0002
medium with a high constraint on RISK-F-0001's remediation, filed as a
peer and escalated only on the ordering, RISK-F-0003 high/embargoed/no
escalation. No unset field remains.

REGISTER.md is generated; make check reports overdue, stalled, ungraded
and unanswered escalations without changing anything.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 23:29:39 +02:00

96 lines
3.2 KiB
Python

#!/usr/bin/env python3
"""Report what the register is not saying out loud.
RISK-WP-0001-T08. Report only: it writes nothing, changes no field,
escalates nothing on its own, and blocks nothing. A human or the custodian
acts on the output. Exit code is 0 unless a finding cannot be read.
"""
from __future__ import annotations
import datetime as dt
import register_lib as lib
TODAY = dt.date.today()
def date(value):
if isinstance(value, dt.date):
return value
if isinstance(value, str) and value not in ("", "unset"):
return dt.date.fromisoformat(value)
return None
def main() -> int:
fs = [f for f in lib.findings() if f.get("status") == "open"]
lines: list[str] = []
def section(title: str, rows: list[str], quiet: str) -> None:
lines.append(f"{title}:")
if rows:
lines.extend(f" {r}" for r in rows)
else:
lines.append(f" {quiet}")
lines.append("")
ungraded = [
f"{f['id']}{', '.join(k for k in lib.GRADED_FIELDS if str(f.get(k, 'unset')) == 'unset')}"
for f in fs
if any(str(f.get(k, "unset")) == "unset" for k in lib.GRADED_FIELDS)
]
section("Ungraded", ungraded, "none — every open finding carries a grade")
overdue = []
for f in fs:
due = date(f.get("review_by"))
if due and TODAY > due:
overdue.append(f"{f['id']} — review was due {due} ({(TODAY - due).days}d ago)")
section("Overdue review", overdue, "none")
stale = []
for f in fs:
seen = date(f.get("last_reviewed"))
interval = lib.REVIEW_INTERVAL_DAYS.get(f.get("severity"))
if not seen or not interval or f.get("severity") == "low":
continue
limit = seen + dt.timedelta(days=interval * lib.STALE_MULTIPLIER)
if TODAY > limit:
stale.append(
f"{f['id']} ({f.get('severity')}) — untouched since {seen}; "
f"escalation trigger 5 fires (limit was {limit})"
)
section("Stalled — escalation trigger 5", stale, "none")
embargo = []
for f in fs:
if f.get("disclosure") != "embargoed":
continue
due = date(f.get("embargo_review"))
if due and TODAY > due:
embargo.append(
f"{f['id']} — embargo not re-decided since {due}; lifts when: {f.get('embargo_condition')}"
)
section("Embargo overdue for re-decision", embargo, "none")
esc = [
f"{f['id']} — trigger {f.get('escalation_trigger')}, {f.get('escalation_status')}"
for f in fs
if f.get("escalation") == "required" and f.get("escalation_status") != "answered"
]
section("Escalations awaiting the operator", esc, "none")
rescore = [
f"{f['id']}{f.get('severity')} now, {f.get('severity_at_production')} at production"
for f in fs
if f.get("production_rescore")
]
section("Owed at the production transition", rescore, "none — no finding is graded lower for build mode")
print(f"Register check — {TODAY}\n{len(fs)} open finding(s)\n")
print("\n".join(lines).rstrip())
return 0
if __name__ == "__main__":
raise SystemExit(main())