cpuai's picture
Install complete Linux VS Code + AHP MCP development workstation 2026-10-12
c12eb19 verified
Raw History Blame Contribute Delete
3.57 kB
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Validate structured evidence, domain invariants, and human science approval.
Pass a domain-specific topic.json containing claims, scenes and assertion checks.
This deliberately refuses to claim a diagram has been proved correct by a string check.
"""
import argparse,json,re,sys
from pathlib import Path
from domain_router import route
def review(topic, require_review=False):
errors=[];warnings=[]
title=topic.get('title','')
domain=topic.get('topic',topic.get('domain'))
resolved=route(title,domain if domain in ('astronomy','biology','physics','chemistry','geography','general') else None)
ids=set()
for c in topic.get('claims',[]):
if isinstance(c,list):
if len(c)<3:errors.append('claims entry incomplete');continue
cid,statement,url=c[0:3]
else:
cid,statement,url=c.get('id'),c.get('statement'),c.get('sources',[])
if cid in ids:errors.append(f'duplicate claim id: {cid}')
ids.add(cid)
if not statement:errors.append(f'{cid}: missing statement')
urls=[url] if isinstance(url,str) else url
if not urls or not all(re.match(r'^https://',u) for u in urls):errors.append(f'{cid}: no attributable HTTPS source')
if len(ids)<2:errors.append('At least two independent source-traced claims are needed')
scenes=topic.get('scenes',[])
if len(scenes)<5:errors.append('Insufficient scenes; need observable mechanism and recap')
for i,sc in enumerate(scenes):
if isinstance(sc,list):continue
if not sc.get('text') and not sc.get('lines'):errors.append(f'scene[{i}]: no voiced scientific explanation')
if not sc.get('heading'):errors.append(f'scene[{i}]: missing teaching title')
if not sc.get('role') and not sc.get('lines'):errors.append(f'scene[{i}]: missing voice role')
tags=set(topic.get('mechanism_tags',[]))
req=set(resolved['required_mechanism_tags'])
if not tags: warnings.append('Mechanism tags not recorded. Must review scene-to-claim alignment by hand.')
elif req-tags:errors.append('Missing domain-specific mechanisms: '+', '.join(sorted(req-tags)))
approvals=topic.get('science_review',{})
if not approvals.get('visual_truth_approved'):
warnings.append('Human reviewed diagram truth not signed')
if require_review:errors.append('Publication requires explicit human diagram review')
if not approvals.get('sources_opened'):
warnings.append('Sources are listed but not marked as inspected')
if require_review:errors.append('Publication requires opened sources')
if not approvals.get('misconceptions_checked'):
warnings.append('Misconception checklist not acknowledged')
if require_review:errors.append('Publication requires misconception audit')
result={'domain':resolved['domain'],'science_structural_pass':not errors,'manual_approval_required':True,'hard_errors':errors,'warnings':warnings,'required_diagram_invariants':resolved['required_mechanism_tags']}
return result
if __name__=='__main__':
p=argparse.ArgumentParser();p.add_argument('--topic',required=True);p.add_argument('--publish',action='store_true');p.add_argument('--output');a=p.parse_args()
result=review(json.loads(Path(a.topic).read_text(encoding='utf-8')),a.publish)
if a.output:Path(a.output).write_text(json.dumps(result,ensure_ascii=False,indent=2),encoding='utf-8')
print(json.dumps(result,ensure_ascii=False,indent=2));sys.exit(0 if result['science_structural_pass'] else 2)