atlas-iac/testing/tests/test_suite_recovery.py

245 lines
12 KiB
Python

"""Fault injection exercises real orchestration without hosted model requests."""
import copy
import json
import threading
from pathlib import Path
import sys
import pytest
sys.path.insert(0, str(Path(__file__).resolve().parents[2] / 'scripts/ops'))
sys.path.insert(0, str(Path(__file__).resolve().parents[2] / 'services/hermes/scripts'))
import suite_backends
import suite_hierarchical
import suite_multipass as workflow
import suite_recovery
from suite_contract import MODELS, Problem, preflight, validate_request, validate_result
from suite_profiles import PROFILE_FIELDS, profile_source, validate_profiles
from suite_recovery import Checkpoints
from suite_sizing import balanced_sizes
from suite_synthetic import fixture, score
from test_suite_multipass import natural, public, review, wire_value
from suite_capacity_fixture import fixture as realistic_fixture
class NoWait:
"""Cancellation remains testable without real retry sleeps."""
def is_set(self):
return False
def wait(self, _):
return False
def source(size=14, large=False):
raw, expected = realistic_fixture() if large else fixture(size)
raw['routing'] = {'allow_external': True, 'allowed_external_providers': ['claude']}
raw['execution'] = {'strategy': 'whole_suite', 'max_seconds': 7200, 'max_cost_usd': 60}
return validate_request(raw, ['claude']), expected
def oracle(monkeypatch, expected, failures=None):
"""Use an independent fixture map to check cross-batch control flow and validation."""
calls = []
failures = dict(failures or {})
def backend(request, cancel, *, invocation, progress=None, job_deadline=None):
stage = invocation['stage']
calls.append({'stage': stage, 'aliases': sorted(c['alias'] for c in request['cases']),
'seconds': request['execution']['max_seconds'], 'deadline': job_deadline,
'turns': invocation['max_turns'], 'source': copy.deepcopy(request['cases'])})
if failures.get(stage, 0):
failures[stage] -= 1
raise Problem('incomplete_generation', 502, final_event_subtype='success',
final_is_error=True, exit_code=1, assistant_api_error_seen=True,
structured_output_present=False, turns=1, max_turns=invocation['max_turns'],
cost_usd_estimate=0, usage={'input_tokens':0,'output_tokens':0})
if stage == 'implementation_profiles':
value = {'profiles': {}}
for c in request['cases']:
name = expected[c['alias']]
p = {k: None for k in PROFILE_FIELDS}
p.update(target=name, work='Implement '+name+' tests.', setup=name+' fixture',
stimulus=name+' stimulus', observations=name+' measurements',
machinery=name, evidence={'field':'success_criteria', 'quote':c['success_criteria'][:90]})
value['profiles'][c['alias']] = p
else:
parts = {}
for c in request['cases']:
parts.setdefault(expected[c['alias']], []).append(c['alias'])
decision = natural(request, list(parts.values()), list(parts))
if stage in ('proposal_a','proposal_b','profile_proposal_a','profile_proposal_b','profile_reconciliation'):
decision = public(decision)
if stage in ('large_family_review','decision_audit'):
decision = review(decision, decision)
value = wire_value(decision, invocation)
return value, {'model':MODELS['claude']['model'], 'cost_usd_estimate': 25.0,
'usage':{'input_tokens':100,'output_tokens':50}, 'turns':2, 'duration_api_ms':2,
'compaction':False, 'truncation':False, 'cli_diagnostics':{'exit_code':0}}
monkeypatch.setattr(suite_backends, 'claude_generate', backend)
return calls
def run(monkeypatch, *, mode='direct', size=14, large=False, failures=None):
request, expected = source(size, large)
calls = oracle(monkeypatch, expected, failures)
selected = {**preflight(request), 'execution_mode':mode}
updates = []
result, metadata = workflow.generate(request, selected, NoWait(), '192.168.22.8', updates.append,
credential_scope={'owner':'synthetic-test','providers':['claude']})
validate_result(result, request)
return request, expected, calls, result, metadata, updates
def test_proposal_b_retry_keeps_validated_a_and_same_source(monkeypatch):
request, expected, calls, result, meta, updates = run(monkeypatch, failures={'proposal_b':1})
assert [c['stage'] for c in calls].count('proposal_a') == 1
assert [c['stage'] for c in calls].count('proposal_b') == 2
attempts = [c for c in calls if c['stage']=='proposal_b']
assert attempts[0]['source'] == attempts[1]['source']
assert meta['retry_count']['proposal_b'] == 1
assert 'proposal_a' in meta['checkpointed_passes']
assert meta['cost_usd_estimate'] > 60 and meta['cost_guard_enforced'] is False
assert all(c['deadline']==calls[0]['deadline'] for c in calls)
assert score({'groups':meta['review_summary']['natural_families']}, expected)['false_merge_pairs']==0
def test_review_failure_does_not_regenerate_prior_passes(monkeypatch):
_, _, calls, _, meta, _ = run(monkeypatch, size=75, failures={'large_family_review':1})
for name in ('proposal_a','proposal_b','reconciliation'):
assert [c['stage'] for c in calls].count(name)==1
assert [c['stage'] for c in calls].count('large_family_review')==2
assert meta['retry_count']['large_family_review']==1
@pytest.mark.parametrize('mode', ['direct','hierarchical'])
def test_large_comparable_fixture_complete_and_globally_reconciled(monkeypatch, mode):
request, expected, calls, result, meta, updates = run(monkeypatch, mode=mode, large=True)
assert len(request['cases'])==363
assert max(len(g['members']) for g in result['groups'])<=5
assert len(result['groups'])==90 and meta['natural_family_count']==45
quality=score({'groups':meta['review_summary']['natural_families']}, expected)
assert quality['false_merge_pairs']==quality['missed_merge_pairs']==0
assert all(d['part_sizes']==balanced_sizes(d['natural_case_count']) for d in meta['review_summary']['capacity_divisions'])
if mode=='hierarchical':
assert meta['profile_batch_count']==16
for c in calls:
if c['stage'] in ('profile_proposal_a','profile_proposal_b','profile_reconciliation'):
assert len(c['aliases'])==363
originals={c['alias']:c for c in request['cases']}
reopened=[c for call in calls if call['stage']=='source_review' for c in call['source']]
assert {c['alias']:c for c in reopened}==originals
assert meta['cross_batch_review_count']==1
assert 'Implement ' not in json.dumps(updates)
def test_failed_direct_switches_only_after_bounded_recovery(monkeypatch):
_, _, calls, _, meta, _ = run(monkeypatch, failures={'proposal_b':3})
assert [c['stage'] for c in calls].count('proposal_a')==1
assert [c['stage'] for c in calls].count('proposal_b')==3
assert meta['execution_mode']=='hierarchical'
assert meta['strategy_events'][-1]['reason']=='pass_generation_retries_exhausted'
@pytest.mark.parametrize('code', ['provider_authentication','provider_forbidden','cancelled',
'invalid_review_evidence','worker_isolation_failed','job_time_budget_exhausted'])
def test_nonretriable_conditions_stop_without_fallback(monkeypatch, code):
request, _ = source()
seen=[]
def fail(*args, **kw):
seen.append(kw['invocation']['stage'])
raise Problem(code, 502)
monkeypatch.setattr(suite_backends,'claude_generate',fail)
with pytest.raises(Problem, match='^'+code+'$'):
workflow.generate(request, preflight(request), NoWait(),'192.168.22.8')
assert seen==['proposal_a']
def test_turn_recovery_grows_only_within_capacity(monkeypatch):
request, expected = source()
calls=oracle(monkeypatch,expected)
original=suite_backends.claude_generate
turns=[]
def backend(*args,**kw):
turns.append(kw['invocation']['max_turns'])
if len(turns)<3:
raise Problem('pass_turn_limit',502,cost_usd_estimate=0,turns=turns[-1],
max_turns=turns[-1],usage={'input_tokens':1,'output_tokens':1})
return original(*args,**kw)
monkeypatch.setattr(suite_backends,'claude_generate',backend)
workflow.generate(request,preflight(request),NoWait(),'192.168.22.8')
assert turns[:3]==[4,5,6]
def test_checkpoint_scope_hash_and_restart_behavior():
request,_=source()
call={'stage':'proposal_a','input':'synthetic','prior_hash':'a'}
store=Checkpoints(request,'claude',{'owner':'a'},float('inf'))
key=store.key(call);store.put(key,'proposal_a',{'groups':[]})
assert store.get(key,'proposal_a')=={'groups':[]}
assert store.key({**call,'prior_hash':'b'})!=key
assert Checkpoints(request,'claude',{'owner':'b'},float('inf')).key(call)!=key
assert Checkpoints(request,'claude',{'owner':'a'},float('inf')).get(key,'proposal_a') is None
store.clear();assert store.get(key,'proposal_a') is None
def test_cli_cost_guard_is_absent_and_legacy_request_cost_is_unenforced():
request,_=source()
request['execution']['max_cost_usd']=1e9
assert validate_request(request,['claude'])['execution']['max_cost_usd']==1e9
assert '--max-budget-usd' not in suite_backends.claude_command(MODELS['claude']['model'],60)
assert preflight(request)['cost_guard_enforced'] is False
def test_full_profile_set_fits_global_comparison_at_service_case_limit():
"""Bounded profiles keep every alias globally visible; no neighborhood shortcut."""
from suite_policy import invocation
request = {'campaign':'SYNTHETIC','suite':'CAPACITY','cases':[
{'alias':'CASE-'+str(i).zfill(48),'description':'Synthetic'} for i in range(400)]}
profiles = {c['alias']:{k:'x'*n for k,n in PROFILE_FIELDS.items()} for c in request['cases']}
compact = profile_source(request, profiles)
proposal = {'groups':[{'name':'x'*56,'members':[c['alias']]} for c in request['cases']]}
call = invocation('profile_reconciliation',compact,{'proposal_a':proposal,'proposal_b':proposal})
result = workflow.capacity(call,'claude',400)
assert result['max_turns'] >= 4 and result['context_reserved_tokens'] <= 1000000
assert len(call['schema']['properties']['assignments']['required']) == 400
def test_profile_evidence_and_exact_aliases_are_independently_validated():
request,expected=source()
c=request['cases'][0]
p={k:None for k in PROFILE_FIELDS}
p['evidence']={'field':'success_criteria','quote':c['success_criteria'][:90]}
subset={**request,'cases':[c]}
validate_profiles({'profiles':{c['alias']:p}},subset)
with pytest.raises(Problem,match='invalid_case_assignments'):
validate_profiles({'profiles':{'CASE-invented':p}},subset)
p['evidence']['quote']='unsupported secret instructions'
with pytest.raises(Problem,match='invalid_review_evidence'):
validate_profiles({'profiles':{c['alias']:p}},subset)
def test_checkpoint_hit_launches_no_new_model_call(monkeypatch):
request,expected=source()
calls=oracle(monkeypatch,expected)
worker=workflow.Workflow(request,preflight(request),NoWait(),'192.168.22.8',credential_scope='synthetic')
first=worker.call('proposal_a',request)
second=worker.call('proposal_a',request)
assert first==second and len(calls)==1
assert worker.safe_state()['checkpoint_reused']==['proposal_a']
assert len(worker.records)==1
def test_one_structured_assignment_repair_preserves_source(monkeypatch):
request,expected=source()
calls=oracle(monkeypatch,expected)
original=suite_backends.claude_generate
def backend(*args,**kwargs):
value,metadata=original(*args,**kwargs)
if len(calls)==1:
value['assignments'].pop(next(iter(value['assignments'])))
return value,metadata
monkeypatch.setattr(suite_backends,'claude_generate',backend)
result,meta=workflow.generate(request,preflight(request),NoWait(),'192.168.22.8')
assert meta['retry_count']=={'proposal_a':1}
assert calls[0]['source']==calls[1]['source']
validate_result(result,request)