"""Complete P18 changed-function review context; no acceptance or limit changes.""" import hashlib import json import re import subprocess from pathlib import Path TASK = 'P18-01-CODE' BASE = 'd2a1f80a613e7c77b02b941026bc49c2d85db863' SPEC = '04e9ae701b6ee1e399542564add695ca7fce54499e52dd2e907b1dbdc23a366d' RUNTIME = 'autoload/simulation_runtime.gd' MARKERS = 'docs/plans/original-completion-2026-10-02/execution/completion_marker_contracts.json' FOCUS = [ 'tests/s4/test_original_relationship_model.gd', 'tests/s4/test_original_relationship_runtime.gd', 'tests/s4/test_relationship_event_service.gd', 'tests/s4/test_runtime_relationship_events.gd', 'tests/s6/test_runtime_snapshot_serialization.gd', 'tests/s6/test_runtime_save_lifecycle.gd', 'tests/ui/test_staff_management.gd', ] def sha(text): return hashlib.sha256(text.encode()).hexdigest() def source(repo, revision, path): return subprocess.check_output(['git', 'show', revision + ':' + path], cwd=repo).decode('utf-8') def method_ranges(text): lines = text.splitlines(keepends=True) starts = [(i, re.match(r'^(?:static )?func\s+(\w+)\(', line).group(1)) for i, line in enumerate(lines) if re.match(r'^(?:static )?func\s+(\w+)\(', line)] assert starts, 'Runtime method boundaries missing' methods = {name: (start, starts[i + 1][0] if i + 1 < len(starts) else len(lines)) for i, (start, name) in enumerate(starts)} assert len(methods) == len(starts), 'duplicate Runtime methods' return lines, starts[0][0], methods def runtime_context(git, repo, revision): full = source(repo, revision, RUNTIME) old = source(repo, BASE, RUNTIME) lines, header_end, methods = method_ranges(full) old_lines, _, old_methods = method_ranges(old) delta = git(repo, 'diff', '--no-ext-diff', '--unified=0', BASE, revision, '--', RUNTIME) selected = set() hunks = [] for match in re.finditer(r'(?m)^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@', delta): old_start, old_count, start, count = match.groups() old_start, old_count = int(old_start), int(old_count or '1') start, count = int(start), int(count or '1') touched = list(range(max(start - 1, 0), start - 1 + count)) if count else [max(start - 1, 0)] names = {name for name, (lo, hi) in methods.items() if any(lo <= n < hi for n in touched)} for name, (lo, hi) in old_methods.items(): if any(lo <= n < hi for n in range(max(old_start - 1, 0), old_start - 1 + old_count)) and name in methods: names.add(name) selected.update(names) hunks.append(dict(new_start=start, new_count=count, methods=sorted(names))) selected.update(name for name in methods if name in { 'create_snapshot', 'restore_snapshot', '_initialize_s4_relationship_events', '_configure_relationship_event_boundaries', '_connect_relationship_signals', '_execute_create_relationship', '_execute_change_relationship', '_execute_attack_relationship_shield', '_on_relationship_registered', '_on_relationship_value_changed', '_on_relationship_shield_changed', '_on_relationship_route_lock_changed', '_initialize_mvp_content_catalog', '_register_or_validate_legacy_catalog_definitions', '_validate_catalog_staff_crosslinks', }) covered = set(range(header_end)) pieces = [''.join(lines[:header_end])] for name in sorted(selected, key=lambda n: methods[n][0]): lo, hi = methods[name] covered.update(range(lo, hi)) pieces.append('\n# COMPLETE METHOD %s; original lines %d-%d\n' % (name, lo + 1, hi)) pieces.append(''.join(lines[lo:hi])) for hunk in hunks: assert all(n in covered for n in range(hunk['new_start'] - 1, hunk['new_start'] - 1 + hunk['new_count'])), 'changed Runtime lines omitted' omitted_changed_methods = [name for name in old_methods if name not in methods and name in delta] assert not omitted_changed_methods, 'removed methods need explicit old full context' context = ''.join(pieces) proof = dict(path=RUNTIME, revision=revision, complete_source_sha256=sha(full), base_source_sha256=sha(old), context_sha256=sha(context), selected_complete_methods=sorted(selected), hunks=hunks, all_new_changed_lines_included=True, complete_diff_in_packet=True, omitted_scope='Unchanged Runtime methods outside the above complete methods. Full immutable source remains in Git at the supplied revision; request further context if needed.', entire_Runtime_review_claimed=False) return context, proof def unchanged_dependency_context(repo, revision): selected = { 'scripts/relationship/relationship_state.gd': None, 'scripts/staff/staff_service.gd': ['remove_staff', 'retire_staff'], 'scripts/guest/guest_service.gd': ['despawn_guest'], } result = {} for path, names in selected.items(): full = source(repo, revision, path) assert full == source(repo, BASE, path), 'relationship dependency changed; review complete delta first' entry = {'path': path, 'revision': revision, 'whole_source_sha256': sha(full), 'unchanged_from_base': True, 'whole_file_included': names is None} if names is None: entry['source'] = full else: lines, _, methods = method_ranges(full) assert all(name in methods for name in names), 'required dependency method absent' entry['complete_methods'] = {name: ''.join(lines[methods[name][0]:methods[name][1]]) for name in names} entry['omitted_scope'] = 'Other unchanged methods; not entire service review' result[path] = entry return result def packet(runner, task_id, revision, original_packet): from runner.core import git, allowed, secret_path, read_json, CONTROL, require task = runner.task(task_id) contract = json.loads(task['contract']) require(task_id == TASK and runner.config['project'] == 'the-tree-p18-01-model' and contract['base_commit'] == BASE and contract['spec_sha256'] == SPEC, 'P18 context exact contract guard') ordinary = original_packet(runner, task_id, 'implementer', revision) body = json.loads(ordinary.split('\nDATA:\n', 1)[1]) body['diff'] = git(runner.repo, 'diff', '--no-ext-diff', BASE, revision) names = git(runner.repo, 'ls-tree', '-r', '--name-only', revision).splitlines() body['sources'] = {p: source(runner.repo, revision, p) for p in names if allowed(p, contract['allowed_paths']) and not secret_path(p)} context, proof = runtime_context(git, runner.repo, revision) body['sources'][RUNTIME] = context marker = json.loads(body['sources'][MARKERS]) old_marker = json.loads(source(runner.repo, BASE, MARKERS)) other_old = [x for x in old_marker['rows'] if x['test'] not in FOCUS] other_new = [x for x in marker['rows'] if x['test'] not in FOCUS] require(other_old == other_new, 'unrelated marker records changed') reduced = dict(marker, rows=[x for x in marker['rows'] if x['test'] in FOCUS]) require(len(reduced['rows']) == len(FOCUS), 'all seven complete marker records required') body['review_context_provenance'] = { 'runtime': proof, 'markers': dict(path=MARKERS, complete_source_sha256=sha(body['sources'][MARKERS]), base_source_sha256=sha(source(runner.repo, BASE, MARKERS)), complete_selected_records=FOCUS, omitted_records_proven_unchanged=True), 'rules': 'Review every fixed backend criterion and all changes using full diff, complete selected methods/sources and actual evidence. Context limits do not waive criteria; request more context or reject if evidence is insufficient. Whole P18-01 completion is not claimed.'} body['sources'][MARKERS] = json.dumps(reduced, ensure_ascii=False, indent=2) body['immutable_identity_catalog'] = {p: source(runner.repo, revision, p) for p in ['data/characters/mvp_unique_characters.json']} body['immutable_relationship_dependencies'] = unchanged_dependency_context(runner.repo, revision) body['tests'] = [read_json(row[0]) for row in runner.db.execute( "SELECT artifact FROM evidence WHERE task_id=? AND kind='validation' AND commit_sha=? AND passed=1", (task_id, revision))] body['validation_sources'] = {'tools/run_p18_relationship_tests.py': body['sources']['tools/run_p18_relationship_tests.py']} return (CONTROL / 'prompts/reviewer.txt').read_text() + '\nDATA:\n' + json.dumps(body, ensure_ascii=False)