Add bounded same-state update validation and functional gates
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
"""Exclusive preregistration for a finite NEW execution-boundary experiment.
|
||||
|
||||
No sampler, brain, update or historical experiment is executed by preparation.
|
||||
Frozen checksums are read. Future outputs are derived later from explicit rules,
|
||||
never given fabricated preregistered hashes. Real learning is NOT authorized.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
import boundary_plan as PLAN
|
||||
import execution_authority as A
|
||||
|
||||
ROOT=Path('/data/digital-drosophila')
|
||||
MODEL=Path(__file__).resolve().parent
|
||||
EXP=ROOT/'experiments/phase4aq-conditioning-execution'
|
||||
AP=ROOT/'experiments/phase4ap-conditioning-interface-v2'
|
||||
AO=ROOT/'experiments/phase4ao-conditioning-interface'
|
||||
LAB=MODEL.parent/'olfactory-conditioning-lab-v1'
|
||||
require,read,digest=A.require,A.read,A.digest
|
||||
|
||||
|
||||
def save(path,value):
|
||||
with Path(path).open('x',encoding='utf-8') as f:
|
||||
json.dump(value,f,sort_keys=True,indent=2,allow_nan=False,ensure_ascii=False);f.write('\n')
|
||||
|
||||
|
||||
def copy_exclusive(source,target):
|
||||
with Path(source).open('rb') as inp,Path(target).open('xb') as out:shutil.copyfileobj(inp,out)
|
||||
require(digest(source)==digest(target),'Exclusive source copy differs')
|
||||
|
||||
|
||||
def npz(path):
|
||||
with np.load(path,allow_pickle=False) as f:return {n:f[n].copy() for n in f.files}
|
||||
|
||||
|
||||
def save_npz(path,values):
|
||||
with Path(path).open('xb') as f:np.savez_compressed(f,**values)
|
||||
|
||||
|
||||
def verify(pins):
|
||||
for path,sha in pins.items():require(A.pin(path)['sha256']==sha,'Pinned input changed: '+str(path))
|
||||
|
||||
|
||||
def old_context():
|
||||
pins={str(AP/k):v for k,v in PLAN.AP_ANCHORS.items()}
|
||||
pins.update({str(MODEL.parent/k):v for k,v in PLAN.SOURCE_PINS.items()})
|
||||
verify(pins)
|
||||
apreg=read(AP/'protocol/preregistered.json')
|
||||
verify({**apreg['input_sha256'],**apreg['source_sha256'],**apreg['prepared_file_sha256']})
|
||||
path=MODEL.parent/'conditioning-interface-v2/coordinator.py'
|
||||
raw=path.read_bytes();name='_conditioning_execution_prior_integrity'
|
||||
require(name not in sys.modules,'Fresh preparation/integrity process required')
|
||||
spec=importlib.util.spec_from_file_location(name,path);module=importlib.util.module_from_spec(spec)
|
||||
sys.modules[name]=module;exec(compile(raw,str(path),'exec'),module.__dict__)
|
||||
return module,apreg,pins
|
||||
|
||||
|
||||
def integrity():
|
||||
old,apreg,pins=old_context()
|
||||
earlier=old.previous_integrity();current=old.helper().verify_seal(AP)
|
||||
require(read(AP/'audit/final-status.json')['status']=='PASS-EXACT-PROCESS-ISOLATED-DELTA-INTERFACE-NOT-LEARNING',
|
||||
'AP interface gate changed')
|
||||
return dict(complete=True,AP=current,prior=earlier,anchors=pins,
|
||||
old_experiments_reexecuted=False,old_files_modified=False,
|
||||
five_frozen_reference_trials_rerun_here=False,
|
||||
historical_reference_evidence_scope='Preserved AM numerical regression evidence; checksums now reverified',
|
||||
scientific_learning_pass_claimed=False)
|
||||
|
||||
|
||||
def source_inventory():
|
||||
entries=list(MODEL.iterdir())
|
||||
require(entries and all(p.is_file() and not p.is_symlink() and p.suffix in ('.py','.md') for p in entries),
|
||||
'Source directory may contain only explicit unlinked Python/Markdown source files')
|
||||
return {str(p):digest(p) for p in sorted(entries)}
|
||||
|
||||
|
||||
def prepare():
|
||||
require(sys.dont_write_bytecode and EXP.is_dir() and not any(EXP.iterdir()),'Use -B and exact new empty experiment directory')
|
||||
old,apreg,anchors=old_context()
|
||||
before=dict(complete=True,AP=old.helper().verify_seal(AP),prior=old.previous_integrity(),
|
||||
five_frozen_reference_trials_rerun_here=False,old_files_modified=False)
|
||||
plan=PLAN.build_plan();PLAN.validate_plan(plan)
|
||||
source=source_inventory();commit=subprocess.check_output(['git','-C',str(ROOT),'rev-parse','HEAD']).decode().strip()
|
||||
require(len(commit)==40,'Missing actual code commit')
|
||||
for path,sha in source.items():
|
||||
raw=subprocess.check_output(['git','-C',str(ROOT),'show',commit+':'+Path(path).relative_to(ROOT).as_posix()])
|
||||
require(hashlib.sha256(raw).hexdigest()==sha,'Source not equal to committed blob: '+path)
|
||||
budget=dict(root=str(EXP),output_cap_bytes=4*1024**3,minimum_free_reserve_bytes=10*1024**3,
|
||||
child_timeout_seconds=1800,workflow_timeout_seconds=7200)
|
||||
require(shutil.disk_usage(EXP).free>=budget['output_cap_bytes']+budget['minimum_free_reserve_bytes'],
|
||||
'Insufficient space for finite validation budget')
|
||||
pins={**anchors,**apreg['input_sha256'],**apreg['source_sha256'],**apreg['prepared_file_sha256']}
|
||||
parents={}
|
||||
for arm,descriptor in plan['imported_parents'].items():
|
||||
directory=Path(descriptor['checkpoint_manifest']).parent
|
||||
record=old.C.load_checkpoint(directory,descriptor['sha256'])
|
||||
require(record['fresh'] and record['steps']==1200,'Imported parent is not the declared fresh epoch')
|
||||
authority=AP/'jobs'/f'{arm}--reference--epoch-001.authority.json'
|
||||
update=AP/'updates'/f'{arm}--reference--epoch-001'
|
||||
ea=read(authority)
|
||||
require(ea['checkpoint_dir']==str(directory) and ea['checkpoint_manifest_sha256']==descriptor['sha256'],
|
||||
'Original update authority is not bound to selected parent')
|
||||
for path in (directory/'checkpoint-manifest.json',authority,*update.iterdir()):pins[str(path)]=digest(path)
|
||||
parents[descriptor['role']]=dict(directory=str(directory),checkpoint_sha256=descriptor['sha256'],
|
||||
epoch_authority=A.pin(authority),update_dir=str(update),update_sha256={p.name:digest(p) for p in update.iterdir()},
|
||||
before_overlay=dict(overlay_file=ea['files']['overlay_before']['path'],overlay_manifest=ea['files']['overlay_manifest_before']['path']),
|
||||
after_overlay=dict(overlay_file=str(update/'delta-after.npz'),overlay_manifest=str(update/'overlay-manifest.json')))
|
||||
zero=apreg['initial_overlay']
|
||||
require(A.pin(zero['overlay_file'])==plan['initial_overlay']['overlay_file'] and
|
||||
A.pin(zero['overlay_manifest'])==plan['initial_overlay']['overlay_manifest'],'Initial zero reference differs')
|
||||
require(not np.any(npz(zero['overlay_file'])['plastic_delta_mv'].view(np.uint32)),'Initial delta is not positive zero')
|
||||
template=read(AP/'cases/D1--reference--epoch-001/spec.json')
|
||||
for name in ('protocol/source-snapshot','protocol/case-templates','inputs/static','cases','runs','updates',
|
||||
'jobs','authorities','receipts','logs','audit','regression'):(EXP/name).mkdir(parents=True)
|
||||
for path in source:copy_exclusive(path,EXP/'protocol/source-snapshot'/Path(path).name)
|
||||
save(EXP/'regression/integrity-before.json',before)
|
||||
templates={}
|
||||
for call in plan['calls']:
|
||||
group=call.get('case_group',call['call_id'])
|
||||
spec=PLAN.derive_case_spec(template,call['call_id'],budget_root=str(EXP))
|
||||
if group in templates:require(spec==read(templates[group]),'Shared comparison case templates differ')
|
||||
else:
|
||||
dest=EXP/'protocol/case-templates'/f'{group}.json';save(dest,spec);templates[group]=str(dest)
|
||||
ea=read(parents[plan['imported_parents']['D1']['role']]['epoch_authority']['path'])
|
||||
candidate=npz(ea['files']['candidate_map']['path'])
|
||||
population_file=AO/'inputs/static/populations.npz'
|
||||
require(str(population_file) in pins,'Original anatomical population inventory not pinned by AP')
|
||||
populations=npz(population_file);dan=populations['PAM15']
|
||||
requests,selection=PLAN.mechanical_requests(candidate,dan,identity_binding=dict(
|
||||
candidate_map_sha256=ea['files']['candidate_map']['sha256'],
|
||||
pam15_membership_sha256=hashlib.sha256(dan.tobytes()).hexdigest()))
|
||||
require(np.isin(candidate['source_neuron_idx'],populations['Kenyon_Cell']).all(),'Candidate source outside original KC population')
|
||||
save_npz(EXP/'inputs/static/mechanical-requests.npz',requests)
|
||||
save(EXP/'inputs/static/mechanical-selection.json',selection)
|
||||
# Original physiological PN mapping is recomputed without stochastic sampling.
|
||||
import conditioning_preflight_inputs as I
|
||||
rates=I.load_rate_tables(ROOT)
|
||||
for cue,table in rates['tables'].items():
|
||||
existing=npz(AO/f'inputs/static/{cue}-rates.npz')
|
||||
require(all(table[k].dtype==existing[k].dtype and table[k].shape==existing[k].shape and
|
||||
table[k].tobytes()==existing[k].tobytes() for k in ('targets','rates_hz')),
|
||||
'Prior physiological PN mapping differs')
|
||||
copy_exclusive(AO/f'inputs/static/{cue}-rates.npz',EXP/f'inputs/static/{cue}-rates.npz')
|
||||
save(EXP/'inputs/static/rate-audit.json',rates['audit'])
|
||||
fullplan=AO/'protocol/full-trial-plan.json'
|
||||
require(str(fullplan) in pins,'Original full seed/trial plan not pinned')
|
||||
prepared={str(p):digest(p) for sub in ('protocol','inputs/static','regression') for p in (EXP/sub).rglob('*') if p.is_file()}
|
||||
reg=dict(schema='conditioning-execution-registration-v1',engineering_only=True,scientific_acquisition_authorized=False,
|
||||
scope='bounded updated-state boundary, fixed functional-gate code, complete-process budget measurement',
|
||||
plan=plan,source_sha256=source,source_code_commit=commit,input_sha256=pins,prepared_file_sha256=prepared,
|
||||
parent_records=parents,initial_overlay=zero,case_templates=templates,budget=budget,original_full_plan=A.pin(fullplan),
|
||||
old_source_changes=False,old_experiments_reexecuted=False,brain_or_sampler_run_during_preparation=False,
|
||||
future_hashes_fabricated=False,learning_success_claimed=False,
|
||||
failure_policy='stop and preserve partials; never automatic retry, tuning, seed search, or trial truncation')
|
||||
verify({**pins,**source,**prepared})
|
||||
save(EXP/'protocol/preregistered.json',reg)
|
||||
return digest(EXP/'protocol/preregistered.json')
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
parser=argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('mode',choices=('prepare','integrity'))
|
||||
parser.add_argument('--output')
|
||||
args=parser.parse_args()
|
||||
if args.mode=='prepare':print('REGISTRATION_SHA256',prepare(),flush=True)
|
||||
else:
|
||||
require(args.output and not Path(args.output).exists(),'Exclusive integrity report required')
|
||||
save(args.output,integrity());print('INTEGRITY_SHA256',digest(args.output),flush=True)
|
||||
Reference in New Issue
Block a user