intelligence-radar/intelligence_radar/__main__.py
tegwick 29ceb77938 Build reproducible capability advisor and scheduled source capture
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a09c77-b1a9-7eb3-b501-6cb24b458c97
2026-09-13 23:07:41 +02:00

223 lines
11 KiB
Python

"""Run with python3 -m intelligence_radar. Standard library only."""
import argparse
from datetime import date, datetime
import hashlib
import json
from pathlib import Path
import re
import sys
from urllib.parse import urlparse
def canonical(value):
return json.dumps(value, sort_keys=True, separators=(',', ':'), ensure_ascii=False, allow_nan=False).encode()
def digest(value):
return hashlib.sha256(canonical(value)).hexdigest()
def validate(record):
if not isinstance(record, dict):
raise ValueError('record must be an object')
required = {'schema_version', 'title', 'claim', 'source_url', 'source_kind',
'content_sha256', 'observed_at', 'event_date', 'status', 'observer'}
allowed = required | {'supersedes', 'notes'}
if set(record) - allowed or required - set(record):
raise ValueError('record has missing or unknown fields')
if type(record['schema_version']) is not int or record['schema_version'] != 1:
raise ValueError('schema_version must be 1')
for key in allowed - {'schema_version'}:
if key in record and (not isinstance(record[key], str) or not record[key].strip()):
raise ValueError(f'{key} must be nonempty text')
if record['source_kind'] not in {'primary', 'secondary', 'local', 'synthetic'}:
raise ValueError('invalid source_kind')
if record['status'] not in {'reported', 'corroborated', 'disputed', 'retracted'}:
raise ValueError('invalid status')
url = urlparse(record['source_url'])
if url.scheme not in {'https', 'http', 'file'} or (url.scheme != 'file' and not url.netloc):
raise ValueError('source_url must be an http(s) or file URL')
if url.username or url.password:
raise ValueError('source_url must not contain credentials')
for key in ('content_sha256', 'supersedes'):
if key in record and not re.fullmatch('[0-9a-f]{64}', record[key]):
raise ValueError(f'{key} must be a lowercase SHA-256')
observed = datetime.fromisoformat(record['observed_at'].replace('Z', '+00:00'))
if observed.tzinfo is None:
raise ValueError('observed_at requires a timezone')
event = date.fromisoformat(record['event_date'])
if event.isoformat() != record['event_date']:
raise ValueError('event_date requires YYYY-MM-DD')
if event > observed.date():
raise ValueError('event_date cannot follow observation date; describe future plans in claim')
def ledger(root):
result = []
for path in sorted((root / 'data/observations').glob('*.json')):
envelope = json.loads(path.read_text())
if not isinstance(envelope, dict) or set(envelope) != {'id', 'record'}:
raise ValueError(f'invalid envelope: {path}')
validate(envelope['record'])
ident = digest(envelope['record'])
if envelope['id'] != ident or path.stem != ident:
raise ValueError(f'integrity mismatch: {path}')
result.append(envelope)
ids = {item['id'] for item in result}
for item in result:
parent = item['record'].get('supersedes')
if parent and parent not in ids:
raise ValueError(f'unknown superseded observation: {parent}')
return result
def record(root, value):
validate(value)
items = ledger(root)
if value.get('supersedes') and value['supersedes'] not in {x['id'] for x in items}:
raise ValueError('supersedes must reference an existing observation')
ident = digest(value)
path = root / 'data/observations' / f'{ident}.json'
path.parent.mkdir(parents=True, exist_ok=True)
envelope = {'id': ident, 'record': value}
from .store import atomic
atomic(path, (json.dumps(envelope, indent=2, ensure_ascii=False) + '\n').encode(), immutable=True)
return ident
def draft(root, period):
if re.fullmatch(r'\d{4}-W\d{2}', period):
year, week = period.split('-W')
start = date.fromisocalendar(int(year), int(week), 1)
matches = lambda d: d.isocalendar()[:2] == start.isocalendar()[:2]
kind = 'weekly'
else:
start = date.fromisoformat(period)
if start.isoformat() != period:
raise ValueError('use YYYY-MM-DD or YYYY-Www')
matches = lambda d: d == start
kind = 'daily'
items = [x for x in ledger(root) if matches(date.fromisoformat(x['record']['event_date']))]
lines = [f'# Radar {kind} draft — {period}', '',
'Status: draft; editorial review required. Claims retain their reported status.', '',
'Selection: event date; observation timestamps below preserve when evidence was received.', '']
if not items:
lines += ['No recorded observations for this period. This does not establish that no events occurred.', '']
for item in items:
r = item['record']
lines += [f"## {r['title']}", '', r['claim'], '',
f"- Status: {r['status']}; source kind: {r['source_kind']}",
f"- Source: {r['source_url']}", f"- Observed: {r['observed_at']}",
f"- Observation: {item['id']}"]
if r.get('supersedes'):
lines.append(f"- Supersedes: {r['supersedes']}")
lines.append('')
lines += ['## Editorial follow-up', '',
'Review source claims, contradictions, frontier/price impacts, compendium edits,',
'benchmark health, and evidence gaps. Draft generation is not fact verification.', '']
path = root / 'digests' / kind / f'{period}.md'
path.parent.mkdir(parents=True, exist_ok=True)
with path.open('x') as stream:
stream.write('\n'.join(lines))
return path
def check(root):
required = ['INTENT.md', 'GOAL.md', 'SCOPE.md', 'AGENTS.md', 'README.md',
'TaskModelEvaluationMethod.md', 'task-router/METHOD.md',
'policies/model-ranking-v0.1.yaml', 'policies/benchmark-selection-v0.1.yaml',
'ops/RUNBOOK.md', 'history/MANIFEST.json']
for name in required:
if not (root / name).is_file():
raise ValueError(f'missing {name}')
manifest = json.loads((root / 'history/MANIFEST.json').read_text())
for item in manifest['archives']:
path = (root / item['path']).resolve()
if not path.is_relative_to((root / 'history').resolve()):
raise ValueError('archive path escapes history')
if hashlib.sha256(path.read_bytes()).hexdigest() != item['sha256']:
raise ValueError(f'archive checksum mismatch: {path}')
from .ingest import check_artifacts
from .store import all_records
check_artifacts(root)
for kind in ('recommendations', 'outcomes', 'ingestion-runs', 'scheduler-runs'):
all_records(root, kind)
from .advisor import replay
for ident, _ in all_records(root, 'recommendations'):
replay(root, ident)
return len(ledger(root))
def main(argv=None):
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--root', type=Path, default=Path.cwd(), help='repository or isolated ledger root')
commands = parser.add_subparsers(dest='command', required=True)
commands.add_parser('check', help='check repository, archive integrity, and ledger')
commands.add_parser('validate', help='validate every observation and integrity hash')
add = commands.add_parser('record', help='record a source observation JSON without overwriting history')
add.add_argument('input', type=Path)
render = commands.add_parser('digest', help='create a daily or ISO-week draft, refusing overwrite')
render.add_argument('period')
ingest_command = commands.add_parser('ingest', help='capture registered primary-source artifacts')
ingest_command.add_argument('registry', type=Path)
advisor_command = commands.add_parser('advise', help='save a reproducible task-specific recommendation')
advisor_command.add_argument('task', type=Path)
advisor_command.add_argument('--catalog', type=Path, required=True)
advisor_command.add_argument('--policy', type=Path, default=Path('policies/advisor-v0.2.json'))
advisor_command.add_argument('--as-of', required=True)
advisor_command.add_argument('--synthetic', action='store_true')
report_command = commands.add_parser('report', help='render a saved comparison as Markdown')
report_command.add_argument('id')
replay_command = commands.add_parser('replay', help='verify a saved recommendation using its frozen inputs')
replay_command.add_argument('id')
outcome_command = commands.add_parser('outcome', help='record an actual task execution and acceptance result')
outcome_command.add_argument('input', type=Path)
schedule_command = commands.add_parser('run-due', help='run latest due daily/weekly jobs; safe to invoke repeatedly')
schedule_command.add_argument('--config', type=Path, default=Path('ops/schedule.json'))
commands.add_parser('health', help='show durable scheduler health')
args = parser.parse_args(argv)
try:
if args.command == 'ingest':
from .ingest import ingest
result = ingest(args.root, json.loads(args.registry.read_text()))
print(json.dumps(result, indent=2))
return 0 if result['ok'] else 1
elif args.command == 'advise':
from .advisor import recommend
ident, report = recommend(args.root, json.loads(args.task.read_text()),
json.loads(args.catalog.read_text()), json.loads(args.policy.read_text()),
args.as_of, args.synthetic)
print(json.dumps({'recommendation_id': ident, **report}, indent=2))
elif args.command == 'report':
from .advisor import render_report
print(render_report(args.root, args.id))
elif args.command == 'replay':
from .advisor import replay
print(json.dumps(replay(args.root, args.id), indent=2))
elif args.command == 'outcome':
from .advisor import outcome
print(outcome(args.root, json.loads(args.input.read_text())))
elif args.command == 'run-due':
from .scheduler import run_due
result = run_due(args.root, json.loads(args.config.read_text()))
print(json.dumps(result, indent=2))
return 0 if result['ok'] else 1
elif args.command == 'health':
path = args.root / '.runtime/scheduler.json'
print(path.read_text() if path.exists() else '{"status": "not_run"}')
elif args.command == 'record':
print(record(args.root, json.loads(args.input.read_text())))
elif args.command == 'digest':
print(draft(args.root, args.period))
elif args.command == 'validate':
print(f'{len(ledger(args.root))} valid observations')
else:
print(f'Repository and archives valid; {check(args.root)} observations')
except (ValueError, OSError, KeyError, TypeError) as exc:
print(f'error: {exc}', file=sys.stderr)
return 1
return 0
if __name__ == '__main__':
sys.exit(main())