The register had nine waits in four days, one four hops deep: F-0003's embargo waited on F-0009, which waited on railiance-platform, which waited on live OpenBao verification, which waited on a credential nobody has. No single link was wrong, which is why it needed a rule. docs/method/dependencies.md: the register never waits to decide, it decides and revises. Every wait carries who, what, since, what it would change, what happens if nobody answers, and the date that default applies. Depth one — a record never waits on a record that is itself waiting. Defaults are dates and are pessimistic: silence costs the grade the evidence supports rather than buying a softer one, and owners are told the default in advance because a default nobody was warned about is an ambush. Applied: F-0009's embargo now lifts on railiance-platform reporting coverage, with live verification as a refinement rather than a condition, cutting the F-0003 chain from four hops to two. All eight open waits are typed with defaults. make check reports them with age, owner and default date, flags defaults come due, and catches depth-two violations. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
183 lines
7.9 KiB
Python
183 lines
7.9 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
|
|
|
|
NOW = lib.now()
|
|
|
|
|
|
def main() -> int:
|
|
fs = [f for f in lib.findings() if lib.watched(f.get("status"))]
|
|
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("")
|
|
|
|
seen: dict[str, str] = {}
|
|
dupes = []
|
|
for f in lib.findings():
|
|
prior = seen.get(f["id"])
|
|
if prior:
|
|
dupes.append(f"{f['id']} — filed twice: {prior} and {f['_path'].name}; renumber the later commit")
|
|
seen[f["id"]] = f["_path"].name
|
|
if dupes:
|
|
section("Duplicate ids", dupes, "none")
|
|
|
|
unknown = [
|
|
f"{f['id']} — status '{f.get('status')}' is not one of {', '.join(lib.KNOWN_STATUSES)}; watched anyway"
|
|
for f in fs
|
|
if f.get("status") not in lib.KNOWN_STATUSES
|
|
]
|
|
if unknown:
|
|
section("Unrecognised status", unknown, "none")
|
|
|
|
# T03 — the `mitigated` defect was one instance of a class: the tooling
|
|
# quietly tolerating something it did not expect. Everything below is
|
|
# reported by name, and never silently ignored.
|
|
ids = {f["id"] for f in lib.findings()}
|
|
malformed: list[str] = []
|
|
for f in fs:
|
|
fid = f["id"]
|
|
for field in ("last_checked", "next_check", "embargo_since", "deferred_to"):
|
|
if f.get(field) and lib.moment(f[field]) is None:
|
|
malformed.append(f"{fid} — {field} is not a date: {f[field]!r}")
|
|
if (c := f.get("cadence")) and c not in lib.CADENCE_NAMES:
|
|
malformed.append(f"{fid} — cadence '{c}' is not a rung on the ladder")
|
|
if (d := f.get("disclosure")) and d not in ("public", "embargoed", "restricted", "unset"):
|
|
malformed.append(f"{fid} — disclosure '{d}' is not a defined state")
|
|
if (s := f.get("severity")) and s not in lib.SEVERITIES + ["unset"]:
|
|
malformed.append(f"{fid} — severity '{s}' is not on the scale")
|
|
if (on := f.get("constraint_on")) and on not in ids:
|
|
malformed.append(f"{fid} — constraint_on points at {on}, which does not exist")
|
|
for ref in (f.get("related") or []):
|
|
if ref not in ids:
|
|
malformed.append(f"{fid} — related names {ref}, which does not exist")
|
|
if f.get("embargo_condition") and f.get("disclosure") != "embargoed":
|
|
malformed.append(f"{fid} — carries an embargo_condition but disclosure is '{f.get('disclosure')}'")
|
|
if f.get("disclosure") == "embargoed" and not f.get("embargo_condition"):
|
|
malformed.append(f"{fid} — embargoed with no condition; a hold with no lift is a silence")
|
|
if f.get("escalation") == "required" and not f.get("escalation_trigger"):
|
|
malformed.append(f"{fid} — escalated with no trigger named")
|
|
if malformed:
|
|
section("Malformed", malformed, "none")
|
|
|
|
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 watched finding carries a grade")
|
|
|
|
due, deferred = [], []
|
|
for f in fs:
|
|
if f.get("deferred_to"):
|
|
until = lib.moment(f["deferred_to"])
|
|
if until and NOW < until:
|
|
deferred.append(f"{f['id']} — deferred by the operator until {f['deferred_to']}")
|
|
continue
|
|
when = lib.moment(f.get("next_check"))
|
|
if when is None:
|
|
due.append(f"{f['id']} — no next_check set")
|
|
elif NOW >= when:
|
|
late = NOW - when
|
|
hours = int(late.total_seconds() // 3600)
|
|
rung = f.get("cadence", "instant")
|
|
due.append(
|
|
f"{f['id']} ({f.get('severity')}) — due {f['next_check']}"
|
|
f"{f', {hours}h late' if hours else ''}, cadence {rung}"
|
|
)
|
|
section("Checks due", due, "none")
|
|
if deferred:
|
|
section("Deferred by the operator", deferred, "none")
|
|
|
|
# The rung is the signal: how long this matter has held still.
|
|
stability = []
|
|
for f in sorted(fs, key=lambda f: lib.rung_index(f.get("cadence", "instant"))):
|
|
rung = f.get("cadence", "instant")
|
|
streak = f.get("clean_streak", 0)
|
|
note = " — at the ceiling" if rung == lib.TOP_RUNG else ""
|
|
stability.append(f"{f['id']}: {rung} ({streak} clean in a row){note}")
|
|
section("Stability — where each finding sits on the ladder", stability, "nothing watched")
|
|
|
|
bottom = [
|
|
f"{f['id']} ({f.get('severity')}) — still at the bottom rung since {f.get('last_checked')}"
|
|
for f in fs
|
|
if lib.rung_index(f.get("cadence", "instant")) == 0
|
|
and (m := lib.moment(f.get("last_checked")))
|
|
and NOW - m > dt.timedelta(days=14)
|
|
]
|
|
section("Stalled — escalation trigger 5", bottom, "none")
|
|
|
|
# Waits: typed, dated, and defaulted (docs/method/dependencies.md).
|
|
waiting, due_defaults, deep = [], [], []
|
|
waiting_ids = {f["id"] for f in fs if f.get("waiting_on")}
|
|
for f in fs:
|
|
for w in (f.get("waiting_on") or []):
|
|
since = lib.moment(w.get("since"))
|
|
age = f"{(NOW - since).days}d" if since else "?"
|
|
when = lib.moment(w.get("default_at"))
|
|
waiting.append(f"{f['id']} — {w.get('who')}: {str(w.get('what'))[:64]} ({age} old, defaults {w.get('default_at')})")
|
|
if when and NOW >= when:
|
|
due_defaults.append(
|
|
f"{f['id']} — {w.get('who')} did not answer by {w.get('default_at')}; apply: {w.get('default')}"
|
|
)
|
|
# depth-two check: a record waiting on a record that is itself waiting
|
|
for ref in ([f.get("constraint_on")] if f.get("constraint_on") else []):
|
|
if ref in waiting_ids and f.get("waiting_on"):
|
|
deep.append(f"{f['id']} waits, and points at {ref} which also waits — depth two, cut one")
|
|
section("Waiting on someone", waiting, "nothing is waiting on anyone")
|
|
if due_defaults:
|
|
section("Defaults now due — apply them", due_defaults, "none")
|
|
if deep:
|
|
section("Dependency depth violations", deep, "none")
|
|
|
|
embargo = [
|
|
f"{f['id']} — lifts when: {f.get('embargo_condition')}"
|
|
for f in fs
|
|
if f.get("disclosure") == "embargoed"
|
|
]
|
|
section("Embargoed", 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")
|
|
|
|
reg = []
|
|
for r in lib.regulatory():
|
|
when = lib.moment(r.get("next_check")) or lib.moment(r.get("review_by"))
|
|
if when is None:
|
|
reg.append(f"{r.get('id')} — no next_check set")
|
|
elif NOW >= when:
|
|
reg.append(f"{r.get('id')} — due {when:%Y-%m-%d}: {str(r.get('title','')).strip()}")
|
|
section("Regulatory records due", reg, "none")
|
|
|
|
print(f"Register check — {NOW:%Y-%m-%d %H:%MZ}\n{len(fs)} live finding(s)\n")
|
|
print("\n".join(lines).rstrip())
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|