frontend-patterns/scripts/research_execution.py
tegwick cfa249ab13 Reduce research calls with screened reuse and draft VC-02 walkthrough
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0cffe-206f-7323-89d3-b20ca4cf4bf9
2026-09-25 08:43:32 +02:00

82 lines
4.6 KiB
Python

"""Conditional execution and explicit reuse of structurally screened stage results."""
import hashlib
import json
from pathlib import Path
from infospace_bench.workflow import AssistedGenerationResult, FixtureAssistedGenerationAdapter
from research_admission import json_block, screen
def fingerprint(value):
return hashlib.sha256(json.dumps(value, sort_keys=True).encode()).hexdigest()
def identity(adapter):
if isinstance(adapter, FixtureAssistedGenerationAdapter):
return {'fixture': sorted((list(k), v.markdown, v.provider, v.metadata)
for k, v in adapter.responses.items())}
if hasattr(adapter, 'config') and hasattr(adapter, 'endpoint'):
return {'class': type(adapter).__name__, 'endpoint': adapter.endpoint,
'config': adapter.config.to_dict(), 'diagnostics': adapter.diagnostics}
raise ValueError('Optimized execution requires llm-connect or a fixture adapter')
class ResearchExecution:
def __init__(self, limited, context, reuse_from=None):
self.limited = limited
self.context = {**context, 'adapter': identity(limited.adapter)}
self.candidates = None
self.relations = '```json\n[]\n```'
self.events, self.cache, self.previous = [], {}, {}
self.reuse_from = str(Path(reuse_from).resolve()) if reuse_from else None
if reuse_from:
root = Path(reuse_from)
receipt = json.loads((root / 'reports/research-run.json').read_text())
raw = (root / 'reports/stage-cache.json').read_bytes()
if (receipt['status'] != 'completed' or
hashlib.sha256(raw).hexdigest() != receipt.get('stage_cache_sha256')):
raise ValueError('Reuse requires a completed run and matching cache digest')
self.previous = json.loads(raw)
def generate(self, request):
stage = request.stage_id
if stage == 'relations' and len(json_block(self.candidates)['candidates']) < 2:
self.events.append({'stage': stage, 'execution': 'deterministic',
'reason': 'fewer than two candidates'})
return AssistedGenerationResult(self.relations, provider='deterministic',
metadata={'reason': 'fewer than two candidates'})
if stage == 'critique':
report = screen(self.candidates, self.relations)
self.events.append({'stage': stage, 'execution': 'deterministic', 'screen': report})
return AssistedGenerationResult(
'# Editorial review required\n\nThis is a structural screen, not model critique.\n\n'
+ '```json\n' + json.dumps(report, indent=2) + '\n```\n\n'
+ 'Check source fidelity, known-use independence, unsupported guarantees, '
'counterexamples and scenario relevance. Record corrections in the editorial review.\n',
provider='deterministic', metadata={'admission': 'not_granted'})
key = fingerprint({'context': self.context, 'stage': stage, 'prompt': request.prompt,
'workflow': request.workflow_id, 'input': request.input_artifact_id})
cached = self.previous.get(key)
event = {'stage': stage, 'execution': 'cache' if cached else 'provider'}
self.events.append(event)
if cached:
result = AssistedGenerationResult(cached['markdown'], cached['provider'],
{**cached['metadata'], 'reused_from': self.reuse_from, 'current_provider_call': False})
else:
result = self.limited.generate(request)
if stage in ('candidates', 'relations'):
report = screen(result.markdown if stage == 'candidates' else self.candidates,
'```json\n[]\n```' if stage == 'candidates' else result.markdown)
event['screen'] = report
if report['structural_status'] != 'passed':
event['rejected_assertions'] = len(report['findings'])
# Keep rejected research output for review, but do not propagate/cache it.
self.rejected = {'stage': stage, 'content': result.markdown, 'screen': report}
raise ValueError(f'{stage} structural screen blocked; inspect rejected-stage.json')
if stage == 'candidates':
self.candidates = result.markdown
if stage == 'relations':
self.relations = result.markdown
self.cache[key] = cached or {'markdown': result.markdown, 'provider': result.provider,
'metadata': result.metadata}
return result