diff --git a/.github/workflows/remainder-rate.yml b/.github/workflows/remainder-rate.yml index d32aa63cb..3ee30582e 100644 --- a/.github/workflows/remainder-rate.yml +++ b/.github/workflows/remainder-rate.yml @@ -5,6 +5,8 @@ name: Remainder rate exact controls paths: - 'frontiers/remainder_rate_20260930/**' - '.github/workflows/remainder-rate.yml' + - 'tools/remainder_rate_replay.py' + - 'tests/test_remainder_rate_workflow.py' # bound merged sources (consumed in SOURCES.json) and the pinned unmerged dependency (#191; verified by blob) - 'frontiers/remainder_vanishing_20260930/PROOF.md' - 'frontiers/three_fronts_20260924/LIFETIME_REMAINDER.md' @@ -31,6 +33,13 @@ jobs: - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 with: python-version: '3.11.16' + - name: Exercise full-shell rejection contracts in both modes + env: + PYTHONDONTWRITEBYTECODE: '1' + run: | + set -euo pipefail + python -B -S -m unittest discover -s tests -p test_remainder_rate_workflow.py -v + python -B -O -S -m unittest discover -s tests -p test_remainder_rate_workflow.py -v - name: Verify sources, replay both modes, reject mutants env: PYTHONDONTWRITEBYTECODE: '1' @@ -80,19 +89,9 @@ jobs: if len(data) != entry['bytes'] or hashlib.sha256(data).hexdigest() != entry['sha256'] or hashlib.sha1(framed).hexdigest() != entry['git_blob']: raise ValueError('consumed unmerged dependency differs from the pinned blob (rebind required): ' + entry['path'] + ' via ' + where) print(json.dumps({'consumed_unmerged_verified': entry['path'], 'git_blob': entry['git_blob'], 'via': where})) - script = str(root / 'rate_ledger_check.py') - expected = (root / 'RESULTS.json').read_bytes() - for flags in (['-B', '-S'], ['-B', '-O', '-S']): - out = subprocess.run([sys.executable, *flags, script], check=True, capture_output=True, timeout=600).stdout - if out != expected: - raise RuntimeError('output differs from RESULTS.json under ' + ' '.join(flags)) - for m in manifest['mutants']: - rc = subprocess.run([sys.executable, *flags, script, '--mutant', m], capture_output=True, timeout=600).returncode - if rc != 1: - raise RuntimeError('mutant ' + m + ' not rejected') - rc = subprocess.run([sys.executable, *flags, script, '--mutant', 'M9'], capture_output=True, timeout=600).returncode - if rc != 2: - raise RuntimeError('unknown mutant label not rejected with exit 2') + sys.path.insert(0, str(pathlib.Path('tools').resolve())) + from remainder_rate_replay import replay + replay(root, manifest['mutants']) print(json.dumps({'scientific_effect': 'NONE', 'mathematical_acceptance': False})) PY git diff --exit-code diff --git a/reviews/remainder_rate_protocol_20261006/SCOPE.md b/reviews/remainder_rate_protocol_20261006/SCOPE.md new file mode 100644 index 000000000..b9b0b4498 --- /dev/null +++ b/reviews/remainder_rate_protocol_20261006/SCOPE.md @@ -0,0 +1,108 @@ +# Remainder-rate execution protocol repair + +Dylan Roy — delegated AI engineering. Actual author OpenAI / GPT-6 Astra Pro, +`remainder-protocol-followthrough-20261006`; pickup Math-#322/6009571878. +Scientific effect NONE; organizational-independence credit 0. No author self-merge. +This is one workflow repair, not acceptance of the remainder theorem or closure +of the repository-wide legacy-wrapper issue. + +## Exact original sources + +Original source cut: `91821f9262b30ce7684b8ec5f1b4742893dac3d7`. + +| Source | Bytes | Git blob | SHA256 | +|---|---:|---|---| +| .github/workflows/remainder-rate.yml | 5703 | d32aa63cb0733e879e9d8ca3c362ea6fa5520e5b | fa18af037d9131fd8faae40e76bd4f8e6709e26184ac92a40d82f2f140b7d044 | +| frontiers/remainder_rate_20260930/rate_ledger_check.py | 18229 | 3293ca22ab89bd650f361832c62b03724a976f03 | 5ad2b0ca9e7a131040252db5f23a3dc6444c3b0120912fbede4a593fbe7cb5d2 | +| frontiers/remainder_rate_20260930/RESULTS.json | 1074 | 88d97cc6a45d2213399cf87260a3a358d73d9df7 | c2c8ed1ccf0e15c992d88aff04caae1a99291f6d71b75f59db943cadbf5dc7e0 | + +The complete checker, RESULTS and workflow were authenticated before execution. +An initial manually transcribed comprehension failed the source hash; native +base64 recovery corrected that local copy before any checker execution. Original +scientific packet and dependency files are not edited by this proposal. + +## Measured contract + +Actual local CPython 3.13.5: baseline, M1-M4 and M9 in each normal/optimized child +mode, twelve completed native processes. All six stdout/stderr pairs match. +Baseline is the byte-exact 1074-byte RESULTS report, exit 0, empty stderr. +Each named mutant exits 1 with empty stderr and its entire nested report: +M1 changes E1's claimed exponent; M2 changes E2's cubic-barrier diagnostic; +M3 changes E3's determinant diagnostic; M4 changes E5's sign-window diagnostic. +The helper stores the exact independently measured baseline and four changes. +All other nested fields, including the still-passing checks' integer counts, +must match. M9 exits 2 with empty stdout and exactly `unknown mutant label\n`. + +Baseline byte equality is retained. Mutants permit harmless JSON whitespace, +key order and equivalent string escapes, but not duplicate keys, wrong types, +floats/nonfinite values, wrong labels/reasons, missing/extra fields, altered +positive-check details, silence, crashes or unexpected stderr. Recursive typed +equality does not equate bool/int or int/float. Full ordered M1-M4 inventory is +required before any child; expectations never come from the invocation under test. +Children inherit the original working directory. Timeout/launch exceptions +propagate unchanged. The helper retains the original 600-second child budget. + +## Test-first execution + +Ten published unittest methods contain 120 distinct complete-shell fixtures. +They use real committed temporary Git repositories, real Bash/Python children, +nonempty consumed/cited/unmerged tree pins and external ordered call traces. +No subprocess is mocked in the full-shell tests. Synthetic checker outputs are +specified in the test source, never imported from production validation. + +The full ORIGINAL normal-mode coverage yields 84 intended assertion failures, +zero errors: 82 invalid-output admissions, one truncated-inventory admission, +and one missing workflow-wiring assertion. Nine genuine/formatting fixtures +are admitted and 28 other controls correctly rejected; 1234 children execute. +The repaired source has 120/120 expected outcomes in each normal and optimized +outer mode: nine valid/formatting admissions and 111 rejections, 752 children +per mode. Same 120 scenario keys and identical test source in all three phases. +These are not 360 distinct scenario types or mathematical proof obligations. +Every rejection is checked against its exact ordered target prefix; seven +source guards stop before children. The dirty-tree case reaches all twelve +children before the final Git check rejects the changed tracked file. + +Completed local coverage is partitioned into explicit disjoint subcase groups +because the execution envelope interrupted two original group attempts and one +full optimized discovery attempt. Nonselected subcases are explicitly skipped +in the local-only partition runner; complete coverage is checked independently +from the 120 unique saved records per phase. Interrupted records remain separate +and excluded. No uninterrupted full-suite result or full repository checkout is +claimed. The unchanged published test source has no partition filtering; hosted +CI runs the two complete discovery commands. + +Twelve further genuine invocations through the repaired helper match every +native-characterization exit and stream hash; sources remain unchanged. +Twenty-nine additional local-only injected process-boundary cases per mode +verify twelve stopping positions for each of TimeoutExpired/OSError and five +bad inventories; exact exception objects and 600-second/capture/command contracts +are preserved. Those are transparently synthetic injections, not native runs. +The first optimized probe used bare assertions and is not credited; corrected +explicit-raise probes passed in both modes. A test-generator quoting error was +corrected before test execution. All these development records are retained. + +## Preserved boundaries and release conditions + +The original 3099-byte source preflight, including the #191 pinned GitHub-blob +fallback, is byte-identical (SHA256 +f94b86d9e9fdfade99335aba3193862246114181f4fcd768b5bb8f9eb1ac1dd4). +The final 137-byte JSON/Git postflight is byte-identical (SHA256 +752aa03685dbbe54ec40c3e91b8709eb6453c41c146e9636b295b2129c586cdc). +These sizes include workflow indentation. Only the intervening process loop, +helper/test triggers and a two-mode focused regression step change. Action pins, +Python 3.11.16, read-only permissions and ten-minute job budget stay unchanged. +All packet, proof, result, manifest, cited and consumed dependency bytes remain. +The synthetic unmerged-pin controls exercise the existing tree route; no local +live GitHub API-fallback execution is claimed. Actual full-tree pinned-runtime +execution must be established by the dedicated workflow. No unmerged-source +rebind, scientific tolerance change, no-argument generation, Lean execution, +new proof/statement alignment, or whole-program acceptance is supplied. + +A separate nonauthor engineering source review and actual applicable dedicated, +general and required checks on the real candidate remain necessary. An eligible +separate nonauthor/nonreader integrator must reconcile current refs, ownership, +reviewed blobs, dependencies and threads before guarded ordinary merge and +verify landing afterwards. A base change does not transfer an old receipt. +#322 and unrelated wrapper repairs retain their scopes. This helper is not a +hostile-source sandbox, a bounded-output-memory service or durable raw-output +archive. Source authentication and historical mathematical qualifications remain. diff --git a/tests/test_remainder_rate_workflow.py b/tests/test_remainder_rate_workflow.py new file mode 100644 index 000000000..dd06207cb --- /dev/null +++ b/tests/test_remainder_rate_workflow.py @@ -0,0 +1,221 @@ +"""Complete-shell regression fixtures; synthetic protocols, not theorem proofs.""" +import copy +import hashlib +import json +import os +from pathlib import Path +import shutil +import subprocess +import sys +import tempfile +import unittest + +ROOT = Path(__file__).resolve().parents[1] +PACKET = 'frontiers/remainder_rate_20260930' +WORKFLOW = ROOT / '.github/workflows/remainder-rate.yml' +HELPER = ROOT / 'tools/remainder_rate_replay.py' +STAGES = ('baseline', 'M1', 'M2', 'M3', 'M4', 'M9') +# Independently measured native reports, not imported from the production helper. +BASELINE = {'checks': {'E1_exponent_ledger': {'info': {'grid_points': 208, 'relative_exponents': {'v1': '1/2', 'v1.1': '7/12'}, 'twelfth_power_points': 4, 'v1': {'rate': '1/6', 'theta': '1/6'}, 'v1.1': {'rate': '1/4', 'theta': '1/12'}}, 'passed': True}, 'E2_barrier_arithmetic': {'info': {'barrier_cases': 48, 'solved_form_points': 4}, 'passed': True}, 'E3_soft_eigenvalue_determinant': {'info': {'matrices': 5, 'sizes': [2, 3, 4]}, 'passed': True}, 'E4_integrals_and_cutoff_ledger': {'info': {'cutoff_ledger_points': 3, 'integral_points': 3, 'window_integral_points': 3}, 'passed': True}, 'E5_sign_window': {'info': {'exact_equality_cases': 0, 'near_boundary_case': True, 'same_sign_instances': 13858, 'typed_instances': 15962}, 'passed': True}}, 'mutant': None, 'object': 'CL-D2-REMAINDER-RATE-20260930-v1.1', 'passed': True, 'scientific_effect': 'NONE'} +MUTATIONS = {'M1': ('E1_exponent_ledger', {'info': 'v1.1 ledger minimum at theta = 1/12 is 1/4, not the claimed rate 1/3', 'passed': False}), 'M2': ('E2_barrier_arithmetic', {'info': 'cubic term not dominated at t = 3/25 (lambda 1/5, K 3)', 'passed': False}), 'M3': ('E3_soft_eigenvalue_determinant', {'info': "det <= lambda_min lambda_max^(d-1) fails (spectrum ['1/100', '2'])", 'passed': False}), 'M4': ('E5_sign_window', {'info': '|det K_i| bound fails at (Fraction(0, 1), Fraction(-2, 1), Fraction(-3, 1), Fraction(1, 3), Fraction(-2, 5), Fraction(1, 10))', 'passed': False})} +REPORTS = {'baseline': BASELINE} +for name, (check, value) in MUTATIONS.items(): + report = copy.deepcopy(BASELINE) + report['mutant'] = name + report['passed'] = False + report['checks'][check] = value + REPORTS[name] = report + + +def replay_shell(text): + marker = ' - name: Verify sources, replay both modes, reject mutants\n' + if text.count(marker) != 1: + raise ValueError('exactly one original replay step required') + tail = text.split(marker, 1)[1].split(' run: |\n', 1)[1] + lines = [] + for line in tail.splitlines(): + if line and not line.startswith(' '): + break + lines.append(line[10:] if line else '') + if not lines or lines[0] != 'set -euo pipefail': + raise ValueError('strict shell missing') + return '\n'.join(lines) + '\n' + + +def identity(path, data): + return {'path': path, 'bytes': len(data), 'sha256': hashlib.sha256(data).hexdigest(), + 'git_blob': hashlib.sha1(b'blob %d\0' % len(data) + data).hexdigest()} + + +def checker_source(): + # This child never imports production validation or learns its own oracle. + return 'import json, os, sys\nfrom pathlib import Path\nreports = ' + repr(REPORTS) + r''' +a = sys.argv[1:] +name = 'baseline' if not a else a[1] if len(a) == 2 and a[0] == '--mutant' else 'BAD' +if name not in ('baseline', 'M1', 'M2', 'M3', 'M4', 'M9'): + raise RuntimeError('unexpected command inventory') +mode = sys.flags.optimize +with open(os.environ['REMAINDER_TRACE'], 'a') as f: + f.write(json.dumps([mode, name])+'\n') +code = 0 if name == 'baseline' else 2 if name == 'M9' else 1 +out = b'' if name == 'M9' else (json.dumps(reports[name], indent=1, sort_keys=True)+'\n').encode() +err = b'unknown mutant label\n' if name == 'M9' else b'' +if os.environ['REMAINDER_CASE'] == 'dirty': + Path(os.environ['REMAINDER_RESULTS']).write_text('changed after preflight\n') +if name == os.environ['REMAINDER_STAGE'] and mode == int(os.environ['REMAINDER_MODE']): + case = os.environ['REMAINDER_CASE'] + if case == 'crash': raise RuntimeError('unrelated synthetic crash') + if case == 'silent': out = b''; err = b'' + elif case == 'garbage': out = b'not the intended report\n' + elif case == 'stderr': err += b'unrelated stderr\n' + elif case == 'wrong-exit': code = 0 if name != 'baseline' else 1 + elif case == 'signal': os.kill(os.getpid(), 15) + elif case == 'unknown-wrong': err = b'an unrelated error\n' + elif case == 'unknown-extra': out = b'not empty\n' + elif case == 'unknown-prefix': err = b'prefix unknown mutant label\n' + elif case == 'formatted': out = (' \n'+json.dumps(reports[name], indent=3)+' \n').encode() + elif name != 'M9': + row = reports[name] + if case == 'wrong-reason': + for v in row['checks'].values(): + if v['passed'] is False: v['info'] = 'unrelated reason' + elif case == 'wrong-mutant': row['mutant'] = 'M4' if name != 'M4' else 'M1' + elif case == 'integer-bool': row['passed'] = int(row['passed']) + elif case == 'nested-bool': row['checks']['E4_integrals_and_cutoff_ledger']['passed'] = 1 + elif case == 'nested-float': row['checks']['E4_integrals_and_cutoff_ledger']['info']['integral_points'] = 3.0 + elif case == 'wrong-positive-info': row['checks']['E4_integrals_and_cutoff_ledger']['info']['integral_points'] = 4 + elif case == 'missing': del row['checks']['E4_integrals_and_cutoff_ledger'] + elif case == 'extra': row['checks']['extra'] = {'passed': True} + elif case == 'wrong-object': row['object'] = 'UNRELATED' + elif case == 'array': row = [row] + out = (json.dumps(row, indent=1, sort_keys=True)+'\n').encode() + if case == 'duplicate': out = out.rstrip()[:-1] + b',"passed":false}\n' + elif case == 'nonfinite': out = out.replace(b'15962', b'NaN') + elif case == 'trailing': out += b'{}\n' + elif case == 'bad-utf8': out = b'\xff'+out +sys.stdout.buffer.write(out);sys.stderr.buffer.write(err);sys.exit(code) +''' + + +class RemainderWorkflowTests(unittest.TestCase): + def run_case(self, case='valid', stage='baseline', mode=0, guard=None): + with tempfile.TemporaryDirectory(prefix='remainder-fixture-') as tmp: + home = Path(tmp); repo = home/'repo'; repo.mkdir() + packet = repo/PACKET; packet.mkdir(parents=True) + trace = home/'calls.jsonl' + (packet/'rate_ledger_check.py').write_text(checker_source()) + (packet/'RESULTS.json').write_text(json.dumps(BASELINE, indent=1, sort_keys=True)+'\n') + records = {} + for name in ('consumed', 'cited_only', 'consumed_unmerged'): + data = ('synthetic pinned '+name+'\n').encode() + (repo/(name+'.txt')).write_bytes(data) + records[name] = [identity(name+'.txt',data)] + records.update(files=[identity(x.name,x.read_bytes()) for x in sorted(packet.iterdir())], + mutants=['M1','M2','M3','M4']) + (packet/'SOURCES.json').write_text(json.dumps(records)) + if HELPER.exists(): + (repo/'tools').mkdir();shutil.copyfile(HELPER,repo/'tools'/HELPER.name) + env = {k:v for k,v in os.environ.items() if not k.startswith('GIT_')} + env.update(HOME=str(home),GIT_CONFIG_NOSYSTEM='1',GIT_CONFIG_GLOBAL=os.devnull, + GIT_AUTHOR_NAME='Fixture',GIT_AUTHOR_EMAIL='fixture@example.invalid', + GIT_COMMITTER_NAME='Fixture',GIT_COMMITTER_EMAIL='fixture@example.invalid', + PYTHONDONTWRITEBYTECODE='1',REMAINDER_TRACE=str(trace),REMAINDER_CASE=case, + REMAINDER_STAGE=stage,REMAINDER_MODE=str(mode),REMAINDER_RESULTS=str(packet/'RESULTS.json')) + env['PATH']=str(Path(sys.executable).parent)+os.pathsep+env.get('PATH','') + for args in (['init','-q'],['config','core.hooksPath',os.devnull], + ['config','commit.gpgsign','false'],['config','maintenance.auto','false'], + ['config','gc.auto','0'],['add','.'],['commit','-qm','synthetic controls']): + subprocess.run(['git',*args],cwd=repo,env=env,capture_output=True,check=True,timeout=15) + if guard == 'source': + with (packet/'rate_ledger_check.py').open('a') as f:f.write('\n# altered source\n') + elif guard in ('consumed','cited_only','consumed_unmerged'): + (repo/(guard+'.txt')).write_bytes(b'changed pin\n') + elif guard == 'extra': (packet/'extra.txt').write_bytes(b'extra') + elif guard == 'missing': (packet/'RESULTS.json').unlink() + elif guard == 'symlink': + shutil.copyfile(packet/'RESULTS.json',home/'target');(packet/'RESULTS.json').unlink() + (packet/'RESULTS.json').symlink_to(home/'target') + elif guard == 'mutant-inventory': + records['mutants']=['M1','M2','M3'];(packet/'SOURCES.json').write_text(json.dumps(records)) + subprocess.run(['git','add','.'],cwd=repo,env=env,check=True,capture_output=True,timeout=15) + subprocess.run(['git','commit','-qm','coherent inventory variant'],cwd=repo,env=env,check=True,capture_output=True,timeout=15) + result=subprocess.run(['bash','--noprofile','--norc','-c',replay_shell(WORKFLOW.read_text())], + cwd=repo,env=env,capture_output=True,timeout=20) + calls=[json.loads(x) for x in trace.read_text().splitlines()] if trace.exists() else [] + if saved:=os.environ.get('REMAINDER_SAVE'): + dest=Path(saved)/(case+'-'+stage+'-'+str(mode)+'-'+str(guard));dest.mkdir(parents=True,exist_ok=True) + (dest/'stdout').write_bytes(result.stdout);(dest/'stderr').write_bytes(result.stderr) + (dest/'record.json').write_text(json.dumps({'case':case,'stage':stage,'mode':mode, + 'guard':guard,'returncode':result.returncode,'calls':calls},sort_keys=True)+'\n') + return result,calls + + def reject_at(self, case, stage, mode): + result,calls=self.run_case(case,stage,mode) + order=[[m,s] for m in (0,1) for s in STAGES] + end=order.index([mode,stage])+1 + self.assertIn([mode,stage],calls,'intended stage not reached') + self.assertNotEqual(result.returncode,0,'invalid admission: '+repr((case,stage,mode))) + self.assertEqual(calls,order[:end],'rejection must stop at the intended stage') + + def test_valid_full_inventory(self): + result,calls=self.run_case() + self.assertEqual(result.returncode,0,result.stderr.decode(errors='replace')) + self.assertEqual(calls,[[m,s] for m in (0,1) for s in STAGES]) + + def test_each_mutant_reason_crash_and_silence(self): + for case in ('wrong-reason','crash','silent','stderr','garbage','wrong-mutant'): + for mode in (0,1): + for stage in STAGES[1:5]: + with self.subTest(case=case,mode=mode,stage=stage):self.reject_at(case,stage,mode) + + def test_complete_nested_json_contract(self): + for case in ('integer-bool','nested-bool','nested-float','wrong-positive-info', + 'missing','extra','wrong-object','array','duplicate','nonfinite','trailing','bad-utf8'): + for mode in (0,1): + with self.subTest(case=case,mode=mode):self.reject_at(case,'M1',mode) + + def test_baseline_exact_bytes_exit_and_stderr(self): + for case in ('silent','garbage','stderr','wrong-exit','formatted'): + for mode in (0,1): + with self.subTest(case=case,mode=mode):self.reject_at(case,'baseline',mode) + + def test_unknown_label_exact_contract(self): + for case in ('silent','unknown-wrong','unknown-extra','unknown-prefix','wrong-exit','signal'): + for mode in (0,1): + with self.subTest(case=case,mode=mode):self.reject_at(case,'M9',mode) + + def test_mutant_formatting_and_wrong_exits(self): + for mode in (0,1): + for stage in STAGES[1:5]: + with self.subTest(mode=mode,stage=stage): + result,calls=self.run_case('formatted',stage,mode) + self.assertEqual(result.returncode,0,result.stderr.decode(errors='replace')) + self.assertEqual(calls,[[m,s]for m in (0,1)for s in STAGES]) + self.reject_at('wrong-exit',stage,mode) + + def test_guards_stop_before_replay(self): + for guard in ('source','consumed','cited_only','consumed_unmerged','extra','missing','symlink'): + with self.subTest(guard=guard): + result,calls=self.run_case(guard=guard) + self.assertNotEqual(result.returncode,0);self.assertEqual(calls,[]) + + def test_full_mutant_inventory_required(self): + result,calls=self.run_case(guard='mutant-inventory') + self.assertNotEqual(result.returncode,0);self.assertEqual(calls,[]) + + def test_tracked_mutation_fails_postflight(self): + result,calls=self.run_case('dirty') + self.assertNotEqual(result.returncode,0) + self.assertEqual(calls,[[m,s]for m in (0,1)for s in STAGES]) + self.assertIn(b'changed after preflight',result.stdout) + + def test_regression_is_wired_in_both_modes(self): + text=WORKFLOW.read_text() + for path in ('tools/remainder_rate_replay.py','tests/test_remainder_rate_workflow.py'): + self.assertIn("- '"+path+"'",text) + for flags in ('-B -S','-B -O -S'): + self.assertIn('python '+flags+' -m unittest discover -s tests -p test_remainder_rate_workflow.py -v',text) + + +if __name__ == '__main__': + unittest.main() diff --git a/tools/remainder_rate_replay.py b/tools/remainder_rate_replay.py new file mode 100644 index 000000000..dddc5acdb --- /dev/null +++ b/tools/remainder_rate_replay.py @@ -0,0 +1,102 @@ +"""Source-bound output protocol for the unchanged remainder-rate finite controls. + +The caller authenticates the full packet, consumed/cited inputs and the pinned +unmerged dependency first. Fixed report values were measured from checker blob +3293ca22ab89bd650f361832c62b03724a976f03; no running child supplies its own oracle. +This is engineering validation, not a proof of the accompanying rate theorem. +""" +import copy +import hashlib +import json +from pathlib import Path +import subprocess +import sys + +BASELINE = {'checks': {'E1_exponent_ledger': {'info': {'grid_points': 208, 'relative_exponents': {'v1': '1/2', 'v1.1': '7/12'}, 'twelfth_power_points': 4, 'v1': {'rate': '1/6', 'theta': '1/6'}, 'v1.1': {'rate': '1/4', 'theta': '1/12'}}, 'passed': True}, 'E2_barrier_arithmetic': {'info': {'barrier_cases': 48, 'solved_form_points': 4}, 'passed': True}, 'E3_soft_eigenvalue_determinant': {'info': {'matrices': 5, 'sizes': [2, 3, 4]}, 'passed': True}, 'E4_integrals_and_cutoff_ledger': {'info': {'cutoff_ledger_points': 3, 'integral_points': 3, 'window_integral_points': 3}, 'passed': True}, 'E5_sign_window': {'info': {'exact_equality_cases': 0, 'near_boundary_case': True, 'same_sign_instances': 13858, 'typed_instances': 15962}, 'passed': True}}, 'mutant': None, 'object': 'CL-D2-REMAINDER-RATE-20260930-v1.1', 'passed': True, 'scientific_effect': 'NONE'} +# Only these observed check records change; every other nested field stays fixed. +MUTATIONS = {'M1': ('E1_exponent_ledger', {'info': 'v1.1 ledger minimum at theta = 1/12 is 1/4, not the claimed rate 1/3', 'passed': False}), 'M2': ('E2_barrier_arithmetic', {'info': 'cubic term not dominated at t = 3/25 (lambda 1/5, K 3)', 'passed': False}), 'M3': ('E3_soft_eigenvalue_determinant', {'info': "det <= lambda_min lambda_max^(d-1) fails (spectrum ['1/100', '2'])", 'passed': False}), 'M4': ('E5_sign_window', {'info': '|det K_i| bound fails at (Fraction(0, 1), Fraction(-2, 1), Fraction(-3, 1), Fraction(1, 3), Fraction(-2, 5), Fraction(1, 10))', 'passed': False})} +MUTANTS = ('M1', 'M2', 'M3', 'M4') + + +class ProtocolError(RuntimeError): + """A completed invocation did not satisfy its complete fixed contract.""" + + +def unique_object(pairs): + result = {} + for key, value in pairs: + if key in result: + raise ValueError('duplicate JSON key: ' + key) + result[key] = value + return result + + +def reject_float(value): + raise ValueError('floating or nonfinite JSON value: ' + value) + + +def typed_equal(actual, expected): + """Recursive equality without Boolean/integer or integer/float coercion.""" + if type(actual) is not type(expected): + return False + if type(expected) is dict: + return actual.keys() == expected.keys() and all( + typed_equal(actual[key], value) for key, value in expected.items()) + if type(expected) is list: + return len(actual) == len(expected) and all( + typed_equal(a, b) for a, b in zip(actual, expected)) + return actual == expected + + +def verify_report(result, label, baseline_bytes): + if label not in ('baseline', *MUTANTS, 'M9'): + raise ValueError('unknown protocol stage') + expected_exit = 0 if label == 'baseline' else 2 if label == 'M9' else 1 + if type(result.returncode) is not int or result.returncode != expected_exit: + raise ProtocolError(label + ': unexpected exit ' + repr(result.returncode)) + if type(result.stdout) is not bytes or type(result.stderr) is not bytes: + raise ProtocolError(label + ': both binary streams must be captured') + if label == 'M9': + if result.stdout != b'' or result.stderr != b'unknown mutant label\n': + raise ProtocolError('M9: unknown-label diagnostic differs') + return + if result.stderr != b'': + raise ProtocolError(label + ': unexpected stderr') + if label == 'baseline' and result.stdout != baseline_bytes: + raise ProtocolError('baseline: output differs from frozen RESULTS.json bytes') + try: + report = json.loads(result.stdout.decode('utf-8'), object_pairs_hook=unique_object, + parse_float=reject_float, parse_constant=reject_float) + except (ValueError, UnicodeError, RecursionError) as exc: + raise ProtocolError(label + ': invalid complete UTF-8/JSON report') from exc + expected = copy.deepcopy(BASELINE) + if label != 'baseline': + check, value = MUTATIONS[label] + expected['mutant'] = label + expected['passed'] = False + expected['checks'][check] = value + if not typed_equal(report, expected): + raise ProtocolError(label + ': complete typed report differs from fixed contract') + + +def replay(root, mutants): + """Run exactly twelve original invocations, preserving the 600-second budget. + + Launch and timeout exceptions propagate unchanged and stop subsequent work. + Children inherit the caller's working directory, as in the original workflow. + """ + if type(mutants) is not list or mutants != list(MUTANTS): + raise ProtocolError('full ordered M1-M4 inventory required') + root = Path(root).resolve() + expected = (root / 'RESULTS.json').read_bytes() + script = str(root / 'rate_ledger_check.py') + for flags in (['-B', '-S'], ['-B', '-O', '-S']): + for label in ('baseline', *MUTANTS, 'M9'): + args = [] if label == 'baseline' else ['--mutant', label] + result = subprocess.run([sys.executable, *flags, script, *args], + capture_output=True, timeout=600) + verify_report(result, label, expected) + print(json.dumps({'flags': flags, 'stage': label, 'returncode': result.returncode, + 'stdout_sha256': hashlib.sha256(result.stdout).hexdigest(), + 'stderr_sha256': hashlib.sha256(result.stderr).hexdigest(), + 'scientific_effect': 'NONE'}, sort_keys=True), flush=True)