Files
2026-09-30 13:18:18 +08:00

121 lines
5.7 KiB
Python

"""A new validation envelope; sealed brain implementations remain read-only."""
import hashlib
import importlib.util
import json
import sys
from pathlib import Path
sys.dont_write_bytecode = True
ROOT = Path('/data/digital-drosophila')
MODEL = Path(__file__).resolve().parent
EXP = ROOT / 'experiments/phase4ak-apl-timing-validation'
AJ_MODEL = ROOT / 'models/male-cns-lif/apl-timing-lab-v1'
AJ = ROOT / 'experiments/phase4aj-apl-timing'
AG_MODEL = ROOT / 'models/male-cns-lif/author-apl-lab-v2'
AG = ROOT / 'experiments/phase4ag-author-apl-r2'
COEFF = ROOT / 'experiments/phase4af-author-fullgraph/oracle/no_input/coefficients.json'
STATIC = ROOT / 'experiments/phase4l-olfactory-grounding'
CFG = json.loads((MODEL / 'config.json').read_text(encoding='utf-8'))
PINS = {
'models/male-cns-lif/apl-timing-lab-v1/manifest.json': '52b05dd1ff30b6b51ff960fe95904532f5c147731a83f0b5c31f98ca7e53c216',
'experiments/phase4aj-apl-timing/manifest.json': '7f490ada0db30785c61954d8b92147378ddc8bc16b229fe3808bbe501caff44a',
'models/male-cns-lif/phase4l.py': 'e97d58d8c1f44920d0e953f8f5831ddc86fa0198784e86460e315de4116ac553',
'models/male-cns-lif/olfactory-grounding-v1/phase4l.yaml': '9b8bcb7e031bf9063033a1854a439a7cd0bf6730301c2d2d02ca99a76f098d6e',
'models/male-cns-lif/apl-timing-lab-v1/gpu_timing.py': 'af1975ba5e5e700208c0a598d3cbe648a3cf10885c6231239b6e4b28f76d173b',
'models/male-cns-lif/apl-timing-lab-v1/oracle_timing.py': '39d8c47c94bc2faddf016864a43e7715907fb987f56f7b27098060a88851f6be',
'models/male-cns-lif/apl-timing-lab-v1/compare_timing.py': '9010f070fba9b7c9cf2d86187ee2abc57f3ac606ebc08a42baad4f3922b51734',
'models/male-cns-lif/apl-timing-lab-v1/timing_queue.py': '54df6d4818e2a0c26e96fb0aaf5d9b71cd964981706da937562d48af79aca14e',
'models/male-cns-lif/apl-timing-lab-v1/calibration.py': 'fb15ddeaa108305c8de697bbae36b23ab0414a7c58db51c66dce9feb4a048a0d',
'models/male-cns-lif/author-apl-lab-v2/calibration.py': 'edb9cb2d890471fd07afd88c959ef3540b0cd40af490fac3f26396b5e7f5bf9c',
'models/male-cns-lif/author-apl-lab-v2/validate_components.py': '5cfc9a4505da6b8fb4e7d2617cdaedaa8475ed46a11ec9bdf0d4d25b1d22c2d3',
'experiments/phase4l-olfactory-grounding/odor-encoder/frozen-odor-panel.parquet': '907f16a56e024a8e2112b5751e53b0e6037b329fa110098af3d31b119c10a1a0',
'experiments/phase4l-olfactory-grounding/odor-encoder/mapped-glomerular-vectors.npz': 'f057563152e0fa22060080af13019f319e7f36563a775eff829bbc1929c451b0',
'experiments/phase4l-olfactory-grounding/odor-encoder/selection.json': '1b832becf9d08935716fe9ba5e3cd3e619e7d208dfb43c4fa197c969d095f113',
'experiments/phase4l-olfactory-grounding/receptor-mapping/olfactory-mapping.parquet': 'a01d27000533e9844458a4c559cac084f1c34ca20a1104e97e6a0f72b0cc93b1'
}
def digest(path):
result = hashlib.sha256()
with Path(path).open('rb') as stream:
for block in iter(lambda: stream.read(8 << 20), b''):
result.update(block)
return result.hexdigest()
def load_module(name, path, expected_hash=None):
path = Path(path)
data = path.read_bytes()
if expected_hash is not None:
assert hashlib.sha256(data).hexdigest() == expected_hash, str(path)
spec = importlib.util.spec_from_file_location(name, path)
assert spec and spec.loader
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
exec(compile(data, str(path), 'exec'), module.__dict__)
return module
def pinned(name, relative):
return load_module(name, ROOT / relative, PINS[relative])
def read(path):
return json.loads(Path(path).read_text(encoding='utf-8'))
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, indent=2, ensure_ascii=False, allow_nan=False)
stream.write('\n')
def sources():
return {p.relative_to(MODEL).as_posix(): digest(p) for p in sorted(MODEL.rglob('*')) if p.is_file()
and '__pycache__' not in p.parts and p.name not in ('manifest.json', 'checksums.sha256')}
def integrity():
old = load_module('sealed_aj_context_ak', AJ_MODEL / 'context.py')
result = old.integrity()
sys.path.insert(0, str(ROOT / 'models/male-cns-lif/terminal-scope-diagnostic-v1'))
from diagnostic import manifest_check
for path in (AJ_MODEL, AJ):
result[str(path.relative_to(ROOT))] = manifest_check(path, digest)
assert all(row['pass'] for row in result.values())
return result
def check():
registered = read(EXP / 'protocol/preregistered.json')
assert registered['sources'] == sources(), 'Registered validation source changed'
assert registered['config'] == CFG
for row in registered['inputs']:
assert digest(ROOT / row['path']) == row['sha256'], row['path']
for row in read(EXP / 'protocol/prepared-hashes.json'):
assert digest(EXP / row['path']) == row['sha256'], row['path']
return registered
def budget():
size = sum(p.stat().st_size for p in EXP.rglob('*') if p.is_file())
assert size < CFG['output_budget_bytes'], 'Output budget exceeded; preserve partial evidence'
return size
def seal(root):
rows = [dict(path=p.relative_to(root).as_posix(), bytes=p.stat().st_size, sha256=digest(p))
for p in sorted(root.rglob('*')) if p.is_file() and '__pycache__' not in p.parts]
save(root / 'manifest.json', dict(root=str(root), files=rows))
with (root / 'checksums.sha256').open('x', encoding='utf-8') as stream:
for row in rows:
stream.write(row['sha256'] + ' ' + row['path'] + '\n')
stream.write(digest(root / 'manifest.json') + ' manifest.json\n')
def bit_equal(a, b):
return a.dtype == b.dtype and a.shape == b.shape and a.tobytes() == b.tobytes()