Keep review obligations visible and reconcile owner evidence (RISK-WP-0006, RISK-WP-0007)

check_all runs every check stage even when one fails; malformed dates are
reported rather than aborting; accepted findings and closure evidence are
shown; defer requires a valid future date. Adds SCOPE.md, the scope
assessment, the open-findings source review and a unittest suite. Stops
tracking __pycache__.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 6903@bnt-lap001
Assistant-Session: 8319e8a8-ffa6-4eb3-b8bf-b29945628f89
This commit is contained in:
tegwick 2026-09-22 07:56:58 +02:00
parent 29f50d5143
commit bbbede5f47
25 changed files with 1007 additions and 43 deletions

View file

@ -16,7 +16,8 @@ NOW = lib.now()
def main() -> int:
fs = [f for f in lib.findings() if lib.watched(f.get("status"))]
all_findings = lib.findings()
fs = [f for f in all_findings if lib.watched(f.get("status"))]
lines: list[str] = []
def section(title: str, rows: list[str], quiet: str) -> None:
@ -50,9 +51,9 @@ def main() -> int:
# reported by name, and never silently ignored.
ids = {f["id"] for f in lib.findings()}
malformed: list[str] = []
for f in fs:
for f in all_findings:
fid = f["id"]
for field in ("last_checked", "next_check", "embargo_since", "deferred_to"):
for field in ("last_checked", "next_check", "embargo_since", "embargo_review", "deferred_to", "escalation_sent"):
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:
@ -147,6 +148,10 @@ def main() -> int:
# RISK-WP-0005-T01: the fix's own state, read from the owner's workplan
# file rather than from our memory of what they told us.
section("Fix state", fix_tracker.report(), "no finding claims a tracked fix")
section("Closure evidence pending", [
f"{f['id']}{f['closure_condition']}"
for f in fs if f.get("closure_condition")
], "none recorded")
if due_defaults:
section("Defaults now due — apply them", due_defaults, "none")
if deep:
@ -154,11 +159,26 @@ def main() -> int:
embargo = [
f"{f['id']} — lifts when: {f.get('embargo_condition')}"
for f in fs
for f in all_findings
if f.get("disclosure") == "embargoed"
]
section("Embargoed", embargo, "none")
embargo_due = []
for f in all_findings:
if f.get("disclosure") != "embargoed":
continue
when = lib.moment(f.get("embargo_review"))
if when is None:
embargo_due.append(f"{f['id']} — missing or invalid embargo_review; re-decide the hold")
elif NOW >= when:
embargo_due.append(f"{f['id']} — embargo review due {f['embargo_review']}; re-decide the hold")
section("Embargo reviews due", embargo_due, "none")
section("Publication handovers pending", [
f"{f['id']} ({f.get('status')}) — pending policy-nexus handover: {f.get('publication_id', 'no publication id')}"
for f in all_findings if f.get("publication") == "pending-handover"
], "none")
# T05 — an escalation nobody acknowledged is indistinguishable from one
# never sent, which is the failure this register fixed for its own inbox
# and not, until now, for the path that matters more.
@ -184,6 +204,14 @@ def main() -> int:
reg = []
for r in lib.regulatory():
invalid = [field for field in ("last_checked", "next_check", "review_by", "deferred_to")
if r.get(field) and lib.moment(r[field]) is None]
if invalid:
reg.append(f"{r.get('id')} — invalid date: {', '.join(invalid)}; review required")
continue
until = lib.moment(r.get("deferred_to"))
if until and NOW < until:
continue
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")