"""Register only normal acquisition; never sample inputs or execute a brain. Prior sealed files stay read-only. Complete historical integrity is checked at the phase boundary; each trial rehashes its actual runtime dependency closure, not every historical engineering result. No source or budget changes after registration. Outcome files have no invented pre-outcome hashes. """ from __future__ import annotations import argparse import copy from datetime import datetime, timezone, timedelta import shutil import subprocess import sys from normal_io import * import normal_plan as PLAN AQ_EXP = ROOT/'experiments/phase4aq-conditioning-execution' AP_EXP = ROOT/'experiments/phase4ap-conditioning-interface-v2' AO_EXP = ROOT/'experiments/phase4ao-conditioning-interface' AQ_ANCHORS = { 'protocol/preregistered.json':'dad0ba33ded8c6725662c419525ef4185a6ff169042a402c18d0bd760dad7358', 'manifest.json':'2dc0feca75f718f2ee0d7c9240da503221823573fd25f1344d2fd97d97eb2db7', 'audit/final-status.json':'dcbb58f296bd0d51e3c8757f0c45dd5585b3a76f8c2a0b5881f4c14076721882', } H_ANCHORS = { 'audit/phase4h.py':'28bb2ab7c4c95af3d95b0bf0bc45a5a9bea791996c59ce296ec66b71e01b1695', 'mappings/mbon-to-downstream-actual-edges.parquet':'76bac27c50cec41c48fd6414bcef5a6e270753ac4062b92537f38226018e9278', 'manifests/checksums.sha256':'1ea0394fd0477bb40d656ed0854108964f3809d633b5561bed9de43cda630ba1', 'manifests/manifest.json':'d1f187f164f7775a1a02fff259c8f5e31ae035929d808c3876cfc0013d19c73c', } # Exact arrays consumed by the pinned isolated worker, not every reference file # colocated in its graph/APL directories. Tests compare these to that worker. GRAPH_FILES = ('nodes.npy', 'edge_id.npy', 'src.npy', 'dst.npy', 'signed_raw.npy', 'ptr.npy', 'weights.npy') APL_FILES = ('input_matrix.npy', 'output_matrix.npy', 'kc_globals.npy', 'apl_globals.npy') def runtime_array_paths(template): return {str(Path(template['graph_dir'])/name) for name in GRAPH_FILES} | { str(Path(template['apl_bundle_dir'])/name) for name in APL_FILES} | {template['coefficients_path']} def readout_populations(population_file): import numpy as np import pyarrow.parquet as pq h=ROOT/'experiments/phase4h-dopamine-plasticity' verify({str(h/p):s for p,s in H_ANCHORS.items()}) rows=pq.read_table(h/'mappings/mbon-to-downstream-actual-edges.parquet',columns=['target_neuron_idx'])['target_neuron_idx'].to_numpy() require(rows.dtype==np.int32 and len(rows)==39279 and np.all((rows>=0)&(rows<166700)), 'Original H endpoint schema differs') old=npz(population_file) result={k:old[k] for k in ('MBON','MBON01','MBON12')} result['legacyDownstream']=np.unique(rows).astype(np.int32) result['nonMBONDownstream']=np.setdiff1d(result['legacyDownstream'],result['MBON']) require(not len(np.setdiff1d(result['MBON'],result['legacyDownstream'])),'H downstream no longer includes all MBON') hashes={k:hashlib.sha256(v.tobytes()).hexdigest() for k,v in result.items()} require(hashes['legacyDownstream']=='ce9edbb56854be8f6891bfb83559dd7529c70acac6867864947f32f933175dbc' and hashes['nonMBONDownstream']=='01e3fbdde8bf2558665f142cdf546d8b89b4898427b90e2f4368f21f4e241a7f', 'Actual H readout membership changed') return result,dict(source_sha256={str(h/p):s for p,s in H_ANCHORS.items()}, original_populations=pin(population_file),definition='unique actual H MBON-edge target_neuron_idx, int32; no plastic/active subset', nonMBON_definition='exact set difference legacyDownstream minus full anatomical MBON', counts={k:len(v) for k,v in result.items()},raw_membership_sha256=hashes, historical_current_model_source_used=False,original_sealed_audit_source_used=True) def historical_integrity(): verify({str(AQ_EXP/p):s for p,s in AQ_ANCHORS.items()}) ar = read(AQ_EXP/'protocol/preregistered.json') verify(ar['source_sha256']) # This function is executed in a separate preparation/integrity CPU process. for p in (AQ, AP, LAB): sys.path.insert(0,str(p)) old = load_source('_normal_previous_integrity',AQ/'prepare_execution.py',ar['source_sha256'][str(AQ/'prepare_execution.py')]) prior = old.integrity() helper = load_source('_normal_AQ_seal_reader', MODEL.parent/'pn-recruitment-audit-v1/publication.py', '7a79c499098b74163e7bb16adabcbc54e7069dafa204d0b99c7f4c03d79f8016') sealed = helper.verify_seal(AQ_EXP) require(read(AQ_EXP/'audit/final-status.json')['status'] == 'PASS-EXACT-UPDATED-BOUNDARY-ENGINEERING-NOT-LEARNING','AQ gate differs') return dict(complete=True,prior=prior,AQ=sealed,old_experiments_reexecuted=False, frozen_five_reexecuted=False,scope='actual historical seal bytes reverified, preserved numerical evidence; not a new numerical trial') def resource_policy(): """Engineering ceiling, not a measured all-condition forecast or stop-for-success.""" return dict(root=str(EXP),output_cap_bytes=256*1024**3,minimum_free_reserve_bytes=100*1024**3, child_timeout_seconds=1800,workflow_timeout_seconds=21*86400,max_uniform_draws=10_000_000, next_child_headroom_bytes=4*1024**3, execution='serial_single_4090',no_automatic_retry=True, forecast_scope='rough planning arithmetic from one AQ warm training cycle and one probe; not condition-complete measurement', AQ_measured_training_cycle_seconds=24.771224757998425,AQ_measured_probe_seconds=10.394962482001574, AQ_linear_wall_scenario_seconds=30000*24.771224757998425+3920*10.394962482001574, uncertainties=['startup and materialization','event-dependent output size','all control/DAN/odor activity', 'ledger growth','shared service contention','final full integrity audit'], cap_or_timeout_policy='preserve all outputs, stop incomplete; no shortening epochs or selecting favorable outcomes') def prepare(): require(sys.dont_write_bytecode and unlinked(EXP).is_dir() and not any(EXP.iterdir()), 'Exact new empty EXP and -B required') files=sorted(MODEL.iterdir()) require(files and all(p.is_file() and not p.is_symlink() and p.suffix in ('.py','.md') for p in files), 'Source-only model directory') sources={str(p):digest(p) for p in files} commit=subprocess.check_output(['git','-C',str(ROOT),'rev-parse','HEAD']).decode().strip() for path,sha in sources.items(): blob=subprocess.check_output(['git','-C',str(ROOT),'show',commit+':'+Path(path).relative_to(ROOT).as_posix()]) require(hashlib.sha256(blob).hexdigest()==sha, 'Uncommitted source '+path) budget=resource_policy() budget['registered_utc']=datetime.now(timezone.utc).isoformat() budget['not_after_utc']=(datetime.now(timezone.utc)+timedelta(seconds=budget['workflow_timeout_seconds'])).isoformat() require(shutil.disk_usage(EXP).free >= budget['output_cap_bytes']+budget['minimum_free_reserve_bytes'], 'Insufficient reserved capacity') for name in ('protocol/source-snapshot','inputs/static','jobs','cases','runs','updates','validation','results','receipts','logs','audit','regression'): unlinked(EXP/name).mkdir(parents=True) tests=subprocess.run([sys.executable,'-B',str(MODEL/'run_cpu_tests.py'),'--output',str(EXP/'audit/cpu-tests.json')], capture_output=True,text=True,timeout=1800,env={**dict(__import__('os').environ),'CUDA_VISIBLE_DEVICES':''}) save(EXP/'audit/cpu-tests.process.json',dict(exit_code=tests.returncode,stdout=tests.stdout,stderr=tests.stderr, actual_parent_observation=True)) require(tests.returncode==0 and read(EXP/'audit/cpu-tests.json')['pass_all'] is True, 'CPU/source tests failed; no sampler or brain started') # Old integrity readers may own a private R/C module graph. Keep them in an # exec-isolated CPU process, never the table/registration interpreter. integrity_command=[sys.executable,'-B',str(MODEL/'normal_prepare.py'),'integrity', '--output',str(EXP/'regression/integrity-before.json')] checked=subprocess.run(integrity_command,capture_output=True,text=True,timeout=1800, env={**dict(__import__('os').environ),'CUDA_VISIBLE_DEVICES':''}) save(EXP/'regression/integrity-before.process.json',dict(argv=integrity_command,exit_code=checked.returncode, stdout=checked.stdout,stderr=checked.stderr,actual_parent_observation=True)) require(checked.returncode==0,'Historical integrity child failed; preserve artifacts') before=read(EXP/'regression/integrity-before.json');require(before['complete'] is True,'Integrity child incomplete') aq=read(AQ_EXP/'protocol/preregistered.json') full=read(PLAN.AO_TRIAL_PATH) require(digest(PLAN.AO_TRIAL_PATH)==PLAN.AO_TRIAL_FILE_SHA256,'Original full plan pin differs') evaluation=PLAN.expand_pinned_evaluation(full) plan=PLAN.build_normal_plan(full,evaluation) from normal_inputs import derive_rates, inventory_from_plan, PINS, dependencies rate_tables,rate_audit=derive_rates() inputs=inventory_from_plan(plan) template_path=AP_EXP/'cases/D1--reference--epoch-001/spec.json' authority_path=AP_EXP/'jobs/D1--reference--epoch-001.authority.json' template=read(template_path); epoch=read(authority_path) pinned={**aq['input_sha256'],**aq['source_sha256'],**aq['prepared_file_sha256']} for path in (template_path,authority_path,AO_EXP/'inputs/static/populations.npz'): require(str(path) in pinned and digest(path)==pinned[str(path)],'Original template/population not pinned') for path in sources: with Path(path).open('rb') as i,(EXP/'protocol/source-snapshot'/Path(path).name).open('xb') as o:shutil.copyfileobj(i,o) save(EXP/'protocol/normal-plan.json',plan) save(EXP/'protocol/evaluation-policy.json',evaluation['config']) save(EXP/'protocol/input-inventory.json',inputs) save(EXP/'protocol/case-template.json',template) # Freeze scientific predicates before any new CS sample or outcome. gate_sources={str(AQ/'learning_gates.py'):'8ae9bcb77fe14dbdda164f86ffdbfc1e2976be752766ef526777577223b4dd99', str(LAB/'metrics.py'):'47319e21db3c8b030b1bafbf0703cd86fb588d23bb29436accbacdba73d08c3c'} verify(gate_sources) save(EXP/'protocol/gates.json',dict(source_sha256=gate_sources,all_eight_cells_required=True, same_replicate_conjunction_at_least=3,training_replicates=5,terminal_checkpoint=50, normal_failure_prevents_followups=True,intermediate_checkpoints_cannot_rescue_terminal=True, downstream_policy='nonMBONDownstream-pre-outcome-operationalization-v1', H_mapping='each-DAN-control-source-separately-both-pass-v1', physiological_and_matched_energy_not_pooled=True,unknown_compartments_not_guessed=True)) save(EXP/'inputs/static/rate-audit.json',rate_audit) for key,table in rate_tables.items():save_npz(EXP/f'inputs/static/{key}.npz',table) populations,pop_audit=readout_populations(AO_EXP/'inputs/static/populations.npz') save_npz(EXP/'inputs/static/readout-populations.npz',populations) save(EXP/'inputs/static/readout-population-binding.json',pop_audit) # Actual consumed neural dependency closure, all inherited byte pins. required=runtime_array_paths(template) require(required <= pinned.keys(), 'Consumed runtime arrays missing inherited pins: '+str(sorted(required-pinned.keys()))) original_sources={p:s for p,s in epoch['frozen_inputs'].items() if p.startswith(str(ROOT/'models/male-cns-lif/') ) and ('author-' in p or 'apl-timing-lab-v1/' in p)} runtime={p:pinned[p] for p in required} runtime.update(original_sources) roles={k:v for k,v in epoch['files'].items() if k not in ('spec','requests','state','overlay_before','overlay_manifest_before')} runtime.update({v['path']:v['sha256'] for v in roles.values()}) save(EXP/'protocol/epoch-template.json',dict(schema=epoch['schema'],files=roles,frozen_inputs=runtime)) static={str(LAB/n):s for n,s in {**PLAN.SOURCE_PINS,**PINS}.items()} static.update({str(ROOT/p):s for p,s in rate_audit['original_source_sha256'].items()}) external={**runtime,**static,**gate_sources,**pop_audit['source_sha256'],**{str(AQ_EXP/p):s for p,s in AQ_ANCHORS.items()}, str(PLAN.AO_TRIAL_PATH):PLAN.AO_TRIAL_FILE_SHA256,str(AP/'isolated_workers.py'):AP_SHA, str(authority_path):pinned[str(authority_path)],str(template_path):pinned[str(template_path)], str(AO_EXP/'inputs/static/populations.npz'):pinned[str(AO_EXP/'inputs/static/populations.npz')], str(AQ/'validate_update_cpu.py'):aq['source_sha256'][str(AQ/'validate_update_cpu.py')]} for name in ('conditioning_epoch.py','conditioning_preflight_compare.py','engineering_compare.py'): path=str(LAB/name);require(path in pinned,'Missing original verifier source pin');external[path]=pinned[path] zero=aq['initial_overlay'] external.update({p:digest(p) for p in zero.values()}) verify(external) prepared={p:row['sha256'] for p,row in inventory(EXP).items()} reg=dict(schema='normal-conditioning-registration-v1',scientific_scope='normal-acquisition-only', subsequent_assays_authorized=False,source_code_commit=commit,source_sha256=sources,input_sha256=external, static_input_sha256=static,runtime_input_sha256=runtime,prepared_sha256=prepared,budget=budget, initial_overlay=zero,population_file=str(AO_EXP/'inputs/static/populations.npz'), readout_population_file=str(EXP/'inputs/static/readout-populations.npz'), readout_population_binding_file=str(EXP/'inputs/static/readout-population-binding.json'), original_full_trial_plan=pin(PLAN.AO_TRIAL_PATH),normal_inventory=plan['inventory'], evidence_scope='AQ validates exact interface, not learning; this new registration admits actual normal outcomes', brain_parameters_changed=False,learning_success_claimed=False, execution_order='original fixed block/arm order; actual A/B baseline each arm; no outcome selection', biological_hypotheses='D18 branch; PAM15/PPL103 compartment hypotheses only, not all-PAM/PPL functional assignment', historical_integrity_scope=before['scope'],failure_policy='stop preserve partials, never auto retry', administrative_supervisor_directory=str(ROOT/'logs/phase4ar-normal-conditioning'), supervisor_logging_scope='outside immutable EXP ledger; real top-level exit and logs must be included by final outer auditor', full_plan_in_old_frozen_location=True,future_artifact_hashes_fabricated=False) save(EXP/'protocol/preregistered.json',reg) return digest(EXP/'protocol/preregistered.json') if __name__=='__main__': p=argparse.ArgumentParser();p.add_argument('mode',choices=('prepare','integrity'));p.add_argument('--output') a=p.parse_args() if a.mode=='prepare':print('REGISTRATION_SHA256',prepare(),flush=True) else: require(a.output,'Exclusive report path required');save(a.output,historical_integrity())