Seal Phase 4AJ fixed APL timing hypothesis audit
This commit is contained in:
@@ -0,0 +1,255 @@
|
||||
"""Post-seal descriptive extraction; not another scientific gate or model run.
|
||||
|
||||
The four original CAL summary dictionaries are copied, not recalculated.
|
||||
Origin totals use only the earliest-cohort/pre-first-KC audit window from
|
||||
the 60 sealed AG-r2 control trials. No AI population/window share is imported.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections import Counter
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
import math
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path('/data/digital-drosophila')
|
||||
MODEL_RELATIVE = Path('models/male-cns-lif/apl-timing-lab-v1')
|
||||
EXPERIMENT_RELATIVE = Path('experiments/phase4aj-apl-timing')
|
||||
REGISTRY_RELATIVE = Path('registry/phase4aj-apl-timing')
|
||||
HELPER_RELATIVE = Path('models/male-cns-lif/pn-recruitment-audit-v1/publication.py')
|
||||
HELPER_SHA256 = '7a79c499098b74163e7bb16adabcbc54e7069dafa204d0b99c7f4c03d79f8016'
|
||||
LEGACY_CALIBRATION_SHA256 = 'edb9cb2d890471fd07afd88c959ef3540b0cd40af490fac3f26396b5e7f5bf9c'
|
||||
MODES = ('physiological', 'matched_energy')
|
||||
ARMS = ('delay0', 'delay18')
|
||||
CAL_MODE_FIELDS = frozenset(('KC_active_fraction_mean', 'KC_active_fraction_min', 'KC_active_fraction_max',
|
||||
'same_odor_jaccard_mean', 'different_odor_jaccard_mean', 'same_odor_euclidean_mean',
|
||||
'different_odor_euclidean_mean', 'different_odor_cosine_mean', 'different_odor_correlation_mean',
|
||||
'within_variance', 'between_distance_mean', 'pairwise_separation_pass_count', 'pair_count',
|
||||
'expected_event_count_cv', 'actual_event_count_cv', 'within_distance_count', 'between_distance_count',
|
||||
'pairwise_baseline', 'pairs', 'conditions', 'gate'))
|
||||
WINDOW = 'cohort_pre_KC_and_pre_first'
|
||||
GROUP_FIELDS = ('events', 'positive_events', 'negative_events', 'positive_weight_SI', 'negative_abs_weight_SI')
|
||||
OUTGOING_FIELDS = ('cohort_ALLN_outgoing_events', 'outgoing_events_with_since_reset_design_antecedent',
|
||||
'outgoing_events_without_since_reset_design_antecedent', 'compact_join_pair_count')
|
||||
RELATIONS = frozenset(('no_non_design_spike', 'KC_unobserved', 'before', 'same_tick', 'after'))
|
||||
MAX_BYTES = 4 * 1024 ** 2
|
||||
|
||||
|
||||
def require(ok, message):
|
||||
if not ok:
|
||||
raise ValueError(message)
|
||||
|
||||
|
||||
def load_helpers(path):
|
||||
path = Path(path)
|
||||
require(path.is_absolute() and path.is_file() and not path.is_symlink(), 'Invalid frozen verification helper')
|
||||
source = path.read_bytes()
|
||||
require(hashlib.sha256(source).hexdigest() == HELPER_SHA256, 'Frozen AI helper hash mismatch')
|
||||
spec = importlib.util.spec_from_file_location('phase4aj_describe_frozen_ai_helpers', path)
|
||||
require(spec is not None and spec.loader is not None, 'Cannot define frozen helper module')
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
# Exact pinned bytes; no pyc read/write in the old sealed model directory.
|
||||
exec(compile(source, str(path), 'exec'), module.__dict__)
|
||||
return module
|
||||
|
||||
|
||||
def _boolean_fields(value):
|
||||
return {key: item for key, item in value.items() if type(item) is bool}
|
||||
|
||||
|
||||
def _nonnegative_integer(value, field):
|
||||
require(type(value) is int and value >= 0, 'Invalid nonnegative count: ' + field)
|
||||
return value
|
||||
|
||||
|
||||
def aggregate_origin(trials):
|
||||
"""Sum stored audit totals, retaining source labels and the fixed window.
|
||||
|
||||
These are descriptive sums of already aggregated nominal weights. They
|
||||
have no arithmetic-error-bound, membrane-effect, or causal interpretation.
|
||||
"""
|
||||
groups = {}
|
||||
relations = Counter()
|
||||
outgoing = {field: 0 for field in OUTGOING_FIELDS}
|
||||
before_trials = before_neurons = censored = cohort_occurrences = 0
|
||||
per_trial = []
|
||||
for trial in trials:
|
||||
source = trial['window_source_accounting'][WINDOW]
|
||||
require(isinstance(source, dict), 'Origin source groups must be a dictionary')
|
||||
for label, values in source.items():
|
||||
require(isinstance(label, str) and set(values) == set(GROUP_FIELDS), 'Unexpected origin source-group schema')
|
||||
target = groups.setdefault(label, {key: [] for key in GROUP_FIELDS})
|
||||
for key in GROUP_FIELDS[:3]:
|
||||
target[key].append(_nonnegative_integer(values[key], key))
|
||||
require(values['positive_events'] + values['negative_events'] <= values['events'], 'Origin sign count exceeds events')
|
||||
for key in GROUP_FIELDS[3:]:
|
||||
require(type(values[key]) in (int, float) and math.isfinite(values[key]) and values[key] >= 0,
|
||||
'Invalid nominal source weight: ' + key)
|
||||
target[key].append(float(values[key]))
|
||||
relation = trial['cohort_relation_to_first_KC']
|
||||
require(relation in RELATIONS, 'Unknown earliest-cohort/first-KC relation')
|
||||
require(type(trial['cohort_before_first_KC']) is bool and
|
||||
trial['cohort_before_first_KC'] == (relation == 'before'), 'Inconsistent saved first-KC relation')
|
||||
require(type(trial['pre_kc_window_censored']) is bool, 'Invalid saved censoring flag')
|
||||
count = _nonnegative_integer(trial['cohort_neurons'], 'cohort_neurons')
|
||||
relations[relation] += 1
|
||||
cohort_occurrences += count
|
||||
before_trials += int(trial['cohort_before_first_KC'])
|
||||
before_neurons += count if trial['cohort_before_first_KC'] else 0
|
||||
censored += int(trial['pre_kc_window_censored'])
|
||||
for key in OUTGOING_FIELDS:
|
||||
outgoing[key] += _nonnegative_integer(trial[key], key)
|
||||
require(trial[OUTGOING_FIELDS[1]] + trial[OUTGOING_FIELDS[2]] == trial[OUTGOING_FIELDS[0]],
|
||||
'Saved ALLN outgoing partition is inconsistent')
|
||||
per_trial.append({key: trial[key] for key in ('case', 'mode', 'odor_id', 'seed', 'pass_all',
|
||||
'first_any_KC_tick', 'earliest_tick', 'cohort_neurons', 'cohort_before_first_KC',
|
||||
'cohort_relation_to_first_KC', 'pre_kc_window_censored', *OUTGOING_FIELDS)} |
|
||||
{'source_groups': source, 'exact': trial['exact']})
|
||||
totals = {label: {key: sum(parts[key]) if key in GROUP_FIELDS[:3] else math.fsum(parts[key])
|
||||
for key in GROUP_FIELDS} for label, parts in sorted(groups.items())}
|
||||
direct_pn = {key: sum(totals.get(label, {}).get(key, 0) for label in ('design_ALPN', 'non_design_ALPN'))
|
||||
if key in GROUP_FIELDS[:3] else math.fsum(totals.get(label, {}).get(key, 0.0)
|
||||
for label in ('design_ALPN', 'non_design_ALPN')) for key in GROUP_FIELDS}
|
||||
return dict(trial_count=len(trials), source_window=WINDOW, source_groups=totals,
|
||||
direct_ALPN_combined=direct_pn, direct_ALPN_labels=['design_ALPN', 'non_design_ALPN'],
|
||||
first_before_KC_trial_count=before_trials, cohort_neuron_occurrences_before_first_KC=before_neurons,
|
||||
cohort_neuron_occurrences_across_trials=cohort_occurrences,
|
||||
first_KC_window_censored_trial_count=censored, cohort_relation_trial_counts=dict(sorted(relations.items())),
|
||||
**outgoing, per_trial=per_trial,
|
||||
absent_group_semantics='Producer emits only observed groups; an absent group contributes zero accepted events in this window',
|
||||
nominal_weight_units='SI volts; accepted edge-weight increments, not membrane effect or causal contribution',
|
||||
aggregation='Integer counts and math.fsum of saved per-trial nominal float totals; descriptive, no new roundoff-bound claim',
|
||||
pair_count_semantics='Existing compact temporal join pairs; shared antecedents can recur for multiple outgoing edges, not unique causal chains')
|
||||
|
||||
|
||||
def describe(root=ROOT, helper_path=None):
|
||||
"""Write two exclusive post-publication files; never alter a seal/receipt."""
|
||||
root = Path(root)
|
||||
require(root.is_absolute() and root.is_dir() and not root.is_symlink(), 'Invalid project root')
|
||||
root = root.resolve(strict=True)
|
||||
model, experiment, registry = (root / item for item in (MODEL_RELATIVE, EXPERIMENT_RELATIVE, REGISTRY_RELATIVE))
|
||||
output, checksum = registry / 'interpretation-metrics.json', registry / 'interpretation-metrics.sha256'
|
||||
require(registry.is_dir() and not registry.is_symlink(), 'Publish the sealed evidence registry first')
|
||||
require(not output.exists() and not output.is_symlink() and not checksum.exists() and not checksum.is_symlink(),
|
||||
'Interpretation output already exists; no overwrite/resume')
|
||||
for target in (model, experiment, registry):
|
||||
path = root
|
||||
for part in target.relative_to(root).parts:
|
||||
path /= part
|
||||
require(not path.is_symlink(), 'Symlink in descriptive source/output path')
|
||||
helper_path = root / HELPER_RELATIVE if helper_path is None else Path(helper_path)
|
||||
helper = load_helpers(helper_path)
|
||||
verified = {'model': helper.verify_seal(model), 'experiment': helper.verify_seal(experiment)}
|
||||
inventories = {name: {row['path']: row for row in verification['files']} for name, verification in verified.items()}
|
||||
inputs = {}
|
||||
|
||||
def sealed_json(relative):
|
||||
require(relative in inventories['experiment'], 'Required descriptive input absent from seal: ' + relative)
|
||||
path = helper._regular_file(experiment, relative)
|
||||
row = inventories['experiment'][relative]
|
||||
inputs[relative] = row['sha256']
|
||||
return helper._json_bytes(path.read_bytes())
|
||||
|
||||
status = sealed_json('audit/final-status.json')
|
||||
calibration = sealed_json('calibration/summary.json')
|
||||
origin = sealed_json('origin-audit/summary.json')
|
||||
inventory = sealed_json('protocol/calibration-cases.json')
|
||||
frozen = sealed_json('regression/frozen-five.json')
|
||||
integrity = sealed_json('regression/old-integrity-after.json')
|
||||
require(isinstance(status.get('status'), str) and status['status'].startswith(('PASS-', 'FAIL-', 'INCOMPLETE-')),
|
||||
'Missing finalized status; publication is not a substitute for finalization')
|
||||
require(status.get('candidate_generated') is False and status.get('learning_achieved') is False and
|
||||
status.get('shared_APL_arithmetic_oracle_limitation') is True, 'Unexpected finalized scope')
|
||||
require(calibration.get('legacy_calibration_sha256') == LEGACY_CALIBRATION_SHA256,
|
||||
'CAL summary does not identify the sealed original metric implementation')
|
||||
require(set(calibration['arms']) == set(ARMS), 'Both CAL arm summaries are required')
|
||||
cal_modes = {}
|
||||
arm_flags = {}
|
||||
for arm in ARMS:
|
||||
value = calibration['arms'][arm]
|
||||
require(set(value['modes']) == set(MODES), 'Both original mode summaries are required: ' + arm)
|
||||
# Preserve the complete existing dictionaries, including pairs, CV,
|
||||
# conditions, gate and the original pairwise baseline description.
|
||||
cal_modes[arm] = {mode: value['modes'][mode] for mode in MODES}
|
||||
require(all(isinstance(value['modes'][mode], dict) and CAL_MODE_FIELDS.issubset(value['modes'][mode])
|
||||
for mode in MODES), 'Incomplete saved original CAL mode summary')
|
||||
arm_flags[arm] = _boolean_fields(value)
|
||||
require(len(inventory) == 60 and len({row['name'] for row in inventory}) == 60, 'Require the fixed 60 CAL r0 cases')
|
||||
names = {row['name']: row for row in inventory}
|
||||
require(Counter(row['mode'] for row in inventory) == Counter({mode: 30 for mode in MODES}), 'Origin mode coverage changed')
|
||||
require(len(origin['trials']) == 60 and {row['case'] for row in origin['trials']} == set(names),
|
||||
'Origin trial inventory must match all 60 fixed control cases')
|
||||
trials = []
|
||||
for row in sorted(origin['trials'], key=lambda value: value['case']):
|
||||
name = row['case']
|
||||
require(helper._relative_name(name).name == name, 'Origin case must be a single relative name')
|
||||
relative = 'origin-audit/' + name + '/summary.json'
|
||||
trial = sealed_json(relative)
|
||||
require(row['summary_sha256'] == inputs[relative], 'Origin receipt does not bind its sealed trial summary')
|
||||
require(trial['case'] == name and trial['repeat'] == 0 and all(
|
||||
trial[key] == names[name][key] for key in ('mode', 'odor_id', 'seed')), 'Origin case identity mismatch')
|
||||
trials.append(trial)
|
||||
receipt_path = helper._regular_file(registry, 'publication-receipt.json')
|
||||
receipt_sha = helper._digest(receipt_path)
|
||||
receipt = helper._json_bytes(receipt_path.read_bytes())
|
||||
require(receipt.get('publication_complete') is True and receipt.get('declared_audit_status') == status['status'] and
|
||||
all(receipt.get(name + '_manifest_sha256') == verified[name]['manifest_sha256']
|
||||
for name in ('model', 'experiment')), 'Existing publication receipt belongs to different seals/status')
|
||||
for row in receipt['files']:
|
||||
path = helper._regular_file(registry, row['path'])
|
||||
require(path.stat().st_size == row['bytes'] and helper._digest(path) == row['sha256'], 'Previously published evidence changed')
|
||||
source_hashes = {'describe_phase4aj.py': helper._digest(Path(__file__)),
|
||||
'frozen_AI_publication.py': HELPER_SHA256,
|
||||
'sealed_AG_calibration.py': LEGACY_CALIBRATION_SHA256}
|
||||
for name in ('al_origin_audit.py', 'calibration.py'):
|
||||
require(name in inventories['model'], 'Registered metric-producing source absent from model seal: ' + name)
|
||||
source_hashes['AJ_model/' + name] = inventories['model'][name]['sha256']
|
||||
result = dict(kind='postseal-descriptive-interpretation-metrics', declared_final_status=status['status'],
|
||||
final_status_boolean_flags=_boolean_fields(status), calibration_boolean_flags=_boolean_fields(calibration),
|
||||
calibration_arm_boolean_flags=arm_flags, original_CAL_mode_summaries=cal_modes,
|
||||
finalized_numerical_evidence={key: status[key] for key in ('gates', 'comparisons', 'repeats', 'controls', 'components')},
|
||||
frozen_reference_report=frozen, frozen_integrity_report=integrity,
|
||||
origin_audit_declared_status=origin['status'], origin_audit_boolean_flags=_boolean_fields(origin),
|
||||
origin_scope='60 sealed AG-r2 control CAL r0 trials, 30 per mode; not a new delay18-origin audit',
|
||||
origin_window=WINDOW, origin_all_modes=aggregate_origin(trials),
|
||||
origin_by_mode={mode: aggregate_origin([trial for trial in trials if trial['mode'] == mode]) for mode in MODES},
|
||||
source_sha256=source_hashes, sealed_input_sha256=inputs,
|
||||
model_manifest_sha256=verified['model']['manifest_sha256'],
|
||||
experiment_manifest_sha256=verified['experiment']['manifest_sha256'],
|
||||
model_checksums_sha256=verified['model']['checksums_sha256'],
|
||||
experiment_checksums_sha256=verified['experiment']['checksums_sha256'],
|
||||
publication_receipt_sha256_unchanged=receipt_sha,
|
||||
postseal_addition_outside_original_receipt=True, source_and_receipt_files_modified=False,
|
||||
original_metric_dicts_copied_without_recalculation=True, new_scientific_gate=False,
|
||||
scientific_pass_inferred_from_description=False, new_brain_simulation=False, GPU_used=False,
|
||||
parameters_changed=False, unique_cause_proven=False, necessity_proven=False, learning_achieved=False,
|
||||
inherited_AI_other_population_or_window_share=False,
|
||||
limitations=['Nominal accepted weight sums are not voltage attribution, necessity, or unique causation.',
|
||||
'Origin cohorts include all ties at the earliest non-design ALPN spike, with strict pre-first-target and pre-first-any-KC cutoffs.',
|
||||
'Counts of timed ALLN outgoing edge events and antecedent pairs are distinct and need not denote unique paths.',
|
||||
'Post-seal aggregation changes no original scientific gate or PASS/FAIL/INCOMPLETE status.',
|
||||
'Origin data are sealed control trajectories; no treatment-specific origin conclusion is inferred.'])
|
||||
after = {'model': helper.verify_seal(model), 'experiment': helper.verify_seal(experiment)}
|
||||
require(after == verified and helper._digest(helper_path) == HELPER_SHA256, 'A sealed source changed during description')
|
||||
require(helper._digest(receipt_path) == receipt_sha, 'Existing publication receipt changed during description')
|
||||
data = (json.dumps(result, indent=2, ensure_ascii=False, allow_nan=False) + '\n').encode('utf-8')
|
||||
require(len(data) <= MAX_BYTES, 'Descriptive output exceeds the 4 MiB small-evidence limit')
|
||||
with output.open('xb') as stream:
|
||||
stream.write(data)
|
||||
output_sha = hashlib.sha256(data).hexdigest()
|
||||
with checksum.open('xb') as stream:
|
||||
stream.write((output_sha + ' interpretation-metrics.json\n').encode('ascii'))
|
||||
require(helper._digest(output) == output_sha and helper._digest(receipt_path) == receipt_sha,
|
||||
'Output or original receipt changed while writing')
|
||||
return dict(description_complete=True, declared_final_status=status['status'], output=str(output),
|
||||
sha256=output_sha, new_scientific_gate=False, learning_achieved=False)
|
||||
|
||||
|
||||
def main():
|
||||
print(json.dumps(describe(), ensure_ascii=False, allow_nan=False), flush=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,203 @@
|
||||
"""Exclusive small-evidence publication after both Phase 4AJ seals verify.
|
||||
|
||||
Publication verifies and copies bytes. It never runs a brain, re-evaluates a
|
||||
scientific gate, converts FAIL/INCOMPLETE into PASS, or changes frozen sources.
|
||||
The source-pinned Phase 4AI verification/copy helpers are executed unchanged.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
from pathlib import Path, PurePosixPath
|
||||
|
||||
|
||||
ROOT = Path('/data/digital-drosophila')
|
||||
MODEL_RELATIVE = Path('models/male-cns-lif/apl-timing-lab-v1')
|
||||
EXPERIMENT_RELATIVE = Path('experiments/phase4aj-apl-timing')
|
||||
REGISTRY_RELATIVE = Path('registry/phase4aj-apl-timing')
|
||||
HELPER_RELATIVE = Path('models/male-cns-lif/pn-recruitment-audit-v1/publication.py')
|
||||
HELPER_SHA256 = '7a79c499098b74163e7bb16adabcbc54e7069dafa204d0b99c7f4c03d79f8016'
|
||||
MAX_EVIDENCE_BYTES = 4 * 1024 ** 2
|
||||
EVIDENCE_SUFFIXES = frozenset(('.json', '.csv', '.md', '.log', '.sha256'))
|
||||
FINAL_STATUSES = frozenset((
|
||||
'PASS-FIXED-CAL-APL-TIMING-HYPOTHESIS',
|
||||
'FAIL-FIXED-CAL-APL-TIMING-HYPOTHESIS',
|
||||
'FAIL-FROZEN-INTEGRITY-OR-REGRESSION',
|
||||
'FAIL-NUMERICAL-OR-CONTROL-GATE',
|
||||
'INCOMPLETE-NUMERICAL-OR-CAL-EXECUTION',
|
||||
))
|
||||
REQUIRED_EVIDENCE = ('audit/final-status.json', 'regression/frozen-five.json',
|
||||
'regression/old-integrity-after.json')
|
||||
|
||||
|
||||
def require(condition, message):
|
||||
if not condition:
|
||||
raise ValueError(message)
|
||||
|
||||
|
||||
def load_helpers(path):
|
||||
"""Instantiate the unchanged module from its exact pinned source bytes.
|
||||
|
||||
Using module_from_spec plus the source bytes avoids writing/importing a pyc
|
||||
inside the sealed old model, even if the publisher was invoked without -B.
|
||||
No old module global is redirected or modified after module initialization.
|
||||
"""
|
||||
path = Path(path)
|
||||
require(path.is_absolute() and path.is_file() and not path.is_symlink(), 'Invalid frozen helper path')
|
||||
data = path.read_bytes()
|
||||
require(hashlib.sha256(data).hexdigest() == HELPER_SHA256, 'Frozen AI publication helper hash mismatch')
|
||||
spec = importlib.util.spec_from_file_location('phase4aj_frozen_ai_publication_helpers', path)
|
||||
require(spec is not None and spec.loader is not None, 'Unable to define frozen helper module')
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
exec(compile(data, str(path), 'exec'), module.__dict__)
|
||||
require(module._digest(path) == HELPER_SHA256, 'Helper source changed while loading')
|
||||
return module
|
||||
|
||||
|
||||
def _copy(helper, source, destination, size, checksum):
|
||||
"""Separate local delegation point for interruption-only synthetic tests."""
|
||||
helper._copy_verified(source, destination, size, checksum)
|
||||
|
||||
|
||||
def _write_small_json(helper, path, value):
|
||||
data = (json.dumps(value, indent=2, ensure_ascii=False, allow_nan=False) + '\n').encode('utf-8')
|
||||
require(len(data) <= MAX_EVIDENCE_BYTES, 'Generated registry evidence exceeds 4 MiB: ' + str(path))
|
||||
with Path(path).open('xb') as stream:
|
||||
stream.write(data)
|
||||
require(Path(path).stat().st_size == len(data), 'Generated registry evidence size changed')
|
||||
|
||||
|
||||
def _status_evidence(helper, experiment, rows):
|
||||
for relative in REQUIRED_EVIDENCE:
|
||||
require(relative in rows, 'Required finalized evidence absent from seal: ' + relative)
|
||||
require(rows[relative]['bytes'] <= MAX_EVIDENCE_BYTES, 'Required finalized evidence exceeds 4 MiB')
|
||||
status, reference, integrity = [helper._json_bytes((experiment / relative).read_bytes())
|
||||
for relative in REQUIRED_EVIDENCE]
|
||||
require(isinstance(status, dict) and status.get('status') in FINAL_STATUSES,
|
||||
'Unrecognized Phase 4AJ final status')
|
||||
for key in ('numerical_gate_pass', 'full_CAL_execution_gate_pass', 'delay0_representation_pass',
|
||||
'delay18_representation_pass', 'old_frozen_integrity_and_five_reference_pass'):
|
||||
require(type(status.get(key)) is bool, 'Missing/non-Boolean finalized result: ' + key)
|
||||
for key in ('candidate_generated', 'learning_achieved', 'heldout_generalization_tested',
|
||||
'biological_delay_measured', 'whole_brain_equal_inhibition_integral_claim',
|
||||
'universal_equivalence_claim'):
|
||||
require(status.get(key) is False, 'Unexpected finalized scope claim: ' + key)
|
||||
require(status.get('shared_APL_arithmetic_oracle_limitation') is True,
|
||||
'Missing shared-APL-component oracle limitation')
|
||||
require(isinstance(reference, dict) and type(reference.get('pass_all')) is bool and
|
||||
isinstance(reference.get('trials'), list), 'Missing/invalid frozen reference report')
|
||||
require(isinstance(integrity, dict) and bool(integrity) and all(
|
||||
isinstance(row, dict) and type(row.get('pass')) is bool for row in integrity.values()),
|
||||
'Missing/invalid frozen-integrity report')
|
||||
# This is consistency of declarations, not a new scientific evaluation.
|
||||
frozen_declared = reference['pass_all'] and all(row['pass'] for row in integrity.values())
|
||||
require(status['old_frozen_integrity_and_five_reference_pass'] == frozen_declared,
|
||||
'Final status contradicts its frozen-integrity/reference reports')
|
||||
if status['status'].startswith('PASS-'):
|
||||
require(status['numerical_gate_pass'] and status['full_CAL_execution_gate_pass'] and
|
||||
status['delay18_representation_pass'] and frozen_declared,
|
||||
'Declared PASS contradicts finalized gate flags')
|
||||
return status, reference, integrity
|
||||
|
||||
|
||||
def publish(root=ROOT, helper_path=None):
|
||||
"""Publish the fixed AJ registry exclusively; root override is for tests.
|
||||
|
||||
Only sealed small experiment evidence and the two model seal controls are
|
||||
copied. Every bulk payload is nevertheless verified before and after copying.
|
||||
An interrupted registry is preserved and cannot be overwritten or resumed.
|
||||
"""
|
||||
root = Path(root)
|
||||
require(root.is_absolute() and root.is_dir() and not root.is_symlink(), 'Invalid project root')
|
||||
root = root.resolve(strict=True)
|
||||
model, experiment, registry = (root / part for part in
|
||||
(MODEL_RELATIVE, EXPERIMENT_RELATIVE, REGISTRY_RELATIVE))
|
||||
require(not registry.exists() and not registry.is_symlink(), 'Registry already exists; no overwrite/resume')
|
||||
helper_path = root / HELPER_RELATIVE if helper_path is None else Path(helper_path)
|
||||
helper = load_helpers(helper_path)
|
||||
for path in (model, experiment, registry.parent):
|
||||
current = root
|
||||
for part in path.relative_to(root).parts:
|
||||
current = current / part
|
||||
require(not current.is_symlink(), 'Symlink in publication root path: ' + str(current))
|
||||
verified = {'model': helper.verify_seal(model), 'experiment': helper.verify_seal(experiment)}
|
||||
experiment_rows = {row['path']: row for row in verified['experiment']['files']}
|
||||
status, reference, integrity = _status_evidence(helper, experiment, experiment_rows)
|
||||
plans, omitted = [], []
|
||||
for row in verified['experiment']['files'] + helper._control_rows(experiment, verified['experiment']):
|
||||
if PurePosixPath(row['path']).suffix.lower() in EVIDENCE_SUFFIXES and row['bytes'] <= MAX_EVIDENCE_BYTES:
|
||||
plans.append((experiment, row, 'evidence/' + row['path']))
|
||||
else:
|
||||
omitted.append(dict(path=row['path'], bytes=row['bytes'], sha256=row['sha256'],
|
||||
reason='exceeds_4_MiB' if row['bytes'] > MAX_EVIDENCE_BYTES else 'bulk_or_non_evidence_extension'))
|
||||
for row in helper._control_rows(model, verified['model']):
|
||||
require(row['bytes'] <= MAX_EVIDENCE_BYTES, 'Model seal control exceeds small-evidence limit')
|
||||
plans.append((model, row, 'model/' + row['path']))
|
||||
destinations = {target for _, _, target in plans}
|
||||
for relative in ('manifest.json', 'checksums.sha256', *REQUIRED_EVIDENCE):
|
||||
require('evidence/' + relative in destinations, 'Required experiment evidence cannot be copied: ' + relative)
|
||||
require(len(destinations) == len(plans), 'Duplicate planned evidence destination')
|
||||
registry.parent.mkdir(parents=True, exist_ok=True)
|
||||
registry.mkdir(exist_ok=False)
|
||||
try:
|
||||
records = []
|
||||
for source_root, row, relative in plans:
|
||||
source = helper._regular_file(source_root.resolve(), row['path'])
|
||||
_copy(helper, source, registry / relative, row['bytes'], row['sha256'])
|
||||
records.append(dict(source=source.relative_to(root).as_posix(), copy=relative,
|
||||
bytes=row['bytes'], sha256=row['sha256']))
|
||||
after = {'model': helper.verify_seal(model), 'experiment': helper.verify_seal(experiment)}
|
||||
require(after == verified, 'A sealed tree changed during publication')
|
||||
require(helper._digest(helper_path) == HELPER_SHA256, 'Frozen helper changed during publication')
|
||||
proof = {name: {key: value for key, value in report.items() if key != 'files'}
|
||||
for name, report in verified.items()}
|
||||
_write_small_json(helper, registry / 'seal-verification.json', proof)
|
||||
_write_small_json(helper, registry / 'evidence-index.json', records)
|
||||
files = [dict(path=path.relative_to(registry).as_posix(), bytes=path.stat().st_size,
|
||||
sha256=helper._digest(path)) for path in sorted(registry.rglob('*')) if path.is_file()]
|
||||
receipt = dict(publication_complete=True, registry=registry.relative_to(root).as_posix(),
|
||||
project_root=str(root), declared_audit_status=status['status'],
|
||||
declared_gate_results={key: status[key] for key in ('numerical_gate_pass',
|
||||
'full_CAL_execution_gate_pass', 'delay0_representation_pass', 'delay18_representation_pass',
|
||||
'old_frozen_integrity_and_five_reference_pass')},
|
||||
frozen_reference_report=dict(path='evidence/regression/frozen-five.json',
|
||||
sha256=experiment_rows['regression/frozen-five.json']['sha256'],
|
||||
declared_pass_all=reference['pass_all'], reported_trial_count=len(reference['trials'])),
|
||||
frozen_integrity_report=dict(path='evidence/regression/old-integrity-after.json',
|
||||
sha256=experiment_rows['regression/old-integrity-after.json']['sha256'],
|
||||
declared_pass_by_root={name: row['pass'] for name, row in integrity.items()}),
|
||||
frozen_helper_source=str(helper_path), frozen_helper_sha256=HELPER_SHA256,
|
||||
publisher_sha256=helper._digest(Path(__file__)), helper_globals_redirected=False,
|
||||
model_manifest_sha256=verified['model']['manifest_sha256'],
|
||||
experiment_manifest_sha256=verified['experiment']['manifest_sha256'],
|
||||
source_trees_verified_before_and_after_copy=True,
|
||||
copied_evidence_files=len(records), copied_evidence_bytes=sum(row['bytes'] for row in records),
|
||||
files=files, experiment_payload_not_copied=omitted,
|
||||
model_payload_not_duplicated=True, model_payload_remains_at=MODEL_RELATIVE.as_posix(),
|
||||
bulk_remains_at=EXPERIMENT_RELATIVE.as_posix(), complete_bulk_backup=False,
|
||||
scientific_gate_executed_by_publisher=False, scientific_gate_certified_by_publication=False,
|
||||
publication_success_is_not_scientific_pass=True, candidate_generated=False,
|
||||
learning_achieved=False, existing_files_modified=False,
|
||||
receipt_self_hash='Not self-referential; returned by publish() and printed by main()',
|
||||
limits=dict(max_selected_evidence_file_bytes=MAX_EVIDENCE_BYTES,
|
||||
selected_suffixes=sorted(EVIDENCE_SUFFIXES)))
|
||||
receipt_path = registry / 'publication-receipt.json'
|
||||
_write_small_json(helper, receipt_path, receipt)
|
||||
return dict(publication_complete=True, registry=str(registry), declared_audit_status=status['status'],
|
||||
copied_evidence_files=len(records), receipt_sha256=helper._digest(receipt_path),
|
||||
scientific_gate_executed_by_publisher=False, publication_success_is_not_scientific_pass=True)
|
||||
except Exception as error:
|
||||
failure = registry / 'publication-failure.json'
|
||||
if not failure.exists():
|
||||
_write_small_json(helper, failure, dict(publication_complete=False, type=type(error).__name__,
|
||||
message=str(error), partial_outputs_preserved=True, existing_files_modified=False))
|
||||
raise
|
||||
|
||||
|
||||
def main():
|
||||
print(json.dumps(publish(), ensure_ascii=False, allow_nan=False), flush=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,166 @@
|
||||
"""Synthetic sealed documents only; no real run, registry or scientific gate."""
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
import describe_phase4aj as descriptive
|
||||
import publish_phase4aj as publication
|
||||
|
||||
|
||||
HELPER = Path(__file__).resolve().parents[1] / 'pn-recruitment-audit-v1/publication.py'
|
||||
if not HELPER.is_file():
|
||||
HELPER = publication.ROOT / publication.HELPER_RELATIVE
|
||||
|
||||
|
||||
def digest(path):
|
||||
return hashlib.sha256(path.read_bytes()).hexdigest()
|
||||
|
||||
|
||||
def write(path, value):
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps(value, indent=2), encoding='utf-8')
|
||||
|
||||
|
||||
def seal(root):
|
||||
rows = [dict(path=path.relative_to(root).as_posix(), bytes=path.stat().st_size, sha256=digest(path))
|
||||
for path in sorted(root.rglob('*')) if path.is_file() and path.name not in ('manifest.json', 'checksums.sha256')]
|
||||
write(root / 'manifest.json', dict(root=str(root), files=rows))
|
||||
lines = [row['sha256'] + ' ' + row['path'] for row in rows]
|
||||
lines.append(digest(root / 'manifest.json') + ' manifest.json')
|
||||
(root / 'checksums.sha256').write_text('\n'.join(lines) + '\n', encoding='utf-8')
|
||||
|
||||
|
||||
def origin_trial(name, mode, seed, odor):
|
||||
group = lambda positive, negative: dict(events=3, positive_events=2, negative_events=1,
|
||||
positive_weight_SI=positive, negative_abs_weight_SI=negative)
|
||||
return dict(case=name, mode=mode, seed=seed, odor_id=odor, repeat=0, pass_all=True,
|
||||
exact={name: True for name in ('step', 'neuron_idx', 'counts', 'v', 'g', 'ref')},
|
||||
first_any_KC_tick=40, earliest_tick=20, cohort_neurons=2, cohort_before_first_KC=True,
|
||||
cohort_relation_to_first_KC='before', pre_kc_window_censored=False,
|
||||
cohort_ALLN_outgoing_events=5, outgoing_events_with_since_reset_design_antecedent=3,
|
||||
outgoing_events_without_since_reset_design_antecedent=2, compact_join_pair_count=17,
|
||||
window_source_accounting={descriptive.WINDOW: {'design_ALPN': group(.25, .03125),
|
||||
'non_design_ALPN': group(.125, .0625), 'ALLN': group(.0625, .125)},
|
||||
'never_active_pre_KC': {'ALLN': group(99999, 99999)}})
|
||||
|
||||
|
||||
class DescriptionTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
temporary = tempfile.TemporaryDirectory(prefix='phase4aj-description-synthetic-')
|
||||
self.addCleanup(temporary.cleanup)
|
||||
self.root = Path(temporary.name).resolve()
|
||||
self.model = self.root / descriptive.MODEL_RELATIVE
|
||||
self.experiment = self.root / descriptive.EXPERIMENT_RELATIVE
|
||||
self.registry = self.root / descriptive.REGISTRY_RELATIVE
|
||||
self.model.mkdir(parents=True)
|
||||
self.experiment.mkdir(parents=True)
|
||||
for name in ('al_origin_audit.py', 'calibration.py'):
|
||||
(self.model / name).write_text('# Synthetic producer placeholder, never executed\n', encoding='utf-8')
|
||||
self.status = dict(status='FAIL-FIXED-CAL-APL-TIMING-HYPOTHESIS', numerical_gate_pass=True,
|
||||
full_CAL_execution_gate_pass=True, delay0_representation_pass=False, delay18_representation_pass=False,
|
||||
old_frozen_integrity_and_five_reference_pass=True, candidate_generated=False, learning_achieved=False,
|
||||
heldout_generalization_tested=False, biological_delay_measured=False,
|
||||
whole_brain_equal_inhibition_integral_claim=False, universal_equivalence_claim=False,
|
||||
shared_APL_arithmetic_oracle_limitation=True,
|
||||
gates={'fixtures': {'pass_all': True}}, comparisons={'synthetic': True},
|
||||
repeats={'synthetic': True}, controls={'synthetic': True}, components={'synthetic': True})
|
||||
write(self.experiment / 'audit/final-status.json', self.status)
|
||||
write(self.experiment / 'regression/frozen-five.json', {'pass_all': True, 'trials': [{'synthetic': True}] * 5})
|
||||
write(self.experiment / 'regression/old-integrity-after.json', {'synthetic-frozen-tree': {'pass': True}})
|
||||
metric = {key: 0.125 for key in descriptive.CAL_MODE_FIELDS}
|
||||
metric.update(gate=False, pairs=[{'gate': False, 'synthetic': 'retained'}], conditions={'mean_sparsity': False},
|
||||
pairwise_baseline='synthetic original pair baseline', extra_existing_field='must remain untouched')
|
||||
self.calibration = dict(pass_all=False, execution_gate_pass=True, numerical_integrity_pass=True,
|
||||
legacy_calibration_sha256=descriptive.LEGACY_CALIBRATION_SHA256,
|
||||
arms={arm: dict(original_representation_gate_pass=False, numerical_integrity_pass=True,
|
||||
modes={mode: dict(metric) for mode in descriptive.MODES}) for arm in descriptive.ARMS})
|
||||
write(self.experiment / 'calibration/summary.json', self.calibration)
|
||||
inventory, receipts = [], []
|
||||
for mode in descriptive.MODES:
|
||||
for odor in range(6):
|
||||
for seed in range(51101, 51106):
|
||||
name = f'cal-{mode}-{odor:02d}-s{seed}'
|
||||
inventory.append(dict(name=name, mode=mode, seed=seed, odor_id='synthetic-odor-' + str(odor)))
|
||||
trial = origin_trial(name, mode, seed, 'synthetic-odor-' + str(odor))
|
||||
path = self.experiment / 'origin-audit' / name / 'summary.json'
|
||||
write(path, trial)
|
||||
receipts.append(dict(case=name, summary_sha256=digest(path)))
|
||||
write(self.experiment / 'protocol/calibration-cases.json', inventory)
|
||||
write(self.experiment / 'origin-audit/summary.json', dict(status='PASS-CONDITIONAL-EARLIEST-AL-ORIGIN-AUDIT',
|
||||
pass_all=True, unique_cause_proven=False, trials=receipts))
|
||||
seal(self.model)
|
||||
seal(self.experiment)
|
||||
publication.publish(self.root, HELPER)
|
||||
|
||||
def describe(self):
|
||||
return descriptive.describe(self.root, HELPER)
|
||||
|
||||
def test_full_mode_dicts_fail_status_and_scope_are_retained(self):
|
||||
receipt = digest(self.registry / 'publication-receipt.json')
|
||||
result = self.describe()
|
||||
self.assertEqual(result['declared_final_status'], self.status['status'])
|
||||
path = self.registry / 'interpretation-metrics.json'
|
||||
saved = json.loads(path.read_text(encoding='utf-8'))
|
||||
for arm in descriptive.ARMS:
|
||||
self.assertEqual(saved['original_CAL_mode_summaries'][arm], self.calibration['arms'][arm]['modes'])
|
||||
self.assertFalse(saved['calibration_boolean_flags']['pass_all'])
|
||||
self.assertFalse(saved['new_scientific_gate'])
|
||||
self.assertFalse(saved['unique_cause_proven'])
|
||||
self.assertFalse(saved['learning_achieved'])
|
||||
self.assertFalse(saved['inherited_AI_other_population_or_window_share'])
|
||||
self.assertIn('control', saved['origin_scope'])
|
||||
self.assertEqual(saved['origin_window'], descriptive.WINDOW)
|
||||
self.assertEqual(digest(self.registry / 'publication-receipt.json'), receipt)
|
||||
self.assertEqual((self.registry / 'interpretation-metrics.sha256').read_text(),
|
||||
digest(path) + ' interpretation-metrics.json\n')
|
||||
|
||||
def test_only_fixed_cohort_window_aggregated_and_counts_not_conflated(self):
|
||||
self.describe()
|
||||
result = json.loads((self.registry / 'interpretation-metrics.json').read_text(encoding='utf-8'))
|
||||
for value in result['origin_by_mode'].values():
|
||||
self.assertEqual(value['trial_count'], 30)
|
||||
self.assertEqual(value['source_groups']['ALLN']['positive_weight_SI'], 30 * .0625)
|
||||
self.assertEqual(value['direct_ALPN_combined']['positive_weight_SI'], 30 * .375)
|
||||
self.assertEqual(value['source_groups']['ALLN']['negative_abs_weight_SI'], 30 * .125)
|
||||
self.assertEqual(value['first_before_KC_trial_count'], 30)
|
||||
self.assertEqual(value['cohort_ALLN_outgoing_events'], 150)
|
||||
self.assertEqual(value['outgoing_events_with_since_reset_design_antecedent'], 90)
|
||||
self.assertEqual(value['compact_join_pair_count'], 510)
|
||||
|
||||
def test_never_overwrite_either_existing_output(self):
|
||||
path = self.registry / 'interpretation-metrics.sha256'
|
||||
path.write_bytes(b'keep partial checksum\n')
|
||||
with self.assertRaisesRegex(ValueError, 'already exists'):
|
||||
self.describe()
|
||||
self.assertEqual(path.read_bytes(), b'keep partial checksum\n')
|
||||
self.assertFalse((self.registry / 'interpretation-metrics.json').exists())
|
||||
|
||||
def test_published_receipt_or_sealed_input_corruption_blocks(self):
|
||||
path = self.experiment / 'calibration/summary.json'
|
||||
path.write_bytes(b'x' * path.stat().st_size)
|
||||
with self.assertRaisesRegex(ValueError, 'Payload SHA-256 mismatch'):
|
||||
self.describe()
|
||||
self.assertFalse((self.registry / 'interpretation-metrics.json').exists())
|
||||
|
||||
def test_success_cannot_be_rerun(self):
|
||||
self.describe()
|
||||
path = self.registry / 'interpretation-metrics.json'
|
||||
before = digest(path)
|
||||
with self.assertRaisesRegex(ValueError, 'already exists'):
|
||||
self.describe()
|
||||
self.assertEqual(digest(path), before)
|
||||
|
||||
def test_censoring_and_first_tick_relation_are_not_relabelled(self):
|
||||
trial = origin_trial('synthetic', 'physiological', 51101, 'synthetic')
|
||||
trial.update(first_any_KC_tick=-1, cohort_before_first_KC=False,
|
||||
cohort_relation_to_first_KC='KC_unobserved', pre_kc_window_censored=True)
|
||||
result = descriptive.aggregate_origin([trial])
|
||||
self.assertEqual(result['first_before_KC_trial_count'], 0)
|
||||
self.assertEqual(result['first_KC_window_censored_trial_count'], 1)
|
||||
self.assertEqual(result['cohort_relation_trial_counts'], {'KC_unobserved': 1})
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,198 @@
|
||||
"""Temporary synthetic seals only; never publish/register any real evidence."""
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
import publish_phase4aj as publication
|
||||
|
||||
|
||||
HELPER = Path(__file__).resolve().parents[1] / 'pn-recruitment-audit-v1/publication.py'
|
||||
if not HELPER.is_file():
|
||||
HELPER = publication.ROOT / publication.HELPER_RELATIVE
|
||||
|
||||
|
||||
def sha(path):
|
||||
return hashlib.sha256(path.read_bytes()).hexdigest()
|
||||
|
||||
|
||||
def write(path, value):
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps(value, indent=2), encoding='utf-8')
|
||||
|
||||
|
||||
def seal(root):
|
||||
rows = [dict(path=path.relative_to(root).as_posix(), bytes=path.stat().st_size, sha256=sha(path))
|
||||
for path in sorted(root.rglob('*')) if path.is_file() and
|
||||
path.name not in ('manifest.json', 'checksums.sha256') and '__pycache__' not in path.parts]
|
||||
write(root / 'manifest.json', dict(root=str(root), files=rows))
|
||||
lines = [row['sha256'] + ' ' + row['path'] for row in rows]
|
||||
lines.append(sha(root / 'manifest.json') + ' manifest.json')
|
||||
(root / 'checksums.sha256').write_text('\n'.join(lines) + '\n', encoding='utf-8')
|
||||
|
||||
|
||||
class PublicationTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
temporary = tempfile.TemporaryDirectory(prefix='phase4aj-publication-synthetic-')
|
||||
self.addCleanup(temporary.cleanup)
|
||||
self.root = Path(temporary.name).resolve()
|
||||
self.model = self.root / publication.MODEL_RELATIVE
|
||||
self.experiment = self.root / publication.EXPERIMENT_RELATIVE
|
||||
self.registry = self.root / publication.REGISTRY_RELATIVE
|
||||
self.model.mkdir(parents=True)
|
||||
self.experiment.mkdir(parents=True)
|
||||
(self.model / 'module.py').write_text('# synthetic, not a model\n', encoding='utf-8')
|
||||
self.status = dict(status='FAIL-FIXED-CAL-APL-TIMING-HYPOTHESIS', numerical_gate_pass=True,
|
||||
full_CAL_execution_gate_pass=True, delay0_representation_pass=False, delay18_representation_pass=False,
|
||||
old_frozen_integrity_and_five_reference_pass=True, candidate_generated=False, learning_achieved=False,
|
||||
heldout_generalization_tested=False, biological_delay_measured=False,
|
||||
whole_brain_equal_inhibition_integral_claim=False, universal_equivalence_claim=False,
|
||||
shared_APL_arithmetic_oracle_limitation=True)
|
||||
write(self.experiment / 'audit/final-status.json', self.status)
|
||||
write(self.experiment / 'regression/frozen-five.json', dict(pass_all=True, trials=[{'synthetic': i} for i in range(5)]))
|
||||
write(self.experiment / 'regression/old-integrity-after.json', {'synthetic-old-tree': {'pass': True}})
|
||||
write(self.experiment / 'nested/case/summary.json', {'synthetic': True})
|
||||
(self.experiment / 'REPORT.md').write_text('Synthetic failed hypothesis.\n', encoding='utf-8')
|
||||
(self.experiment / 'tests.log').write_text('Synthetic log\n', encoding='utf-8')
|
||||
(self.experiment / 'bulk.npy').write_bytes(b'synthetic bulk bytes, not an array')
|
||||
seal(self.model)
|
||||
seal(self.experiment)
|
||||
|
||||
def publish(self):
|
||||
return publication.publish(self.root, HELPER)
|
||||
|
||||
def test_failed_hypothesis_is_published_without_scientific_pass(self):
|
||||
before = {str(path): sha(path) for base in (self.model, self.experiment)
|
||||
for path in base.rglob('*') if path.is_file()}
|
||||
result = self.publish()
|
||||
self.assertTrue(result['publication_complete'])
|
||||
self.assertEqual(result['declared_audit_status'], self.status['status'])
|
||||
receipt = json.loads((self.registry / 'publication-receipt.json').read_text(encoding='utf-8'))
|
||||
self.assertFalse(receipt['declared_gate_results']['delay18_representation_pass'])
|
||||
self.assertFalse(receipt['scientific_gate_certified_by_publication'])
|
||||
self.assertTrue(receipt['publication_success_is_not_scientific_pass'])
|
||||
self.assertTrue((self.registry / 'evidence/nested/case/summary.json').is_file())
|
||||
self.assertTrue((self.registry / 'model/checksums.sha256').is_file())
|
||||
self.assertFalse((self.registry / 'model/module.py').exists())
|
||||
self.assertFalse((self.registry / 'evidence/bulk.npy').exists())
|
||||
for row in receipt['files']:
|
||||
self.assertEqual(sha(self.registry / row['path']), row['sha256'])
|
||||
self.assertEqual(before, {str(path): sha(path) for base in (self.model, self.experiment)
|
||||
for path in base.rglob('*') if path.is_file()})
|
||||
|
||||
def test_incomplete_final_status_remains_incomplete(self):
|
||||
self.status.update(status='INCOMPLETE-NUMERICAL-OR-CAL-EXECUTION', numerical_gate_pass=False,
|
||||
full_CAL_execution_gate_pass=False)
|
||||
write(self.experiment / 'audit/final-status.json', self.status)
|
||||
seal(self.experiment)
|
||||
self.assertEqual(self.publish()['declared_audit_status'], self.status['status'])
|
||||
|
||||
def test_pass_requires_consistent_declared_gate_flags(self):
|
||||
self.status['status'] = 'PASS-FIXED-CAL-APL-TIMING-HYPOTHESIS'
|
||||
write(self.experiment / 'audit/final-status.json', self.status)
|
||||
seal(self.experiment)
|
||||
with self.assertRaisesRegex(ValueError, 'Declared PASS contradicts'):
|
||||
self.publish()
|
||||
self.assertFalse(self.registry.exists())
|
||||
self.status['delay18_representation_pass'] = True
|
||||
write(self.experiment / 'audit/final-status.json', self.status)
|
||||
seal(self.experiment)
|
||||
self.assertEqual(self.publish()['declared_audit_status'], self.status['status'])
|
||||
|
||||
def test_explicit_frozen_failure_is_recorded_not_hidden(self):
|
||||
self.status.update(status='FAIL-FROZEN-INTEGRITY-OR-REGRESSION', old_frozen_integrity_and_five_reference_pass=False)
|
||||
write(self.experiment / 'audit/final-status.json', self.status)
|
||||
write(self.experiment / 'regression/old-integrity-after.json', {'synthetic-old-tree': {'pass': False}})
|
||||
seal(self.experiment)
|
||||
self.publish()
|
||||
receipt = json.loads((self.registry / 'publication-receipt.json').read_text(encoding='utf-8'))
|
||||
self.assertFalse(receipt['frozen_integrity_report']['declared_pass_by_root']['synthetic-old-tree'])
|
||||
|
||||
def test_existing_registry_never_overwritten_or_resumed(self):
|
||||
self.registry.mkdir(parents=True)
|
||||
sentinel = self.registry / 'keep.txt'
|
||||
sentinel.write_bytes(b'keep these bytes')
|
||||
with self.assertRaisesRegex(ValueError, 'Registry already exists'):
|
||||
self.publish()
|
||||
self.assertEqual(sentinel.read_bytes(), b'keep these bytes')
|
||||
self.assertEqual(list(self.registry.iterdir()), [sentinel])
|
||||
|
||||
def test_missing_frozen_report_blocks_before_destination(self):
|
||||
(self.experiment / 'regression/frozen-five.json').unlink()
|
||||
seal(self.experiment)
|
||||
with self.assertRaisesRegex(ValueError, 'Required finalized evidence absent'):
|
||||
self.publish()
|
||||
self.assertFalse(self.registry.exists())
|
||||
|
||||
def test_bulk_corruption_blocks_even_though_bulk_is_not_copied(self):
|
||||
path = self.experiment / 'bulk.npy'
|
||||
path.write_bytes(b'x' * path.stat().st_size)
|
||||
with self.assertRaisesRegex(ValueError, 'Payload SHA-256 mismatch'):
|
||||
self.publish()
|
||||
self.assertFalse(self.registry.exists())
|
||||
|
||||
def test_unlisted_payload_and_bad_manifest_self_hash_fail(self):
|
||||
extra = self.experiment / 'unlisted.csv'
|
||||
extra.write_text('unlisted\n')
|
||||
with self.assertRaisesRegex(ValueError, 'unlisted/missing'):
|
||||
self.publish()
|
||||
extra.unlink()
|
||||
controls = self.experiment / 'checksums.sha256'
|
||||
lines = controls.read_text().splitlines()
|
||||
lines[-1] = '0' * 64 + ' manifest.json'
|
||||
controls.write_text('\n'.join(lines) + '\n')
|
||||
with self.assertRaisesRegex(ValueError, 'manifest self-checksum'):
|
||||
self.publish()
|
||||
self.assertFalse(self.registry.exists())
|
||||
|
||||
def test_large_json_verified_but_not_copied(self):
|
||||
path = self.experiment / 'large.json'
|
||||
path.write_bytes(b' ' * (publication.MAX_EVIDENCE_BYTES + 1))
|
||||
seal(self.experiment)
|
||||
self.publish()
|
||||
self.assertFalse((self.registry / 'evidence/large.json').exists())
|
||||
receipt = json.loads((self.registry / 'publication-receipt.json').read_text(encoding='utf-8'))
|
||||
self.assertEqual(next(r for r in receipt['experiment_payload_not_copied'] if r['path'] == 'large.json')['reason'],
|
||||
'exceeds_4_MiB')
|
||||
|
||||
def test_interrupted_copy_retained_and_cannot_resume(self):
|
||||
with mock.patch.object(publication, '_copy', side_effect=OSError('synthetic interrupted copy')):
|
||||
with self.assertRaisesRegex(OSError, 'synthetic interrupted copy'):
|
||||
self.publish()
|
||||
self.assertTrue((self.registry / 'publication-failure.json').is_file())
|
||||
self.assertFalse((self.registry / 'publication-receipt.json').exists())
|
||||
with self.assertRaisesRegex(ValueError, 'Registry already exists'):
|
||||
self.publish()
|
||||
|
||||
def test_after_copy_full_verification_detects_bulk_change(self):
|
||||
original = publication._copy
|
||||
changed = False
|
||||
|
||||
def copy_then_change(helper, source, destination, size, checksum):
|
||||
nonlocal changed
|
||||
original(helper, source, destination, size, checksum)
|
||||
if not changed:
|
||||
changed = True
|
||||
(self.experiment / 'bulk.npy').write_bytes(b'changed after initial seal check')
|
||||
|
||||
with mock.patch.object(publication, '_copy', side_effect=copy_then_change):
|
||||
with self.assertRaises(ValueError):
|
||||
self.publish()
|
||||
self.assertTrue((self.registry / 'publication-failure.json').is_file())
|
||||
self.assertFalse((self.registry / 'publication-receipt.json').exists())
|
||||
|
||||
def test_helper_pin_checked_without_modifying_old_globals_or_cache(self):
|
||||
helper = publication.load_helpers(HELPER)
|
||||
self.assertEqual(helper.MODEL_RELATIVE, Path('models/male-cns-lif/pn-recruitment-audit-v1'))
|
||||
self.assertEqual(helper.FINAL_STATUS, 'PASS-CONDITIONAL-PN-APL-SOURCE-AUDIT')
|
||||
wrong = self.root / 'wrong-helper.py'
|
||||
wrong.write_bytes(b'raise RuntimeError("must never execute")\n')
|
||||
with self.assertRaisesRegex(ValueError, 'helper hash mismatch'):
|
||||
publication.publish(self.root, wrong)
|
||||
self.assertFalse(self.registry.exists())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user