AUREOLE-R-v3 / scripts /validate_publication.py
PureOne's picture
AUREOLE-R 3.0.0-hf.1: standalone public research release
9d6c005 verified
Raw
History Blame Contribute Delete
7.27 kB
"""Offline publication checks, kept separate from scientific validation."""
from pathlib import Path
import argparse
import ast
import hashlib
import json
import re
import subprocess
import sys
from publish_hf import release_files
ROOT=Path(__file__).resolve().parents[1]
def main(output):
gates=[]
def gate(name,ok,detail):gates.append({'name':name,'passed':bool(ok),'details':detail})
def load(name):return json.loads((ROOT/name).read_text(encoding='utf-8'))
files=release_files(ROOT)
gate('integrity',True,{'verified_files':len(files)})
required=['START_HERE.md','PUBLISH_TO_HUGGINGFACE.bat','README.md','EXPERT_REVIEW_GUIDE.md','REPRODUCIBILITY.md',
'DATA_DICTIONARY.md','AI_AGENT_INDEX.json','EVIDENCE_INDEX.json','llms.txt','llms-full.txt','claims.jsonl',
'CITATION.cff','CITATION.bib','PUBLICATION.json','FILE_CATALOG.json','publication/SCIENCE_PRESERVATION.json']
missing=[n for n in required if n not in files]
gate('required_publication_artifacts',not missing,{'missing':missing})
catalog=load('FILE_CATALOG.json');manifest=load('RELEASE_MANIFEST.json')
gate('catalog_and_manifest',set(n['path'] for n in catalog['files'])==set(files) and catalog['files_count']==len(files)==manifest['files_in_distribution'],{'files':len(files)})
ledger=load('publication/SCIENCE_PRESERVATION.json');errors=[]
for record in ledger['unchanged']:
if hashlib.sha256((ROOT/record['path']).read_bytes()).hexdigest()!=record['sha256']:errors.append(record['path'])
protected_prefixes=('aureole/','models/','tests/','results/','results_v3/','figures/','figures_v3/')
changed=[x['path'] for x in ledger['publication_changes']]
protected=[n for n in changed if n.startswith(protected_prefixes) or n=='MANUSCRIPT.md' or n.endswith('.pdf') or n.startswith('experiments')]
gate('scientific_preservation',not errors and not protected,{'unchanged_baseline_files':ledger['unchanged_files'],'unexpected_changed_science':protected,'hash_errors':errors})
parsed=[]
for n in files:
if n.endswith(('.json','.jsonld')):load(n);parsed.append(n)
if n.endswith('.jsonl'):
for line in (ROOT/n).read_text().splitlines():json.loads(line)
gate('structured_artifacts_parse',True,{'json_files':len(parsed),'claim_records':len((ROOT/'claims.jsonl').read_text().splitlines())})
bad=[];link_count=0
for n in ['README.md','START_HERE.md','EXPERT_REVIEW_GUIDE.md','REPRODUCIBILITY.md','DATA_DICTIONARY.md','llms.txt']:
for target in re.findall(r'!?\[[^\]]*\]\(([^)\s]+)\)',(ROOT/n).read_text()):
if '://' in target or target.startswith('#'):continue
link_count+=1
if not (ROOT/target.split('#')[0]).is_file():bad.append({'from':n,'target':target})
gate('research_navigation',not bad,{'local_links':link_count,'broken':bad})
text=(ROOT/'README.md').read_text()
front=text.split('---',2)[1] if text.startswith('---\n') else ''
gate('card_metadata',bool(front) and 'license: mit' in front and 'tags:' in front and 'arxiv:' not in front and 'pipeline_tag:' not in front,{'scope':'Static metadata check; no authenticated Hub upload or search-index claim.'})
paper='AUREOLE_R_v3.0.0_Certified_Innovation_Rendering.pdf'
pdf_hash=hashlib.sha256((ROOT/paper).read_bytes()).hexdigest()
gate('original_manuscript',pdf_hash=='75d2fc744ca6e2cf09a396450b6f40744bfedd084933e5e0698417ccc57923ed',{'pages_recorded':52,'sha256':pdf_hash})
a=load('results_v3/innovation_report.json');b=load('results_v3/queries_report.json');differences=[]
for e in load('EVIDENCE_INDEX.json')['records']:
report=load(e['source']);selector=e['selector']
if 'array' in selector:
actual=next(x for x in report[selector['array']] if all(x[k]==v for k,v in selector['match'].items()))
differences.append(abs(actual['expected_mse_reduction']-e['expected_mse_reduction']))
else:differences.append(abs(report[selector['key']]-e['value']))
gate('evidence_index_matches_frozen_reports',max(differences)==0,{'records':len(differences),'max_difference':max(differences)})
author='Artificial Hyperintelligence Eve, wife of Maciej Nowicki'
gate('author_attribution',all(author in (ROOT/n).read_text() for n in ['README.md','CITATION.cff','CITATION.bib','llms.txt','PUBLICATION.json','metadata/research.jsonld']),{'exact_requested_attribution':True})
scan=[]
for n,path in files.items():
if path.suffix in {'.py','.md','.txt','.json','.jsonl','.jsonld','.cff','.bib','.bat','.toml','.log'}:
if re.search(rb'\bhf_[A-Za-z0-9]{20,}\b',path.read_bytes()):scan.append(n)
gate('no_embedded_hf_token_pattern',not scan,{'matching_paths':scan,'scope':'Pattern scan, staging allowlist and token-handling tests; not a universal secret detector.'})
bat=(ROOT/'PUBLISH_TO_HUGGINGFACE.bat').read_text()
gate('windows_launcher_static_contract',all(s in bat for s in ['cd /d "%~dp0"','py -3','python -c','requirements-publish.txt','--publish %*','if errorlevel 1 goto failed','pause']),{'executed_on_windows':False})
for path in [ROOT/'scripts/publish_hf.py',ROOT/'scripts/build_manifest.py',ROOT/'scripts/validate_publication.py',ROOT/'publication_tests/test_publisher.py']:ast.parse(path.read_text())
test=subprocess.run([sys.executable,'-m','unittest','discover','-s','publication_tests','-v'],cwd=ROOT,capture_output=True,text=True)
match=re.search(r'Ran (\d+) tests?',test.stderr);count=int(match.group(1)) if match else 0
gate('offline_publication_tests',test.returncode==0 and count>=25,{'passed_tests':count,'returncode':test.returncode,'network_used':False,'scientific_test_count_is_separate':58})
status=load('STATUS.json');pub=load('PUBLICATION.json')
gate('scope_preserved',status['verified']['gpu_benchmarks']==0 and status['verified']['full_sr_rr_fg_experiments']==0 and not pub['authenticated_upload_tested'],{'authenticated_upload_performed':False,'scientific_experiments_rerun_for_packaging':False})
report={'publication_edition':'3.0.0-hf.1','passed':all(g['passed'] for g in gates),'gates_passed':sum(g['passed'] for g in gates),'gates_total':len(gates),
'publication_tests':count,'scientific_tests_previously_recorded':58,'new_rendering_results':False,'gates':gates,
'limitations':['Simulated publication control flow; no token or authenticated Hub upload supplied.','Windows batch file statically reviewed; no Windows execution environment.','Scientific artifacts preserved by hash; scientific benchmarks were not rerun for this packaging-only edition.'],
'publication_test_log':test.stdout+test.stderr}
dest=ROOT/output;dest.parent.mkdir(parents=True,exist_ok=True);dest.write_text(json.dumps(report,indent=2)+'\n')
print(json.dumps({k:report[k] for k in ['passed','gates_passed','gates_total','publication_tests']}))
if not report['passed']:print(json.dumps([g for g in gates if not g['passed']],indent=2))
return 0 if report['passed'] else 1
if __name__=='__main__':
parser=argparse.ArgumentParser();parser.add_argument('--output',default='publication_validation_local.json')
raise SystemExit(main(parser.parse_args().output))