Seal Phase 4AN exact continuation engineering evidence

This commit is contained in:
Digital Drosophila Archive
2026-09-30 16:46:21 +08:00
parent de61cf14b1
commit aeccb7d0cc
628 changed files with 127078 additions and 1 deletions
@@ -0,0 +1,335 @@
"""Fetch exactly the externally pinned AN registry, never remote brain bulk.
No network at import. ``fetch`` accepts an authenticated read-only SFTP client;
the CLI requires existing host trust and environment-only credentials. Local
paths preserve registry relative names. A partial destination is not resumed.
This checks selected bytes and publication cross-links, not scientific gates
or the untransferred experiment/model payload.
"""
from __future__ import annotations
import argparse
import hashlib
import json
import os
from pathlib import Path, PurePosixPath
import re
import stat
REMOTE_ROOT = '/data/digital-drosophila'
EXP_REL = 'experiments/phase4an-engineering-validation'
MODEL_REL = 'models/male-cns-lif/olfactory-conditioning-lab-v1'
REGISTRY_REL = 'registry/phase4an-engineering-validation'
REGISTRY_ROOT = REMOTE_ROOT + '/' + REGISTRY_REL
DEFAULT_DESTINATION = Path(__file__).resolve().parents[2] / 'reports/phase4an-engineering-validation'
PREREG_SHA = '7317441126f191ccc6e6d28438870b3921537ebe282a6acb163716a690057945'
MAX_FILE_BYTES = 4 * 1024**2
MAX_TOTAL_BYTES = 1024**3
SUFFIXES = frozenset(('.json', '.csv', '.md', '.log', '.sha256'))
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([m + '.py' for m in MODULES] + ['test_' + m + '.py' for m in MODULES] + ['ENGINEERING_GATE_DRAFT.md']))
GENERATED = frozenset(('seal-verification.json', 'evidence-index.json', 'source-identity.json'))
CONTROLS = ('manifest.json', 'checksums.sha256')
PASS = 'PASS-EXACT-LIGHT-CONTINUATION-ENGINEERING-NOT-LEARNING'
STATUSES = frozenset((PASS, 'FAIL-NUMERICAL', 'INCOMPLETE-COVERAGE'))
SHA = re.compile('[0-9a-f]{64}\\Z')
def require(ok, message):
if not ok:
raise ValueError(message)
def sha(data):
return hashlib.sha256(data).hexdigest()
def json_bytes(data):
def unique(pairs):
out = {}
for key, value in pairs:
require(key not in out, 'Duplicate JSON key')
out[key] = value
return out
def bad(value):
raise ValueError('Nonfinite JSON constant')
return json.loads(data.decode('utf-8'), object_pairs_hook=unique, parse_constant=bad)
def relative_name(value):
require(type(value) is str and value and not any(ord(c) < 32 or c in '\\:"<>|?*' for c in value), 'Invalid relative filename')
path = PurePosixPath(value)
require(not path.is_absolute() and path.as_posix() == value and
all(x not in ('.', '..', '__pycache__') and not x.endswith((' ', '.')) for x in path.parts), 'Noncanonical relative filename')
devices = {'CON', 'PRN', 'AUX', 'NUL', *(prefix + number for prefix in ('COM', 'LPT') for number in '123456789¹²³')}
require(all(x.split('.')[0].upper() not in devices for x in path.parts), 'Reserved local filename')
return path
def file_row(row, small=False):
require(type(row) is dict and set(row) == {'path', 'bytes', 'sha256'}, 'Unexpected file row')
relative_name(row['path'])
require(type(row['bytes']) is int and row['bytes'] >= 0 and type(row['sha256']) is str and SHA.fullmatch(row['sha256']), 'Invalid size/SHA')
require(not small or row['bytes'] <= MAX_FILE_BYTES, 'File exceeds 4 MiB')
return row
def _collision_check(names):
folded = [relative_name(name).as_posix().casefold() for name in names]
values = set(folded)
require(len(values) == len(folded) and not any(parent.as_posix().casefold() in values
for name in names for parent in PurePosixPath(name).parents if str(parent) != '.'), 'Local case/prefix path collision')
def selected(row):
path = PurePosixPath(row['path'])
if path.parts[0] == 'extension-build': return None, 'build_artifact'
if row['bytes'] > MAX_FILE_BYTES: return None, 'exceeds_4_MiB'
if path.parts[:2] == ('protocol', 'source-snapshot') and len(path.parts) == 3 and path.name in SOURCE_FILES:
return 'source-snapshot/' + path.name, None
if path.suffix.lower() not in SUFFIXES: return None, 'bulk_binary_or_unselected_suffix_including_jsonl'
return 'evidence/' + row['path'], None
def validate_receipt(raw, expected_sha):
require(sha(raw) == expected_sha, 'External receipt SHA mismatch')
receipt = json_bytes(raw)
require(type(receipt) is dict and receipt.get('schema') == 'phase4an-engineering-publication-v1' and
receipt.get('publication_complete') is True and receipt.get('project_root') == REMOTE_ROOT and
receipt.get('registry') == REGISTRY_REL and receipt.get('declared_status') in STATUSES, 'Wrong/incomplete publication receipt')
for key in ('used_sources_verified_before_and_after', 'complete_checksums_reference_bulk_not_copied',
'publication_success_is_not_engineering_or_learning_pass'):
require(receipt.get(key) is True, 'Missing publication qualification: ' + key)
for key in ('model_directory_sealed', 'model_files_copied', 'complete_bulk_backup', 'numerical_gate_rerun_by_publisher',
'training', 'candidate_generated', 'learning_pass_claimed', 'existing_files_modified', 'helper_globals_modified'):
require(receipt.get(key) is False, 'Unexpected publication claim: ' + key)
require(receipt.get('selection_policy') == dict(max_file_bytes=MAX_FILE_BYTES, suffixes=sorted(SUFFIXES),
source_snapshot_names=list(SOURCE_FILES), excluded_tree='extension-build', all_jsonl_excluded=True), 'Selection policy changed')
require(receipt.get('used_source_count') == 21 and receipt.get('completed_calls') == 32 and receipt.get('executed_ticks') == 11074 and
receipt.get('preregistration_sha256') == PREREG_SHA and receipt.get('source_identity') == 'source-identity.json' and
receipt.get('bulk_remains_at') == EXP_REL, 'Receipt authority/scope changed')
for key in ('experiment_manifest_sha256', 'experiment_checksums_sha256', 'final_sha256', 'analysis_sha256', 'publisher_sha256', 'helper_sha256'):
require(type(receipt.get(key)) is str and SHA.fullmatch(receipt[key]), 'Missing SHA anchor: ' + key)
rows = {}
require(type(receipt.get('files')) is list and receipt['files'], 'Empty publication inventory')
for row in receipt['files']:
file_row(row, small=True); name = row['path']
allowed = name in GENERATED or name in {'source-snapshot/' + n for n in SOURCE_FILES} or (
name.startswith('evidence/') and PurePosixPath(name).suffix.lower() in SUFFIXES and not name.startswith('evidence/extension-build/'))
require(allowed and name not in rows, 'Unexpected/duplicate registry file')
rows[name] = row
required = {*GENERATED, *('source-snapshot/' + n for n in SOURCE_FILES),
'evidence/manifest.json', 'evidence/checksums.sha256', 'evidence/protocol/preregistered.json',
'evidence/audit/final-status.json', 'evidence/audit/engineering-analysis.json'}
require(required <= set(rows), 'Missing required evidence/source/control files')
_collision_check([*rows, 'publication-receipt.json', 'fetch-verification.json', 'fetch-failure.json'])
return receipt, rows
def validate_manifest(manifest_raw, checksums_raw, receipt):
require(sha(manifest_raw) == receipt['experiment_manifest_sha256'] and sha(checksums_raw) == receipt['experiment_checksums_sha256'], 'Manifest/control anchor mismatch')
manifest = json_bytes(manifest_raw)
require(type(manifest) is dict and set(manifest) == {'root', 'files'} and manifest['root'] == REMOTE_ROOT + '/' + EXP_REL and
type(manifest['files']) is list and manifest['files'], 'Wrong experiment manifest')
rows = {}
for row in manifest['files']:
file_row(row); require(row['path'] not in rows and row['path'] not in CONTROLS, 'Duplicate/control manifest payload')
rows[row['path']] = row
checks = {}
for line in checksums_raw.decode('utf-8').splitlines():
require(len(line) >= 67 and line[64:66] == ' ' and SHA.fullmatch(line[:64]), 'Malformed checksum line')
name = line[66:]; relative_name(name)
require(name not in checks, 'Duplicate checksum path'); checks[name] = line[:64]
require(checks == {**{k: row['sha256'] for k, row in rows.items()}, 'manifest.json': receipt['experiment_manifest_sha256']},
'Manifest self-SHA/checksum inventory mismatch')
return rows
def validate_links(cached, receipt, rows, manifest_rows):
"""Cross-link selected metadata; never pretend untransferred bulk is local."""
expected, omitted = {}, {}
controls = [dict(path=name, bytes=len(cached['evidence/' + name]), sha256=sha(cached['evidence/' + name])) for name in CONTROLS]
for row in [*manifest_rows.values(), *controls]:
destination, reason = selected(row)
if destination:
require(destination not in expected, 'Selection maps multiple files to one destination')
expected[destination] = dict(path=destination, bytes=row['bytes'], sha256=row['sha256'])
else: omitted[row['path']] = dict(row, reason=reason)
require({k: v for k, v in rows.items() if k not in GENERATED} == expected, 'Receipt selection is not the exact sealed policy inventory')
actual_omitted = {}
require(type(receipt.get('experiment_payload_not_copied')) is list, 'Missing omitted inventory')
for row in receipt['experiment_payload_not_copied']:
require(type(row) is dict and set(row) == {'path', 'bytes', 'sha256', 'reason'} and row['path'] not in actual_omitted, 'Malformed omitted inventory')
file_row({k: row[k] for k in ('path', 'bytes', 'sha256')}); actual_omitted[row['path']] = row
require(actual_omitted == omitted, 'Omitted inventory contradicts selection policy')
index = json_bytes(cached['evidence-index.json']); indexed = {}
require(type(index) is list, 'Invalid evidence index')
for item in index:
require(type(item) is dict and set(item) == {'source', 'copy', 'bytes', 'sha256'} and item['copy'] in expected and item['copy'] not in indexed,
'Invalid/duplicate indexed file')
name = item['copy']; original = ('protocol/' + name if name.startswith('source-snapshot/') else name[len('evidence/'):])
require(item == dict(source=EXP_REL + '/' + original, copy=name, bytes=expected[name]['bytes'], sha256=expected[name]['sha256']), 'Evidence index source/hash mismatch')
indexed[name] = item
require(set(indexed) == set(expected) and receipt.get('copied_evidence_files') == len(expected) and
receipt.get('copied_evidence_bytes') == sum(x['bytes'] for x in expected.values()), 'Evidence index coverage/count mismatch')
proof = json_bytes(cached['seal-verification.json'])
require(proof.get('pass_all') is True and proof.get('root') == REMOTE_ROOT + '/' + EXP_REL and
proof.get('manifest_sha256') == receipt['experiment_manifest_sha256'] and
proof.get('checksums_sha256') == receipt['experiment_checksums_sha256'] and proof.get('payload_file_count') == len(manifest_rows) and
proof.get('payload_bytes') == sum(x['bytes'] for x in manifest_rows.values()), 'Seal proof disagrees with controls')
reg_raw, final_raw, analysis_raw = (cached['evidence/' + name] for name in
('protocol/preregistered.json', 'audit/final-status.json', 'audit/engineering-analysis.json'))
require(sha(reg_raw) == PREREG_SHA and sha(final_raw) == receipt['final_sha256'] and sha(analysis_raw) == receipt['analysis_sha256'], 'Prereg/final/analysis anchor mismatch')
reg, final, analysis = map(json_bytes, (reg_raw, final_raw, analysis_raw))
require(final.get('status') == analysis.get('status') == receipt['declared_status'] and final.get('analysis_sha256') == receipt['analysis_sha256'] and
final.get('registration_sha256') == analysis.get('registration_sha256') == PREREG_SHA and
final.get('analysis_recomputed_exactly') is True and final.get('completed_calls') == 32 and final.get('executed_ticks') == 11074 and
analysis.get('expected_calls') == analysis.get('analyzed_calls') == 32 and analysis.get('executed_ticks') == 11074,
'Final/analysis scope or linkage mismatch')
require(final.get('training') is False and final.get('learned_candidate') is False and final.get('learning_pass_claimed') is False and
analysis.get('training') is False and analysis.get('candidate_generated') is False and analysis.get('learning_pass_claimed') is False,
'Final/analysis asserts learning or training')
numerical, covered = analysis.get('numerical_exact'), analysis.get('nonvacuous_temporal_coverage')
require(type(numerical) is type(covered) is bool and receipt.get('declared_numerical_exact') is numerical and
receipt.get('declared_live_coverage') is covered and analysis.get('pass_all') is (numerical and covered) and
receipt.get('declared_engineering_pass') is analysis['pass_all'] and final['status'] ==
('FAIL-NUMERICAL' if not numerical else (PASS if covered else 'INCOMPLETE-COVERAGE')), 'Engineering status was promoted or contradicted')
sources = json_bytes(cached['source-identity.json'])
require(type(sources) is list and len(sources) == 21, 'Source identity inventory missing')
expected_sources, seen = {}, set()
for item in sources:
require(type(item) is dict and set(item) == {'model_source', 'sealed_source', 'copy', 'bytes', 'sha256'}, 'Invalid source identity row')
name = item['copy']; require(name in {'source-snapshot/' + n for n in SOURCE_FILES} and name not in seen, 'Unexpected/duplicate source identity')
seen.add(name); filename = PurePosixPath(name).name
expected_item = dict(model_source=MODEL_REL + '/' + filename, sealed_source=EXP_REL + '/protocol/' + name,
copy=name, bytes=rows[name]['bytes'], sha256=rows[name]['sha256'])
require(item == expected_item, 'Source identity disagrees with registered snapshot')
expected_sources[REMOTE_ROOT + '/' + item['model_source']] = item['sha256']
require(reg.get('input_sha256', {}).get(REMOTE_ROOT + '/' + item['sealed_source']) == item['sha256'], 'Snapshot missing from preregistered input authority')
require(reg.get('source_sha256') == analysis.get('source_sha256') == expected_sources, 'Original 21-source inventory differs from source identities')
class BoundedSFTP:
def __init__(self, sftp, byte_budget=MAX_TOTAL_BYTES):
self.sftp, self.byte_budget, self.bytes_read = sftp, byte_budget, 0
def read(self, remote, size=None, checksum=None):
require(remote.startswith(REGISTRY_ROOT + '/'), 'Only the fixed AN registry may be downloaded')
relative_name(remote[len(REGISTRY_ROOT) + 1:])
parent = PurePosixPath(remote).parent
for directory in reversed((parent, *parent.parents)):
require(stat.S_ISDIR(self.sftp.lstat(str(directory)).st_mode), 'Remote symlink/non-directory')
info = self.sftp.lstat(remote)
require(stat.S_ISREG(info.st_mode), 'Remote symlink/nonregular file')
require(0 <= info.st_size <= MAX_FILE_BYTES and (size is None or info.st_size == size), 'Remote size outside bounded inventory')
require(self.bytes_read + info.st_size <= self.byte_budget, 'Total SFTP read budget exceeded')
chunks, total = [], 0
with self.sftp.open(remote, 'rb') as stream:
while total < info.st_size:
data = stream.read(min(1 << 20, info.st_size - total, self.byte_budget - self.bytes_read))
require(data, 'Remote file ended before its declared size')
total += len(data); self.bytes_read += len(data)
require(total <= MAX_FILE_BYTES and self.bytes_read <= self.byte_budget, 'Remote file grew beyond download limit'); chunks.append(data)
raw = b''.join(chunks)
after = self.sftp.lstat(remote)
require(stat.S_ISREG(after.st_mode) and after.st_size == info.st_size and len(raw) == info.st_size and
(size is None or len(raw) == size), 'Remote type/size changed during read')
require(checksum is None or sha(raw) == checksum, 'Remote file SHA mismatch')
return raw
def check_destination(path):
require(path.is_absolute() and '..' not in path.parts, 'Destination must be canonical and absolute')
for node in (path, *path.parents):
require(not node.is_symlink() and not getattr(node, 'is_junction', lambda: False)(), 'Local symlink/junction destination')
require(not path.exists(), 'Destination exists; no overwrite or partial retry')
def write_bytes(path, raw):
path.parent.mkdir(parents=True, exist_ok=True)
with path.open('xb') as stream: stream.write(raw)
require(path.stat().st_size == len(raw) and sha(path.read_bytes()) == sha(raw), 'Local byte/SHA verification failed')
def fetch(sftp, destination, receipt_sha256, *, max_total_bytes=MAX_TOTAL_BYTES):
require(type(receipt_sha256) is str and SHA.fullmatch(receipt_sha256), 'External receipt SHA required')
require(type(max_total_bytes) is int and 0 < max_total_bytes <= MAX_TOTAL_BYTES, 'Download cap cannot exceed 1 GiB')
destination = Path(destination); check_destination(destination)
remote = BoundedSFTP(sftp, max_total_bytes)
receipt_raw = remote.read(REGISTRY_ROOT + '/publication-receipt.json', checksum=receipt_sha256)
receipt, rows = validate_receipt(receipt_raw, receipt_sha256)
total = len(receipt_raw) + sum(row['bytes'] for row in rows.values())
require(total + len(receipt_raw) <= max_total_bytes, 'Exact inventory plus final anchor reread exceeds total download budget')
essentials = {*GENERATED, 'evidence/manifest.json', 'evidence/checksums.sha256',
'evidence/protocol/preregistered.json', 'evidence/audit/final-status.json', 'evidence/audit/engineering-analysis.json'}
cached = {name: remote.read(REGISTRY_ROOT + '/' + name, rows[name]['bytes'], rows[name]['sha256']) for name in sorted(essentials)}
manifest_rows = validate_manifest(cached['evidence/manifest.json'], cached['evidence/checksums.sha256'], receipt)
validate_links(cached, receipt, rows, manifest_rows)
check_destination(destination); destination.mkdir(parents=True, exist_ok=False)
try:
write_bytes(destination / 'publication-receipt.json', receipt_raw)
downloaded = [dict(path='publication-receipt.json', bytes=len(receipt_raw), sha256=receipt_sha256)]
for name, row in sorted(rows.items()):
raw = cached[name] if name in cached else remote.read(REGISTRY_ROOT + '/' + name, row['bytes'], row['sha256'])
require(len(raw) == row['bytes'] and sha(raw) == row['sha256'], 'Cached/downloaded byte mismatch')
write_bytes(destination / name, raw); downloaded.append(dict(row))
remote.read(REGISTRY_ROOT + '/publication-receipt.json', len(receipt_raw), receipt_sha256)
expected_names = {row['path'] for row in downloaded}
require({x.relative_to(destination).as_posix() for x in destination.rglob('*') if x.is_file()} == expected_names and
not any(x.is_symlink() or getattr(x, 'is_junction', lambda: False)() for x in destination.rglob('*')), 'Local unexpected/linked payload')
require(all((destination / row['path']).stat().st_size == row['bytes'] and sha((destination / row['path']).read_bytes()) == row['sha256']
for row in downloaded), 'Local payload changed during fetch')
result = dict(fetch_complete=True, publication_receipt_sha256=receipt_sha256, declared_status=receipt['declared_status'],
experiment_manifest_sha256=receipt['experiment_manifest_sha256'], final_sha256=receipt['final_sha256'], preregistration_sha256=PREREG_SHA,
registry_relative_names_preserved=True, exact_receipt_inventory_downloaded=True, files=downloaded,
downloaded_file_count=len(downloaded), downloaded_bytes=total, total_download_limit_bytes=max_total_bytes,
sftp_bytes_read_including_anchor_reread=remote.bytes_read,
manifest_self_checksum_and_selected_links_verified=True, source_snapshot_count=21,
original_model_sources_downloaded=False, remote_bulk_downloaded=False, remote_bulk_rehashed_locally=False,
full_remote_seal_verification_is_publisher_claim=True, complete_bulk_backup=False,
engineering_gate_executed=False, fetch_success_is_not_engineering_or_learning_pass=True,
learning_pass_claimed=False, candidate_generated=False, existing_files_modified=False)
raw = (json.dumps(result, sort_keys=True, indent=2, allow_nan=False) + '\n').encode()
require(len(raw) <= MAX_FILE_BYTES, 'Fetch receipt exceeds 4 MiB')
write_bytes(destination / 'fetch-verification.json', raw)
return result
except Exception as error:
path = destination / 'fetch-failure.json'
if not path.exists():
write_bytes(path, (json.dumps(dict(fetch_complete=False, error_type=type(error).__name__, message=str(error),
partial_outputs_preserved=True, existing_files_modified=False), allow_nan=False) + '\n').encode())
raise
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--receipt-sha256', required=True)
parser.add_argument('--destination', type=Path, default=DEFAULT_DESTINATION)
parser.add_argument('--host', default='192.168.10.51'); parser.add_argument('--port', type=int, default=22)
parser.add_argument('--user-env', default='MALECNS_REMOTE_USER')
parser.add_argument('--password-env', default='MALECNS_REMOTE_PASSWORD')
parser.add_argument('--known-hosts', type=Path, default=Path.home() / '.ssh/known_hosts')
args = parser.parse_args()
require(SHA.fullmatch(args.receipt_sha256), 'External receipt SHA required'); check_destination(args.destination)
require(args.known_hosts.is_file(), 'Existing known_hosts required; trust must be configured separately')
username, password = os.environ.get(args.user_env), os.environ.get(args.password_env)
require(username and password, 'Credential environment variables are required')
import paramiko
client = paramiko.SSHClient()
client.load_system_host_keys(str(args.known_hosts))
client.set_missing_host_key_policy(paramiko.RejectPolicy())
try:
client.connect(args.host, port=args.port, username=username, password=password, allow_agent=False, look_for_keys=False,
timeout=15, auth_timeout=15, banner_timeout=15)
with client.open_sftp() as sftp:
result = fetch(sftp, args.destination, args.receipt_sha256)
print(json.dumps({key: result[key] for key in ('fetch_complete', 'declared_status', 'publication_receipt_sha256', 'downloaded_file_count')}), flush=True)
finally:
client.close()
if __name__ == '__main__':
main()
@@ -0,0 +1,279 @@
"""Exclusive small-evidence delivery of a completed, sealed AN engineering gate.
The two external hashes are mandatory. This tool verifies bytes and declared
completion, not numerical science, and never imports an AN execution module.
Only the 21 registered source snapshots are delivered; the mutable model tree
is neither copied nor declared sealed. Failed/incomplete engineering results
retain their exact status. Partial publications are preserved, never resumed.
"""
from __future__ import annotations
import argparse
import hashlib
import importlib.util
import json
from pathlib import Path, PurePosixPath
import re
import sys
ROOT = Path('/data/digital-drosophila')
MODEL_REL = Path('models/male-cns-lif/olfactory-conditioning-lab-v1')
EXP_REL = Path('experiments/phase4an-engineering-validation')
REGISTRY_REL = Path('registry/phase4an-engineering-validation')
HELPER_REL = Path('models/male-cns-lif/pn-recruitment-audit-v1/publication.py')
HELPER_SHA = '7a79c499098b74163e7bb16adabcbc54e7069dafa204d0b99c7f4c03d79f8016'
PREREG_SHA = '7317441126f191ccc6e6d28438870b3921537ebe282a6acb163716a690057945'
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([m + '.py' for m in MODULES] + ['test_' + m + '.py' for m in MODULES] + ['ENGINEERING_GATE_DRAFT.md']))
PASS = 'PASS-EXACT-LIGHT-CONTINUATION-ENGINEERING-NOT-LEARNING'
STATUSES = frozenset((PASS, 'FAIL-NUMERICAL', 'INCOMPLETE-COVERAGE'))
SUFFIXES = frozenset(('.json', '.csv', '.md', '.log', '.sha256'))
MAX_BYTES = 4 * 1024**2
REQUIRED = ('protocol/preregistered.json', 'audit/final-status.json', 'audit/engineering-analysis.json',
'audit/analysis-execution.json', 'audit/execution-complete.json',
'regression/old-integrity-before.json', 'regression/old-integrity-after.json',
'regression/AM-seals-after.json')
def require(value, message):
if not value:
raise ValueError(message)
def digest(path):
h = hashlib.sha256()
with Path(path).open('rb') as stream:
for data in iter(lambda: stream.read(8 << 20), b''):
h.update(data)
return h.hexdigest()
def is_sha(value):
return type(value) is str and re.fullmatch('[0-9a-f]{64}', value) is not None
def load_helper(path):
raw = Path(path).read_bytes()
require(hashlib.sha256(raw).hexdigest() == HELPER_SHA, 'AI publication helper pin mismatch')
spec = importlib.util.spec_from_file_location('phase4an_delivery_pinned_AI', path)
module = importlib.util.module_from_spec(spec)
exec(compile(raw, str(path), 'exec'), module.__dict__)
return module
def _small_json(helper, experiment, rows, name):
require(name in rows and rows[name]['bytes'] <= MAX_BYTES, 'Required small evidence missing/oversize: ' + name)
path = helper._regular_file(experiment, name)
require(digest(path) == rows[name]['sha256'], 'Evidence changed: ' + name)
return helper._json_bytes(path.read_bytes())
def _write(path, value):
raw = (json.dumps(value, sort_keys=True, indent=2, ensure_ascii=False, allow_nan=False) + '\n').encode('utf-8')
require(len(raw) <= MAX_BYTES, 'Generated delivery evidence exceeds 4 MiB')
with Path(path).open('xb') as stream:
stream.write(raw)
def _sources(helper, root, experiment, rows, reg):
model = root / MODEL_REL
expected_paths = {str(model / name) for name in SOURCE_FILES}
require(type(reg.get('source_sha256')) is dict and set(reg['source_sha256']) == expected_paths,
'Registered source inventory is not the exact 21 used files')
actual_snapshots = {p for p in rows if p.startswith('protocol/source-snapshot/')}
require(actual_snapshots == {'protocol/source-snapshot/' + name for name in SOURCE_FILES}, 'Snapshot inventory differs from the 21 used sources')
proof = []
for name in SOURCE_FILES:
relative = 'protocol/source-snapshot/' + name
original = helper._regular_file(root, (MODEL_REL / name).as_posix())
snapshot = helper._regular_file(experiment, relative)
expected = reg['source_sha256'][str(original)]
require(is_sha(expected) and rows[relative]['sha256'] == expected and
reg['input_sha256'].get(str(snapshot)) == expected and digest(original) == digest(snapshot) == expected,
'Actual used source / registered snapshot mismatch: ' + name)
require(original.stat().st_size == rows[relative]['bytes'] <= MAX_BYTES, 'Used source exceeds small delivery limit')
proof.append(dict(model_source=(MODEL_REL / name).as_posix(), sealed_source=(EXP_REL / relative).as_posix(),
copy='source-snapshot/' + name, bytes=rows[relative]['bytes'], sha256=expected))
return proof
def _declared_evidence(helper, experiment, rows):
evidence = {name: _small_json(helper, experiment, rows, name) for name in REQUIRED}
reg = evidence['protocol/preregistered.json']; final = evidence['audit/final-status.json']
analysis = evidence['audit/engineering-analysis.json']; execution = evidence['audit/execution-complete.json']
require(reg.get('schema') == 'phase4an-engineering-registration-v1' and reg.get('training') is False, 'Wrong registration scope')
require(final.get('schema') == 'phase4an-engineering-final-v1' and final.get('status') in STATUSES and
final.get('registration_sha256') == PREREG_SHA and final.get('analysis_recomputed_exactly') is True,
'Missing finalized/recomputed engineering evidence')
require(analysis.get('schema') == 'phase4an-engineering-analysis-v1' and analysis.get('status') == final['status'] and
analysis.get('registration_sha256') == PREREG_SHA and analysis.get('source_sha256') == reg['source_sha256'],
'Final/analysis/registration disagreement')
for obj in (final, analysis, execution):
require(obj.get('training') is False and obj.get('learning_pass_claimed') is False, 'Unexpected learning/training claim')
require(final.get('learned_candidate') is False and analysis.get('candidate_generated') is False and
analysis.get('GPU_used') is False and analysis.get('no_new_brain_runs_during_analysis') is True,
'Unexpected candidate or analysis scope')
require(final.get('model_directory_sealed') is False and final.get('used_engineering_source_snapshots_sealed') is True,
'Do not declare the mutable model directory sealed')
for obj, key, expected in ((final, 'completed_calls', 32), (final, 'executed_ticks', 11074),
(analysis, 'expected_calls', 32), (analysis, 'analyzed_calls', 32), (analysis, 'executed_ticks', 11074),
(execution, 'expected_calls', 32), (execution, 'executed_ticks', 11074)):
require(type(obj.get(key)) is int and obj[key] == expected, 'Incomplete declared engineering inventory: ' + key)
require(all(type(analysis.get(k)) is bool for k in ('pass_all', 'numerical_exact', 'nonvacuous_temporal_coverage')),
'Missing explicit numerical/coverage declarations')
numerical, covered = analysis['numerical_exact'], analysis['nonvacuous_temporal_coverage']
declared = 'FAIL-NUMERICAL' if not numerical else (PASS if covered else 'INCOMPLETE-COVERAGE')
require(final['status'] == declared and analysis['pass_all'] is (numerical and covered), 'Declared status contradicts its numerical/coverage flags')
analysis_sha = rows['audit/engineering-analysis.json']['sha256']
analysis_exec = evidence['audit/analysis-execution.json']
require(final.get('analysis_sha256') == analysis_sha and analysis_exec.get('analysis_sha256') == analysis_sha and
analysis_exec.get('registration_sha256') == PREREG_SHA, 'Final analysis SHA linkage mismatch')
plan = reg.get('plan', {}); planned = plan.get('rows')
require(plan.get('total_calls') == 32 and plan.get('total_ticks') == 11074 and type(planned) is list and len(planned) == 32,
'Incomplete registered plan')
ids = [row.get('row_id') for row in planned]
require(all(type(x) is str and re.fullmatch('[a-zA-Z0-9_-]+', x) for x in ids) and len(set(ids)) == 32 and
all(type(row.get('steps')) is int and row['steps'] > 0 for row in planned) and sum(row['steps'] for row in planned) == 11074,
'Invalid registered call identities/steps')
complete = execution.get('completed')
require(execution.get('complete') is True and execution.get('registration_sha256') == PREREG_SHA and
type(complete) is list and len(complete) == 32, 'Incomplete execution receipt inventory')
for row, done in zip(planned, complete):
identity = row['row_id']; name = 'receipts/' + identity + '.json'
receipt = _small_json(helper, experiment, rows, name)
runtime_name = 'receipts/' + identity + '.runtime.json'
runtime = _small_json(helper, experiment, rows, runtime_name)
require(done.get('row_id') == identity and done.get('execution_sha256') == rows[name]['sha256'], 'Execution order/receipt SHA mismatch')
require(receipt.get('complete') is True and type(receipt.get('process_exit_code')) is int and receipt['process_exit_code'] == 0 and
receipt.get('row_id') == identity and receipt.get('registration_sha256') == PREREG_SHA and
receipt.get('runtime_record_sha256') == rows[runtime_name]['sha256'], 'Unsuccessful/unbound process receipt')
require(runtime.get('complete') is True and runtime.get('training') is False and runtime.get('registration_sha256') == PREREG_SHA and
runtime.get('row') == row, 'Runtime row does not match its registered descriptor')
for field, suffix in (('stdout_sha256', '.stdout.log'), ('stderr_sha256', '.stderr.log')):
log = 'logs/' + identity + suffix
require(log in rows and receipt.get(field) == rows[log]['sha256'], 'Execution log linkage mismatch')
checkpoint = 'runs/' + identity + '/checkpoint-manifest.json'
require(checkpoint in rows and receipt.get('checkpoint_manifest_sha256') == runtime.get('checkpoint_manifest_sha256') == rows[checkpoint]['sha256'],
'Execution checkpoint linkage mismatch')
before, after = (evidence['regression/old-integrity-' + point + '.json'] for point in ('before', 'after'))
require(type(before) is dict and type(after) is dict and len(before) == len(after) == 28 and set(before) == set(after) and
all(type(r) is dict and r.get('pass') is True for r in [*before.values(), *after.values()]) and
final.get('old_integrity_pass') is True and final.get('old_integrity_roots') == 28 and final.get('AM_seals_preserved') is True,
'Finalized frozen-integrity evidence missing/failed')
for name in before:
for report in (before[name], after[name]):
require(report.get('mismatches', []) == [], 'Frozen integrity report contains mismatches')
for key in ('manifest_sha256', 'checksums_sha256', 'reference_sha256'):
if key in before[name] or key in after[name]:
require(is_sha(before[name].get(key)) and before[name][key] == after[name].get(key),
'Frozen integrity authority changed: ' + name)
am = evidence['regression/AM-seals-after.json']
require(type(am) is dict and set(am) == {'model', 'experiment'} and all(am[k].get('pass_all') is True and
am[k].get('manifest_sha256') == reg['anchors']['am_' + k + '_manifest_sha256'] for k in am), 'AM seal evidence contradicts registered anchors')
return reg, final, analysis
def selection(row):
"""Return a canonical destination or an explicit omitted reason."""
path = PurePosixPath(row['path'])
if path.parts[0] == 'extension-build':
return None, 'build_artifact'
if row['bytes'] > MAX_BYTES:
return None, 'exceeds_4_MiB'
if path.parts[:2] == ('protocol', 'source-snapshot') and len(path.parts) == 3 and path.name in SOURCE_FILES:
return 'source-snapshot/' + path.name, None
if path.suffix.lower() not in SUFFIXES:
return None, 'bulk_binary_or_unselected_suffix_including_jsonl'
return 'evidence/' + row['path'], None
def publish(experiment_manifest_sha, final_sha, *, root=ROOT):
require(sys.dont_write_bytecode, 'Use python -B; registered sources remain read-only')
require(is_sha(experiment_manifest_sha) and is_sha(final_sha), 'Two actual external manifest/final SHA-256 anchors are mandatory')
root = Path(root)
require(root.is_absolute() and root.is_dir() and not root.is_symlink(), 'Invalid project root')
root = root.resolve(strict=True)
publisher_sha = digest(__file__)
experiment, registry = root / EXP_REL, root / REGISTRY_REL
for relative in (EXP_REL, MODEL_REL, REGISTRY_REL, HELPER_REL):
current = root
for part in relative.parts:
current = current / part
require(not current.is_symlink(), 'Symlink in publication path')
require(not registry.exists(), 'Registry exists; no overwrite or retry')
helper_path = root / HELPER_REL; helper = load_helper(helper_path)
require(digest(experiment / 'manifest.json') == experiment_manifest_sha and
digest(experiment / 'audit/final-status.json') == final_sha and
digest(experiment / 'protocol/preregistered.json') == PREREG_SHA, 'External/fixed authority mismatch')
verified = helper.verify_seal(experiment)
require(verified['manifest_sha256'] == experiment_manifest_sha, 'Experiment authority changed during verification')
rows = {row['path']: row for row in verified['files']}
require(not any(PurePosixPath(name).name in ('stopped.json', 'preparation-failure.json', 'error.json', 'runtime-error.json') for name in rows),
'Execution/error partial cannot be published as a completed engineering gate')
reg, final, analysis = _declared_evidence(helper, experiment, rows)
source_proof = _sources(helper, root, experiment, rows, reg)
plans, omitted = [], []
for row in verified['files'] + helper._control_rows(experiment, verified):
destination, reason = selection(row)
if destination:
plans.append((row, destination))
else:
omitted.append(dict(row, reason=reason))
targets = {destination for _, destination in plans}
require(len(targets) == len(plans) and all('evidence/' + name in targets for name in (*REQUIRED, 'manifest.json', 'checksums.sha256')),
'Required controls/evidence cannot fit the fixed small-copy policy')
require(all('source-snapshot/' + name in targets for name in SOURCE_FILES), 'Missing deliverable registered source')
registry.parent.mkdir(parents=True, exist_ok=True); registry.mkdir(exist_ok=False)
try:
records = []
for row, destination in plans:
source = helper._regular_file(experiment, row['path'])
helper._copy_verified(source, registry / destination, row['bytes'], row['sha256'])
records.append(dict(source=(EXP_REL / row['path']).as_posix(), copy=destination, bytes=row['bytes'], sha256=row['sha256']))
require(helper.verify_seal(experiment) == verified and _sources(helper, root, experiment, rows, reg) == source_proof and
digest(helper_path) == HELPER_SHA and digest(__file__) == publisher_sha,
'Sealed payload, helper, publisher or original used sources changed during publication')
_write(registry / 'seal-verification.json', {k: v for k, v in verified.items() if k != 'files'})
_write(registry / 'evidence-index.json', records)
_write(registry / 'source-identity.json', source_proof)
files = [dict(path=path.relative_to(registry).as_posix(), bytes=path.stat().st_size, sha256=digest(path))
for path in sorted(registry.rglob('*')) if path.is_file()]
receipt = dict(schema='phase4an-engineering-publication-v1', publication_complete=True,
registry=REGISTRY_REL.as_posix(), project_root=str(root), declared_status=final['status'],
declared_numerical_exact=analysis['numerical_exact'], declared_live_coverage=analysis['nonvacuous_temporal_coverage'],
declared_engineering_pass=analysis['pass_all'], completed_calls=32, executed_ticks=11074,
experiment_manifest_sha256=experiment_manifest_sha, experiment_checksums_sha256=verified['checksums_sha256'],
final_sha256=final_sha, analysis_sha256=final['analysis_sha256'], preregistration_sha256=PREREG_SHA,
publisher_sha256=publisher_sha, helper_sha256=HELPER_SHA, helper_globals_modified=False,
used_sources_verified_before_and_after=True, used_source_count=21, model_directory_sealed=False,
model_files_copied=False, copied_evidence_files=len(records), copied_evidence_bytes=sum(r['bytes'] for r in records),
source_identity='source-identity.json', files=files, experiment_payload_not_copied=omitted,
selection_policy=dict(max_file_bytes=MAX_BYTES, suffixes=sorted(SUFFIXES),
source_snapshot_names=list(SOURCE_FILES), excluded_tree='extension-build', all_jsonl_excluded=True),
complete_checksums_reference_bulk_not_copied=True, bulk_remains_at=EXP_REL.as_posix(), complete_bulk_backup=False,
numerical_gate_rerun_by_publisher=False, publication_success_is_not_engineering_or_learning_pass=True,
training=False, candidate_generated=False, learning_pass_claimed=False, existing_files_modified=False,
receipt_self_hash='Excluded from files; its SHA is returned externally, never embedded in itself')
path = registry / 'publication-receipt.json'; _write(path, receipt)
return dict(publication_complete=True, declared_status=final['status'], registry=str(registry),
copied_evidence_files=len(records), receipt_sha256=digest(path))
except Exception as error:
failure = registry / 'publication-failure.json'
if not failure.exists():
_write(failure, dict(publication_complete=False, error_type=type(error).__name__, error=str(error), partial_outputs_preserved=True))
raise
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--experiment-manifest-sha256', required=True)
parser.add_argument('--final-sha256', required=True)
args = parser.parse_args()
print(json.dumps(publish(args.experiment_manifest_sha256, args.final_sha256), ensure_ascii=False), flush=True)
if __name__ == '__main__':
main()
@@ -0,0 +1,229 @@
"""In-memory SFTP / temporary local files only; no real server access."""
import io
import json
from pathlib import Path
import stat
import tempfile
import types
import unittest
from unittest.mock import patch
import fetch_phase4an as f
def data(value):
return (json.dumps(value, sort_keys=True, allow_nan=False) + '\n').encode()
def row(name, raw):
return dict(path=name, bytes=len(raw), sha256=f.sha(raw))
class FakeSFTP:
def __init__(self, files):
self.files, self.opened, self.symlinks, self.hook = files, [], set(), None
def lstat(self, name):
if name in self.symlinks: return types.SimpleNamespace(st_mode=stat.S_IFLNK | 0o777, st_size=1)
if name in self.files: return types.SimpleNamespace(st_mode=stat.S_IFREG | 0o644, st_size=len(self.files[name]))
if any(x.startswith(name.rstrip('/') + '/') for x in self.files): return types.SimpleNamespace(st_mode=stat.S_IFDIR | 0o755, st_size=0)
raise FileNotFoundError(name)
def open(self, name, mode):
if mode != 'rb': raise AssertionError('Remote writes are forbidden')
self.opened.append(name)
if self.hook: self.hook(name)
return io.BytesIO(self.files[name])
def fixture(status=f.PASS):
payload, sources, inputs, identities = {}, {}, {}, []
for name in f.SOURCE_FILES:
content = ('# synthetic ' + name).encode(); path = 'protocol/source-snapshot/' + name
payload[path] = content
sources[f.REMOTE_ROOT + '/' + f.MODEL_REL + '/' + name] = f.sha(content)
inputs[f.REMOTE_ROOT + '/' + f.EXP_REL + '/' + path] = f.sha(content)
identities.append(dict(model_source=f.MODEL_REL + '/' + name, sealed_source=f.EXP_REL + '/' + path,
copy='source-snapshot/' + name, bytes=len(content), sha256=f.sha(content)))
payload['protocol/preregistered.json'] = data(dict(source_sha256=sources, input_sha256=inputs))
prereg = f.sha(payload['protocol/preregistered.json'])
numerical, covered = status != 'FAIL-NUMERICAL', status == f.PASS
analysis = dict(status=status, registration_sha256=prereg, source_sha256=sources, expected_calls=32,
analyzed_calls=32, executed_ticks=11074, numerical_exact=numerical, nonvacuous_temporal_coverage=covered,
pass_all=numerical and covered, training=False, candidate_generated=False, learning_pass_claimed=False)
payload['audit/engineering-analysis.json'] = data(analysis)
analysis_sha = f.sha(payload['audit/engineering-analysis.json'])
final = dict(status=status, analysis_sha256=analysis_sha, registration_sha256=prereg, analysis_recomputed_exactly=True,
completed_calls=32, executed_ticks=11074, training=False, learned_candidate=False, learning_pass_claimed=False)
payload['audit/final-status.json'] = data(final)
payload.update({'runs/example/state.npz': b'bulk', 'runs/example/queue.jsonl': b'bulk queue',
'extension-build/build.log': b'not selected', 'logs/readable.log': b'small log'})
manifest_rows = [row(name, raw) for name, raw in sorted(payload.items())]
manifest = data(dict(root=f.REMOTE_ROOT + '/' + f.EXP_REL, files=manifest_rows))
checksums = (''.join(r['sha256'] + ' ' + r['path'] + '\n' for r in manifest_rows) + f.sha(manifest) + ' manifest.json\n').encode()
controls = {'manifest.json': manifest, 'checksums.sha256': checksums}
registry, evidence_index, omitted = {}, [], []
for name, raw in sorted({**payload, **controls}.items()):
r = row(name, raw); target, reason = f.selected(r)
if target:
registry[target] = raw
evidence_index.append(dict(source=f.EXP_REL + '/' + name, copy=target, bytes=len(raw), sha256=f.sha(raw)))
else: omitted.append(dict(r, reason=reason))
proof = dict(pass_all=True, root=f.REMOTE_ROOT + '/' + f.EXP_REL, manifest_sha256=f.sha(manifest), checksums_sha256=f.sha(checksums),
payload_file_count=len(manifest_rows), payload_bytes=sum(r['bytes'] for r in manifest_rows))
registry['seal-verification.json'] = data(proof)
registry['evidence-index.json'] = data(evidence_index)
registry['source-identity.json'] = data(identities)
receipt = dict(schema='phase4an-engineering-publication-v1', publication_complete=True, project_root=f.REMOTE_ROOT,
registry=f.REGISTRY_REL, declared_status=status, used_sources_verified_before_and_after=True,
complete_checksums_reference_bulk_not_copied=True, publication_success_is_not_engineering_or_learning_pass=True,
model_directory_sealed=False, model_files_copied=False, complete_bulk_backup=False, numerical_gate_rerun_by_publisher=False,
training=False, candidate_generated=False, learning_pass_claimed=False, existing_files_modified=False, helper_globals_modified=False,
selection_policy=dict(max_file_bytes=f.MAX_FILE_BYTES, suffixes=sorted(f.SUFFIXES), source_snapshot_names=list(f.SOURCE_FILES),
excluded_tree='extension-build', all_jsonl_excluded=True),
used_source_count=21, completed_calls=32, executed_ticks=11074, preregistration_sha256=prereg,
source_identity='source-identity.json', bulk_remains_at=f.EXP_REL, experiment_manifest_sha256=f.sha(manifest),
experiment_checksums_sha256=f.sha(checksums), final_sha256=f.sha(payload['audit/final-status.json']), analysis_sha256=analysis_sha,
publisher_sha256='a'*64, helper_sha256='b'*64, files=[row(name, raw) for name, raw in sorted(registry.items())],
experiment_payload_not_copied=omitted, copied_evidence_files=len(evidence_index),
copied_evidence_bytes=sum(r['bytes'] for r in evidence_index), declared_numerical_exact=numerical,
declared_live_coverage=covered, declared_engineering_pass=numerical and covered)
registry['publication-receipt.json'] = data(receipt)
return FakeSFTP({f.REGISTRY_ROOT + '/' + name: raw for name, raw in registry.items()}), prereg, f.sha(registry['publication-receipt.json'])
class FetchTests(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory(prefix='phase4an-fetch-test-'); self.addCleanup(self.temp.cleanup)
self.destination = Path(self.temp.name).resolve() / 'report'
self.sftp, self.prereg, self.pin = fixture()
def fetch(self, **kwargs):
with patch.object(f, 'PREREG_SHA', self.prereg):
return f.fetch(self.sftp, self.destination, self.pin, **kwargs)
def receipt(self): return f.json_bytes(self.sftp.files[f.REGISTRY_ROOT + '/publication-receipt.json'])
def resign(self, receipt):
raw = data(receipt); self.sftp.files[f.REGISTRY_ROOT + '/publication-receipt.json'] = raw; self.pin = f.sha(raw)
def change_selected(self, name, content):
self.sftp.files[f.REGISTRY_ROOT + '/' + name] = content
receipt = self.receipt(); next(r for r in receipt['files'] if r['path'] == name).update(bytes=len(content), sha256=f.sha(content))
self.resign(receipt)
def test_exact_small_registry_mirror_and_receipt_hashes_no_model_or_bulk(self):
result = self.fetch()
self.assertTrue(result['fetch_complete']); self.assertTrue(result['exact_receipt_inventory_downloaded'])
self.assertFalse(result['engineering_gate_executed']); self.assertFalse(result['learning_pass_claimed'])
self.assertTrue((self.destination / 'evidence/audit/final-status.json').is_file())
self.assertTrue((self.destination / 'source-snapshot/runtime_light.py').is_file())
self.assertEqual(len(result['files']), len(self.receipt()['files']) + 1)
self.assertEqual(result['sftp_bytes_read_including_anchor_reread'], result['downloaded_bytes'] + len(self.sftp.files[f.REGISTRY_ROOT + '/publication-receipt.json']))
for r in result['files']:
self.assertEqual(f.sha((self.destination / r['path']).read_bytes()), r['sha256'])
self.assertTrue(all(name.startswith(f.REGISTRY_ROOT + '/') for name in self.sftp.opened))
self.assertFalse(any(name.endswith(('.npz', '.npy', '.jsonl')) or '/extension-build/' in name for name in self.sftp.opened))
def test_failure_and_incomplete_declarations_never_promoted(self):
for status in ('FAIL-NUMERICAL', 'INCOMPLETE-COVERAGE'):
with self.subTest(status=status), tempfile.TemporaryDirectory() as directory:
sftp, prereg, pin = fixture(status)
with patch.object(f, 'PREREG_SHA', prereg): result = f.fetch(sftp, Path(directory).resolve() / 'report', pin)
self.assertEqual(result['declared_status'], status)
self.assertTrue(result['fetch_success_is_not_engineering_or_learning_pass'])
def test_external_receipt_pin_and_fixed_prereg_required_before_payload(self):
for pin in ('', 'x'*64, '0'*64):
self.sftp.opened.clear()
with self.assertRaises(ValueError): f.fetch(self.sftp, self.destination, pin)
self.assertFalse(self.destination.exists())
self.assertTrue(all(name.endswith('/publication-receipt.json') for name in self.sftp.opened))
with self.assertRaisesRegex(ValueError, 'authority/scope'): f.fetch(self.sftp, self.destination, self.pin)
def test_forbidden_paths_and_binary_or_extra_source_fail_before_more_reads(self):
for name in ('../bad.json', 'evidence/x/../bad.json', 'evidence/C:/bad.json', 'evidence/CON.log',
'source-snapshot/unregistered.py', 'evidence/state.npz', 'evidence/queue.jsonl', 'evidence/extension-build/info.json'):
with self.subTest(name=name):
self.sftp, self.prereg, self.pin = fixture(); receipt = self.receipt()
receipt['files'].append(dict(path=name, bytes=1, sha256='a'*64)); self.resign(receipt)
with self.assertRaises(ValueError): self.fetch()
self.assertFalse(self.destination.exists()); self.assertEqual(len(self.sftp.opened), 1)
def test_case_prefix_collision_and_receipt_self_inventory_rejected(self):
for name in ('EVIDENCE/audit/final-status.json', 'evidence/audit', 'publication-receipt.json', 'fetch-verification.json'):
with self.subTest(name=name):
self.sftp, self.prereg, self.pin = fixture(); receipt = self.receipt()
receipt['files'].append(dict(path=name, bytes=1, sha256='a'*64)); self.resign(receipt)
with self.assertRaises(ValueError): self.fetch()
self.assertFalse(self.destination.exists())
def test_budget_is_hard_cap_and_cannot_be_raised(self):
with self.assertRaises(ValueError): self.fetch(max_total_bytes=f.MAX_TOTAL_BYTES + 1)
self.assertFalse(self.sftp.opened)
with self.assertRaisesRegex(ValueError, 'budget'): self.fetch(max_total_bytes=1)
self.assertFalse(self.destination.exists())
def test_manifest_checksum_link_checked_even_after_receipt_resigned(self):
name = 'evidence/checksums.sha256'; raw = self.sftp.files[f.REGISTRY_ROOT + '/' + name]
lines = raw.decode().splitlines(); lines[-1] = '0'*64 + ' manifest.json'; changed = ('\n'.join(lines)+'\n').encode()
self.change_selected(name, changed); receipt = self.receipt(); receipt['experiment_checksums_sha256'] = f.sha(changed); self.resign(receipt)
with self.assertRaisesRegex(ValueError, 'self-SHA'): self.fetch()
self.assertFalse(self.destination.exists())
def test_source_identity_and_index_crosslinks_not_just_receipt_flags(self):
for name, mutation in (('source-identity.json', 'model_source'), ('evidence-index.json', 'source')):
with self.subTest(name=name):
self.sftp, self.prereg, self.pin = fixture(); values = f.json_bytes(self.sftp.files[f.REGISTRY_ROOT + '/' + name])
values[0][mutation] = 'wrong/source.py'; self.change_selected(name, data(values))
with self.assertRaises(ValueError): self.fetch()
self.assertFalse(self.destination.exists())
def test_exact_omitted_and_selection_inventory_cannot_drop_evidence(self):
receipt = self.receipt(); receipt['experiment_payload_not_copied'].pop(); self.resign(receipt)
with self.assertRaisesRegex(ValueError, 'Omitted'): self.fetch()
self.assertFalse(self.destination.exists())
self.sftp, self.prereg, self.pin = fixture(); receipt = self.receipt()
receipt['files'] = [r for r in receipt['files'] if r['path'] != 'evidence/logs/readable.log']; self.resign(receipt)
with self.assertRaisesRegex(ValueError, 'exact sealed policy'): self.fetch()
def test_existing_or_alias_destination_denied_without_remote_reads(self):
self.destination.mkdir()
with self.assertRaisesRegex(ValueError, 'exists'): self.fetch()
self.assertFalse(self.sftp.opened)
with self.assertRaises(ValueError): f.check_destination(self.destination / '..' / 'other')
def test_remote_symlink_directory_and_file_denied(self):
for remote in (f.REGISTRY_ROOT, f.REGISTRY_ROOT + '/publication-receipt.json'):
self.sftp.symlinks.add(remote)
with self.assertRaisesRegex(ValueError, 'symlink'): self.fetch()
self.assertFalse(self.sftp.opened); self.sftp.symlinks.clear()
def test_payload_corruption_preserves_partial_and_prevents_retry(self):
remote = f.REGISTRY_ROOT + '/evidence/logs/readable.log'; self.sftp.files[remote] = b'x' * len(self.sftp.files[remote])
with self.assertRaisesRegex(ValueError, 'SHA'): self.fetch()
self.assertTrue((self.destination / 'fetch-failure.json').is_file())
self.assertFalse((self.destination / 'fetch-verification.json').exists())
with self.assertRaisesRegex(ValueError, 'exists'): self.fetch()
def test_remote_receipt_changed_during_download_fails_final_anchor(self):
def change(name):
if name.endswith('/source-snapshot/runtime_light.py'):
self.sftp.files[f.REGISTRY_ROOT + '/publication-receipt.json'] += b' '
self.sftp.hook = change
with self.assertRaises(ValueError): self.fetch()
self.assertTrue((self.destination / 'fetch-failure.json').exists())
self.assertFalse((self.destination / 'fetch-verification.json').exists())
def test_cli_host_trust_credentials_and_default_destination_are_explicit(self):
source = Path(f.__file__).read_text(encoding='utf-8')
self.assertIn('paramiko.RejectPolicy()', source)
self.assertIn('client.load_system_host_keys(str(args.known_hosts))', source)
self.assertIn('allow_agent=False, look_for_keys=False', source)
self.assertNotIn('AutoAddPolicy', source)
self.assertNotIn("add_argument('--password'", source)
self.assertEqual(f.DEFAULT_DESTINATION, Path(f.__file__).resolve().parents[2] / 'reports/phase4an-engineering-validation')
if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,228 @@
"""Temporary synthetic payloads only; no real publishing, GPU or old writes."""
import hashlib
import json
from pathlib import Path
import tempfile
import unittest
from unittest.mock import patch
import publish_phase4an as p
AI = Path(__file__).resolve().parent.parent / 'pn-recruitment-audit-v1/publication.py'
if not AI.is_file():
AI = p.ROOT / p.HELPER_REL
def write(path, value):
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(value, sort_keys=True), encoding='utf-8')
def read(path):
return json.loads(path.read_text(encoding='utf-8'))
def seal(exp):
rows = [dict(path=path.relative_to(exp).as_posix(), bytes=path.stat().st_size, sha256=p.digest(path))
for path in sorted(exp.rglob('*')) if path.is_file() and path.relative_to(exp).as_posix() not in ('manifest.json', 'checksums.sha256')]
write(exp / 'manifest.json', {'root': str(exp), 'files': rows})
(exp / 'checksums.sha256').write_text(''.join(r['sha256'] + ' ' + r['path'] + '\n' for r in rows) +
p.digest(exp / 'manifest.json') + ' manifest.json\n', encoding='utf-8')
return p.digest(exp / 'manifest.json'), p.digest(exp / 'audit/final-status.json')
def fixture(root, status=p.PASS):
exp, model = root / p.EXP_REL, root / p.MODEL_REL
exp.mkdir(parents=True); model.mkdir(parents=True)
helper = root / p.HELPER_REL; helper.parent.mkdir(parents=True); helper.write_bytes(AI.read_bytes())
sources, inputs = {}, {}
for name in p.SOURCE_FILES:
raw = ('# synthetic used source: ' + name + '\n').encode()
original, snapshot = model / name, exp / 'protocol/source-snapshot' / name
original.write_bytes(raw); snapshot.parent.mkdir(parents=True, exist_ok=True); snapshot.write_bytes(raw)
sources[str(original)] = inputs[str(snapshot)] = hashlib.sha256(raw).hexdigest()
(model / 'unregistered-science.py').write_bytes(b'not copied or sealed')
planned = [dict(row_id='synthetic-' + str(i), steps=348 if i == 31 else 346) for i in range(32)]
anchors = dict(am_model_manifest_sha256='a'*64, am_experiment_manifest_sha256='b'*64)
reg = dict(schema='phase4an-engineering-registration-v1', training=False, source_sha256=sources, input_sha256=inputs,
anchors=anchors, plan=dict(total_calls=32, total_ticks=11074, rows=planned))
write(exp / 'protocol/preregistered.json', reg); prereg = p.digest(exp / 'protocol/preregistered.json')
completed = []
for row in planned:
identity = row['row_id']
checkpoint = exp / 'runs' / identity / 'checkpoint-manifest.json'; write(checkpoint, {'synthetic': True})
runtime = dict(complete=True, training=False, registration_sha256=prereg, row=row, checkpoint_manifest_sha256=p.digest(checkpoint))
runtime_path = exp / 'receipts' / (identity + '.runtime.json'); write(runtime_path, runtime)
for suffix in ('.stdout.log', '.stderr.log'):
target = exp / 'logs' / (identity + suffix); target.parent.mkdir(exist_ok=True); target.write_bytes(b'synthetic log')
receipt = dict(complete=True, process_exit_code=0, row_id=identity, registration_sha256=prereg,
runtime_record_sha256=p.digest(runtime_path), checkpoint_manifest_sha256=p.digest(checkpoint),
stdout_sha256=p.digest(exp / 'logs' / (identity + '.stdout.log')),
stderr_sha256=p.digest(exp / 'logs' / (identity + '.stderr.log')))
receipt_path = exp / 'receipts' / (identity + '.json'); write(receipt_path, receipt)
completed.append(dict(row_id=identity, execution_sha256=p.digest(receipt_path)))
write(exp / 'audit/execution-complete.json', dict(complete=True, registration_sha256=prereg, completed=completed,
expected_calls=32, executed_ticks=11074, training=False, learning_pass_claimed=False))
numerical, covered = status != 'FAIL-NUMERICAL', status == p.PASS
analysis = dict(schema='phase4an-engineering-analysis-v1', status=status, registration_sha256=prereg,
source_sha256=sources, training=False, learning_pass_claimed=False, candidate_generated=False, GPU_used=False,
no_new_brain_runs_during_analysis=True, expected_calls=32, analyzed_calls=32, executed_ticks=11074,
pass_all=numerical and covered, numerical_exact=numerical, nonvacuous_temporal_coverage=covered)
write(exp / 'audit/engineering-analysis.json', analysis)
analysis_sha = p.digest(exp / 'audit/engineering-analysis.json')
write(exp / 'audit/analysis-execution.json', dict(registration_sha256=prereg, analysis_sha256=analysis_sha))
final = dict(schema='phase4an-engineering-final-v1', status=status, registration_sha256=prereg,
analysis_sha256=analysis_sha, analysis_recomputed_exactly=True, completed_calls=32, executed_ticks=11074,
training=False, learned_candidate=False, learning_pass_claimed=False, model_directory_sealed=False,
used_engineering_source_snapshots_sealed=True, old_integrity_pass=True, old_integrity_roots=28, AM_seals_preserved=True)
write(exp / 'audit/final-status.json', final)
old = {str(i): {'pass': True} for i in range(28)}
write(exp / 'regression/old-integrity-before.json', old); write(exp / 'regression/old-integrity-after.json', old)
write(exp / 'regression/AM-seals-after.json', {key: {'pass_all': True, 'manifest_sha256': anchors['am_' + key + '_manifest_sha256']}
for key in ('model', 'experiment')})
(exp / 'runs/synthetic-0/queue.jsonl').write_bytes(b'bulk queue\n')
(exp / 'runs/synthetic-0/state.npz').write_bytes(b'synthetic binary')
(exp / 'extension-build').mkdir(); (exp / 'extension-build/build.log').write_bytes(b'not selected even log')
return prereg, seal(exp)
class DeliveryTests(unittest.TestCase):
def test_success_uses_real_verifier_copies_only_registered_sources_and_small_evidence(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory).resolve(); prereg, anchors = fixture(root)
with patch.object(p, 'PREREG_SHA', prereg):
result = p.publish(*anchors, root=root)
registry = root / p.REGISTRY_REL; receipt = read(registry / 'publication-receipt.json')
self.assertTrue(result['publication_complete']); self.assertEqual(result['declared_status'], p.PASS)
self.assertEqual(result['receipt_sha256'], p.digest(registry / 'publication-receipt.json'))
self.assertEqual(len(list((registry / 'source-snapshot').iterdir())), 21)
self.assertFalse((registry / 'model').exists())
self.assertFalse(any(x.name == 'unregistered-science.py' for x in registry.rglob('*')))
self.assertFalse((registry / 'evidence/runs/synthetic-0/queue.jsonl').exists())
self.assertFalse((registry / 'evidence/extension-build/build.log').exists())
self.assertEqual(len(receipt['experiment_payload_not_copied']), 3)
self.assertNotIn('publication-receipt.json', {x['path'] for x in receipt['files']})
self.assertTrue(receipt['complete_checksums_reference_bulk_not_copied'])
self.assertFalse(receipt['numerical_gate_rerun_by_publisher'])
for row in receipt['files']:
self.assertEqual(p.digest(registry / row['path']), row['sha256'])
self.assertEqual(p.digest(root / p.EXP_REL / 'manifest.json'), anchors[0])
def test_failed_and_incomplete_status_are_delivered_without_promotion(self):
for status in ('FAIL-NUMERICAL', 'INCOMPLETE-COVERAGE'):
with self.subTest(status=status), tempfile.TemporaryDirectory() as directory:
root = Path(directory).resolve(); prereg, anchors = fixture(root, status)
with patch.object(p, 'PREREG_SHA', prereg):
result = p.publish(*anchors, root=root)
receipt = read(root / p.REGISTRY_REL / 'publication-receipt.json')
self.assertEqual(result['declared_status'], status)
self.assertFalse(receipt['declared_engineering_pass'])
self.assertFalse(receipt['learning_pass_claimed'])
def test_two_external_hashes_are_mandatory_and_fixed_prereg_is_not_inferred(self):
with self.assertRaises(TypeError): p.publish()
for anchors in ((None, 'a'*64), ('x'*64, 'b'*64)):
with self.assertRaises(ValueError): p.publish(*anchors)
with tempfile.TemporaryDirectory() as directory:
root = Path(directory).resolve(); _, anchors = fixture(root)
with self.assertRaisesRegex(ValueError, 'authority mismatch'): p.publish(*anchors, root=root)
self.assertFalse((root / p.REGISTRY_REL).exists())
def test_wrong_external_manifest_or_final_is_rejected_before_writes(self):
for position in (0, 1):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory).resolve(); prereg, anchors = fixture(root); bad = list(anchors); bad[position] = 'c'*64
with patch.object(p, 'PREREG_SHA', prereg), self.assertRaises(ValueError): p.publish(*bad, root=root)
self.assertFalse((root / p.REGISTRY_REL).exists())
def test_source_mutation_and_missing_source_are_rejected(self):
for mutation in ('changed', 'missing'):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory).resolve(); prereg, anchors = fixture(root)
source = root / p.MODEL_REL / 'runtime_light.py'
if mutation == 'changed': source.write_bytes(b'changed')
else: source.unlink()
with patch.object(p, 'PREREG_SHA', prereg), self.assertRaises(ValueError): p.publish(*anchors, root=root)
self.assertFalse((root / p.REGISTRY_REL).exists())
def test_snapshot_mutation_rejected_even_if_new_experiment_seal_is_valid(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory).resolve(); prereg, _ = fixture(root); exp = root / p.EXP_REL
(exp / 'protocol/source-snapshot/runtime_light.py').write_bytes(b'different')
anchors = seal(exp)
with patch.object(p, 'PREREG_SHA', prereg), self.assertRaisesRegex(ValueError, 'snapshot mismatch'):
p.publish(*anchors, root=root)
def test_partial_or_unlisted_seal_payload_is_not_ignored(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory).resolve(); prereg, anchors = fixture(root)
(root / p.EXP_REL / 'unlisted').write_bytes(b'unlisted')
with patch.object(p, 'PREREG_SHA', prereg), self.assertRaises(ValueError): p.publish(*anchors, root=root)
def test_helper_pin_and_integrity_authority_are_checked(self):
for mutation in ('helper', 'old-authority'):
with self.subTest(mutation=mutation), tempfile.TemporaryDirectory() as directory:
root = Path(directory).resolve(); prereg, anchors = fixture(root); exp = root / p.EXP_REL
if mutation == 'helper':
(root / p.HELPER_REL).write_bytes(b'# not the pinned verifier')
else:
for point, value in (('before', 'a'), ('after', 'b')):
path = exp / ('regression/old-integrity-' + point + '.json')
record = read(path); record['0']['manifest_sha256'] = value * 64; write(path, record)
anchors = seal(exp)
with patch.object(p, 'PREREG_SHA', prereg), self.assertRaises(ValueError): p.publish(*anchors, root=root)
self.assertFalse((root / p.REGISTRY_REL).exists())
def test_final_false_success_learning_and_bad_count_rejected(self):
for key, value in (('status', 'FAIL-NUMERICAL'), ('learned_candidate', True), ('completed_calls', 31), ('completed_calls', True),
('analysis_recomputed_exactly', False), ('model_directory_sealed', True)):
with self.subTest(key=key, value=value), tempfile.TemporaryDirectory() as directory:
root = Path(directory).resolve(); prereg, _ = fixture(root); exp = root / p.EXP_REL
final = read(exp / 'audit/final-status.json'); final[key] = value; write(exp / 'audit/final-status.json', final)
with patch.object(p, 'PREREG_SHA', prereg), self.assertRaises(ValueError): p.publish(*seal(exp), root=root)
def test_changed_execution_order_or_checkpoint_link_rejected(self):
for mutation in ('order', 'checkpoint'):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory).resolve(); prereg, _ = fixture(root); exp = root / p.EXP_REL
if mutation == 'order':
name = exp / 'audit/execution-complete.json'; data = read(name); data['completed'].reverse(); write(name, data)
else:
name = exp / 'runs/synthetic-0/checkpoint-manifest.json'; write(name, {'synthetic': False})
with patch.object(p, 'PREREG_SHA', prereg), self.assertRaises(ValueError): p.publish(*seal(exp), root=root)
def test_policy_limits_also_exclude_small_build_json_and_all_jsonl(self):
for name in ('extension-build/info.json', 'x/queue.jsonl', 'x/state.npz', 'x/trace.npy', 'x/random.py'):
self.assertIsNone(p.selection(dict(path=name, bytes=1))[0])
self.assertIsNone(p.selection(dict(path='large.json', bytes=p.MAX_BYTES + 1))[0])
self.assertEqual(p.selection(dict(path='protocol/source-snapshot/runtime_light.py', bytes=1))[0], 'source-snapshot/runtime_light.py')
def test_existing_registry_is_never_overwritten_or_retried(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory).resolve(); prereg, anchors = fixture(root)
destination = root / p.REGISTRY_REL; destination.mkdir(parents=True); (destination / 'partial').write_bytes(b'preserve')
with patch.object(p, 'PREREG_SHA', prereg), self.assertRaisesRegex(ValueError, 'no overwrite'):
p.publish(*anchors, root=root)
self.assertEqual((destination / 'partial').read_bytes(), b'preserve')
def test_copy_failure_preserves_partial_and_disallows_retry(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory).resolve(); prereg, anchors = fixture(root)
helper = p.load_helper(root / p.HELPER_REL); original = helper._copy_verified; calls = []
def fail_second(*args):
calls.append(args)
if len(calls) == 2: raise OSError('synthetic write failure')
return original(*args)
with patch.object(p, 'PREREG_SHA', prereg), patch.object(p, 'load_helper', return_value=helper), patch.object(helper, '_copy_verified', side_effect=fail_second):
with self.assertRaises(OSError): p.publish(*anchors, root=root)
registry = root / p.REGISTRY_REL
self.assertTrue((registry / 'publication-failure.json').is_file())
self.assertTrue(calls[0][1].is_file())
self.assertFalse((registry / 'publication-receipt.json').exists())
with patch.object(p, 'PREREG_SHA', prereg), self.assertRaisesRegex(ValueError, 'no overwrite'):
p.publish(*anchors, root=root)
if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,208 @@
"""Temporary Git repositories only; production verification performs no writes."""
import contextlib
import hashlib
import io
import json
from pathlib import Path
import subprocess
import tempfile
import unittest
import verify_git_payload as v
def data(value):
return (json.dumps(value, sort_keys=True, indent=2) + '\n').encode()
def row(name, raw):
return dict(path=name, bytes=len(raw), sha256=v.sha(raw))
class TemporaryGit(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.repo = Path(self.temp.name).resolve()
self.git('init', '-q')
self.git('config', 'user.name', 'Synthetic Test')
self.git('config', 'user.email', 'synthetic@example.invalid')
self.git('config', 'core.autocrlf', 'false')
self.pin = self.fixture()
self.stage()
def tearDown(self):
self.temp.cleanup()
def git(self, *args, input=None):
result = subprocess.run(['git', '-C', str(self.repo), *args], input=input,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
self.assertEqual(result.returncode, 0, result.stderr.decode('utf-8', 'replace'))
return result.stdout
def write(self, path, raw):
target = self.repo / path; target.parent.mkdir(parents=True, exist_ok=True); target.write_bytes(raw)
def stage(self):
self.git('add', '--', v.MODEL, v.REGISTRY)
def fixture(self, status='PASS-EXACT-LIGHT-CONTINUATION-ENGINEERING-NOT-LEARNING'):
payload, source_rows = {}, []
source_sha, input_sha = {}, {}
for name in v.SOURCES:
raw = ('# synthetic source ' + name + '\n').encode()
sealed = 'protocol/source-snapshot/' + name
payload[sealed] = raw
self.write(v.MODEL + '/' + name, raw)
source_sha[v.PROJECT + '/' + v.MODEL + '/' + name] = v.sha(raw)
input_sha[v.PROJECT + '/' + v.EXPERIMENT + '/' + sealed] = v.sha(raw)
source_rows.append(dict(model_source=v.MODEL + '/' + name, sealed_source=v.EXPERIMENT + '/' + sealed,
copy='source-snapshot/' + name, bytes=len(raw), sha256=v.sha(raw)))
payload['protocol/preregistered.json'] = data(dict(schema='phase4an-engineering-registration-v1', training=False,
source_sha256=source_sha, input_sha256=input_sha))
payload['audit/final-status.json'] = data(dict(status=status))
payload['audit/engineering-analysis.json'] = data(dict(status=status))
payload['audit/small.json'] = data({'synthetic': True})
payload['runs/a/state.npz'] = b'not copied bulk'
payload['runs/a/queue.jsonl'] = b'not copied jsonl\n'
payload['extension-build/provenance.json'] = b'not copied build'
rows = [row(name, raw) for name, raw in sorted(payload.items())]
manifest = data(dict(root=v.PROJECT + '/' + v.EXPERIMENT, files=rows))
checksums = ''.join(r['sha256'] + ' ' + r['path'] + '\n' for r in rows)
checksums = (checksums + v.sha(manifest) + ' manifest.json\n').encode()
all_data = {**payload, 'manifest.json': manifest, 'checksums.sha256': checksums}
index, omitted = [], []
for name, raw in all_data.items():
current = row(name, raw); destination, reason = v._selection(current)
if destination is None:
omitted.append(dict(current, reason=reason))
else:
self.write(v.REGISTRY + '/' + destination, raw)
index.append(dict(source=v.EXPERIMENT + '/' + name, copy=destination, bytes=len(raw), sha256=v.sha(raw)))
self.write(v.REGISTRY + '/evidence-index.json', data(index))
self.write(v.REGISTRY + '/source-identity.json', data(source_rows))
self.write(v.REGISTRY + '/seal-verification.json', data(dict(pass_all=True, root=v.PROJECT + '/' + v.EXPERIMENT,
manifest_sha256=v.sha(manifest), checksums_sha256=v.sha(checksums), payload_file_count=len(rows), payload_bytes=sum(r['bytes'] for r in rows))))
directory = self.repo / v.REGISTRY
receipt = dict(schema='phase4an-engineering-publication-v1', publication_complete=True, registry=v.REGISTRY,
project_root=v.PROJECT, bulk_remains_at=v.EXPERIMENT, declared_status=status, model_directory_sealed=False,
used_source_count=21, model_files_copied=False, complete_bulk_backup=False, training=False,
candidate_generated=False, learning_pass_claimed=False, source_identity='source-identity.json',
experiment_manifest_sha256=v.sha(manifest), experiment_checksums_sha256=v.sha(checksums),
preregistration_sha256=v.sha(payload['protocol/preregistered.json']), final_sha256=v.sha(payload['audit/final-status.json']),
analysis_sha256=v.sha(payload['audit/engineering-analysis.json']), copied_evidence_files=len(index),
copied_evidence_bytes=sum(r['bytes'] for r in index), experiment_payload_not_copied=omitted,
files=[row(path.relative_to(directory).as_posix(), path.read_bytes()) for path in sorted(directory.rglob('*'))
if path.is_file() and path.name != 'publication-receipt.json'])
raw = data(receipt); self.write(v.REGISTRY + '/publication-receipt.json', raw)
return v.sha(raw)
def refresh_receipt(self, **updates):
path = self.repo / v.REGISTRY / 'publication-receipt.json'
receipt = json.loads(path.read_bytes()); receipt.update(updates)
receipt['files'] = [row(r['path'], (self.repo / v.REGISTRY / r['path']).read_bytes()) for r in receipt['files']]
raw = data(receipt); path.write_bytes(raw); self.pin = v.sha(raw); self.stage()
def test_index_and_commit_pass_without_touching_index(self):
before = (self.repo / '.git/index').read_bytes()
result = v.verify(self.repo, self.pin, staged=True)
self.assertTrue(result['pass_all'])
self.assertFalse(result['working_tree_payload_used'])
self.assertFalse(result['experiment_bulk_verified_by_this_tool'])
self.assertEqual(result['model_source_files'], 21)
self.assertEqual((self.repo / '.git/index').read_bytes(), before)
self.git('commit', '-qm', 'synthetic publication')
committed = v.verify(self.repo, self.pin, commit='HEAD')
self.assertEqual(committed['source'], 'commit')
self.assertEqual(committed['commit'], self.git('rev-parse', 'HEAD').decode().strip())
def test_working_tree_never_substitutes_for_staged_or_committed_blobs(self):
target = v.MODEL + '/' + v.SOURCES[0]
self.git('commit', '-qm', 'valid synthetic')
original = (self.repo / target).read_bytes()
self.write(target, b'bad working tree but index is valid\n')
self.assertTrue(v.verify(self.repo, self.pin, staged=True)['pass_all'])
self.git('add', '--', target)
self.write(target, original)
with self.assertRaisesRegex(ValueError, 'SHA/bytes'):
v.verify(self.repo, self.pin, staged=True)
self.assertTrue(v.verify(self.repo, self.pin, commit='HEAD')['pass_all'])
def test_external_receipt_sha_and_exclusive_source_mode_are_required(self):
for kwargs, pin in [({'staged': True}, '0' * 64), ({}, self.pin), ({'staged': True, 'commit': 'HEAD'}, self.pin)]:
with self.subTest(kwargs=kwargs), self.assertRaises(ValueError):
v.verify(self.repo, pin, **kwargs)
def test_extra_scientific_draft_and_registry_file_are_rejected(self):
for name in (v.MODEL + '/PROTOCOL_DRAFT.md', v.REGISTRY + '/unlisted.json'):
self.write(name, b'not in registered inventory\n'); self.git('add', '--', name)
with self.subTest(name=name), self.assertRaises(ValueError):
v.verify(self.repo, self.pin, staged=True)
self.git('rm', '--cached', '--', name)
(self.repo / name).unlink()
def test_missing_source_and_nonregular_index_entry_rejected(self):
path = v.MODEL + '/' + v.SOURCES[0]
self.git('rm', '--cached', '--', path)
with self.assertRaises(ValueError):
v.verify(self.repo, self.pin, staged=True)
self.git('add', '--', path)
oid = self.git('hash-object', '-w', '--stdin', input=b'elsewhere\n').decode().strip()
self.git('update-index', '--cacheinfo', '120000,' + oid + ',' + path)
with self.assertRaisesRegex(ValueError, 'nonregular'):
v.verify(self.repo, self.pin, staged=True)
def test_source_identity_semantics_checked_even_under_new_receipt_pin(self):
path = self.repo / v.REGISTRY / 'source-identity.json'
identities = json.loads(path.read_bytes()); identities[0]['sha256'] = 'f' * 64
path.write_bytes(data(identities)); self.refresh_receipt()
with self.assertRaisesRegex(ValueError, 'Source/snapshot'):
v.verify(self.repo, self.pin, staged=True)
def test_evidence_index_source_and_escaping_receipt_paths_fail(self):
path = self.repo / v.REGISTRY / 'evidence-index.json'
index = json.loads(path.read_bytes()); index[0]['source'] = 'wrong/source.py'
path.write_bytes(data(index)); self.refresh_receipt()
with self.assertRaisesRegex(ValueError, 'Evidence index'):
v.verify(self.repo, self.pin, staged=True)
receipt_path = self.repo / v.REGISTRY / 'publication-receipt.json'
receipt = json.loads(receipt_path.read_bytes()); receipt['files'][0]['path'] = '../escape.json'
raw = data(receipt); receipt_path.write_bytes(raw); self.pin = v.sha(raw); self.stage()
with self.assertRaisesRegex(ValueError, 'escaping'):
v.verify(self.repo, self.pin, staged=True)
def test_checksums_manifest_self_hash_is_not_just_trusted(self):
path = self.repo / v.REGISTRY / 'evidence/checksums.sha256'
text = path.read_text(); lines = text.splitlines(); lines[-1] = '0' * 64 + ' manifest.json'
raw = ('\n'.join(lines) + '\n').encode(); path.write_bytes(raw)
self.refresh_receipt(experiment_checksums_sha256=v.sha(raw))
with self.assertRaisesRegex(ValueError, 'Checksum inventory'):
v.verify(self.repo, self.pin, staged=True)
def test_declared_fail_status_is_preserved_not_relabelled_science_pass(self):
self.pin = self.fixture(status='FAIL-NUMERICAL'); self.stage()
result = v.verify(self.repo, self.pin, staged=True)
self.assertTrue(result['pass_all'])
self.assertEqual(result['declared_status'], 'FAIL-NUMERICAL')
self.assertTrue(result['publication_integrity_is_not_scientific_pass'])
self.assertFalse(result['scientific_gate_executed'])
def test_duplicate_JSON_field_in_receipt_is_rejected(self):
path = self.repo / v.REGISTRY / 'publication-receipt.json'
raw = path.read_bytes().replace(b'{', b'{"publication_complete":true,', 1)
path.write_bytes(raw); self.pin = v.sha(raw); self.stage()
with self.assertRaisesRegex(ValueError, 'Duplicate JSON'):
v.verify(self.repo, self.pin, staged=True)
def test_cli_emits_compact_summary_without_full_payload(self):
out = io.StringIO()
with contextlib.redirect_stdout(out):
status = v.main(['--repo', str(self.repo), '--receipt-sha256', self.pin, '--staged'])
self.assertEqual(status, 0)
result = json.loads(out.getvalue())
self.assertTrue(result['pass_all'])
self.assertNotIn('verified_blobs', result)
self.assertLess(len(out.getvalue()), 1800)
if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,282 @@
"""Verify AN publication bytes in Git's index or one immutable commit.
No working-tree payload fallback, Git writes, network, bulk verification or
scientific execution. The publication receipt SHA must be externally trusted.
Only the 21 registered engineering sources are allowed in the AN model scope.
"""
from __future__ import annotations
import argparse
import hashlib
import json
import os
from pathlib import Path, PurePosixPath
import re
import subprocess
import sys
PROJECT = '/data/digital-drosophila'
MODEL = 'models/male-cns-lif/olfactory-conditioning-lab-v1'
EXPERIMENT = 'experiments/phase4an-engineering-validation'
REGISTRY = 'registry/phase4an-engineering-validation'
MODULES = ('runtime_light', 'runtime_continuation', 'engineering_inputs', 'engineering_plan',
'engineering_compare', 'engineering_queue_audit', 'engineering_prepare',
'engineering_workflow', 'engineering_scopes', 'engineering_analysis')
SOURCES = tuple(sorted([m + '.py' for m in MODULES] + ['test_' + m + '.py' for m in MODULES] + ['ENGINEERING_GATE_DRAFT.md']))
MAX_BYTES = 4 * 1024**2
SUFFIXES = frozenset(('.json', '.csv', '.md', '.log', '.sha256'))
CONTROL = frozenset(('manifest.json', 'checksums.sha256'))
SIDE = frozenset(('evidence-index.json', 'source-identity.json', 'seal-verification.json'))
SHA = re.compile(r'[0-9a-f]{64}\Z')
OID = re.compile(r'(?:[0-9a-f]{40}|[0-9a-f]{64})\Z')
STATUSES = frozenset(('PASS-EXACT-LIGHT-CONTINUATION-ENGINEERING-NOT-LEARNING', 'FAIL-NUMERICAL', 'INCOMPLETE-COVERAGE'))
def require(value, message):
if not value:
raise ValueError(message)
def sha(data):
return hashlib.sha256(data).hexdigest()
def relative(name):
require(type(name) is str and name and not any(c in name for c in '\\\x00\r\n\t'), 'Invalid relative path')
path = PurePosixPath(name)
require(not path.is_absolute() and str(path) == name and all(p not in ('', '.', '..') and ':' not in p for p in path.parts),
'Noncanonical or escaping path: ' + name)
return name
def parse(data):
def pairs(rows):
result = {}
for name, value in rows:
require(name not in result, 'Duplicate JSON field: ' + name)
result[name] = value
return result
return json.loads(data.decode('utf-8'), object_pairs_hook=pairs,
parse_constant=lambda value: (_ for _ in ()).throw(ValueError('Nonfinite JSON: ' + value)))
def inventory(rows):
require(type(rows) is list and rows, 'Missing payload inventory')
indexed = {}
for row in rows:
require(type(row) is dict and set(row) == {'path', 'bytes', 'sha256'}, 'Invalid inventory row schema')
path = relative(row['path'])
require(path not in indexed and '__pycache__' not in PurePosixPath(path).parts and
type(row['bytes']) is int and row['bytes'] >= 0 and type(row['sha256']) is str and SHA.fullmatch(row['sha256']),
'Invalid/duplicate inventory row: ' + path)
indexed[path] = row
return indexed
class GitBlobs:
def __init__(self, repo, staged, commit):
require(type(staged) is bool and staged != (commit is not None), 'Select exactly one of staged or commit')
self.repo = Path(repo).resolve(strict=True)
env = os.environ.copy()
for key in ('GIT_DIR', 'GIT_WORK_TREE', 'GIT_INDEX_FILE', 'GIT_COMMON_DIR', 'GIT_OBJECT_DIRECTORY', 'GIT_ALTERNATE_OBJECT_DIRECTORIES'):
env.pop(key, None)
env.update(GIT_OPTIONAL_LOCKS='0', GIT_NO_REPLACE_OBJECTS='1', GIT_NO_LAZY_FETCH='1')
self.env = env
self.base = ['git', '--no-optional-locks', '-c', 'core.fsmonitor=false', '-c', 'gc.auto=0', '-C', str(self.repo)]
require(Path(self.command('rev-parse', '--show-toplevel').decode().strip()).resolve() == self.repo, 'Supply repository top-level')
self.staged, self.commit = staged, None
if not staged:
require(type(commit) is str and commit and not commit.startswith('-') and not any(c in commit for c in '\x00\r\n'), 'Invalid commit selector')
self.commit = self.command('rev-parse', '--verify', '--end-of-options', commit + '^{commit}').decode('ascii').strip()
require(OID.fullmatch(self.commit), 'Unresolved commit identity')
self.snapshot = self.listing()
self.entries, self.verified = {}, {}
require(self.snapshot.endswith(b'\0'), 'Empty or malformed scoped Git inventory')
for raw in self.snapshot[:-1].split(b'\0'):
metadata, path = raw.split(b'\t', 1); fields = metadata.decode('ascii').split(' ')
require(len(fields) == 3, 'Malformed Git inventory entry')
mode, second, third = fields
oid = second if staged else third
require((third == '0' if staged else second == 'blob') and mode in ('100644', '100755') and OID.fullmatch(oid),
'Unmerged, symlink, gitlink or nonregular blob is forbidden')
name = relative(path.decode('utf-8'))
require(name.startswith(MODEL + '/') or name.startswith(REGISTRY + '/'), 'Out-of-scope Git blob')
require(name not in self.entries, 'Duplicate Git path')
self.entries[name] = (mode, oid)
self.batch = subprocess.Popen(self.base + ['cat-file', '--batch'], env=self.env,
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def command(self, *args):
result = subprocess.run(self.base + list(args), env=self.env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
require(result.returncode == 0, 'Git read failed: ' + result.stderr.decode('utf-8', 'replace').strip())
return result.stdout
def listing(self):
return (self.command('ls-files', '--stage', '--full-name', '-z', '--', MODEL, REGISTRY) if self.staged else
self.command('ls-tree', '-r', '-z', '--full-tree', self.commit, '--', MODEL, REGISTRY))
def read(self, path, expected=None):
require(path in self.entries, 'Missing Git blob: ' + path)
mode, oid = self.entries[path]
self.batch.stdin.write((oid + '\n').encode('ascii')); self.batch.stdin.flush()
fields = self.batch.stdout.readline(256).decode('ascii').strip().split(' ')
require(len(fields) == 3 and fields[:2] == [oid, 'blob'] and fields[2].isdigit(), 'Invalid Git blob response')
size = int(fields[2]); require(size <= MAX_BYTES, 'Selected Git blob exceeds 4 MiB: ' + path)
data = self.batch.stdout.read(size)
require(len(data) == size and self.batch.stdout.read(1) == b'\n', 'Truncated Git object')
if expected is not None:
require(size == expected['bytes'] and sha(data) == expected['sha256'], 'Git blob SHA/bytes mismatch: ' + path)
self.verified[path] = dict(path=path, bytes=size, sha256=sha(data), git_oid=oid, git_mode=mode)
return data
def close(self):
# On a malformed/oversize object the child might still be writing.
# Terminating this read-only batch process cannot alter the repository.
if self.batch.poll() is None:
self.batch.terminate()
self.batch.communicate(timeout=10)
def _seal(manifest_bytes, checksum_bytes, receipt):
require(sha(manifest_bytes) == receipt['experiment_manifest_sha256'] and
sha(checksum_bytes) == receipt['experiment_checksums_sha256'], 'Receipt-bound seal control mismatch')
manifest = parse(manifest_bytes)
require(type(manifest) is dict and set(manifest) == {'root', 'files'} and manifest['root'] == PROJECT + '/' + EXPERIMENT,
'Wrong experiment seal root/schema')
rows = inventory(manifest['files']); require(not (set(rows) & CONTROL), 'Seal controls cannot be payload rows')
checks = {}
for line in checksum_bytes.decode('utf-8').splitlines():
require(len(line) >= 67 and SHA.fullmatch(line[:64]) and line[64:66] == ' ', 'Malformed checksum row')
name = relative(line[66:]); require(name not in checks, 'Duplicate checksum row'); checks[name] = line[:64]
require(checks == {**{k: v['sha256'] for k, v in rows.items()}, 'manifest.json': sha(manifest_bytes)},
'Checksum inventory or manifest self-SHA mismatch')
return rows
def _selection(row):
path = PurePosixPath(row['path'])
if path.parts[0] == 'extension-build':
return None, 'build_artifact'
if row['bytes'] > MAX_BYTES:
return None, 'exceeds_4_MiB'
if path.parts[:2] == ('protocol', 'source-snapshot') and len(path.parts) == 3 and path.name in SOURCES:
return 'source-snapshot/' + path.name, None
if path.suffix.lower() not in SUFFIXES:
return None, 'bulk_binary_or_unselected_suffix_including_jsonl'
return 'evidence/' + row['path'], None
def verify(repo, receipt_sha, *, staged=False, commit=None):
require(type(receipt_sha) is str and SHA.fullmatch(receipt_sha), 'Externally trusted receipt SHA-256 is mandatory')
git = GitBlobs(repo, staged, commit)
try:
raw = git.read(REGISTRY + '/publication-receipt.json')
require(sha(raw) == receipt_sha, 'External receipt SHA-256 mismatch')
receipt = parse(raw)
require(receipt.get('schema') == 'phase4an-engineering-publication-v1' and receipt.get('publication_complete') is True and
receipt.get('registry') == REGISTRY and receipt.get('project_root') == PROJECT and receipt.get('bulk_remains_at') == EXPERIMENT and
receipt.get('declared_status') in STATUSES and receipt.get('model_directory_sealed') is False and
type(receipt.get('used_source_count')) is int and receipt['used_source_count'] == 21 and
receipt.get('model_files_copied') is False and receipt.get('complete_bulk_backup') is False and
receipt.get('training') is False and receipt.get('candidate_generated') is False and
receipt.get('learning_pass_claimed') is False, 'Wrong AN publication scope or declarations')
rows = inventory(receipt['files']); require('publication-receipt.json' not in rows, 'Receipt cannot self-hash')
actual = {p[len(REGISTRY) + 1:] for p in git.entries if p.startswith(REGISTRY + '/')}
require(actual == set(rows) | {'publication-receipt.json'}, 'Registry has unlisted/missing Git files')
required = SIDE | {'evidence/manifest.json', 'evidence/checksums.sha256', 'evidence/protocol/preregistered.json',
'evidence/audit/final-status.json', 'evidence/audit/engineering-analysis.json'}
require(required <= rows.keys(), 'Missing registry controls/evidence')
retained = {}
for name, row in rows.items():
require(row['bytes'] <= MAX_BYTES, 'Registry file exceeds publication cap')
data = git.read(REGISTRY + '/' + name, row)
if name in required:
retained[name] = data
payload = _seal(retained['evidence/manifest.json'], retained['evidence/checksums.sha256'], receipt)
require({name for name in payload if name.startswith('protocol/source-snapshot/')} ==
{'protocol/source-snapshot/' + name for name in SOURCES}, 'Sealed source snapshots are not exactly the 21 used sources')
controls = {name: dict(path=name, bytes=len(retained['evidence/' + name]), sha256=sha(retained['evidence/' + name])) for name in CONTROL}
expected_index, omitted = {}, []
for row in [*payload.values(), *controls.values()]:
destination, reason = _selection(row)
if destination is None:
omitted.append(dict(row, reason=reason))
else:
require(destination not in expected_index, 'Duplicate publication destination')
expected_index[destination] = dict(source=EXPERIMENT + '/' + row['path'], copy=destination, bytes=row['bytes'], sha256=row['sha256'])
indexed = {}
index = parse(retained['evidence-index.json']); require(type(index) is list, 'Malformed evidence index')
for row in index:
require(type(row) is dict and set(row) == {'source', 'copy', 'bytes', 'sha256'}, 'Invalid evidence-index row')
require(type(row['bytes']) is int and row['bytes'] >= 0 and type(row['sha256']) is str and SHA.fullmatch(row['sha256']), 'Invalid evidence-index size/hash')
name = relative(row['copy']); relative(row['source']); require(name not in indexed, 'Duplicate evidence-index destination')
indexed[name] = row
require(indexed == expected_index and set(rows) == set(indexed) | SIDE, 'Evidence index does not match seal/selection/receipt')
for name, row in indexed.items():
require(rows[name] == dict(path=name, bytes=row['bytes'], sha256=row['sha256']), 'Evidence receipt row mismatch')
require(type(receipt.get('copied_evidence_files')) is int and receipt['copied_evidence_files'] == len(indexed) and
type(receipt.get('copied_evidence_bytes')) is int and receipt['copied_evidence_bytes'] == sum(r['bytes'] for r in indexed.values()) and
sorted(receipt.get('experiment_payload_not_copied', []), key=lambda r: r['path']) == sorted(omitted, key=lambda r: r['path']),
'Copied/omitted payload accounting mismatch')
proof = parse(retained['seal-verification.json'])
require(proof.get('pass_all') is True and proof.get('root') == PROJECT + '/' + EXPERIMENT and
proof.get('manifest_sha256') == receipt['experiment_manifest_sha256'] and
proof.get('checksums_sha256') == receipt['experiment_checksums_sha256'] and
proof.get('payload_file_count') == len(payload) and proof.get('payload_bytes') == sum(r['bytes'] for r in payload.values()),
'Seal-verification sidecar contradicts controls')
reg = parse(retained['evidence/protocol/preregistered.json'])
require(reg.get('schema') == 'phase4an-engineering-registration-v1' and reg.get('training') is False and
sha(retained['evidence/protocol/preregistered.json']) == receipt['preregistration_sha256'], 'Registration anchor mismatch')
identities = parse(retained['source-identity.json'])
require(type(identities) is list and len(identities) == 21 and receipt.get('source_identity') == 'source-identity.json', 'Missing source identity inventory')
require(set(reg['source_sha256']) == {PROJECT + '/' + MODEL + '/' + name for name in SOURCES}, 'Registration does not bind exactly 21 engineering sources')
observed_model = {p[len(MODEL) + 1:] for p in git.entries if p.startswith(MODEL + '/')}
require(observed_model == set(SOURCES), 'Model Git scope must contain exactly the 21 registered used sources, not drafts')
by_copy = {}
for row in identities:
require(type(row) is dict and set(row) == {'model_source', 'sealed_source', 'copy', 'bytes', 'sha256'}, 'Invalid source identity row')
require(type(row['bytes']) is int and row['bytes'] >= 0 and type(row['sha256']) is str and SHA.fullmatch(row['sha256']), 'Invalid source identity size/hash')
name = relative(row['copy']); require(name not in by_copy, 'Duplicate source identity'); by_copy[name] = row
require(set(by_copy) == {'source-snapshot/' + name for name in SOURCES}, 'Source identity coverage mismatch')
for name in SOURCES:
copy_name, sealed = 'source-snapshot/' + name, 'protocol/source-snapshot/' + name
row, manifest_row = by_copy[copy_name], payload[sealed]
expected = dict(model_source=MODEL + '/' + name, sealed_source=EXPERIMENT + '/' + sealed,
copy=copy_name, bytes=manifest_row['bytes'], sha256=manifest_row['sha256'])
require(row == expected and rows[copy_name] == dict(path=copy_name, bytes=row['bytes'], sha256=row['sha256']) and
reg['source_sha256'][PROJECT + '/' + MODEL + '/' + name] == row['sha256'] and
reg['input_sha256'].get(PROJECT + '/' + EXPERIMENT + '/' + sealed) == row['sha256'], 'Source/snapshot/registration disagreement: ' + name)
git.read(MODEL + '/' + name, row)
for name, key in [('audit/final-status.json', 'final_sha256'), ('audit/engineering-analysis.json', 'analysis_sha256')]:
require(sha(retained['evidence/' + name]) == receipt[key], 'Final/analysis anchor mismatch')
require(parse(retained['evidence/' + name]).get('status') == receipt['declared_status'], 'Declared status disagreement')
require(git.listing() == git.snapshot, 'Scoped Git inventory changed during verification')
return dict(pass_all=True, verification='AN actual Git blob publication integrity', source='staged-index' if staged else 'commit',
commit=git.commit, receipt_sha256=receipt_sha, declared_status=receipt['declared_status'], model_source_files=21,
registry_files=len(rows) + 1, verified_blob_count=len(git.verified), verified_bytes=sum(v['bytes'] for v in git.verified.values()),
scoped_git_inventory_sha256=sha(git.snapshot), working_tree_payload_used=False, git_index_modified=False,
experiment_bulk_verified_by_this_tool=False, scientific_gate_executed=False, model_directory_declared_sealed=False,
publication_integrity_is_not_scientific_pass=True)
finally:
git.close()
def main(argv=None):
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--repo', required=True)
parser.add_argument('--receipt-sha256', required=True)
source = parser.add_mutually_exclusive_group(required=True)
source.add_argument('--staged', action='store_true'); source.add_argument('--commit')
args = parser.parse_args(argv)
try:
result = verify(args.repo, args.receipt_sha256, staged=args.staged, commit=args.commit)
except (ValueError, KeyError, TypeError, AttributeError, OSError, UnicodeError, EOFError) as error:
print(json.dumps(dict(pass_all=False, error_type=type(error).__name__, error=str(error), scientific_gate_executed=False)))
return 1
print(json.dumps(result, ensure_ascii=False, allow_nan=False))
return 0
if __name__ == '__main__':
sys.exit(main())