#!/usr/bin/env python3 """Read-only P04 evidence preflight. Never grants original acceptance. Required conditions and authority bindings are fixed here, never supplied by an index. See execution/p04-01/CHECKER_PROTOCOL.md for the supported input subset. """ import argparse import hashlib import json import os from pathlib import Path import re import subprocess import sys ROOT = Path(__file__).resolve().parents[1] SPEC = ROOT / 'docs/spec/acceptance/P04-01.json' SPEC_HASH = '9ec722e7dfb0bee178d291624a026420c08412574e238bba1fde012c7a6f7881' DOMAINS = {'閉店', '停電', '破壊', '退出', '課金', 'シフト交代', '00:00決算'} OWNER_HASH = '4583ee9aad45c4db183d72df4420df48aa8e0897e3b5efda13016f0b5cdbd68e' REGISTERED_COMMIT = 'deb1bcb2374eb378b840ca345db952bd8572cb6e' EXECUTION_ORIGIN = '9767b0a28ca8d252520307dbbac60a1d8cfb87ab' # Fixed membership, never supplied by the evidence index. ORDER_FUNCTIONS = { 'scripts/core/simulation_kernel.gd': ('advance_one_minute', '_run_phase', '_handle_time_boundaries'), 'scripts/core/command_queue.gd': ('_comes_before',), 'autoload/simulation_runtime.gd': ( '_process_tick_commands', '_advance_operations_time', '_run_operations_deferred_suffix', '_advance_mana', '_advance_facilities', '_advance_guest_vitals', '_advance_staff_ai', '_advance_guest_ai_decisions', '_release_closed_business_queues', '_release_closed_business_request', '_complete_service_transaction'), 'scripts/facility/facility_service.gd': ( 'advance_one_minute', '_prepare_service_for_tick', '_complete_service', '_fail_service'), 'scripts/operations/operations_coordinator.gd': ('_process_minute_boundaries',), } # Condition -> (domain, authority refs, required engine measurements). # Measurements describe safety/counts, not the still-pending attribution policy. REQUIRED = { 'power_stop': ('停電', ('BASELINE:183',), {'charges': 0}), 'destruction_stop': ('破壊', ('BASELINE:183',), {'charges': 0}), 'dependency_stop': ('閉店', ('D05-P04-DEPENDENCY',), {'charges': 0, 'progress_delta': 0, 'reservation_ids_preserved': True, 'service_id_preserved': True}), 'shift_completion': ('シフト交代', ('BASELINE:64', 'BASELINE:67', 'D05-P04-SHIFT-1800'), {'minute': 1080, 'completions': 1, 'charges': 1, 'completion_before_shift': True}), 'recovery_completion': ('課金', ('D05-P04-DEPENDENCY',), {'completions': 1, 'charges': 1}), 'same_minute_replay': ('課金', ('D05-P04-DEPENDENCY', 'D05-P04-SHIFT-1800'), {'completions': 1, 'charges': 1, 'duplicate_generations': 0, 'same_minute_replayed': True}), 'closure_release': ('閉店', ('D-034',), {'orphan_reservations': 0, 'released_once': True, 'started_service_continues': True}), 'exit_release': ('退出', ('D-034',), {'orphan_reservations': 0, 'released_once': True}), 'patience_release': ('退出', ('D-034',), {'orphan_reservations': 0, 'released_once': True}), 'paused_midnight': ('00:00決算', ('D05-P04-DEPENDENCY', 'BASELINE:71', 'BASELINE:72'), {'orphan_reservations': 0, 'crossed_midnight_while_paused': True, 'stopped_charges': 0, 'completions': 1, 'charges': 1}), 'midnight_settlement': ('00:00決算', ('BASELINE:71', 'BASELINE:72', 'A01'), {'settlements': 1, 'sales_payments': 1, 'payroll_payments': 1, 'upkeep_payments': 1, 'duty_payments': 1, 'nonzero_payroll': True}), 'midnight_replay': ('00:00決算', ('BASELINE:71', 'BASELINE:72', 'A01'), {'settlements': 1, 'same_minute_replayed': True, 'duplicate_payments': 0}), 'save_restore': ('00:00決算', ('BASELINE:71', 'BASELINE:72', 'A01'), {'settlements': 1, 'duplicate_payments': 0, 'formal_save_restored': True}), 'night_staff_absent': ('シフト交代', ('BASELINE:67', 'D05-P04-SHIFT-1800'), {'minute': 1081, 'state': 'WAITING_FOR_STAFF', 'night_staff_count': 0}), 'overtime_task': ('シフト交代', ('BASELINE:67',), {'interrupt_level': 0, 'is_overtime': True, 'duty_recorded_once': True}), } REACH_REFS = { 'EV': [ ('autoload/simulation_runtime.gd', '_execute_create_staff_task', '8b83aff45ead128b70931343271dbd03a1024b90238d1f46f93e4856290aa0d8', 10), ('scripts/staff/task_dispatcher.gd', '_reserve_pair', '48e2e593c117bd675236a165a294c9cc6233f87018010249cd8e675aff01fc3c', 6), ('autoload/simulation_runtime.gd', '_reserve_staff_task_items', '4f2add093de47cb08abfa45e9d2285f00d906c9bceadb2d98ffa42faae9ede67', 28), ('autoload/simulation_runtime.gd', '_advance_staff_task_travel', '53937aefeec533a5f16169bba4dd6a69b5246101d09de77ca95db7ca174c63ce', 2), ('scripts/transport/elevator_service.gd', 'set_powered', '925f4bf2d109421956fb2958981758d7d84a1ca586a9d4eb51572b8b9677cfba', 6)], 'transport': [ ('autoload/simulation_runtime.gd', '_on_staff_task_completed', '46daaa0197ce85c08883614112efb2d12a2cc0a02fe14ffec8314c73cbba61fc', 8), ('autoload/simulation_runtime.gd', '_handle_rescue_arrival', '11f8d43d0c089b95006009eddfc8bd3d4375a666b29ff19f36e1fa008f3946dd', 24), ('autoload/simulation_runtime.gd', '_advance_staff_rescue', '86bb31b40606fd624cc6b273dfdf7e3e4b3e1bc9997df825dd74136efb69a38f', 52)], } def require(condition, message): if not condition: raise ValueError(message) def sha(path): return hashlib.sha256(path.read_bytes()).hexdigest() def unique(pairs): result = {} for key, value in pairs: require(key not in result, 'duplicate JSON key: ' + key) result[key] = value return result def load(path): return json.loads(path.read_text(encoding='utf-8'), object_pairs_hook=unique, parse_constant=lambda x: require(False, 'nonfinite JSON: ' + x)) def safe(base, relative): require(isinstance(relative, str) and relative, 'invalid path') p = Path(relative) require(not p.is_absolute() and all(x not in {'.', '..'} for x in relative.split('/')), 'unsafe path: ' + relative) current = base for part in p.parts: current = current / part require(not current.is_symlink(), 'symlink: ' + relative) require(current.resolve().is_relative_to(base.resolve()) and current.is_file(), 'missing/outside file: ' + relative) return current def pins(mapping, base): require(isinstance(mapping, dict) and mapping, 'missing pin map') for name, digest in mapping.items(): require(isinstance(digest, str) and re.fullmatch('[0-9a-f]{64}', digest), 'invalid hash: ' + name) require(sha(safe(base, name)) == digest, 'stale pin: ' + name) def pointer(value, path): require(isinstance(path, str) and (path == '' or path.startswith('/')), 'invalid JSON pointer') for token in path.split('/')[1:]: require(not re.search('~(?![01])', token), 'invalid pointer escape') token = token.replace('~1', '/').replace('~0', '~') if isinstance(value, list): require(re.fullmatch('0|[1-9][0-9]*', token) is not None, 'invalid array index') value = value[int(token)] else: require(isinstance(value, dict) and token in value, 'missing pointer: ' + path) value = value[token] return value def literal(a, b): return type(a) is type(b) and json.dumps(a, sort_keys=True) == json.dumps(b, sort_keys=True) def git_bytes(*args): return subprocess.check_output(['git', *args], cwd=ROOT) def function_bytes(data): """Top-level named func through next named func, preserving every raw byte. The prefix is an explicit non-function unit. Nested lambdas do not start a unit. Comments, whitespace, signatures and trailing declarations remain included; uncertain edits fail conservatively, never normalize as equal. """ matches = list(re.finditer(rb'(?m)^(?:static )?func ([A-Za-z_][A-Za-z_0-9]*)\(', data)) result = {'': data[:matches[0].start()] if matches else data} for i, match in enumerate(matches): name = match[1].decode('ascii') require(name not in result, 'ambiguous function: ' + name) result[name] = data[match.start():matches[i + 1].start() if i + 1 < len(matches) else len(data)] return result def resolve_anchor(data, function, digest, line_count): body = function_bytes(data).get(function) require(body is not None, 'reachability function missing: ' + function) lines = body.splitlines(keepends=True) hits = [b''.join(lines[i:i + line_count]) for i in range(len(lines) - line_count + 1) if hashlib.sha256(b''.join(lines[i:i + line_count])).hexdigest() == digest] require(len(hits) == 1, 'reachability anchor missing/ambiguous: ' + function) return hits[0] def source_delta(base, head): """Compute changed function units from Git, including added/deleted files. Only game autoload/scripts GDScript belongs to this applicability scope. The complete tested map still pins every supplied dependency separately. """ paths = git_bytes('diff', '--no-ext-diff', '--no-renames', '--name-only', '-z', base + '..' + head, '--', 'autoload/', 'scripts/').split(b'\0') base_paths = set(git_bytes('ls-tree', '-r', '--name-only', '-z', base).split(b'\0')) head_paths = set(git_bytes('ls-tree', '-r', '--name-only', '-z', head).split(b'\0')) delta = [] for encoded in sorted(p for p in paths if p.endswith(b'.gd')): path = encoded.decode('utf-8') old = function_bytes(git_bytes('show', base + ':' + path)) if encoded in base_paths else {} new = function_bytes(git_bytes('show', head + ':' + path)) if encoded in head_paths else {} for name in sorted(old.keys() | new.keys()): if old.get(name) != new.get(name): delta.append({'path': path, 'function': name}) return delta def boundary_conditions(path, function): # Conservative coverage: new/changed Runtime setup can reach every boundary. if path == 'autoload/simulation_runtime.gd': if any(word in function for word in ('relationship', 'restore', 'snapshot', 'save')): return {'save_restore'} return set(REQUIRED) | {'EV'} if '/relationship/' in path or '/save/' in path: return {'save_restore'} if any(part in path for part in ('/world/', '/transport/', '/staff/')): return {'exit_release', 'closure_release', 'shift_completion', 'EV', 'save_restore'} # No inferred non-impact exemption for previously unseen dependencies. return set(REQUIRED) | {'EV'} def applicability(index, spec, source, head): registered = spec['current_source_pins'] require(index.get('registered_pins') == registered, 'registered pin declaration') for path, digest in registered.items(): require(hashlib.sha256(git_bytes('show', REGISTERED_COMMIT + ':' + path)).hexdigest() == digest, 'registered Git pin: ' + path) require(index.get('versions') == {'execution_origin': EXECUTION_ORIGIN, 'registered': REGISTERED_COMMIT, 'tested': head, 'integration': None}, 'version roles') # Refuse uncommitted game bytes; otherwise Git diff would not describe tested. game_paths = git_bytes('ls-tree', '-r', '--name-only', '-z', head, '--', 'autoload/', 'scripts/').split(b'\0') for encoded in game_paths: if not encoded.endswith(b'.gd'): continue path = encoded.decode('utf-8') require(path in source and sha(safe(ROOT, path)) == hashlib.sha256(git_bytes('show', head + ':' + path)).hexdigest(), 'tested game differs from Git: ' + path) delta = source_delta(REGISTERED_COMMIT, head) require(index.get('applicability_delta') == delta, 'git diff/applicability_delta mismatch') for path, names in ORDER_FUNCTIONS.items(): old = function_bytes(git_bytes('show', REGISTERED_COMMIT + ':' + path)) new = function_bytes(safe(ROOT, path).read_bytes()) for name in names: require(name in old and name in new and old[name] == new[name], 'stale ordering function: ' + path + ':' + name) bindings = index.get('delta_cases') require(isinstance(bindings, dict) and set(bindings) == {r['path'] + ':' + r['function'] for r in delta}, 'delta case bindings') for row in delta: key = row['path'] + ':' + row['function'] required = boundary_conditions(row['path'], row['function']) cases = bindings[key] require(isinstance(cases, dict) and set(cases) == required, 'boundary delta coverage: ' + key) for cid, case_id in cases.items(): declaration = index['reachability']['EV'] if cid == 'EV' else index['conditions'][cid] require(case_id == declaration.get('case_id'), 'boundary delta engine case: ' + key) def coverage(index, raw, source): authority = index['authority'] for ref in {r for _, refs, _ in REQUIRED.values() for r in refs}: entry = authority.get(ref, {}) require(entry.get('status') in {'original', 'approved'}, 'pending/missing authority: ' + ref) aid = entry.get('artifact_id') require(aid in raw and index['artifacts'][aid]['type'] == 'authority', 'raw authority: ' + ref) if ref.startswith('D05-P04-'): require(sha(raw[aid]) == OWNER_HASH, 'owner approval hash mismatch') owner = load(raw[aid]) require(owner.get('origin') == 'direct_user_reply' and owner.get('formal_acceptance') is False, 'owner approval scope') require(ref in {v['id'] for v in owner['approved_choices']}, 'owner approval condition') else: path = ('docs/traceability/original/BASELINE.txt' if ref.startswith('BASELINE:') else 'docs/DESIGN_DECISIONS.md' if ref == 'D-034' else 'docs/plans/original-completion-2026-10-02/execution/p04-01-input-r01/ORDER_CONTRACT_DRAFT.md') require(sha(raw[aid]) == sha(safe(ROOT, path)), 'authority document mismatch: ' + ref) conditions = index.get('conditions') require(isinstance(conditions, dict) and set(conditions) == set(REQUIRED), 'mandatory conditions missing/unknown') for cid, (domain_name, refs, expected) in REQUIRED.items(): condition = conditions[cid] require(condition.get('authority_refs') == list(refs), 'condition authority: ' + cid) require(condition.get('nativeWindows') == 'pending', 'nativeWindows condition: ' + cid) domain = index['domains'][domain_name] require(set(refs) <= set(domain['authority_refs']), 'domain authority: ' + cid) cases = [c for c in domain['cases'] if c['id'] == condition.get('case_id')] require(len(cases) == 1, 'mandatory engine case: ' + cid) case = cases[0] require(case.get('raw_origin') == 'engine', 'case origin: ' + cid) observation = load(raw[case['after']]) measurements = observation.get('conditions', {}).get(cid) require(isinstance(measurements, dict), 'missing engine measurements: ' + cid) for metric, value in expected.items(): require(literal(measurements.get(metric), value), cid + ': measurement ' + metric) require(any(p.get('case_id') == case['id'] and p.get('artifact_id') == case['after'] and p.get('json_pointer') == '/conditions/' + cid + '/' + metric and p.get('operator') == 'eq' and literal(p.get('expected'), value) and p.get('authority_ref') in refs for p in domain['invariants']), cid + ': missing mandatory invariant ' + metric) if cid == 'save_restore': writer = load(raw[case['receipt']]) reader_id = condition.get('restore_receipt') require(reader_id in raw, 'missing restore receipt') reader = load(raw[reader_id]) require(type(reader.get('start_pid')) is int and reader['start_pid'] > 0 and reader['start_pid'] != writer['start_pid'] and reader.get('end_pid') == reader['start_pid'] and type(reader.get('exit_code')) is int and reader['exit_code'] == 0 and reader.get('engine_ended') is True, 'separate PID restore receipt') require(reader.get('source_map') == source and reader.get('environment') == index['environment'], 'restore applicability') require(reader.get('case_id') == case['id'] and reader.get('artifact_hashes') == writer.get('artifact_hashes'), 'restore case artifact binding') save_id = condition.get('save_artifact') require(save_id in raw and index['artifacts'][save_id]['type'] == 'save', 'formal save artifact') require(writer.get('saved_sha256') == sha(raw[save_id]) == reader.get('restored_sha256'), 'save/restore identity') require(reader.get('stdout') in raw and reader.get('native_log') in raw, 'restore logs') reachability = index.get('reachability') require(isinstance(reachability, dict) and set(reachability) == {'EV', 'transport'}, 'reachability required') for name, decision in reachability.items(): refs = decision.get('source_refs') require(isinstance(refs, list) and refs and isinstance(decision.get('reason'), str) and decision['reason'].strip(), 'unsupported reach=false: ' + name) for ref in refs: require(ref.get('path') in source and ref.get('sha256') == source[ref['path']], 'reachability source pin') identity = (ref['path'], ref.get('function'), ref.get('anchor_sha256'), ref.get('line_count')) require(identity in REACH_REFS[name], 'unknown reachability anchor') resolve_anchor(safe(ROOT, ref['path']).read_bytes(), *identity[1:]) require(len(refs) == len(REACH_REFS[name]) and set(REACH_REFS[name]) == { (r['path'], r['function'], r['anchor_sha256'], r['line_count']) for r in refs}, 'missing static reachability chain: ' + name) # Staff dispatch reserves task items before travel. A guest-only exclusion # must not hide this reachable EV reservation path. if name == 'EV': require(decision.get('reach') is True, 'EV staff reservation path is reachable') domain = index['domains']['停電'] cases = [c for c in domain['cases'] if c['id'] == decision.get('case_id')] require(len(cases) == 1 and cases[0].get('raw_origin') == 'engine', 'EV engine case') case = cases[0] ev = load(raw[case['after']]).get('ev', {}) require(ev.get('reserved_before_travel') is True and ev.get('power_stopped') is True, 'EV reserved staff power-stop scenario') require(any(p.get('case_id') == case['id'] and p.get('artifact_id') == case['after'] and p.get('json_pointer') == '/ev/orphan_reservations' and p.get('operator') == 'eq' and literal(p.get('expected'), 0) for p in domain['invariants']), 'EV orphan invariant') else: require(decision.get('reach') is False, 'transport reservation/payment exclusion') NATIVE_RUNS = { 'actual-native': ('import', 'parse', 'repro'), 'dependency-midnight-native': ('import', 'parse', 'repro'), 'dependency-formal-native': ('import', 'parse', 'writer', 'reader'), } SAVE_POINTS = ('before', 'midnight', 'paused', 'after', 'next') SAVE_MEMBERS = {'journal.log', 'manifest.json', 'thumbnail.png', 'world.bin'} def native_file(base, name, pin): path = safe(base, name) require(type(pin.get('bytes')) is int and path.stat().st_size == pin['bytes'], 'native bytes: ' + name) require(sha(path) == pin.get('sha256'), 'native SHA: ' + name) return path def native_cleanup(value): require(value.get('engine_ended') is True and value.get('errors') == [] and literal(value.get('actual_process_exit_code'), 0), 'native cleanup failed') attempts = value.get('attempts') require(isinstance(attempts, list) and attempts, 'native cleanup attempts missing') for attempt in attempts: require(attempt.get('errors') == [] and attempt.get('kill_attempted') is False and attempt.get('wait_completed') is True and literal(attempt.get('wait_returned_code'), 0), 'native cleanup abnormal wait') def native_ownership(base): provenance = load(safe(base, 'OWNERSHIP_RAW_PROVENANCE.json'))['copied'] targets = set() for row in provenance: require(row['target'] not in targets, 'duplicate native provenance target') targets.add(row['target']) native_file(base, row['target'], row) pids = {} for run, phases in NATIVE_RUNS.items(): execution = load(safe(base, run + '/execution.json')) inputs = load(safe(base, run + '/runner-input.json')) require([p['phase'] for p in execution['phases']] == list(phases), 'native phase membership') run_pids = [] cleanups = [] for phase, phase_receipt in zip(phases, execution['phases']): prefix = run + '/' + phase + '/' names = ('started.json', 'process.json', 'ended.json', 'outer-owned-finally.json', 'adapter-owned-cleanup.json', 'stdout.log', 'stderr.log', 'engine-native.log') require({prefix + n for n in names} <= targets, 'native provenance lifecycle missing') start, process, end, outer, cleanup = [load(safe(base, prefix + n)) for n in names[:5]] pid = start['actual_pid'] require(type(pid) is int and pid > 0 and pid not in pids.values(), 'native PID reused') require(start['pid'] == process['pid'] == end['pid'] == end['actual_pid'] == pid, 'native PID chain') require(start['event'] == 'ENGINE_STARTED' and end['event'] == 'ENGINE_ENDED' and start['owner_pid'] == end['owner_pid'] == inputs['owner_runner_pid'] and start['command'] == start['argv'] == process['argv'] == end['argv'] == end['command'] and start['monotonic_ns'] < end['monotonic_ns'], 'native lifecycle identity') require(process['actual_start_binding'] == start and process['actual_end_binding'] == end, 'native process bindings') require(start['current_process_identity']['pid'] == pid and start['current_process_identity']['ppid'] == start['owner_pid'], 'native owner identity') require(load(safe(base, run + '/' + phase + '-receipt.json')) == phase_receipt == load(safe(base, run + '/' + phase + '-actual-phase.json')), 'native phase receipt binding') for record in (process, end, phase_receipt): require(literal(record.get('exit_code'), 0), 'native abnormal exit') require(end.get('engine_ended') is True and end.get('timed_out') is False and process.get('timed_out') is False and end.get('lifecycle_error') is None and process.get('lifecycle_error') is None and literal(end.get('actual_process_exit_code'), 0) and phase_receipt.get('engine_ended') is True, 'native abnormal end') require(phase_receipt['actual_pid'] == pid and phase_receipt['native_process'] == process, 'native execution process binding') require(outer['actual_captured_pids'] == [pid] and outer['outer_cleanup_errors'] == [] and outer.get('all_captured_ended') is True and outer.get('adapter_exception') is None and len(outer['cleanup']) == 1 and outer['cleanup'][0]['pid'] == pid and outer['cleanup'][0]['outer_cleanup_errors'] == [] and outer['cleanup'][0]['cleanup'] == cleanup == process['adapter_owned_cleanup'], 'native owned cleanup binding') native_cleanup(cleanup) for stream in ('stdout', 'stderr'): require(sha(safe(base, prefix + stream + '.log')) == process[stream + '_sha256'], 'native stream hash') for field in ('stdout', 'stderr'): require(safe(base, prefix + field + '.log').is_file(), 'native log missing') native_file(base, prefix + 'engine-native.log', phase_receipt['raw_native_log']) pids[run + '/' + phase] = pid run_pids.append(pid) cleanups.extend(outer['cleanup']) require(execution['actual_captured_PIDs'] == run_pids and execution['cleanup'] == cleanups and execution['cleanup_errors'] == [], 'native execution cleanup membership') formal = 'dependency-formal-native/' records = [load(safe(base, formal + 'restart-evidence/' + role + '.json')) for role in ('writer', 'reader')] require(records[0]['profile'] != records[1]['profile'], 'native writer reader profile reused') for role, record in zip(('writer', 'reader'), records): require(record['pid'] == pids[formal + role], 'native writer reader PID binding') profile = load(safe(base, formal + role + '-profile.json')) phase = load(safe(base, formal + role + '-receipt.json')) require(record['profile'] == profile['actual_user_data_dir'] == profile['expected_user_data_dir'] == phase['controlled_environment']['THE_TREE_PACK_PROFILE_EXPECTED'], 'native profile binding') require(record['slots'] == {p: record['profile'] + '/saves/p04_boundary/' + p for p in SAVE_POINTS}, 'native formal profile slots') return pids def native_applicability(base): """Production evidence identity, separate from A/B checkout applicability.""" app = load(safe(base, 'POST_P18_CURRENT_SOURCE_APPLICABILITY.json')) production = app['production_commit'] require(re.fullmatch('[0-9a-f]{40}', production) is not None, 'native production commit') registered = load(SPEC)['current_source_pins'] pin_rows = app['registered_source_pins'] require(len(pin_rows) == len(registered) and {r['path'] for r in pin_rows} == set(registered), 'native current_source_pins membership') current = {} for row in pin_rows: path = row['path'] current[path] = hashlib.sha256(git_bytes('show', production + ':' + path)).hexdigest() require(row['registered_sha256'] == registered[path] and row['production_sha256'] == current[path], 'native current_source_pins mismatch') rows = app['ordering_functions'] require(len(rows) == sum(map(len, ORDER_FUNCTIONS.values())) and {(r['path'], r['function']) for r in rows} == {(p, f) for p, fs in ORDER_FUNCTIONS.items() for f in fs}, 'native ordering membership') for path, functions in ORDER_FUNCTIONS.items(): old = function_bytes(git_bytes('show', REGISTERED_COMMIT + ':' + path)) new = function_bytes(git_bytes('show', production + ':' + path)) for function in functions: row = next(r for r in rows if (r['path'], r['function']) == (path, function)) body = new[function] require(old[function] == body and hashlib.sha256(body).hexdigest() == row['production_body_sha256'] == row['registered_body_sha256'], 'native ordering bytes') for run, result in zip(NATIVE_RUNS, ('SHIFT_CURRENT', 'DEPENDENCY_MIDNIGHT', 'DEPENDENCY_FORMAL')): summary = load(safe(base, 'ROOT_APPROVED_' + result + '_RESULT.json')) require(summary['production_commit'] == production, 'native production commit mismatch') inputs = load(safe(base, run + '/runner-input.json')) for path, digest in current.items(): require(inputs['source_before'][path]['sha256'] == digest == inputs['selected_source_map'][path], 'native input source pin mismatch') return production def native_saves(base): prefix = 'dependency-formal-native/' execution = load(safe(base, prefix + 'execution.json')) before, after = execution['formal_before'], execution['formal_after'] require(set(before) == set(after) == set(SAVE_POINTS) and before == after, 'native original members changed') summary = load(safe(base, 'ROOT_APPROVED_DEPENDENCY_FORMAL_RESULT.json')) members = summary['formal_member_pins'] require(len(members) == 20 and {(r['point'], r['member']) for r in members} == {(p, m) for p in SAVE_POINTS for m in SAVE_MEMBERS}, 'native formal member membership') for point in SAVE_POINTS: require(set(before[point]) == SAVE_MEMBERS, 'native original member missing') for member in SAVE_MEMBERS: for role in ('writer', 'reader'): path = native_file(base, prefix + 'formal-packages/' + role + '/' + point + '/' + member, before[point][member]) row = next(r for r in members if (r['point'], r['member']) == (point, member)) require(sha(path) == row['sha256'], 'native formal member pin') typed = summary['typed_outputs_14_sha_match_original_native'] expected = {role + '-' + p + suffix + '.var': p for p in SAVE_POINTS for role, suffix in (('writer', '-persisted'), ('reader', '-loaded'))} expected.update({'reader-replayed-' + p + '.var': p for p in SAVE_POINTS if p != 'before'}) require(len(typed) == len(expected) and {Path(r['output']).name for r in typed} == set(expected), 'native typed member membership') inputs = load(safe(base, prefix + 'runner-input.json'))['fixed_input_pins'] for row in typed: name = Path(row['output']).name original = 'midnight-' + expected[name] + '.var' require(Path(row['original']).name == original, 'native typed original identity') source = safe(base, 'dependency-midnight-native/order-evidence/' + original) output = safe(base, prefix + 'restart-evidence/' + name) require(sha(source) == sha(output) == row['sha256'], 'native typed SHA mismatch') pin = [p for p in inputs if p['path'] == row['original']] require(len(pin) == 1, 'native typed input missing') native_file(base, 'dependency-midnight-native/order-evidence/' + original, pin[0]) def receipt_rows(receipts): """Keep multiplicity: sets must never hide duplicated ledger rows.""" require(isinstance(receipts, list), 'native receipts missing') ids, rows = set(), [] for receipt in receipts: require(receipt['id'] not in ids and receipt['rows'], 'native duplicate/empty receipt') ids.add(receipt['id']) for row in receipt['rows']: require(row['transaction_id'] == receipt['id'] and type(row['amount']) is int and row['amount'] >= 0, 'native receipt transaction') require(row not in rows, 'native duplicate receipt row') rows.append(row) return rows def native_ledger(base): prefix = 'dependency-midnight-native/order-evidence/' observations = load(safe(base, prefix + 'observations.json')) series = observations['observations'] require(len(series) == len(SAVE_POINTS), 'native observation series missing') initial = series[0] service = initial['service'] require(service['state'] == 'ACTIVE' and service['elapsed_minutes'] == service['duration_minutes'] - 1, 'native initial service progress') identity = ('service_id', 'request_id', 'facility_id', 'guest_ids', 'inventory_reservations', 'price_snapshot') require(service['inventory_reservations'] and len(service['guest_ids']) == 1, 'native service identity missing') guest_id = service['guest_ids'][0] account = 'GUEST_WALLET:' + guest_id final_state = load(safe(base, prefix + 'midnight-after.json'))['systems']['runtime'] links = [r for r in final_state['economy']['idempotency'] if r['key'] == 'service.payment.' + service['service_id']] require(len(links) == 1, 'native service idempotency missing/duplicate') transaction = links[0]['transaction_id'] previous_rows = [] states = [] for position, (point, observation) in enumerate(zip(SAVE_POINTS, series)): snapshot = load(safe(base, prefix + 'midnight-' + point + '.json')) state = snapshot['systems']['runtime'] states.append(state) facilities = [f for f in state['facilities']['instances'] if f['instance_id'] == service['facility_id']] require(len(facilities) == 1, 'native facility identity') facility = facilities[0] if position == 0: definition_id = facility['definition_id'] require(re.fullmatch('[a-zA-Z0-9_]+', definition_id) is not None, 'native definition identity') definition_path = 'data/facilities/' + definition_id + '.tres' production = load(safe(base, 'POST_P18_CURRENT_SOURCE_APPLICABILITY.json'))['production_commit'] definition = git_bytes('show', production + ':' + definition_path) inputs = load(safe(base, 'dependency-midnight-native/runner-input.json')) require(inputs['selected_source_map'][definition_path] == inputs['source_before'][definition_path]['sha256'] == hashlib.sha256(definition).hexdigest(), 'native original definition pin') for field, value in (('base_price', service['price_snapshot']), ('base_service_minutes', service['duration_minutes'])): matches = re.findall(rb'(?m)^' + field.encode() + rb' = ([0-9]+)$', definition) require(len(matches) == 1 and int(matches[0]) == value == facility[field], 'native original definition value') current = observation['service'] require(all(current[k] == service[k] for k in identity), 'native service identity changed') require(observation['minute'] == initial['minute'] + position == snapshot['clock']['absolute_minute'], 'native minute series') require(current in state['facilities']['service_history'] or any( current in f['active_services'] for f in state['facilities']['instances']), 'native service snapshot binding') require(observation['reservations'] == state['inventory'], 'native reservation snapshot binding') rows = receipt_rows(observation['receipts']) ledger = state['economy']['entries'] initial_ledger = states[0]['economy']['entries'] require(ledger[:len(initial_ledger)] == initial_ledger and ledger[len(initial_ledger):] == rows, 'native ledger receipt delta') require(rows[:len(previous_rows)] == previous_rows, 'native receipt history changed') wallet_delta = sum(r['amount'] * ((r['debit_account'] == account) - (r['credit_account'] == account)) for r in rows) require(observation['wallet'] == initial['wallet'] + wallet_delta, 'native wallet delta') require(observation['wallet'] == sum(r['amount'] * ((r['debit_account'] == account) - (r['credit_account'] == account)) for r in ledger), 'native ledger wallet balance') if observation['guest']: require(observation['guest']['wallet_gold'] == observation['wallet'] and observation['guest']['guest_id'] == guest_id, 'native guest wallet binding') else: require(point == 'next', 'native guest missing before completion') sales = [r for r in rows if r['category'] == 'SERVICE_SALE'] paused = current['state'] == 'PAUSED' if position in (1, 2): require(paused and current['interruption_reason'] == 'RELATED_FACILITY_INACTIVE' and current['elapsed_minutes'] == service['elapsed_minutes'] and not sales, 'native PAUSED sale/progress/reason') elif position >= 3: require(current['state'] == 'COMPLETED' and len(sales) == 1 and current['elapsed_minutes'] == current['duration_minutes'], 'native completion sale count') sale = sales[0] require(sale['transaction_id'] == transaction and sale['credit_account'] == account and sale['source_entity_id'] == service['facility_id'] and sale['debit_account'] == 'FACILITY_REVENUE:' + service['facility_id'] and sale['amount'] == service['price_snapshot'] and sale['absolute_minute'] == current['completed_at'], 'native sale service join') reservations = observation['reservations']['reservations'] require(len(reservations) == len(service['inventory_reservations']) and {r['reservation_id'] for r in reservations} == set(service['inventory_reservations']), 'native orphan reservation membership') requests = state['facilities']['requests'] matching_requests = [r for r in requests if r['request_id'] == service['request_id']] require(len(matching_requests) == (1 if position < 3 else 0), 'native request series') if matching_requests: request = matching_requests[0] require(request['facility_id'] == service['facility_id'] and request['guest_ids'] == service['guest_ids'] and request['quoted_price'] == service['price_snapshot'] and request['reserved_inventory_ids'] == service['inventory_reservations'], 'native request service join') for reservation in reservations: require(reservation['requester_id'] == service['request_id'] and reservation['owner_inventory_id'] == 'facility.inventory:' + service['facility_id'] and reservation['state'] == ('ACTIVE' if position < 3 else 'CONSUMED'), 'native orphan reservation relation') previous_rows = rows require(receipt_rows(observations['first_receipts']) == previous_rows == receipt_rows(observations['replay_receipts']), 'native midnight replay receipts') reader = load(safe(base, 'dependency-formal-native/restart-evidence/reader.json')) require(len(reader['results']) == 1 and receipt_rows(reader['results'][0]['receipts']) == previous_rows, 'native reader receipt delta') sweep = [r for r in previous_rows if r['category'] == 'SERVICE_CASH_SWEEP'] require(len(sweep) == 1 and sweep[0]['transaction_id'] == transaction and sweep[0]['amount'] == service['price_snapshot'] and sweep[0]['credit_account'] == 'FACILITY_REVENUE:' + service['facility_id'] and sweep[0]['debit_account'] == 'PLAYER_CASH', 'native sale cash sweep') maintenance = [r for r in previous_rows if r['category'].startswith('MAINTENANCE_')] accruals = [r for r in maintenance if r['category'] == 'MAINTENANCE_ACCRUAL'] payments = [r for r in maintenance if r['category'] == 'MAINTENANCE_PAYMENT'] require(accruals and len(accruals) == len(payments), 'native maintenance pairs') for accrual in accruals: matches = [r for r in payments if r['transaction_id'] == accrual['transaction_id'] and r['source_entity_id'] == accrual['source_entity_id'] and r['amount'] == accrual['amount'] and r['absolute_minute'] == series[1]['minute'] == accrual['absolute_minute'] + 1] require(len(matches) == 1, 'native maintenance accrual/payment join') return {'service_id': service['service_id'], 'transaction_id': transaction, 'receipt_rows': len(previous_rows), 'formal_original_credit': 0} def verify_native(base): """Finite C-layer check, never a replacement for the 15+EV whole gate.""" for row in load(safe(base, 'SOURCE_MANIFEST.json'))['files']: native_file(base, row['copy'], row) production = native_applicability(base) pids = native_ownership(base) native_saves(base) result = native_ledger(base) return dict(result, production_commit=production, owned_processes=len(pids), verified_conditions=['dependency_stop', 'recovery_completion', 'paused_midnight']) def verify(directory): # Contract hashes the supplied spec string, while the checked-in JSON has # one final LF. Accept only that exact representation difference. spec_bytes = SPEC.read_bytes() require(sha(SPEC) == SPEC_HASH or (spec_bytes.endswith(b'\n') and hashlib.sha256(spec_bytes[:-1]).hexdigest() == SPEC_HASH), 'dispatch spec pin mismatch') spec = load(SPEC) evidence = directory / 'p04-evidence' require(not evidence.is_symlink(), 'symlink evidence directory') index = load(safe(evidence, 'index.json')) require(type(index.get('schema_version')) is int and index['schema_version'] == 1, 'schema_version') require(index.get('task_id') == 'P04-01' and index.get('formal_acceptance') is False, 'task/acceptance') head = subprocess.check_output(['git', 'rev-parse', 'HEAD'], cwd=ROOT, text=True).strip() require(index.get('candidate_commit') == head, 'candidate_commit mismatch') source = index.get('source_map') pins(source, ROOT) applicability(index, spec, source, head) oldmap = load(ROOT / 'docs/plans/original-completion-2026-10-02/execution/p04-01-input-r01/historical-source-map.json') required = {p for p in oldmap if p.endswith('.gd') and p.startswith(('autoload/', 'scripts/'))} require(required <= source.keys(), 'missing runtime/service dependency source pins') environment = index.get('environment') require(isinstance(environment, dict) and isinstance(environment.get('os'), str) and environment['os'], 'environment OS') for kind in ('engine', 'configuration', 'inputs'): pins(environment.get(kind), evidence) artifacts = index.get('artifacts') require(isinstance(artifacts, dict) and artifacts, 'missing artifacts') paths, raw = set(), {} for aid, item in artifacts.items(): require(isinstance(aid, str) and aid and isinstance(item, dict), 'invalid artifact') path = safe(evidence, item['path']) require(path not in paths, 'duplicate artifact path') paths.add(path) require(type(item.get('bytes')) is int and item['bytes'] == path.stat().st_size, 'artifact size: ' + aid) require(sha(path) == item.get('sha256'), 'artifact hash: ' + aid) require(item.get('type') in {'observation', 'state', 'receipt', 'stdout', 'native_log', 'save', 'authority'}, 'artifact type') raw[aid] = path authority = index.get('authority') require(isinstance(authority, dict) and authority, 'missing authority') domains = index.get('domains') require(isinstance(domains, dict) and set(domains) == DOMAINS, 'required seven domains') for name, domain in domains.items(): require(isinstance(domain, dict), 'invalid domain: ' + name) for field in ('source_refs', 'authority_refs', 'cases', 'invariants'): require(isinstance(domain.get(field), list) and domain[field], name + ': missing ' + field) require(domain.get('applicability') == {'source_map': source, 'environment': environment}, name + ': applicability mismatch') for ref in domain['source_refs']: require(isinstance(ref, dict) and ref.get('path') in source and isinstance(ref.get('function'), str) and ref['function'], 'invalid source ref') require(ref.get('sha256') == source[ref['path']], 'source ref hash') for ref in domain['authority_refs']: require(ref in authority and authority[ref].get('status') in {'original', 'approved'}, 'pending/missing authority') require(authority[ref].get('artifact_id') in raw, 'missing raw authority') case_ids = set() for case in domain['cases']: require(isinstance(case, dict) and isinstance(case.get('id'), str) and case['id'] not in case_ids, 'duplicate/invalid case') case_ids.add(case['id']) for field in ('input', 'before', 'operation', 'after', 'receipt'): require(case.get(field) in raw, name + ': missing case artifact ' + field) receipt = load(raw[case['receipt']]) pid = receipt.get('start_pid') require(type(pid) is int and pid > 0 and receipt.get('end_pid') == pid and type(receipt.get('exit_code')) is int and receipt['exit_code'] == 0 and receipt.get('engine_ended') is True, 'unexecuted/incomplete receipt') require(receipt.get('source_map') == source and receipt.get('environment') == environment, 'receipt applicability') for field in ('stdout', 'native_log'): require(receipt.get(field) in raw, 'receipt missing raw ' + field) require(receipt.get('case_id') == case['id'], 'receipt case identity') require(receipt.get('artifact_hashes') == {field: sha(raw[case[field]]) for field in ('input', 'before', 'operation', 'after')}, 'receipt artifact binding') for pred in domain['invariants']: require(isinstance(pred, dict) and pred.get('artifact_id') in raw, 'missing predicate artifact') require(pred.get('authority_ref') in domain['authority_refs'], 'predicate authority') require(pred.get('raw_origin') == 'engine', 'unsupported derivation/origin') value = pointer(load(raw[pred['artifact_id']]), pred['json_pointer']) op = pred.get('operator') if op in {'same_literal', 'distinct'}: require(pred.get('paired_artifact_id') in raw, 'missing paired artifact') other = pointer(load(raw[pred['paired_artifact_id']]), pred['paired_json_pointer']) result = literal(value, other) if op == 'same_literal' else not literal(value, other) elif op == 'eq': result = literal(value, pred['expected']) elif op == 'nonnegative': result = type(value) in (int, float) and value >= 0 elif op == 'count_eq': result = isinstance(value, (list, dict)) and type(pred.get('expected')) is int and len(value) == pred['expected'] else: raise ValueError('unsupported predicate: ' + str(op)) require(result, name + ': predicate failed') require(index.get('review_status') in {'pending_review', 'approved'}, 'review status') coverage(index, raw, source) # Scalar conditions remain necessary declarations, never sufficient proof. binding = index.get('native_bundle') require(isinstance(binding, dict), 'native bundle required; self-reported scalar evidence is insufficient') manifest = safe(evidence, binding['manifest']) require(manifest.name == 'OWNERSHIP_RAW_PROVENANCE.json' and sha(manifest) == binding['sha256'], 'native bundle provenance pin') native = verify_native(manifest.parent) require(native['production_commit'] == head, 'native production/tested mismatch; A/B reuse coverage required') # This adapter covers only the supplied dependency/formal series. Never # promote it to the missing original scenarios through scalar booleans. missing = (set(REQUIRED) | {'EV'}) - set(native['verified_conditions']) require(not missing, 'uncollected original boundaries: ' + ', '.join(sorted(missing)) + '; formal_original_credit=0') def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--verify-only', action='store_true', required=True) parser.parse_args() try: require(bool(os.environ.get('BUILD_OUTPUT_DIR')), 'BUILD_OUTPUT_DIR required') verify(Path(os.environ['BUILD_OUTPUT_DIR'])) except (ValueError, OSError, KeyError, TypeError, IndexError, AttributeError, subprocess.SubprocessError) as exc: print(json.dumps({'task_id': 'P04-01', 'machine_verified': False, 'formal_acceptance': False, 'error': str(exc)}, ensure_ascii=False)) return 1 print(json.dumps({'task_id': 'P04-01', 'machine_verified': True, 'formal_acceptance': False})) return 0 if __name__ == '__main__': sys.exit(main())