Files
digital-drosophila/registry/phase4an-engineering-validation/source-snapshot/engineering_prepare.py
T
2026-09-30 16:46:21 +08:00

533 lines
35 KiB
Python

"""Read-only AM authority verification and exclusive AN engineering preparation.
Public prepare(model_manifest_sha, experiment_manifest_sha, final_sha) requires
three externally recorded, actual AM evidence hashes. It verifies both complete
AM seals once, checks their declared gates, then fixes the first planned r0 case.
It creates only templates/requests/overlay descriptors and a preregistration;
never a GPU trajectory or fictitious future checkpoint hash. The caller records
the returned preregistration SHA outside this experiment before execution.
read_registration(expected_sha) rehashes the exact used source/input inventory
and control anchors without rerunning either scientific gate or full AM seal.
Future spec.json/checkpoint receipts are runtime artifacts, not preregistered
bytes. No frozen model module globals are modified; no Torch is imported.
"""
from __future__ import annotations
import hashlib
import importlib.util
import json
from pathlib import Path, PurePosixPath
import re
import shutil
import sys
import numpy as np
ROOT = Path('/data/digital-drosophila')
MODEL = Path(__file__).resolve().parent
EXP = ROOT / 'experiments/phase4an-engineering-validation'
AM_MODEL_REL = Path('models/male-cns-lif/wholebrain-plastic-interface-v1')
AM_EXP_REL = Path('experiments/phase4am-wholebrain-plastic-interface')
AK_REL = Path('experiments/phase4ak-apl-timing-validation')
AI_HELPER_REL = Path('models/male-cns-lif/pn-recruitment-audit-v1/publication.py')
AI_HELPER_SHA = '7a79c499098b74163e7bb16adabcbc54e7069dafa204d0b99c7f4c03d79f8016'
AM_PREREG_SHA = '465886b78ada08092c2c83de278844707499718977fb6dc6a7608391da0e5304'
AM_OVERLAY_SHA = '7f891d0ba79b393c96e75fd2dee2eddc51e57d8213eaac2779703bc2c18712b4'
FINAL_STATUS = 'PASS-EXACT-WHOLEBRAIN-PLASTIC-INTERFACE-NOT-LEARNING'
REG_SCHEMA = 'phase4an-engineering-registration-v1'
BUDGET = {'output_budget_bytes': 8 * 1024**3, 'minimum_free_reserve_bytes': 10 * 1024**3}
MODULES = ('runtime_light', 'runtime_continuation', 'engineering_inputs', 'engineering_plan',
'engineering_compare', 'engineering_queue_audit', 'engineering_prepare', 'engineering_workflow',
'engineering_scopes', 'engineering_analysis')
SOURCE_FILES = tuple(sorted([name + '.py' for name in MODULES] + ['test_' + name + '.py' for name in MODULES] + ['ENGINEERING_GATE_DRAFT.md']))
REFERENCES = ('auditory-10hz', 'auditory-100hz', 'olfactory-50hz', 'mechanosensory-50hz', 'gustatory-50hz')
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')
_MODULE_CACHE = {}
def require(ok, message):
if not ok:
raise ValueError(message)
def digest(path):
value = hashlib.sha256()
with Path(path).open('rb') as stream:
for block in iter(lambda: stream.read(8 << 20), b''):
value.update(block)
return value.hexdigest()
def sha(value):
return type(value) is str and re.fullmatch('[0-9a-f]{64}', value) is not None
def read(path):
def unique(pairs):
result = {}
for key, value in pairs:
require(key not in result, 'Duplicate JSON key: ' + key)
result[key] = value
return result
return json.loads(Path(path).read_text(encoding='utf-8'), object_pairs_hook=unique,
parse_constant=lambda value: (_ for _ in ()).throw(ValueError('Nonfinite JSON: ' + value)))
def save(path, value):
path = Path(path)
path.parent.mkdir(parents=True, exist_ok=True)
with path.open('x', encoding='utf-8') as stream:
json.dump(value, stream, sort_keys=True, indent=2, ensure_ascii=False, allow_nan=False)
stream.write('\n')
def load_module(name, path, expected):
path = Path(path).resolve(strict=True)
raw = path.read_bytes()
require(hashlib.sha256(raw).hexdigest() == expected, 'Source pin mismatch: ' + str(path))
identity = str(path), expected
if name in sys.modules:
require(_MODULE_CACHE.get(name) == (identity, sys.modules[name]), 'Unverified module namespace collision')
return sys.modules[name]
spec = importlib.util.spec_from_file_location(name, path)
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
try:
exec(compile(raw, str(path), 'exec'), module.__dict__)
except BaseException:
sys.modules.pop(name, None)
raise
_MODULE_CACHE[name] = identity, module
return module
def source_inventory(model):
model = Path(model).resolve(strict=True)
result = {}
for name in SOURCE_FILES:
path = model / name
require(path.is_file() and not path.is_symlink() and path.resolve().parent == model, 'Required engineering source missing/linked: ' + name)
result[str(path)] = digest(path)
return result
def _relative(value):
require(type(value) is str and value and '\\' not in value, 'Invalid relative inventory path')
path = PurePosixPath(value)
require(not path.is_absolute() and str(path) == value and all(part not in ('', '.', '..') and ':' not in part for part in path.parts),
'Noncanonical relative inventory path')
return path
def _safe_file(root, relative):
relative = _relative(relative)
root = Path(root).resolve(strict=True)
path = root
for part in relative.parts:
path = path / part
require(not path.is_symlink(), 'Linked authority/input file')
require(path.is_file() and path.resolve().is_relative_to(root), 'Missing or escaping input file')
return path
def _index(rows):
require(type(rows) is list and rows, 'Missing sealed inventory rows')
result = {}
for row in rows:
require(type(row) is dict and set(row) == {'path', 'bytes', 'sha256'} and
type(row['bytes']) is int and row['bytes'] >= 0 and sha(row['sha256']), 'Invalid sealed inventory row')
_relative(row['path'])
require(row['path'] not in result, 'Duplicate sealed inventory row')
result[row['path']] = row
return result
def _bind(inputs, path, expected=None):
path = Path(path).resolve(strict=True)
actual = digest(path)
require(expected is None or actual == expected, 'Authority/input SHA mismatch: ' + str(path))
require(str(path) not in inputs or inputs[str(path)] == actual, 'Conflicting authority for input')
inputs[str(path)] = actual
return path
def _sealed_json(experiment, index, relative):
require(relative in index, 'Required authority absent from AM seal: ' + relative)
path = _safe_file(experiment, relative)
require(digest(path) == index[relative]['sha256'], 'Sealed JSON changed: ' + relative)
return read(path)
def validate_final_status(final, scientific, before, after, refs):
"""Check actual AM final/summary/report schemas, never infer scientific PASS."""
require(final.get('status') == scientific.get('status') == FINAL_STATUS, 'AM final status is not the required completed interface gate')
for key in ('zero_overlay_exact', 'static25_repeat_exact', 'old_integrity_pass', 'frozen_five_reference_pass',
'frozen_eligibility_and_mask_unchanged', 'base_weights_unchanged'):
require(final.get(key) is True, 'AM final gate failed/missing: ' + key)
require(final.get('primary_trials_per_stage') == 120 and final.get('repeats_per_stage') == 24 and
scientific.get('primary_trials_per_stage') == 120 and scientific.get('technical_repeats_per_stage') == 24,
'AM complete coverage counts changed')
for value in (final, scientific):
require(value.get('training') is False and value.get('learned_candidate') is False, 'AM interface must not claim training/learning')
require(scientific.get('zero_overlay_exact') is True and scientific.get('static25_repeat_exact') is True, 'Scientific summary gate mismatch')
require(type(before) is dict and type(after) is dict and len(before) == len(after) == 28 and set(before) == set(after),
'AM must retain the same complete 28-root old-integrity inventory')
for name in before:
for report in (before[name], after[name]):
require(type(report) is dict and report.get('pass') is True, 'Old-integrity gate failed: ' + name)
if 'mismatches' in report:
require(report['mismatches'] == [], 'Old-integrity mismatch list is nonempty')
for key in ('manifest_sha256', 'checksums_sha256'):
if key in before[name] or key in after[name]:
require(sha(before[name].get(key)) and before[name][key] == after[name].get(key), 'Old-root control changed: ' + name)
require(refs.get('pass_all') is True and type(refs.get('trials')) is list and
[row.get('trial') for row in refs['trials']] == list(REFERENCES), 'Five old deterministic references are incomplete or reordered')
for row in refs['trials']:
require(type(row.get('exact')) is dict and set(row['exact']) == {'step', 'neuron_idx', 'counts', 'v', 'g'} and
all(value is True for value in row['exact'].values()), 'Old reference arrays are not exact')
def validate_planned(planned):
require(type(planned) is list and len(planned) == 144, 'AM planned coverage must be 144')
keys = []
for row in planned:
require(type(row) is dict and type(row.get('name')) is str and re.fullmatch('[A-Za-z0-9_-]+', row['name']) and
row.get('cohort') in ('seed_validation', 'novel_to_aj') and type(row.get('repeat')) is int and row['repeat'] in (0, 1),
'Invalid AM planned row identity')
keys.append((row['name'], row['repeat']))
require(len(set(keys)) == 144 and sum(row['repeat'] == 0 for row in planned) == 120 and sum(row['repeat'] == 1 for row in planned) == 24,
'AM primary/repeat set incomplete')
require(all((name, 0) in set(keys) for name, repeat in keys if repeat == 1), 'AM repeat lacks primary')
return next(dict(row) for row in planned if row['repeat'] == 0)
def validate_stage(experiment, index, stage, planned, root):
"""Validate all 144 declared results against the already verified AM seal."""
receipt = _sealed_json(experiment, index, 'audit/' + stage + '-complete.json')
require(receipt.get('stage') == stage and receipt.get('pass_all') is True and receipt.get('trials') == 144 and
receipt.get('primary_trials') == 120 and receipt.get('technical_repeats') == 24 and receipt.get('training') is False,
'AM stage is incomplete: ' + stage)
completed = receipt.get('completed')
require(type(completed) is list and len(completed) == 144, 'AM stage completion inventory truncated')
for row, done in zip(planned, completed):
require(done.get('name') == row['name'] and done.get('repeat') == row['repeat'], 'AM stage completion order/identity mismatch')
prefix = 'gpu/' + stage + '/' + row['name'] + '-r' + str(row['repeat']) + '/'
expected = [dict(path=key[len(prefix):], bytes=value['bytes'], sha256=value['sha256']) for key, value in sorted(index.items())
if key.startswith(prefix) and key != prefix + 'output-hashes.json']
inventory = _sealed_json(experiment, index, prefix + 'output-hashes.json')
require(inventory == expected and inventory, 'AM completed output inventory differs from sealed payload')
require(done.get('output_hashes_sha256') == index[prefix + 'output-hashes.json']['sha256'] and
done.get('comparison_sha256') == index[prefix + 'comparison.json']['sha256'], 'AM stage receipt SHA mismatch')
summary = _sealed_json(experiment, index, prefix + 'summary.json')
compare = _sealed_json(experiment, index, prefix + 'comparison.json')
folder, case = experiment / prefix.rstrip('/'), root / AK_REL / 'cases' / row['cohort'] / row['name']
require(summary.get('case') == row['name'] and summary.get('complete') is True and summary.get('pass_all') is True and
summary.get('all_finite') is True and summary.get('steps') == summary.get('completed_ticks') == 1000,
'AM selected stage contains a failed/truncated trial')
require(compare.get('pass_all') is True and compare.get('overlay_name') == stage and compare.get('case_dir') == str(case) and
compare.get('right') == str(folder), 'AM comparison identity/gate mismatch')
require(type(compare.get('checks')) is dict and compare['checks'] and all(value is True for value in compare['checks'].values()) and
compare.get('failed_checks') == [] and 'error' not in compare and 'read_manifest_error' not in compare and
compare.get('full_queue_reconstructed') is True, 'AM comparison has a hidden negative/missing numerical gate')
mode = 'zero' if stage == 'zero' else ('repeat' if row['repeat'] else 'self')
left = root / AK_REL / 'gpu' / row['cohort'] / (row['name'] + '-r' + str(row['repeat'])) if stage == 'zero' else (
experiment / 'gpu' / stage / (row['name'] + '-r0') if row['repeat'] else folder)
require(compare.get('mode') == mode and compare.get('left') == str(left), 'AM comparison reference/mode mismatch')
return receipt
def _layout(root, model, experiment):
root, model = Path(root).resolve(strict=True), Path(model).resolve(strict=True)
experiment = Path(experiment).resolve(strict=False)
require(experiment == root / 'experiments/phase4an-engineering-validation' and model.is_relative_to(root / 'models/male-cns-lif'),
'Unexpected project/output layout')
require(not experiment.exists() or (experiment.is_dir() and not any(experiment.iterdir())), 'Refusing populated experiment; preserve all partials')
return root, model, experiment
def _budget(experiment):
experiment = Path(experiment)
used = sum(path.stat().st_size for path in experiment.rglob('*') if path.is_file()) if experiment.exists() else 0
require(used < BUDGET['output_budget_bytes'], '8 GiB engineering budget exhausted; preserve partials')
free = shutil.disk_usage(experiment.parent).free
require(free >= BUDGET['minimum_free_reserve_bytes'] + BUDGET['output_budget_bytes'] - used,
'Insufficient capacity for remaining 8 GiB budget plus 10 GiB free reserve')
return dict(BUDGET, used_bytes=used, free_bytes=free)
def budget():
return _budget(EXP)
def verify_authority(anchors):
"""Full read-only AM seal recheck for the finalizer; no gate rerun."""
require(sys.dont_write_bytecode, 'Use python -B for immutable authority verification')
root = ROOT.resolve(strict=True)
values = [(root / AM_MODEL_REL, 'am_model_manifest_sha256'), (root / AM_EXP_REL, 'am_experiment_manifest_sha256')]
for directory, key in values:
require(sha(anchors.get(key)) and digest(directory / 'manifest.json') == anchors[key], 'External AM manifest anchor mismatch')
require(sha(anchors.get('am_final_sha256')) and digest(root / AM_EXP_REL / 'audit/final-status.json') == anchors['am_final_sha256'],
'External AM final anchor mismatch')
require(anchors.get('am_preregistration_sha256') == AM_PREREG_SHA and
digest(root / AM_EXP_REL / 'protocol/preregistered.json') == AM_PREREG_SHA, 'AM preregistration anchor mismatch')
require(anchors.get('AI_publication_helper_sha256') == AI_HELPER_SHA, 'Publication helper authority changed')
publication = load_module('phase4an_pinned_AI_publication', root / AI_HELPER_REL, AI_HELPER_SHA)
result = {'model': publication.verify_seal(values[0][0]), 'experiment': publication.verify_seal(values[1][0])}
require(result['model']['manifest_sha256'] == anchors['am_model_manifest_sha256'] and
result['experiment']['manifest_sha256'] == anchors['am_experiment_manifest_sha256'], 'AM seal changed during verification')
return result
def _old_integrity(root, context_sha, expected):
"""Reuse the pinned AM read-only integrity chain, not a brain runtime."""
context_path = root / AM_MODEL_REL / 'context.py'
previous_path = list(sys.path)
torch_before = 'torch' in sys.modules
try:
context = load_module('phase4an_sealed_AM_integrity', context_path, context_sha)
require(context.ROOT.resolve() == root.resolve(), 'AM integrity helper belongs to another root')
result = context.integrity()
finally:
sys.path[:] = previous_path
require(torch_before or 'torch' not in sys.modules, 'Integrity unexpectedly imported Torch')
require(type(result) is dict and len(result) == 28 and set(result) == set(expected) and
all(type(row) is dict and row.get('pass') is True for row in result.values()), 'Current 28-root old-integrity gate failed')
for name, row in result.items():
if 'mismatches' in row:
require(row['mismatches'] == [], 'Current old-integrity mismatch list is nonempty')
for key in ('manifest_sha256', 'checksums_sha256', 'reference_sha256'):
if key in expected[name] or key in row:
require(sha(row.get(key)) and row[key] == expected[name].get(key), 'Old integrity authority changed: ' + name)
return result
def verify_old_integrity(registration):
"""Rehash the pinned 28 old roots/snapshot via original CPU-only code."""
require(sys.dont_write_bytecode, 'Use python -B for old-integrity verification')
path = ROOT / AM_MODEL_REL / 'context.py'
expected_sha = registration['input_sha256'].get(str(path.resolve(strict=True)))
require(sha(expected_sha) and digest(path) == expected_sha, 'AM integrity source is not a registered input')
before_path = EXP / 'regression/old-integrity-before.json'
require(digest(before_path) == registration['input_sha256'].get(str(before_path.resolve(strict=True))), 'Before-integrity evidence changed')
return _old_integrity(ROOT, expected_sha, read(before_path))
def _prepare(root, model, experiment, am_model_manifest_sha, am_experiment_manifest_sha, am_final_sha):
require(sys.dont_write_bytecode, 'Preparation requires python -B; old sources must remain byte-for-byte read-only')
require(all(sha(value) for value in (am_model_manifest_sha, am_experiment_manifest_sha, am_final_sha)), 'Three actual external AM SHA-256 anchors are mandatory')
root, model, experiment = _layout(root, model, experiment)
_budget(experiment)
sources = source_inventory(model)
inputs_module = load_module('phase4an_prepare_inputs', model / 'engineering_inputs.py', sources[str(model / 'engineering_inputs.py')])
plan_module = load_module('phase4an_prepare_plan', model / 'engineering_plan.py', sources[str(model / 'engineering_plan.py')])
runtime = load_module('phase4an_prepare_light', model / 'runtime_light.py', sources[str(model / 'runtime_light.py')])
publication = load_module('phase4an_pinned_AI_publication', root / AI_HELPER_REL, AI_HELPER_SHA)
am_model, am = root / AM_MODEL_REL, root / AM_EXP_REL
require(digest(am_model / 'manifest.json') == am_model_manifest_sha and digest(am / 'manifest.json') == am_experiment_manifest_sha and
digest(am / 'audit/final-status.json') == am_final_sha, 'External AM authority mismatch')
verified = {'model': publication.verify_seal(am_model), 'experiment': publication.verify_seal(am)}
require(verified['model']['manifest_sha256'] == am_model_manifest_sha and verified['experiment']['manifest_sha256'] == am_experiment_manifest_sha,
'AM controls changed during full seal verification')
idx = _index(verified['experiment']['files']); midx = _index(verified['model']['files'])
reg = _sealed_json(am, idx, 'protocol/preregistered.json')
require(idx['protocol/preregistered.json']['sha256'] == AM_PREREG_SHA, 'AM preregistration authority differs from the fixed anchor')
planned = reg.get('planned'); selected = validate_planned(planned)
final = _sealed_json(am, idx, 'audit/final-status.json')
scientific = _sealed_json(am, idx, 'audit/scientific-summary.json')
require(final.get('scientific_summary_sha256') == idx['audit/scientific-summary.json']['sha256'], 'AM final does not bind scientific summary')
before = _sealed_json(am, idx, 'regression/old-integrity-before.json')
after = _sealed_json(am, idx, 'regression/old-integrity-after.json')
refs = _sealed_json(am, idx, 'regression/frozen-five.json')
validate_final_status(final, scientific, before, after, refs)
for stage in ('zero', 'static25'):
validate_stage(am, idx, stage, planned, root)
current_old = _old_integrity(root, midx['context.py']['sha256'], after)
inputs = {}
anchors = {'am_model_manifest_sha256': am_model_manifest_sha, 'am_experiment_manifest_sha256': am_experiment_manifest_sha,
'am_final_sha256': am_final_sha, 'am_preregistration_sha256': AM_PREREG_SHA, 'AI_publication_helper_sha256': AI_HELPER_SHA}
for path, expected in ((am_model / 'manifest.json', am_model_manifest_sha), (am / 'manifest.json', am_experiment_manifest_sha),
(am / 'audit/final-status.json', am_final_sha), (root / AI_HELPER_REL, AI_HELPER_SHA),
(am_model / 'overlay.py', AM_OVERLAY_SHA)):
_bind(inputs, path, expected)
require(midx.get('overlay.py', {}).get('sha256') == AM_OVERLAY_SHA, 'AM model seal does not contain the pinned overlay helper')
for name in ('context.py', 'config.json'):
_bind(inputs, am_model / name, midx[name]['sha256'])
for path in (am_model / 'checksums.sha256', am / 'checksums.sha256'):
_bind(inputs, path)
for relative in ('protocol/preregistered.json', 'protocol/prepared-hashes.json', 'audit/scientific-summary.json', 'audit/zero-complete.json', 'audit/static25-complete.json',
'regression/old-integrity-before.json', 'regression/old-integrity-after.json', 'regression/frozen-five.json'):
_bind(inputs, am / relative, idx[relative]['sha256'])
am_inputs = {}
for row in reg['inputs']:
require(set(row) == {'path', 'sha256'} and sha(row['sha256']), 'Invalid AM registered input row')
_relative(row['path']); require(row['path'] not in am_inputs, 'Duplicate AM registered input')
am_inputs[row['path']] = row['sha256']
def authority(path):
path = Path(path).resolve(strict=True)
require(path.is_relative_to(root), 'AM input leaves project root')
relative = path.relative_to(root).as_posix()
if path.is_relative_to(am):
expected = idx[path.relative_to(am).as_posix()]['sha256']
else:
require(relative in am_inputs, 'Dependency absent from AM preregistration: ' + relative)
expected = am_inputs[relative]
return _bind(inputs, path, expected)
original_dir = root / AK_REL / 'cases' / selected['cohort'] / selected['name']
authority(original_dir / 'spec.json'); authority(original_dir / 'requests.npz')
original = read(original_dir / 'spec.json')
require(original['steps'] == 1000 and original['kind'] == 'fullgraph' and original['name'] == selected['name'], 'Fixed selected AM case changed')
with np.load(original_dir / 'requests.npz', allow_pickle=False) as archive:
require(set(archive.files) == {'tick', 'neuron_idx'} and len(archive.files) == 2, 'Unexpected original request arrays')
requests = {key: archive[key].copy() for key in archive.files}
inputs_module.validate_requests(requests, 1000)
for name in GRAPH_FILES:
authority(Path(original['graph_dir']) / name)
for name in APL_FILES:
authority(Path(original['apl_bundle_dir']) / name)
authority(original['coefficients_path'])
selected_outputs = {}
for stage in ('zero', 'static25'):
prefix = 'gpu/' + stage + '/' + selected['name'] + '-r0/'
selected_outputs[stage] = str(am / prefix.rstrip('/'))
for relative, row in idx.items():
if relative.startswith(prefix):
_bind(inputs, am / relative, row['sha256'])
adapted = {}
for stage in ('zero', 'static25'):
old_manifest = authority(am / 'overlays' / (stage + '.json'))
overlay_file = authority(am / 'overlays' / (stage + '.npz'))
declaration = read(old_manifest)
require(declaration['overlay_name'] == stage and declaration['overlay_sha256'] == digest(overlay_file), 'AM overlay declaration mismatch')
for label in ('mask', 'base_candidate'):
require(digest(authority(declaration[label + '_path'])) == declaration[label + '_sha256'], 'Overlay external array authority mismatch')
adapted[stage] = inputs_module.adapt_overlay_manifest(declaration, str(am_model / 'overlay.py'))
require(adapted[stage]['am_overlay_sha256'] == AM_OVERLAY_SHA, 'Adapted helper pin differs')
for relative, expected in runtime.PINS.items():
_bind(inputs, model.parent / relative, expected)
plan = plan_module.validate_plan(plan_module.build_plan())
require(plan['total_calls'] == 32 and plan['total_ticks'] == 11074, 'Engineering plan matrix changed')
# No writes have occurred before all authority/source/space checks above.
experiment.mkdir(parents=True, exist_ok=True)
try:
for folder in ('protocol', 'cases', 'overlays', 'audit', 'runs', 'receipts', 'logs', 'regression', 'extension-build'):
(experiment / folder).mkdir(exist_ok=False)
save(experiment / 'regression/old-integrity-before.json', current_old)
_bind(inputs, experiment / 'regression/old-integrity-before.json')
for source, expected in sources.items():
target = experiment / 'protocol/source-snapshot' / Path(source).name
publication._copy_verified(Path(source), target, Path(source).stat().st_size, expected)
_bind(inputs, target, expected)
save(experiment / 'protocol/AM-seal-verification.json', verified)
save(experiment / 'protocol/AM-gate-authority.json', dict(anchors=anchors, all_144_per_stage_declared_gates_pass=True,
old_roots=28, old_references=list(REFERENCES), verification_scope='Full AM seals and finalized declared gate evidence; no new scientific execution'))
for name in ('AM-seal-verification.json', 'AM-gate-authority.json'):
_bind(inputs, experiment / 'protocol' / name)
overlays, cases = {}, {}
for stage, value in adapted.items():
manifest_path = experiment / 'overlays' / (stage + '.json')
save(manifest_path, value)
_bind(inputs, manifest_path)
overlays[stage] = {'overlay_file': str(am / 'overlays' / (stage + '.npz')), 'overlay_manifest': str(manifest_path)}
for row in plan['rows']:
case = experiment / 'cases' / row['row_id']; case.mkdir(exist_ok=False)
template = {'schema': 'phase4an-engineering-case-template-v1', 'row_id': row['row_id'], 'original_spec': original,
'start': row['start'], 'stop': row['stop'], 'budget_root': str(experiment), 'output_budget_bytes': BUDGET['output_budget_bytes']}
save(case / 'template-spec.json', template)
part = inputs_module.slice_requests(requests, 1000, row['start'], row['stop'])
with (case / 'requests.npz').open('xb') as stream:
np.savez_compressed(stream, **part)
_bind(inputs, case / 'template-spec.json'); _bind(inputs, case / 'requests.npz')
cases[row['row_id']] = {'case_dir': str(case), 'template_spec_sha256': digest(case / 'template-spec.json'),
'requests_sha256': digest(case / 'requests.npz')}
require(source_inventory(model) == sources and all(digest(path) == expected for path, expected in inputs.items()), 'Source/input changed during preparation')
# Repeat the full AM verification after producing only small new inputs.
after_verified = {'model': publication.verify_seal(am_model), 'experiment': publication.verify_seal(am)}
require(after_verified == verified, 'AM sealed payload changed during preparation')
_budget(experiment)
registration = {'schema': REG_SCHEMA, 'plan': plan, 'selected_case': {'row': selected, 'original_dir': str(original_dir), 'AM_outputs': selected_outputs},
'source_sha256': sources, 'input_sha256': inputs, 'cases': cases, 'overlays': overlays, 'budget': dict(BUDGET), 'anchors': anchors,
'training': False, 'new_brain_runs_during_preparation': 0, 'future_checkpoint_hashes_fabricated': False,
'runtime_spec_derivation': 'engineering_inputs.derive_spec(template.original_spec, interval, budget, actual verified parent SHA or None)',
'scope': 'Fixed 32-call engineering gate only; not conditioning or learning registration'}
save(experiment / 'protocol/preregistered.json', registration)
return {'prepared': True, 'registration_path': str(experiment / 'protocol/preregistered.json'),
'registration_sha256': digest(experiment / 'protocol/preregistered.json'), 'calls': 32, 'brain_runs': 0}
except Exception as error:
failure = experiment / 'audit/preparation-failure.json'
if not failure.exists():
save(failure, {'prepared': False, 'type': type(error).__name__, 'message': str(error), 'partial_outputs_preserved': True})
raise
def prepare(am_model_manifest_sha, am_experiment_manifest_sha, am_final_sha):
return _prepare(ROOT, MODEL, EXP, am_model_manifest_sha, am_experiment_manifest_sha, am_final_sha)
def row_path(registration, row_id):
require(type(row_id) is str and row_id in {row['row_id'] for row in registration['plan']['rows']}, 'Unknown engineering row ID')
expected = EXP.resolve(strict=True) / 'cases' / row_id
actual = Path(registration['cases'][row_id]['case_dir'])
require(actual == expected and actual.resolve(strict=True) == expected and actual.is_dir(), 'Row case path is not its fixed safe mapping')
return actual
def read_registration(expected_sha):
require(sys.dont_write_bytecode and sha(expected_sha), 'Require python -B and an external preregistration SHA')
path = EXP / 'protocol/preregistered.json'
require(digest(path) == expected_sha, 'Preregistration differs from external authority')
require(not (EXP / 'audit/preparation-failure.json').exists(), 'Preparation failed; preserve partials')
registration = read(path)
require(registration.get('schema') == REG_SCHEMA and registration.get('training') is False and registration.get('budget') == BUDGET,
'Unexpected registration schema/scope/budget')
require(registration['source_sha256'] == source_inventory(MODEL), 'Registered engineering sources changed or inventory incomplete')
for name, expected in registration['input_sha256'].items():
require(Path(name).is_absolute() and sha(expected) and digest(name) == expected, 'Registered input changed: ' + name)
plan_module = load_module('phase4an_read_plan', MODEL / 'engineering_plan.py', registration['source_sha256'][str(MODEL / 'engineering_plan.py')])
inputs_module = load_module('phase4an_read_inputs', MODEL / 'engineering_inputs.py', registration['source_sha256'][str(MODEL / 'engineering_inputs.py')])
plan_module.validate_plan(registration['plan'])
selected = validate_planned(read(ROOT / AM_EXP_REL / 'protocol/preregistered.json')['planned'])
original_dir = ROOT / AK_REL / 'cases' / selected['cohort'] / selected['name']
require(registration['selected_case']['row'] == selected and registration['selected_case']['original_dir'] == str(original_dir),
'Registered case is not the fixed first AM planned primary')
original = read(original_dir / 'spec.json')
with np.load(original_dir / 'requests.npz', allow_pickle=False) as archive:
require(set(archive.files) == {'tick', 'neuron_idx'} and len(archive.files) == 2, 'Unexpected original sparse request schema')
requests = {key: archive[key].copy() for key in archive.files}
inputs_module.validate_requests(requests, 1000)
require(set(registration['cases']) == {row['row_id'] for row in registration['plan']['rows']}, 'Registered case inventory differs from plan')
for row in registration['plan']['rows']:
case = row_path(registration, row['row_id']); entry = registration['cases'][row['row_id']]
require(entry['template_spec_sha256'] == digest(case / 'template-spec.json') and entry['requests_sha256'] == digest(case / 'requests.npz'),
'Template/request metadata does not bind registered bytes')
template = read(case / 'template-spec.json')
require(set(template) == {'schema', 'row_id', 'original_spec', 'start', 'stop', 'budget_root', 'output_budget_bytes'} and
template['schema'] == 'phase4an-engineering-case-template-v1' and template['original_spec'] == original and
template['row_id'] == row['row_id'] and template['start'] == row['start'] and template['stop'] == row['stop'] and
template['budget_root'] == str(EXP) and template['output_budget_bytes'] == BUDGET['output_budget_bytes'], 'Template rule differs from canonical row')
expected = inputs_module.slice_requests(requests, 1000, row['start'], row['stop'])
with np.load(case / 'requests.npz', allow_pickle=False) as archive:
require(len(archive.files) == 2 and set(archive.files) == set(expected) and
all(archive[key].dtype == expected[key].dtype and archive[key].shape == expected[key].shape and
archive[key].tobytes() == expected[key].tobytes() for key in expected), 'Registered request slice is not exact')
require(set(registration['overlays']) == {'zero', 'static25'}, 'Registered overlay inventory changed')
for stage in ('zero', 'static25'):
entry = registration['overlays'][stage]
expected_file = ROOT / AM_EXP_REL / 'overlays' / (stage + '.npz')
expected_manifest = EXP / 'overlays' / (stage + '.json')
require(entry == {'overlay_file': str(expected_file), 'overlay_manifest': str(expected_manifest)}, 'Overlay path mapping changed')
original_overlay = read(ROOT / AM_EXP_REL / 'overlays' / (stage + '.json'))
require(read(expected_manifest) == inputs_module.adapt_overlay_manifest(original_overlay, str(ROOT / AM_MODEL_REL / 'overlay.py')),
'Adapted overlay manifest is not the exact declared transformation')
anchors = registration['anchors']
for name, relative in (('am_model_manifest_sha256', AM_MODEL_REL / 'manifest.json'),
('am_experiment_manifest_sha256', AM_EXP_REL / 'manifest.json'),
('am_final_sha256', AM_EXP_REL / 'audit/final-status.json')):
require(sha(anchors[name]) and digest(ROOT / relative) == anchors[name], 'AM external anchor changed')
require(anchors['am_preregistration_sha256'] == AM_PREREG_SHA and digest(ROOT / AM_EXP_REL / 'protocol/preregistered.json') == AM_PREREG_SHA and
anchors['AI_publication_helper_sha256'] == AI_HELPER_SHA and digest(ROOT / AI_HELPER_REL) == AI_HELPER_SHA, 'Fixed AM/helper authority changed')
require(digest(path) == expected_sha, 'Registration changed during verification')
return registration