import copy import json from datetime import datetime, timezone from pathlib import Path import pytest from activity_core.context_resolvers import frontend_patterns as f NOW = datetime(2026, 10, 1, 7, tzinfo=timezone.utc) INPUT = {'schema_version': 1, 'as_of': '2026-09-28T09:00:00Z', 'health': {k: 'unverified' for k in ('schedule','collection','verification','publication','rollback','executor')}, 'evidence_ref': 'docs/evidence/report.json', 'decisions': []} EVENT = {'date': '2026-09-28', 'effort': {'research_minutes': 4, 'execution_minutes': 1, 'reported_tokens': None, 'cost_usd': None}} def setup(monkeypatch, data=None, events=None, unavailable=False): data = copy.deepcopy(INPUT if data is None else data) events = [EVENT] if events is None else events def raw(repo, sha, path): assert repo == 'frontend-patterns' and sha == 'a'*40 if path == 'feedback/sources.json': return b'{"schema_version":1,"sources":[]}' if path == 'feedback/monthly-review-input.json': if unavailable: raise ValueError('unavailable') return json.dumps(data).encode() if path == 'research/evolution/ledger.json': return json.dumps({'events': events}).encode() if path == 'docs/evidence/report.json': return b'{}' raise ValueError('unexpected or missing file') monkeypatch.setattr(f, 'raw', raw) monkeypatch.setattr(f, 'revision', lambda *args: 'a'*40) def test_october_packet_with_no_consumers_retains_health_and_unknown_cost(monkeypatch): setup(monkeypatch) r=f.collect('monthly', NOW) assert r['status']=='no_consumers' and r['model_calls']==0 assert r['window']=={'start':'2026-09-01T00:00:00+02:00','end_exclusive':'2026-10-01T00:00:00+02:00'} assert r['review']['health']['executor']=='unverified' assert r['review']['measured_effort']['cost_usd']=={'known':0,'unknown_cycles':1} assert r['review']['measured_effort']['research_minutes']=={'known':4,'unknown_cycles':0} assert r['execution_ready'] is False assert len(json.dumps(r,sort_keys=True,separators=(',',':'))) <= 3900 def test_incomplete_input_degrades_without_losing_receipt_summary(monkeypatch): setup(monkeypatch, unavailable=True) r=f.collect('monthly', NOW) assert r['status']=='degraded' and r['real_uses']==0 assert r['review']['health']=='unknown' and r['review']['decisions']==[] @pytest.mark.parametrize('change', [ {'as_of':'2026-10-02T00:00:00Z'}, {'as_of':'2026-09-28T00:00:00'}, {'evidence_ref':'../secret'}, {'decisions':[{}]*4}, {'health':{'executor':'ready'}}, {'decisions':[{'question':'x','recommendation':'y'}]}, {'evidence_ref':'docs/evidence/missing.json'}, ]) def test_invalid_review_input_never_claims_health(monkeypatch, change): data=copy.deepcopy(INPUT); data.update(change); setup(monkeypatch,data) r=f.collect('monthly', NOW) assert r['status']=='degraded' and r['review']['health']=='unknown' def test_month_filter_and_missing_effort(monkeypatch): old=copy.deepcopy(EVENT); old['date']='2026-08-31' future=copy.deepcopy(EVENT); future['date']='2026-10-01' unknown=copy.deepcopy(EVENT); unknown['effort']['research_minutes']=None setup(monkeypatch, events=[old,future,EVENT,unknown]) r=f.collect('monthly', NOW)['review'] assert r['research_cycles']==2 assert r['measured_effort']['research_minutes']=={'known':4,'unknown_cycles':1} def test_stale_owner_snapshot_is_not_live_health(monkeypatch): data=copy.deepcopy(INPUT); data['as_of']='2026-09-01T00:00:00Z'; setup(monkeypatch,data) r=f.collect('monthly',NOW)['review'] assert r['stale'] is True and 'not live attestation' in r['basis'] @pytest.mark.parametrize('value', [-1, float('nan'), True]) def test_invalid_effort_does_not_invent_totals(monkeypatch, value): event=copy.deepcopy(EVENT); event['effort']['cost_usd']=value setup(monkeypatch, events=[event]) assert f.collect('monthly', NOW)['status']=='degraded' def test_daily_does_not_require_monthly_packet(monkeypatch): setup(monkeypatch, unavailable=True) assert f.collect('daily', NOW)['status']=='no_consumers'