Verify brief publication against live origin and record historical gaps

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a09cbd-43c1-79f3-809e-1ee97b40b64d
This commit is contained in:
tegwick 2026-09-14 00:37:51 +02:00
parent 8a65297d56
commit 8bd2e5ff92
10 changed files with 565 additions and 90 deletions

View file

@ -1,114 +1,192 @@
#!/usr/bin/env python3
"""Fail if State Hub fi_daily_brief events are not on origin/main.
"""Audit Hub completions against a freshly resolved origin/main Git tree.
A brief day is complete only when briefs/YYYY/MM/YYYY-MM-DD.md exists in
this git repository (the clone should be origin/main). Hub events that
claim wrote/committed without a matching file are the 2026-08/09 failure
mode: local commit on railiance, due-bit cleared, durable memory empty.
Usage:
python3 scripts/verify_brief_durability.py
STATE_HUB_URL=http://127.0.0.1:8000 python3 scripts/verify_brief_durability.py
Exit 0 = every hub success event has a brief file.
Exit 1 = mismatch (or hub unreachable when --require-hub is set).
Exit 0: checks pass (or explicitly allowed acknowledged historical gaps).
Exit 1: missing/invalid evidence. Exit 2: verification could not run reliably.
--require-date YYYY-MM-DD also requires a valid completion for that day.
"""
from __future__ import annotations
import argparse
from datetime import date
import json
import os
import sys
import urllib.error
import urllib.request
from pathlib import Path
import re
import subprocess
import sys
import urllib.parse
import urllib.request
ROOT = Path(__file__).resolve().parents[1]
REPO = 'freedom-intelligence'
CONTRACT_START = '2026-09-13'
CORRECTION_TYPE = 'fi_daily_brief_reconciliation'
SHA = re.compile(r'[0-9a-f]{40}')
def brief_path(date: str) -> Path:
year, month, _ = date.split("-")
return ROOT / "briefs" / year / month / f"{date}.md"
def brief_path(day: str) -> str:
if date.fromisoformat(day).isoformat() != day:
raise ValueError('date must be YYYY-MM-DD')
return f'briefs/{day[:4]}/{day[5:7]}/{day}.md'
def load_events(url: str, timeout: float) -> list[dict]:
req = urllib.request.Request(
f"{url.rstrip('/')}/progress/?event_type=fi_daily_brief",
headers={"Accept": "application/json"},
)
with urllib.request.urlopen(req, timeout=timeout) as resp:
data = json.loads(resp.read().decode())
if isinstance(data, list):
return data
if isinstance(data, dict):
for key in ("items", "events", "results"):
if isinstance(data.get(key), list):
return data[key]
raise RuntimeError(f"unexpected hub payload type {type(data)}")
def git(root: Path, *args: str, check=True):
result = subprocess.run(['git', '-C', str(root), *args], capture_output=True,
text=True, timeout=120)
if check and result.returncode:
raise RuntimeError(f'git {args[0]} failed: {result.stderr.strip()}')
return result
class Origin:
def __init__(self, root: Path):
self.root = root
# Never trust a stale tracking ref or the checked-out branch.
remote = git(root, 'ls-remote', '--exit-code', 'origin', 'refs/heads/main').stdout.split()
if len(remote) != 2 or not SHA.fullmatch(remote[0]):
raise RuntimeError('origin/main did not resolve to one commit')
self.sha = remote[0]
if git(root, 'cat-file', '-e', f'{self.sha}^{{commit}}', check=False).returncode:
git(root, 'fetch', '--no-tags', '--no-write-fetch-head', 'origin', 'refs/heads/main')
git(root, 'cat-file', '-e', f'{self.sha}^{{commit}}')
def blob(self, path: str, revision: str | None = None) -> bool:
revision = revision or self.sha
if not SHA.fullmatch(revision):
return False
entry = git(self.root, 'ls-tree', revision, '--', path, check=False)
fields = entry.stdout.split()
# Reject symlinks, trees and empty files as completion artifacts.
if entry.returncode or len(fields) != 4 or fields[0] not in {'100644', '100755'}:
return False
return fields[1] == 'blob' and int(git(self.root, 'cat-file', '-s', fields[2]).stdout) > 0
def published(self, revision: str, path: str) -> bool:
if not SHA.fullmatch(revision):
return False
return (git(self.root, 'merge-base', '--is-ancestor', revision, self.sha,
check=False).returncode == 0 and self.blob(path, revision))
def correction_recorded(self, detail: dict) -> bool:
revision = str(detail.get('evidence_sha', ''))
path = str(detail.get('evidence_path', ''))
if not self.published(revision, path):
return False
try:
evidence = json.loads(git(self.root, 'show', f'{revision}:{path}').stdout)
records = evidence['corrections']
except (ValueError, KeyError, TypeError):
return False
fields = ('original_event_id', 'date', 'path', 'disposition', 'reason')
return any(isinstance(row, dict) and all(row.get(k) == detail.get(k) for k in fields)
for row in records)
def load_events(url: str, timeout: float, event_type='fi_daily_brief', page_size=1000) -> list[dict]:
events = []
seen = set()
for offset in range(0, 1_000_000, page_size):
query = urllib.parse.urlencode(dict(event_type=event_type, limit=page_size, offset=offset))
req = urllib.request.Request(f"{url.rstrip('/')}/progress/?{query}",
headers={'Accept': 'application/json'})
with urllib.request.urlopen(req, timeout=timeout) as response:
page = json.load(response)
if not isinstance(page, list):
raise RuntimeError('unexpected Hub progress payload: expected a list')
for event in page:
if not isinstance(event, dict) or not event.get('id') or event['id'] in seen:
raise RuntimeError('malformed or unstable Hub pagination; retry verification')
seen.add(event['id'])
events.extend(page)
if len(page) < page_size:
return events
raise RuntimeError('Hub pagination exceeded safety bound')
def assess(events, corrections, origin, required_date=None):
result = {'origin_sha': origin.sha, 'valid': [], 'legacy': [], 'reconciled': [], 'failures': []}
correction_index = {}
for correction in corrections:
d = correction.get('detail') or {}
if not isinstance(d, dict) or d.get('repo') != REPO:
continue
if (d.get('disposition') == 'false_completion' and d.get('reason')
and origin.correction_recorded(d)):
correction_index.setdefault(d.get('original_event_id'), []).append(d)
for event in events:
d = event.get('detail') or {}
if not isinstance(d, dict):
result['failures'].append({'id': event.get('id'), 'reason': 'invalid event detail'})
continue
if d.get('repo') not in {None, REPO}:
continue
row = {'id': event.get('id'), 'date': d.get('date')}
try:
path = brief_path(d.get('date', ''))
except (ValueError, TypeError):
result['failures'].append(dict(row, reason='invalid or missing date'))
continue
if not origin.blob(path):
acknowledged = any(c.get('date') == d['date'] and c.get('path') == path
for c in correction_index.get(event.get('id'), []))
target = 'reconciled' if acknowledged else 'failures'
result[target].append(dict(row, reason='brief absent from origin/main', path=path))
continue
if d.get('path', path) != path:
result['failures'].append(dict(row, reason='event path does not match date'))
continue
modern = d['date'] >= CONTRACT_START or 'pushed' in d or 'origin_sha' in d
if modern:
if (d.get('pushed') is not True or d.get('path') != path
or not origin.published(str(d.get('origin_sha', '')), path)):
result['failures'].append(dict(row, reason='invalid pushed/origin_sha publication evidence'))
continue
result['valid'].append(row)
else:
# Historic files exist on origin but predate the push-attestation contract.
result['legacy'].append(row)
if required_date and required_date not in {r['date'] for r in result['valid']}:
result['failures'].append({'date': required_date, 'reason': 'required day has no valid published completion'})
return result
def main() -> int:
ap = argparse.ArgumentParser(description=__doc__)
ap.add_argument(
"--hub",
default=os.environ.get("STATE_HUB_URL", "http://127.0.0.1:8000"),
)
ap.add_argument("--timeout", type=float, default=8.0)
ap.add_argument(
"--require-hub",
action="store_true",
help="exit 1 if the hub cannot be reached (default: warn and check git only)",
)
ap.add_argument('--hub', default=os.environ.get('STATE_HUB_URL', 'http://127.0.0.1:8000'))
ap.add_argument('--timeout', type=float, default=8)
ap.add_argument('--require-hub', action='store_true', help='compatibility flag; Hub is always required')
ap.add_argument('--require-date', help='require a valid pushed completion for this exact day')
ap.add_argument('--allow-reconciled', action='store_true', help='acknowledged historical gaps do not fail the audit')
ap.add_argument('--json', action='store_true', help='machine-readable audit result')
args = ap.parse_args()
git_dates = sorted(
p.stem
for p in (ROOT / "briefs").rglob("20*.md")
if p.name[0].isdigit()
)
print(f"git briefs: {len(git_dates)} last={git_dates[-1] if git_dates else '-'}")
try:
if args.require_date:
brief_path(args.require_date)
origin = Origin(ROOT)
events = load_events(args.hub, args.timeout)
except (urllib.error.URLError, TimeoutError, json.JSONDecodeError, RuntimeError) as exc:
msg = f"hub unreachable or unreadable at {args.hub}: {exc}"
if args.require_hub:
print(f"FAIL {msg}", file=sys.stderr)
return 1
print(f"WARN {msg}")
return 0
missing: list[str] = []
present: list[str] = []
for ev in events:
detail = ev.get("detail") or {}
date = str(detail.get("date") or "")
if not date:
continue
repo = detail.get("repo")
if repo and repo != "freedom-intelligence":
continue
path = brief_path(date)
if path.is_file():
present.append(date)
corrections = load_events(args.hub, args.timeout, CORRECTION_TYPE)
result = assess(events, corrections, origin, args.require_date)
except (OSError, ValueError, RuntimeError, subprocess.SubprocessError) as exc:
if args.json:
print(json.dumps({'ok': False, 'error': str(exc)}))
else:
missing.append(date)
missing = sorted(set(missing))
present = sorted(set(present))
print(f"hub fi_daily_brief dates on git: {len(present)}")
if missing:
print("FAIL hub events with no brief file:")
for date in missing:
print(f" {date} expected {brief_path(date).relative_to(ROOT)}")
print(
"A local-only commit must not clear due. "
"Push to origin, or treat the hub event as a false completion."
)
return 1
print("ok: every hub fi_daily_brief date has a brief file")
return 0
print(f'ERROR verification unavailable: {exc}', file=sys.stderr)
return 2
result['ok'] = not result['failures'] and (args.allow_reconciled or not result['reconciled'])
if args.json:
print(json.dumps(result, indent=2))
else:
print(f'origin/main: {origin.sha} (resolved from live remote)')
print(f"valid published events: {len(result['valid'])}; legacy files on origin: {len(result['legacy'])}")
for row in result['reconciled']:
print(f"GAP acknowledged false completion: {row['date']} event={row['id']}")
for row in result['failures']:
print(f"FAIL {row.get('date', '-')}: {row['reason']}")
print('PASS (acknowledged gaps remain missing)' if result['ok'] and result['reconciled']
else 'PASS' if result['ok'] else 'FAIL durability audit')
return 0 if result['ok'] else 1
if __name__ == "__main__":
if __name__ == '__main__':
sys.exit(main())