From ef473788e6b22f17603f8dfceff16107c94037b6 Mon Sep 17 00:00:00 2001 From: Alexander Schwartzman Date: Tue, 13 Oct 2026 03:18:42 -0400 Subject: [PATCH 1/2] research: improve conditional kappa with two rank-seven helper ends --- research/complex-rank7-end-pair/NOTICE.md | 36 ++ research/complex-rank7-end-pair/PROOF.md | 85 ++++ research/complex-rank7-end-pair/README.md | 85 ++++ research/complex-rank7-end-pair/SEARCH.json | 84 ++++ research/complex-rank7-end-pair/SOURCES.json | 28 ++ .../complex-rank7-end-pair/audit_points.py | 223 ++++++++++ .../complex-rank7-end-pair/build_owners.py | 387 ++++++++++++++++++ research/complex-rank7-end-pair/build_word.py | 68 +++ .../code/admit_candidate.py | 178 ++++++++ .../code/prepare_candidate.py | 239 +++++++++++ .../code/replay_native.py | 184 +++++++++ .../data/END-RECIPE.json | 28 ++ .../complex-rank7-end-pair/data/EXPECTED.json | 42 ++ .../data/OWNER-FLOW.json.gz | Bin 0 -> 5262 bytes .../complex-rank7-end-pair/end_controls.py | 150 +++++++ .../evidence/ASSEMBLY.json.gz | Bin 0 -> 17898 bytes .../evidence/END-CONTROLS.json | 312 ++++++++++++++ .../evidence/POINT-AUDIT.json | 69 ++++ .../evidence/VALIDATION.json | 130 ++++++ research/complex-rank7-end-pair/reproduce.py | 201 +++++++++ 20 files changed, 2529 insertions(+) create mode 100644 research/complex-rank7-end-pair/NOTICE.md create mode 100644 research/complex-rank7-end-pair/PROOF.md create mode 100644 research/complex-rank7-end-pair/README.md create mode 100644 research/complex-rank7-end-pair/SEARCH.json create mode 100644 research/complex-rank7-end-pair/SOURCES.json create mode 100644 research/complex-rank7-end-pair/audit_points.py create mode 100644 research/complex-rank7-end-pair/build_owners.py create mode 100644 research/complex-rank7-end-pair/build_word.py create mode 100644 research/complex-rank7-end-pair/code/admit_candidate.py create mode 100644 research/complex-rank7-end-pair/code/prepare_candidate.py create mode 100644 research/complex-rank7-end-pair/code/replay_native.py create mode 100644 research/complex-rank7-end-pair/data/END-RECIPE.json create mode 100644 research/complex-rank7-end-pair/data/EXPECTED.json create mode 100644 research/complex-rank7-end-pair/data/OWNER-FLOW.json.gz create mode 100644 research/complex-rank7-end-pair/end_controls.py create mode 100644 research/complex-rank7-end-pair/evidence/ASSEMBLY.json.gz create mode 100644 research/complex-rank7-end-pair/evidence/END-CONTROLS.json create mode 100644 research/complex-rank7-end-pair/evidence/POINT-AUDIT.json create mode 100644 research/complex-rank7-end-pair/evidence/VALIDATION.json create mode 100644 research/complex-rank7-end-pair/reproduce.py diff --git a/research/complex-rank7-end-pair/NOTICE.md b/research/complex-rank7-end-pair/NOTICE.md new file mode 100644 index 0000000000..d4ef3c20a7 --- /dev/null +++ b/research/complex-rank7-end-pair/NOTICE.md @@ -0,0 +1,36 @@ +# Attribution and scope + +New contribution by Alexander Schwartzman (`AlexS-scale`), prepared with +substantial OpenAI Codex assistance, including delegated research and review. +The new code and research artifacts use the repository's Apache-2.0 license. +No independent human peer review or full formal proof is claimed. + +This contribution changes two helper ends in the retained PR799 construction +and supplies a new physical owner assignment. It builds on Jeremy Kothe's +(`jeremykothe2`) PR799 X4 assembly and its credited JointXF read exchanges, +Chafik Boukhalfa's (`chafreaky`) PR741 frame coalescences and PR685 ownership +work, icekylinx's Gauge44 construction, and the retained PR635 cold-end and +residual-wrapper machinery. BlockInvert's entrance promotions, G44Pack's +packing work, and the other predecessor layers retain their original credit. +The new end recipe uses the existing cold-end principle; it does not claim +that principle as new. + +The source packages are fetched at exact commits, with their complete source +manifests, notices, and licenses preserved. PR777 by Tekalign (`tekuuu`) +provides the unchanged generic global runner, spec freezing, and independent +owner/moment checker. `code/prepare_candidate.py` adapts its data preparation +to fresh native widths and supplied owners. The mathematical admission +predicates come from the pinned PR799 package and its retained predecessors. + +The bit supplier is the cited PR589 record, including its PR555/eumemic +ancestry and DreamingOfClouds' transport. Douglas Colkitt's repository, +integration, and retained analytic framework are also prerequisites. This +notice supplements the original notices; it does not replace them. + +The investigation and submission branch start at +`66849e1475c930fd7732b1a0067ffee7e1e95f60`. The final development and validation +snapshot is `f567884aeb8851b6e794af1184119a3bfbe1e631`, recorded as +`base_commit` in `SOURCES.json`; it selects PR799's conditional result. +Only the new research package is submitted from the earlier branch base. +The replayed code, source pins, and data are unchanged. No source from PR784 +is used. diff --git a/research/complex-rank7-end-pair/PROOF.md b/research/complex-rank7-end-pair/PROOF.md new file mode 100644 index 0000000000..2fdeda52a5 --- /dev/null +++ b/research/complex-rank7-end-pair/PROOF.md @@ -0,0 +1,85 @@ +# The end pair and its complete cost + +All indices below refer to PR799's pinned raw word. The recipe records both +the old and new value at every changed position and checks the complete input +and output content hashes. + +For both helper registers 588 and 589, replace the old dimension-eight end +with the subspace + +``` +U = span_GF(2) {256, 128, 96, 17, 9, 5, 3}. +``` + +The integers encode vectors in GF(2)^9. The seven generators are independent, +so U has 128 points. In the exact scalar prefix, inverse row 588 is +`e588 - e412`, and inverse row 589 is `e589 - e414`. Each of the two helper +dirt columns has only its diagonal entry. For each helper, the required +end-of-B frames from its inverse row span precisely U. Thus U contains the +complete inverse-row and dirt-column cones required by the retained residual +wrapper contract. + +The new end requires eight B-frame changes, at zero-based positions +1018, 1019, 1050, 1051, 1130, 1131, 1162, and 1163. The two early-cleanup +frames at entries 140 and 141 also become U. No scalar gate changes. The +independent point audit checks containment for every adjacent frame, every +source and target boundary, the center interface, all paid jumps, and the +unchanged scalar program. The unchanged native auditors independently derive +the scalar prefix and check both end cones and both complete orientations. + +There are eight paid changes from rank 3 to rank 2, ten from rank 1 to rank 2, +and four from rank 2 to rank 1. Therefore the local profile change is exactly + +``` +ΔH_local = {1:-6, 2:+14, 3:-8}. +``` + +Both helpers have empty entrances. Each end reduction releases one coordinate, +so the helper width becomes 3776 per call. The width inventory is +`{4:80, 5:32, 7:56, 8:120, 9:216}`. Keeping the predecessor owner assignment +would increase the complete cost. The new assignment is an essential part of +the construction. + +The frozen flow lists width patterns and call counts for the 144 existing +physical windows, each with 112 ports. For a pattern used N times, each width +slot receives N items and each call supplies at most N items. Split the width +counts between those slots and add dummy slots to obtain an N-regular +bipartite multigraph. Repeated perfect matchings give N colors. Each color is +one physical bin with the stated width pattern and at most one item from any +call. Dummy slots do not create helper roles. + +`build_owners.py` performs this integer construction deterministically. It +then checks the literal assignment separately: all 36,288 call/helper pairs +occur exactly once; families are distinct within each call; every role uses +a valid window; and the coordinate intervals are disjoint and fit the stated +capacity. The retained global auditor independently reconstructs the physical +windows and checks the final assignment against the native helper widths. +The complete unused-space profile is exactly `{48:2400}`. + +Across all 72 calls, the global profile change from PR799 is + +``` +ΔH_global = {1:-433, 2:+1008, 3:-577, 44:-1, 48:+4}. +``` + +The rank mass does not change: +`-433 + 2*1008 - 3*577 - 44 + 4*48 = 0`. +The resulting mass is 520704, retaining the deficit 2560 and the same physical +geometry. At PR799's certified complex endpoint, the raw moment decreases by +approximately `0.11903590824390181`. That decimal is a diagnostic; admission +uses the two retained rational interval engines. + +The native complex recurrence is accepted at +`b = 832238996031084233427 / 500000000000000000000000` +and rejected at `b + 10^-24`. The complete bit profile retains its bad-residue +surcharge. Both moment engines and all 47 outer inequalities certify + +``` +κ = 1661712108827881 / 1000000000000000000. +``` + +The scalar program and its finite envelopes retain their source predicates. +The new frames, wrapper ranks, local profile, owner map, global profile, +moments, and outer witness are freshly admitted. This establishes a finite +conditional improvement under the predecessor interfaces, with the scope +stated in `README.md`. diff --git a/research/complex-rank7-end-pair/README.md b/research/complex-rank7-end-pair/README.md new file mode 100644 index 0000000000..a4b04232c5 --- /dev/null +++ b/research/complex-rank7-end-pair/README.md @@ -0,0 +1,85 @@ +# Two rank-seven helper ends: conditional κ = 0.001661712108827881 + +This construction increases PR799's conditional κ from +`0.001661634653669567` to **`0.001661712108827881`**. The exact increase is +`38727579157 / 500000000000000000`, approximately **0.00466138%** of the +preceding κ. This compares asymptotic exponent savings, not measured runtime. + +The change has two parts. Helpers 588 and 589 finish in dimension seven instead +of eight. Eight B frames and two early-cleanup frames change with those ends. +An explicit new owner assignment then combines the released space into +rank-48 residuals. All raw scalar gates, their order, the ports, the center +interface, and the 72-call schedule retain their PR799 values. + +| Quantity | PR799 | This construction | +| --- | ---: | ---: | +| Local rank-one children | 2548 | 2542 | +| Local rank-two children | 338 | 352 | +| Local rank-three children | 430 | 422 | +| Local rank-four / five / eight children | 194 / 56 / 8 | 194 / 56 / 8 | +| Helper width per call | 3778 | 3776 | +| Global idle profile | `{1:1, 3:1, 44:1, 48:2396}` | `{48:2400}` | + +The complete global profile is +`{1:183024, 2:25344, 3:30384, 4:13968, 5:4032, 8:576, 48:2400}`. +Its rank mass is 520704. The certified complex endpoint is +`0.001664477992062168466854`; the retained PR589 bit endpoint is +`0.001733427039589844234749`. The complex supplier remains the limiting one. +The conservative complex calculation separately gives +`κ = 0.001661712105945928`. + +From the repository root, use Python 3.11 or newer and Git: + +```sh +python3 -B research/complex-rank7-end-pair/reproduce.py --work /tmp/rank7-end-pair +``` + +Use a new output directory. The command fetches the three exact source commits +in `SOURCES.json` into that directory. It rebuilds the PR741 ancestry and PR799 +word, applies the twelve changed annotations, rebuilds the owner assignment, +and runs complete native and global admission. No optimizer or Python package +installation is required. If a local repository already contains the pinned +commits, add `--git-repository /absolute/path/to/repository` to use its objects +without fetching. Source files are extracted into the output directory in +either case. + +Expected final output: + +```text +PASS_COLD_RANK7_END_PAIR_COMPLETE_ADMISSION 0.001661712108827881 +``` + +The required checks include every 728-input column in both orientations, +all 2,950 phase edges, exact residual wrappers, 25 native controls, and the +89 applicable inherited cold-end controls. Dedicated controls cover the new +dimension-seven ends and their frame changes. The independent point audit +uses explicit subsets of the 512-point frame space. Owner checks cover all +36,288 roles, complete availability windows, distinct families per call, +capacity, and disjoint compact coordinate prefixes. Discovery is followed by +frozen strict admission, 69 admission controls, 12 bit-supplier controls, +seven independent owner controls, and both exact moment engines with all 47 +outer inequalities. `data/EXPECTED.json` pins the resulting word, programs, +phase recipes, owner map, profile, and κ. + +A complete cold run on Python 3.14.7 and macOS arm64 passed in 685 seconds. +`evidence/VALIDATION.json` records its environment, coverage, and input hashes. + +`evidence/ASSEMBLY.json.gz` preserves the unchanged assembler's complete +output. Its historical descriptions and comparison labels refer to its +predecessors. The profile, moment endpoints, κ, and outer inequalities are +the computed results for this candidate. + +`PROOF.md` explains the end frames, the packing certificate, and the complete +cost change. `SEARCH.json` records how the finite search found this candidate. +Search optimality is not needed to verify the construction. + +This is a finite conditional witness for +`T(n) = O(n (log n)^(1-kappa))`. The inherited all-size compiler, +common-label and mutable-source realization, whole-call hosting, precision, +tape, exact-recovery, analytic-transfer, and bit H1–H5 assumptions remain. +The command reprices the pinned PR589 bit supplier; it does not repeat its +bit-circuit construction. Finite replay does not prove the full multiplication +theorem. The selected certificate is outside this contribution's scope. + +The contribution is independent of PR784. See `NOTICE.md` for predecessor +credit, licensing, and the disclosure of AI assistance. diff --git a/research/complex-rank7-end-pair/SEARCH.json b/research/complex-rank7-end-pair/SEARCH.json new file mode 100644 index 0000000000..70b3b11415 --- /dev/null +++ b/research/complex-rank7-end-pair/SEARCH.json @@ -0,0 +1,84 @@ +{ + "scope": "Discovery of one finite construction; no universal or global optimality claim.", + "research_seed": 143265410407226848, + "winning_frame_search": { + "source_pr": 799, + "source_commit": "80e6463157cfc80b85af09e7e2f14748fe2dac60", + "domain": "20 groups of existing dimension-eight helper ends with dimension-seven lower spaces under fixed scalar code and interfaces. Exact subspace refitting of B and early-cleanup frames.", + "completed_groups": 20, + "selected_group": 17, + "selected_helpers": [ + 588, + 589 + ], + "solver_seed": 73, + "stopping_rule": "Select a legal word with positive complete packing headroom, obtain a literal owner map, and require unchanged full native and global admission.", + "minimalization": "Retain only the eight B frames, two tail frames, and two ends necessary for the verified profile.", + "screen_only": "Local cost and aggregate packing screens are not admitted kappa witnesses." + }, + "packing_search": { + "date": "2026-10-13", + "status": "FROZEN_FEASIBLE_INTEGER_FLOW_NOT_A_GENERAL_OPTIMALITY_CLAIM", + "source_pr": 799, + "source_commit": "80e6463157cfc80b85af09e7e2f14748fe2dac60", + "owner_lineage": "chafreaky PR685, reused by PR741 and adapted by G44Pack for PR799", + "command": "pattern_flow.py --plan source-799/research/gauge44-frames-x/data/PLAN.json --owners source-799/research/gauge44-frames-x/data/OWNERS.json.gz --word exact-search/end-deepen-17-0.word.json.gz --out order-search/packing/end17-free4 --free-legacy --distance 4 --seconds 60 --workers 2", + "random_seed": 73, + "distance": 4, + "free_legacy": true, + "workers": 2, + "time_limit_seconds": 60, + "objective": "feasibility; all nonempty physical bins are full", + "solver": "OR-Tools CP-SAT", + "solver_version": "9.15.6755", + "python_version": "3.12.12", + "solver_receipt": { + "status": "OPTIMAL", + "pattern_variables": 503, + "flow_variables": 25699, + "seconds": 58.33655075000206, + "input_word_sha256": "9f63de243f867e2c52212b18d2253059a3bc965db4a981ecf18b73d83969006c", + "fixed_partial_bins": [] + }, + "search_code_sha256": "88e905223d3691c00bef5e6873d6709273ab2bdf7b2142797448ebab6a390730", + "search_word_content_sha256": "9f63de243f867e2c52212b18d2253059a3bc965db4a981ecf18b73d83969006c", + "final_minimal_word_content_sha256": "796a40505ed9dc38d64c5b7856a0908e70bd9f22cd869edf01ebe66ac02ab15a", + "rebinding": "The final word removes unrelated frame rechoices. Its helper widths and local profile are identical. The frozen flow and literal owners are unchanged.", + "original_flow_content_sha256": "7ff3e4c2bbe9e0beb2592888de7db962fd34971a025be841c8f1711b5139f8f1", + "owner_content_sha256": "02bde66a90b8ae9b0c4d8d563ca2218ad1de851fa6dec3d1abb5d3a30ca3dd2a", + "global_profile": { + "1": 183024, + "2": 25344, + "3": 30384, + "4": 13968, + "5": 4032, + "8": 576, + "48": 2400 + }, + "idle_profile": { + "48": 2400 + }, + "rank_mass": 520704, + "deficit": 2560, + "search_moment_delta_at_baseline_b": "-0.119035908243901811918210669949724217035275333404321692154", + "required_admission": "unchanged native local and strict global replay plus independent exact repricing" + }, + "earlier_searches": [ + { + "domain": "Both pinned words, fixed scalar order and fixed entrance/end interfaces; full induced GF(2)^9 subspace intervals in 140 components.", + "result": "No lower profile found. Integer-rounded moment objectives do not prove a universal real-objective optimum." + }, + { + "domain": "Legal local commuting reorders and exact adjacent shear rewrites with correction gates.", + "result": "No improved candidate passed the cost screen; these searches are not impossibility results." + }, + { + "domain": "Six E4-to-E5 entrance promotions, independently verified natively, plus uniform and small mixed owner inventories.", + "result": "Local savings did not overcome global packing cost. The new end dimensions change the width inventory and escape that restriction." + } + ], + "final_raw_word_sha256": "796a40505ed9dc38d64c5b7856a0908e70bd9f22cd869edf01ebe66ac02ab15a", + "final_owner_sha256": "02bde66a90b8ae9b0c4d8d563ca2218ad1de851fa6dec3d1abb5d3a30ca3dd2a", + "admission_status": "PASS_STRICTLY_IMPROVED_KAPPA_UNCHANGED_ADMISSION", + "kappa": "1661712108827881/1000000000000000000" +} diff --git a/research/complex-rank7-end-pair/SOURCES.json b/research/complex-rank7-end-pair/SOURCES.json new file mode 100644 index 0000000000..3688f6c816 --- /dev/null +++ b/research/complex-rank7-end-pair/SOURCES.json @@ -0,0 +1,28 @@ +{ + "schema": "complex-rank7-end-pair-sources/1", + "base_commit": "f567884aeb8851b6e794af1184119a3bfbe1e631", + "sources": [ + { + "pr": 741, + "repository": "https://github.com/CrocSwap/integer-mult-bounds.git", + "commit": "e516b1463606840a15f80aac1995d64ce0092e89", + "path": "research/complex-sw4-frame8", + "manifest_sha256": "b9b39c206fcd2613382b0dcbda23a371e8781d1bedaf8e2f8e7df1e79dc1fa89" + }, + { + "pr": 799, + "repository": "https://github.com/CrocSwap/integer-mult-bounds.git", + "commit": "80e6463157cfc80b85af09e7e2f14748fe2dac60", + "path": "research/gauge44-frames-x", + "manifest_sha256": "e1b7998c8f7cb24f8674d250d0510f2b5b351b2ed0b35f17a17e6bacf3d9824b" + }, + { + "pr": 777, + "repository": "https://github.com/CrocSwap/integer-mult-bounds.git", + "commit": "eca5c317d8176401a1f71a5ea1e81384c2eab1e0", + "path": "research/pr699-frame-retiming", + "manifest_sha256": "e0102586186663b2a667768565f61db184638b370f68f0ea58dd673e523173ec" + } + ], + "research_start_commit": "66849e1475c930fd7732b1a0067ffee7e1e95f60" +} diff --git a/research/complex-rank7-end-pair/audit_points.py b/research/complex-rank7-end-pair/audit_points.py new file mode 100644 index 0000000000..181f210f08 --- /dev/null +++ b/research/complex-rank7-end-pair/audit_points.py @@ -0,0 +1,223 @@ +"""Independent frame accounting by explicit subsets of the 512-point space. + +No builder, solver, native auditor, or Gaussian elimination is imported. +Scalar identities, row/column cones, phases, and global admission are separate. +Prepared with OpenAI Codex assistance. Apache-2.0. +""" +import argparse +from collections import Counter +import copy +from functools import lru_cache +import gzip +import hashlib +import json +from pathlib import Path + + +BASE_SHA = '1e1d99ba7aab877d6b573c41f7030ee73de9a52fee51d0a822ddaae71251999f' +WORD_SHA = '796a40505ed9dc38d64c5b7856a0908e70bd9f22cd869edf01ebe66ac02ab15a' +RECIPE = Path(__file__).resolve().parent / 'data/END-RECIPE.json' + + +class Reject(ValueError): + pass + + +def require(condition, message): + if not condition: + raise Reject(message) + + +def canonical(value): + return json.dumps(value, sort_keys=True, separators=(',', ':')).encode() + + +def read(path): + raw = gzip.decompress(path.read_bytes()) + return json.loads(raw), hashlib.sha256(raw).hexdigest() + + +@lru_cache(None) +def points(vectors): + space = {0} + for vector in vectors: + require(type(vector) is int and 0 <= vector < 512, 'invalid GF2 vector') + space |= {value ^ vector for value in space} + require(len(space) == 1 << len(vectors), 'dependent frame basis') + return frozenset(space) + + +def dimension(space): + return len(space).bit_length() - 1 + + +def registers(event): + require(event[0] in ('add', 'scale'), 'unknown gate') + result = event[1:3] if event[0] == 'add' else event[1:2] + require(all(type(q) is int and 0 <= q < 728 for q in result), 'register range') + return result + + +def recount(word): + require(tuple(word['report'][k] for k in ('v', 'h', 'R')) == (112, 9, 504), 'dimensions') + require(len(word['ports']) == len(set(word['ports'])) == 112, 'ports') + full, zero = frozenset(range(512)), points(()) + start = [points((p,)) for p in word['ports']] + [zero] * 616 + for q, frame in word['start_extra'].items(): + require(224 <= int(q) < 728, 'start register') + start[int(q)] = points(tuple(frame)) + current, paid = start.copy(), Counter() + + def climb(q, target): + require(current[q] <= target, 'nonmonotone frame') + degree = dimension(target) - dimension(current[q]) + if degree: + paid[degree] += 1 + current[q] = target + + for section in ('A', 'B'): + if section == 'B': + levels = {int(q): points(tuple(frame)) for q, frame in word['target_levels'].items()} + require(all(current[112 + q] == levels.get(q, zero) for q in range(112)), 'target interface') + require(len(word['centers']) == len(word['center_frames']) == 8, 'center count') + for q, frame in zip(word['centers'], word['center_frames']): + frame = points(tuple(frame)) + require(current[q] == frame, 'center interface') + served = {levels.get(event[1] - 112, zero) for event in word['cut'] if event[2] == q} + for target in sorted(served, key=len, reverse=True): + require(target <= frame, 'center descent') + degree = dimension(frame) - dimension(target) + if degree: + paid[degree] += 1 + frame = target + for event in word[section]: + frame = points(tuple(event[-1])) + for q in registers(event): + climb(q, frame) + seen = set() + for index, frame in word['early_cleanup']: + require(type(index) is int and 0 <= index < len(word['cleanup']), 'tail index') + require(index not in seen, 'duplicate tail') + seen.add(index) + for q in registers(word['cleanup'][index]): + climb(q, points(tuple(frame))) + end = ([full] * 112 + + [frozenset(x for x in range(512) if (x & p).bit_count() % 2 == 0) for p in word['ports']] + + [full] * 504) + for q, frame in word['helper_final'].items(): + require(224 <= int(q) < 728, 'end register') + end[int(q)] = points(tuple(frame)) + for q, frame in enumerate(end): + climb(q, frame) + for index, event in enumerate(word['cleanup']): + if index not in seen: + require(all(end[q] == full for q in registers(event)), 'full cleanup reads a low end') + profile = {str(k): count for k, count in sorted(paid.items())} + require(canonical(profile) == canonical(word['report']['local_profile']), 'paid profile') + mass = sum(rank * count for rank, count in paid.items()) + require(type(word['report']['local_rank_mass']) is int and word['report']['local_rank_mass'] == mass, 'rank mass') + widths = [dimension(end[q]) - dimension(start[q]) for q in range(224, 728)] + require(all(0 < width <= 9 for width in widths), 'helper width range') + inventory = {str(k): count for k, count in sorted(Counter(widths).items())} + require(canonical(inventory) == canonical(word['report']['width_inventory']), 'width inventory') + return paid, widths + + +def check_edits(baseline, candidate, recipe): + require(recipe['input_sha256'] == BASE_SHA and recipe['expected']['output_sha256'] == WORD_SHA, 'recipe pins') + restored = copy.deepcopy(candidate) + require([q for q, _, _ in recipe['ends']] == [588, 589], 'end sites') + require([i for i, _, _ in recipe['B_frames']] == + [1018, 1019, 1050, 1051, 1130, 1131, 1162, 1163], 'B-frame sites') + require([i for i, _, _, _ in recipe['early_cleanup']] == [140, 141], 'tail sites') + changes = [] + for q, old, new in recipe['ends']: + require(baseline['helper_final'][str(q)] == old and candidate['helper_final'][str(q)] == new, 'literal end edit') + restored['helper_final'][str(q)] = old + changes.append((old, new)) + for index, old, new in recipe['B_frames']: + require(baseline['B'][index][-1] == old and candidate['B'][index][-1] == new, 'literal B edit') + restored['B'][index][-1] = old + changes.append((old, new)) + for index, cleanup_index, old, new in recipe['early_cleanup']: + require(baseline['early_cleanup'][index] == [cleanup_index, old] and + candidate['early_cleanup'][index] == [cleanup_index, new], 'literal tail edit') + restored['early_cleanup'][index] = [cleanup_index, old] + changes.append((old, new)) + for old, new in changes: + a, b = points(tuple(old)), points(tuple(new)) + require(b < a and len(a) == 2 * len(b), 'codimension-one frame reduction') + for key in ('local_profile', 'local_rank_mass', 'width_inventory'): + require(canonical(candidate['report'][key]) == canonical(recipe['expected'][key]), 'reported recipe result') + restored['report'][key] = baseline['report'][key] + require(canonical(restored) == canonical(baseline), 'changes outside the twelve annotations and accounting') + + +def controls(candidate, recipe): + cases = [] + mutant = copy.deepcopy(candidate) + mutant['report']['local_profile']['1'] += 2 + mutant['report']['local_profile']['2'] -= 1 + cases.append(('mass-preserving false profile', mutant, 'paid profile')) + mutant = copy.deepcopy(candidate) + mutant['report']['local_profile']['1'] = float(mutant['report']['local_profile']['1']) + cases.append(('floating profile count', mutant, 'paid profile')) + mutant = copy.deepcopy(candidate) + mutant['report']['width_inventory']['7'] -= 1 + mutant['report']['width_inventory']['8'] += 1 + cases.append(('false helper widths', mutant, 'width inventory')) + mutant = copy.deepcopy(candidate) + mutant['report']['local_rank_mass'] += 1 + cases.append(('false rank mass', mutant, 'rank mass')) + mutant = copy.deepcopy(candidate) + index, old, _ = recipe['B_frames'][0] + mutant['B'][index][-1] = old + cases.append(('omitted required B lowering', mutant, 'nonmonotone frame')) + result = [] + for name, mutant, expected in cases: + try: + recount(mutant) + except Reject as error: + require(str(error) == expected, 'unexpected point-control rejection: ' + name) + result.append(dict(name=name, rejected=expected)) + else: + raise Reject('accepted point control: ' + name) + return result + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--baseline', type=Path, required=True) + parser.add_argument('--word', type=Path, required=True) + parser.add_argument('--recipe', type=Path, default=RECIPE) + parser.add_argument('--output', type=Path, required=True) + args = parser.parse_args() + baseline, before_sha = read(args.baseline) + candidate, after_sha = read(args.word) + require((before_sha, after_sha) == (BASE_SHA, WORD_SHA), 'input content pins') + recipe = json.loads(args.recipe.read_text(encoding='utf-8')) + check_edits(baseline, candidate, recipe) + before, old_widths = recount(baseline) + after, widths = recount(candidate) + delta = {r: after[r] - before[r] for r in before.keys() | after.keys() if before[r] != after[r]} + require(delta == {1: -6, 2: 14, 3: -8}, 'profile delta') + changes = [dict(helper=q + 224, before=a, after=b) for q, (a, b) in enumerate(zip(old_widths, widths)) if a != b] + require(changes == [dict(helper=588, before=8, after=7), dict(helper=589, before=8, after=7)], 'individual helper widths') + report = dict(status='PASS_EXPLICIT_512_POINT_END_PAIR_ACCOUNTING', + input_sha256=before_sha, output_sha256=after_sha, + changed_annotations=dict(helper_final=2, B=8, early_cleanup=2), + local_profile=dict(sorted(after.items())), delta=delta, + rank_mass_before=sum(r * n for r, n in before.items()), + rank_mass_after=sum(r * n for r, n in after.items()), + width_inventory=dict(sorted(Counter(widths).items())), + width_sum_before=sum(old_widths), width_sum_after=sum(widths), + changed_helper_widths=changes, rejected_controls=controls(candidate, recipe), + scope='Literal source, target, center, gate, tail, and end frames; paid profile; individual helper widths; ' + 'exact twelve-annotation recipe. Scalar identities, cones, phases, owners, and kappa are separate.') + args.output.parent.mkdir(parents=True, exist_ok=True) + args.output.write_text(json.dumps(report, indent=2) + '\n', encoding='utf-8') + print(report['status'], '12 annotations; 5 rejected controls', flush=True) + + +if __name__ == '__main__': + main() diff --git a/research/complex-rank7-end-pair/build_owners.py b/research/complex-rank7-end-pair/build_owners.py new file mode 100644 index 0000000000..887d444d70 --- /dev/null +++ b/research/complex-rank7-end-pair/build_owners.py @@ -0,0 +1,387 @@ +#!/usr/bin/env python3 +"""Reproduce and check the frozen rank-seven whole-owner map. + +The whole-owner interface and source schedule are inherited from the +#685/#741/#799 lineage. No optimizer runs during this reproduction. +""" +import argparse +from collections import Counter, defaultdict, deque +import copy +import gzip +import hashlib +import json +from pathlib import Path + + +def raw(path): + data = Path(path).read_bytes() + return gzip.decompress(data) if str(path).endswith('.gz') else data + + +def read(path): + return json.loads(raw(path)) + + +def schedule_geometry(parent, order, ports): + capacities = {} + child_ports = defaultdict(set) + for row in parent['idle_children']: + child, port, rank = row['child'], row['port'], row['rank'] + assert row['replicas'] == 8 and 0 <= port < ports + assert port not in child_ports[child] + child_ports[child].add(port) + assert capacities.get(child, rank) == rank + capacities[child] = rank + assert all(ps == set(range(ports)) for ps in child_ports.values()) + blocks, source_ids, globals_ = {}, [], [] + stage = None + for index, event in enumerate(parent['execution_schedule']): + if event['kind'] in ('bank_padding_cover_sweep', 'translate_every_live_family'): + globals_.append(index) + continue + if event['kind'] == 'local_cover_sweep': + stage = event['stage'] + assert stage not in blocks + blocks[stage] = [] + assert stage is not None + blocks[stage].append((index, event)) + source_ids.append(index) + assert globals_ == [30, 31] and source_ids == list(range(30)) + stage_pairs = {e['stage']: e['pair'] for e in parent['recipe'] if e['kind'] == 'local'} + projections = defaultdict(list) + last, windows, pairs, sides, calls = {}, {}, {}, {}, {} + position = 0 + for time, (stage, replica) in enumerate(order): + for index, event in blocks[stage]: + projections[replica].append(index) + if event['kind'] == 'local_cover_sweep': + calls[time] = position + last[replica, stage_pairs[stage]] = position + elif event['kind'] == 'bridge': + last[replica, event['src']] = position + last[replica, event['dst']] = position + elif event['kind'] == 'idle_cover_sweep': + for side, child in enumerate(event['child_indices']): + if child not in capacities: + continue + assert (replica, child) not in windows + pair = event['pair'] + assert pairs.get(child, pair) == pair + assert sides.get(child, side) == side + pairs[child], sides[child] = pair, side + windows[replica, child] = (last.get((replica, pair), -1), position) + position += 1 + assert set(projections) == set(range(8)) + assert all(indices == source_ids for indices in projections.values()) + assert set(windows) == {(replica, child) for replica in range(8) for child in capacities} + result = { + f'{replica},{child}': [capacities[child], [t for t in range(72) if left < calls[t] < right]] + for (replica, child), (left, right) in windows.items() + } + return result, pairs, sides + + +def audit(flow, owners, plan, word, parent, word_hash): + ports, helpers = word['report']['v'], word['report']['R'] + assert (ports, helpers) == (112, 504) + order = [tuple(call) for call in plan['order']] + assert len(order) == 72 and set(order) == {(stage, replica) for stage in range(9) for replica in range(8)} + geometry = {key: plan[key] for key in ('order', 'windows', 'pairs', 'sides')} + assert digest(geometry) == flow['geometry_sha256'] + if parent is None: + windows = plan['windows'] + pairs = {int(child): pair for child, pair in plan['pairs'].items()} + sides = {int(child): side for child, side in plan['sides'].items()} + else: + windows, pairs, sides = schedule_geometry(parent, order, ports) + assert plan['windows'] == windows + assert plan['pairs'] == {str(child): pair for child, pair in pairs.items()} + assert plan['sides'] == {str(child): side for child, side in sides.items()} + widths = [ + len(word['helper_final'].get(str(2 * ports + h), range(9))) + - len(word['start_extra'].get(str(2 * ports + h), [])) + for h in range(helpers) + ] + assert flow['input_word_sha256'] == word_hash + assert flow['helper_widths'] == widths and all(1 <= w <= 9 for w in widths) + active_data = { + (call['stage'], call['replica']): {family for family, route in call['owners'][:2 * ports]} + for call in parent['calls'] + } if parent is not None else None + seen, families, bins = set(), defaultdict(set), defaultdict(list) + assert len(owners) == 72 * helpers + fields = {'child', 'copy', 'family', 'helper', 'offset', 'owner_replica', 'port', 'replica', 'stage', 'time', 'width'} + for row in owners: + assert set(row) == fields and all(type(value) is int for value in row.values()) + stage, replica, helper = row['stage'], row['replica'], row['helper'] + role, time = (stage, replica, helper), row['time'] + assert 0 <= helper < helpers and 0 <= time < 72 and order[time] == (stage, replica) + assert role not in seen + seen.add(role) + owner, child, port = row['owner_replica'], row['child'], row['port'] + assert 0 <= owner < 8 and 0 <= port < ports + cap, times = windows[f'{owner},{child}'] + assert time in times and row['copy'] == owner * ports + port + family = owner * 8 * ports + (2 * pairs[child] + sides[child]) * ports + port + assert row['family'] == family and family not in families[time] + if active_data is not None: + assert family not in active_data[stage, replica] + families[time].add(family) + width, offset = row['width'], row['offset'] + assert width == widths[helper] and 0 <= offset and offset + width <= cap + bins[owner, child, port].append((offset, time, width)) + assert seen == {(stage, replica, h) for stage, replica in order for h in range(helpers)} + slots, idle = {}, Counter() + for key, (cap, times) in windows.items(): + owner, child = map(int, key.split(',')) + for port in range(ports): + key3, offset = (owner, child, port), 0 + slot = [] + for actual_offset, time, width in sorted(bins[key3]): + assert actual_offset == offset + offset += width + slot.append((time, width)) + assert offset <= cap + slots[key3] = sorted(slot) + if cap > offset: + idle[cap - offset] += 1 + assert flow['fixed_partial_bins'] == [] + assert len(flow['windows']) == len(windows) + assert {window['key'] for window in flow['windows']} == set(windows) + pattern_count = 0 + for window in flow['windows']: + owner, child = map(int, window['key'].split(',')) + cap, times = windows[window['key']] + used = 0 + for pattern in window['patterns']: + count = pattern['count'] + assert type(count) is int and 0 < count <= ports - used + expected_widths = Counter(pattern['widths']) + assert all(type(w) is int and 1 <= w <= 9 for w in pattern['widths']) + assert sum(pattern['widths']) <= cap + declared = {} + for time, width, amount in pattern['flows']: + assert all(type(value) is int for value in (time, width, amount)) + assert time in times and width in expected_widths and 0 < amount <= count + assert (time, width) not in declared + declared[time, width] = amount + actual = Counter() + for port in range(used, used + count): + slot = slots[owner, child, port] + assert Counter(width for time, width in slot) == expected_widths + assert len({time for time, width in slot}) == len(slot) + actual.update(slot) + assert actual == Counter(declared) + assert all(sum(n for (t, w), n in declared.items() if t == time) <= count for time in times) + used += count + pattern_count += 1 + assert used == ports + profile = Counter({int(rank): 72 * count for rank, count in word['report']['local_profile'].items()}) + profile.update(idle) + mass = sum(rank * count for rank, count in profile.items()) + assert mass == 520704 and 73 * 7168 - mass == 2560 + assert idle == Counter({48: 2400}) + assert dict(profile) == {int(rank): count for rank, count in flow['global_profile'].items()} + return { + 'status': 'PASS_LITERAL_PATTERN_FLOW_AND_ALL_36288_OWNERS', + 'source_windows_reconstructed': parent is not None, + 'roles': len(owners), 'physical_bins': len(slots), 'window_count': len(windows), + 'patterns': pattern_count, 'rank_mass': mass, 'deficit': 2560, + 'helper_width_inventory': dict(sorted(Counter(widths).items())), + 'idle_profile': dict(sorted(idle.items())), 'global_profile': dict(sorted(profile.items())), + } + + +def controls(flow, owners, plan, word, parent, word_hash): + def wrong_flow(candidate): + pattern = next(p for w in candidate[0]['windows'] for p in w['patterns'] if p['flows']) + pattern['flows'][0][2] += 1 + + def wrong_count(candidate): + next(p for w in candidate[0]['windows'] for p in w['patterns'])['count'] += 1 + + def outside_window(candidate): + row = candidate[1][0] + times = candidate[2]['windows'][f"{row['owner_replica']},{row['child']}"][1] + time = next(t for t in range(72) if t not in times) + row['time'] = time + row['stage'], row['replica'] = candidate[2]['order'][time] + + mutations = { + 'call outside owner window': outside_window, + 'duplicate helper role': lambda c: c[1].__setitem__(-1, copy.deepcopy(c[1][0])), + 'wrong native residual width': lambda c: c[1][0].__setitem__('width', c[1][0]['width'] + 1), + 'noncompact prefix': lambda c: c[1][0].__setitem__('offset', c[1][0]['offset'] + 1), + 'wrong physical family': lambda c: c[1][0].__setitem__('family', c[1][0]['family'] + 1), + 'wrong source window capacity': lambda c: next(iter(c[2]['windows'].values())).__setitem__(0, 49), + 'wrong flow multiplicity': wrong_flow, + 'wrong pattern multiplicity': wrong_count, + } + rejected = [] + for name, mutate in mutations.items(): + candidate = [copy.deepcopy(flow), copy.deepcopy(owners), copy.deepcopy(plan)] + mutate(candidate) + try: + audit(*candidate, word, parent, word_hash) + except (AssertionError, KeyError): + rejected.append(name) + else: + raise AssertionError(f'accepted negative control: {name}') + return rejected + + + +def slots_from_flow(pattern): + count, widths = pattern['count'], pattern['widths'] + sockets = len(widths) + if not sockets: + assert not pattern['flows'] + return [[] for _ in range(count)] + flows = {(time, width): n for time, width, n in pattern['flows']} + assert len(flows) == len(pattern['flows']) + times = sorted({time for time, width in flows}) + assert len(times) >= sockets + assert all(sum(n for (t, w), n in flows.items() if t == time) <= count for time in times) + size = len(times) + time_index = {time: index for index, time in enumerate(times)} + edges = [[0] * size for _ in range(size)] + for width in sorted(set(widths)): + available = deque((time, n) for (time, w), n in sorted(flows.items()) if w == width) + for socket, socket_width in enumerate(widths): + if socket_width != width: + continue + left = count + while left: + time, n = available.popleft() + amount = min(left, n) + edges[socket][time_index[time]] += amount + left -= amount + if n > amount: + available.appendleft((time, n - amount)) + assert not available + + # Equal degrees allow one perfect matching for each physical bin. + deficits = deque() + for time in range(size): + missing = count - sum(edges[socket][time] for socket in range(sockets)) + if missing: + deficits.append((time, missing)) + for socket in range(sockets, size): + left = count + while left: + time, n = deficits.popleft() + amount = min(left, n) + edges[socket][time] += amount + left -= amount + if n > amount: + deficits.appendleft((time, n - amount)) + assert not deficits + assert all(sum(row) == count for row in edges) + assert all(sum(edges[i][j] for i in range(size)) == count for j in range(size)) + slots = [] + for _ in range(count): + matched = [-1] * size + + def augment(socket, seen): + for time, multiplicity in enumerate(edges[socket]): + if not multiplicity or time in seen: + continue + seen.add(time) + if matched[time] < 0 or augment(matched[time], seen): + matched[time] = socket + return True + return False + + complete = all(augment(socket, set()) for socket in range(size)) + assert complete, 'regular bipartite graph has no perfect matching' + slot = [] + for time, socket in enumerate(matched): + assert socket >= 0 and edges[socket][time] > 0 + edges[socket][time] -= 1 + if socket < sockets: + slot.append([times[time], widths[socket]]) + slot.sort() + assert len(slot) == sockets and len({time for time, width in slot}) == sockets + slots.append(slot) + assert not any(any(row) for row in edges) + actual = Counter((time, width) for slot in slots for time, width in slot) + assert actual == Counter(flows) + return slots + +def canonical(value): + return json.dumps(value, sort_keys=True, separators=(',', ':')).encode() + + +def digest(value): + return hashlib.sha256(canonical(value)).hexdigest() + + +def expand(flow, plan): + widths = flow['helper_widths'] + pools = defaultdict(deque) + for time in range(72): + for helper, width in enumerate(widths): + pools[time, width].append(helper) + assert flow['fixed_partial_bins'] == [] + owners = [] + + def emit(owner, child, port, slot): + family = owner * 896 + (2 * plan['pairs'][str(child)] + plan['sides'][str(child)]) * 112 + port + offset = 0 + for time, width in sorted(slot): + helper = pools[time, width].popleft() + stage, replica = plan['order'][time] + owners.append(dict(child=child, copy=owner * 112 + port, family=family, + helper=helper, offset=offset, owner_replica=owner, port=port, + replica=replica, stage=stage, time=time, width=width)) + offset += width + + for window in flow['windows']: + owner, child = map(int, window['key'].split(',')) + ports = deque(range(112)) + for pattern in window['patterns']: + for slot in slots_from_flow(pattern): + emit(owner, child, ports.popleft(), slot) + assert not ports + assert not any(pools.values()) + return sorted(owners, key=lambda row: (row['time'], row['helper'])) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--word', type=Path, required=True) + parser.add_argument('--plan', type=Path, required=True) + parser.add_argument('--out', type=Path, required=True) + parser.add_argument('--source-template', type=Path) + args = parser.parse_args() + flow_path = Path(__file__).resolve().parent / 'data' / 'OWNER-FLOW.json.gz' + flow, word, plan = map(read, (flow_path, args.word, args.plan)) + parent = read(args.source_template) if args.source_template else None + word_hash = hashlib.sha256(raw(args.word)).hexdigest() + assert word_hash == '796a40505ed9dc38d64c5b7856a0908e70bd9f22cd869edf01ebe66ac02ab15a' + assert flow['schema'] == 'frozen-rank7-owner-flow/1' + owners = expand(flow, plan) + report = audit(flow, owners, plan, word, parent, word_hash) + payload = canonical(owners) + owner_hash = hashlib.sha256(payload).hexdigest() + assert owner_hash == '02bde66a90b8ae9b0c4d8d563ca2218ad1de851fa6dec3d1abb5d3a30ca3dd2a' + assert owner_hash == flow['owner_content_sha256'] + report['rejected_controls'] = controls(flow, owners, plan, word, parent, word_hash) + report['input_content_sha256'] = { + 'flow': hashlib.sha256(raw(flow_path)).hexdigest(), + 'word': word_hash, 'plan': hashlib.sha256(raw(args.plan)).hexdigest(), + } + if args.source_template: + report['input_content_sha256']['source_template'] = hashlib.sha256(raw(args.source_template)).hexdigest() + report['owner_content_sha256'] = owner_hash + report['geometry_sha256'] = flow['geometry_sha256'] + args.out.mkdir(parents=True, exist_ok=True) + with (args.out / 'OWNERS.json.gz').open('wb') as stream: + with gzip.GzipFile(filename='', mode='wb', fileobj=stream, mtime=0) as archive: + archive.write(payload) + (args.out / 'OWNER-CERTIFICATE.json').write_text(json.dumps(report, indent=2) + '\n') + print(json.dumps(report, indent=2)) + + +if __name__ == '__main__': + main() diff --git a/research/complex-rank7-end-pair/build_word.py b/research/complex-rank7-end-pair/build_word.py new file mode 100644 index 0000000000..c7e10bd6d7 --- /dev/null +++ b/research/complex-rank7-end-pair/build_word.py @@ -0,0 +1,68 @@ +"""Apply the pinned twelve-frame recipe to the retained PR799 word. + +Prepared with OpenAI Codex assistance. Apache-2.0. +""" +import argparse +import gzip +import hashlib +import json +from pathlib import Path + + +BASE_SHA = '1e1d99ba7aab877d6b573c41f7030ee73de9a52fee51d0a822ddaae71251999f' +WORD_SHA = '796a40505ed9dc38d64c5b7856a0908e70bd9f22cd869edf01ebe66ac02ab15a' +RECIPE = Path(__file__).resolve().parent / 'data/END-RECIPE.json' + + +def require(condition, message): + if not condition: + raise ValueError(message) + + +def build(source, recipe): + raw = gzip.decompress(source.read_bytes()) + require(hashlib.sha256(raw).hexdigest() == recipe['input_sha256'] == BASE_SHA, + 'baseline content pin') + require(recipe['schema'] == 1, 'recipe schema') + word = json.loads(raw) + require([q for q, _, _ in recipe['ends']] == [588, 589], 'end sites') + require([i for i, _, _ in recipe['B_frames']] == + [1018, 1019, 1050, 1051, 1130, 1131, 1162, 1163], 'B-frame sites') + require([i for i, _, _, _ in recipe['early_cleanup']] == [140, 141], 'tail sites') + for q, old, new in recipe['ends']: + require(word['helper_final'][str(q)] == old, 'old helper end') + word['helper_final'][str(q)] = new + for index, old, new in recipe['B_frames']: + require(word['B'][index][-1] == old, 'old B frame') + word['B'][index][-1] = new + for index, cleanup_index, old, new in recipe['early_cleanup']: + require(word['early_cleanup'][index] == [cleanup_index, old], 'old tail frame') + word['early_cleanup'][index][1] = new + for key in ('local_profile', 'local_rank_mass', 'width_inventory'): + word['report'][key] = recipe['expected'][key] + result = json.dumps(word, sort_keys=True, separators=(',', ':')).encode() + require(hashlib.sha256(result).hexdigest() == recipe['expected']['output_sha256'] == WORD_SHA, + 'constructed word content pin') + return result + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--input', type=Path, required=True) + parser.add_argument('--recipe', type=Path, default=RECIPE) + parser.add_argument('--output', type=Path, required=True) + args = parser.parse_args() + recipe = json.loads(args.recipe.read_text(encoding='utf-8')) + raw = build(args.input, recipe) + compressed = gzip.compress(raw, compresslevel=9, mtime=0) + # Python versions differ in the gzip OS header byte. + compressed = compressed[:9] + b'\xff' + compressed[10:] + args.output.parent.mkdir(parents=True, exist_ok=True) + args.output.write_bytes(compressed) + print(json.dumps(dict(status='PASS_PINNED_TWELVE_FRAME_CONSTRUCTION', + content_sha256=WORD_SHA, compressed_sha256=hashlib.sha256(compressed).hexdigest(), + changed_annotations=12)), flush=True) + + +if __name__ == '__main__': + main() diff --git a/research/complex-rank7-end-pair/code/admit_candidate.py b/research/complex-rank7-end-pair/code/admit_candidate.py new file mode 100644 index 0000000000..7cc802cce0 --- /dev/null +++ b/research/complex-rank7-end-pair/code/admit_candidate.py @@ -0,0 +1,178 @@ +"""Admit a fresh native candidate with unchanged predecessor predicates. + +The prior full ancestor replay is reused only after its receipt is verified. +No source package is copied or edited; only candidate data are prepared. +""" +import argparse +from fractions import Fraction +import hashlib +import json +import os +from pathlib import Path +import subprocess +import sys +import time +from prepare_candidate import add_native_arguments, selected_dispatch, selected_native_directories + + +HERE = Path(__file__).resolve().parent + + +def read(path): + return json.loads(path.read_text()) + + +def sha(path): + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def dump(path, value): + path.write_text(json.dumps(value, indent=2) + '\n') + + +def need(value, message): + if not value: + raise ValueError(message) + + +def verify_manifest(package): + actual = {p.relative_to(package).as_posix(): sha(p) for p in package.rglob('*') + if p.is_file() and p != package / 'MANIFEST.json' and '__pycache__' not in p.parts} + need(actual == read(package / 'MANIFEST.json'), 'Changed source package: ' + str(package)) + + +def verify_receipt(directory): + receipt = read(directory / 'RECEIPT.json') + for name, expected in receipt['artifacts'].items(): + need(sha(directory / name) == expected, 'Changed replay artifact: ' + str(directory / name)) + return receipt + + +def main(): + ap = argparse.ArgumentParser(description=__doc__) + for name in ('ancestor-package', 'ancestor-replay', 'dependency', 'checker-package', 'out'): + ap.add_argument('--' + name, type=Path, required=True) + add_native_arguments(ap) + ap.add_argument('--owners', type=Path, help='Specified gzipped owner rows for the fresh native widths') + args = ap.parse_args() + ancestor, replay, dep, checker, out = [getattr(args, name).resolve() for name in + ('ancestor_package', 'ancestor_replay', 'dependency', 'checker_package', 'out')] + natives = selected_native_directories(args) + dispatch = selected_dispatch(args, natives) + need(__debug__, 'Assertions must remain enabled') + need(not out.exists(), 'Use a new output directory') + need(not any(out.is_relative_to(p) for p in (ancestor, replay, dep, checker, *natives.values())), + 'Output must be separate from input artifacts and source packages') + for package in (ancestor, dep, checker): + verify_manifest(package) + ancestor_receipt = verify_receipt(replay) + need(ancestor_receipt['manifest_sha256'] == sha(ancestor / 'MANIFEST.json'), 'Ancestor source binding') + need(read(replay / 'RESULT.json')['status'] == + 'PASS_FRESH_SW4_EIGHT_FRAMES_COMPLETE_NATIVE_OWNER_AND_EXACT_GLOBAL_REPLAY', 'Full ancestor replay required') + need(read(replay / 'ANCESTRAL-LINK.json')['status'] == + 'PASS_FRESH_ANCESTRAL_INPUTS_MATCH_PINNED_BASELINE', 'Fresh ancestor semantic linkage required') + need((ancestor / 'data/UPSTREAM-PINS.json').read_bytes() == (dep / 'data/UPSTREAM-PINS.json').read_bytes(), + 'Global ancestry differs from the replayed predecessor') + for native in natives.values(): + verify_receipt(native) + need(read(native / 'RESULT.json')['status'] == 'PASS_COMPLETE_NATIVE_REPLAY_UNCHANGED_CHECKERS', + 'Fresh native pipeline required') + for key, package in (('ancestor_manifest', ancestor), ('dependency_manifest', dep)): + need(read(native / 'RESULT.json')['input_sha256'][key] == sha(package / 'MANIFEST.json'), 'Native source binding') + out.mkdir(parents=True) + root = ancestor / 'vendor/main' + env = dict(os.environ, PYTHONDONTWRITEBYTECODE='1', PYTHONUTF8='1', PYTHONINTMAXSTRDIGITS='0') + for key in ('PYTHONOPTIMIZE', 'WITNESS_SPEC', 'WITNESS_DISCOVER', 'WITNESS_RECORD'): + env.pop(key, None) + stages = [] + started = time.monotonic() + dump(out / 'ANCESTRY-REUSE.json', {'status': 'PASS_HASH_VERIFIED_FRESH_ANCESTRY_REUSE', + 'ancestor_result_sha256': sha(replay / 'RESULT.json'), + 'ancestor_receipt_sha256': sha(replay / 'RECEIPT.json'), + 'ancestral_link_sha256': sha(replay / 'ANCESTRAL-LINK.json'), + 'upstream_pins_sha256': sha(dep / 'data/UPSTREAM-PINS.json'), + 'native_receipt_sha256': {pid: sha(n / 'RECEIPT.json') for pid, n in natives.items()}, + 'source_manifests': {str(p): sha(p / 'MANIFEST.json') for p in (ancestor, dep, checker)}, + 'scope': 'Unchanged ancestral circuits and literal geometry were freshly replayed once. The changed native word and full global admission are checked separately.'}) + + def run(name, script, *arguments): + print('RUN', name, flush=True) + cmd = [sys.executable, '-B', str(script), *map(str, arguments)] + log = out / (name + '.log') + before = time.monotonic() + with log.open('w') as stream: + result = subprocess.run(cmd, stdout=stream, stderr=subprocess.STDOUT, env=env) + stages.append({'name': name, 'command': cmd, 'script_sha256': sha(script), + 'exit_code': result.returncode, 'seconds': time.monotonic() - before, + 'log_sha256': sha(log)}) + dump(out / 'STAGES.json', stages) + if result.returncode: + raise RuntimeError(name + ' failed:\n' + log.read_text()[-8000:]) + print('PASS', name, flush=True) + + witness = out / 'witness' + owner_args = ['--owners', args.owners.resolve()] if args.owners else [] + if args.native: + native_args = ['--native', args.native.resolve()] + else: + frozen_dispatch = out / 'DISPATCH.json' + dump(frozen_dispatch, [[s, r, dispatch[s, r]] for s in range(9) for r in range(8)]) + native_args = [part for pid, path in sorted(natives.items()) + for part in ('--native-provider', pid + '=' + str(path))] + native_args += ['--dispatch', frozen_dispatch] + run('prepare-data', HERE / 'prepare_candidate.py', '--dependency', dep, *native_args, + '--out', witness, *owner_args) + plan, owners, spec = [witness / 'data' / name for name in ('PLAN.json', 'OWNERS.json.gz', 'SPEC.json')] + provider_args = [part for pid, path in sorted(natives.items()) + for part in ('--provider', pid + '=' + str(path / 'local'))] + global_args = ['--main', root, '--dependency', dep, '--plan', plan, '--owners', owners, + '--spec', spec, *provider_args] + run('discovery', checker / 'verify_global.py', *global_args, '--work', out / 'discovery', '--discover') + discovery_spec_sha = sha(spec) + run('freeze-spec', checker / 'freeze_spec.py', '--spec', spec, '--discovery', out / 'discovery') + frozen_spec_sha = sha(spec) + need(discovery_spec_sha != frozen_spec_sha, 'Discovery values must be frozen before strict replay') + run('strict-global', checker / 'verify_global.py', *global_args, '--work', out / 'global-replay') + run('independent-owner-moment', checker / 'audit_owners.py', '--dependency', dep, '--plan', plan, + '--owners', owners, '--spec', spec, *provider_args, + '--output', out / 'INDEPENDENT-OWNERS.json') + run('independent-two-engine-outer47', dep / 'independent/price_profile.py', '--main', root, + '--profile', plan, '--output', out / 'INDEPENDENT-PRICE.json') + need(sha(spec) == frozen_spec_sha, 'Frozen spec changed during strict verification') + assembly = read(out / 'global-replay/ASSEMBLY.json') + expected = read(spec)['expected'] + owner_audit = read(out / 'INDEPENDENT-OWNERS.json') + price = read(out / 'INDEPENDENT-PRICE.json') + kappa = expected['kappa'] + need(kappa == assembly['kappa'] == owner_audit['kappa'] == price['prices']['native']['outer_with_bit']['kappa'], + 'Independent kappa witnesses disagree') + baseline_kappa = read(dep / 'data/SPEC.json')['expected']['kappa'] + need(Fraction(kappa) > Fraction(baseline_kappa), 'A strictly improved kappa is required') + need(len(owner_audit['negative_controls']) == 7 and owner_audit['roles'] == 36288, 'Independent owner census') + for mode in ('native', 'conservative'): + need(price['prices'][mode]['outer_with_bit']['strict_constraints_passed'] == 47, 'All outer constraints') + admission = read(out / 'global-replay/ADMISSION-CONTROLS.json') + discovery_controls = read(out / 'discovery/ADMISSION-CONTROLS.json') + census = discovery_controls['rejected_controls'] + discovery_controls['discovery_accepted_controls'] + need(len(census) == len(set(census)) == expected['assembly_controls_rejected'] + and set(admission['rejected_controls']) == set(census) + and len(admission['rejected_controls']) == len(census) and not admission['discovery_accepted_controls'], + 'Strict admission mutation census') + bit = read(out / 'global-replay/BIT-SUPPLIER-CONTROLS.json') + need(len(bit['rejected_controls']) == 12 and bit['derived_deficit'] == 10272, 'Bit controls') + result = {'status': 'PASS_STRICTLY_IMPROVED_KAPPA_UNCHANGED_ADMISSION', 'kappa': kappa, + 'kappa_decimal': assembly['kappa_decimal'], 'baseline_kappa': baseline_kappa, + 'gain': str(Fraction(kappa) - Fraction(baseline_kappa)), 'complex_lower': assembly['complex_lower'], + 'bit_lower': assembly['bit_lower'], 'global_profile': assembly['complex_profile'], + 'seconds': time.monotonic() - started, 'stages': stages, + 'scope': 'Finite conditional native exact-complex witness. Hash-verified reuse of a fresh ancestral replay; full changed-native and global admission. Cited PR589 bit circuit is repriced with its surcharge and controls. All inherited all-size and analytic-transfer assumptions remain.'} + dump(out / 'RESULT.json', result) + retained = [p for p in out.rglob('*') if p.is_file() and p.name != 'RECEIPT.json'] + dump(out / 'RECEIPT.json', {'status': result['status'], + 'native_receipt_sha256': {pid: sha(n / 'RECEIPT.json') for pid, n in natives.items()}, + 'artifacts': {p.relative_to(out).as_posix(): sha(p) for p in retained}}) + print(result['status'], result['kappa_decimal'], flush=True) + + +if __name__ == '__main__': + main() diff --git a/research/complex-rank7-end-pair/code/prepare_candidate.py b/research/complex-rank7-end-pair/code/prepare_candidate.py new file mode 100644 index 0000000000..152ca5f5f8 --- /dev/null +++ b/research/complex-rank7-end-pair/code/prepare_candidate.py @@ -0,0 +1,239 @@ +"""Bind fresh native artifacts and specified owners to the fixed #799 geometry. + +Data preparation only; unchanged dependency checkers independently admit every +result. Adapted from PR777 prepare_plan.py, with OpenAI Codex assistance. +""" +import argparse +from collections import Counter, defaultdict +import copy +import gzip +import hashlib +import importlib.util +import json +from pathlib import Path +import re +import shutil + + +def read(path): + raw = path.read_bytes() + return json.loads(gzip.decompress(raw) if path.suffix == '.gz' else raw) + + +def sha(path): + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def dump(path, value): + path.write_text(json.dumps(value, indent=2) + '\n') + + +def need(value, message): + if not value: + raise ValueError(message) + + +def verify_manifest(package): + actual = {p.relative_to(package).as_posix(): sha(p) for p in package.rglob('*') + if p.is_file() and p != package / 'MANIFEST.json' and '__pycache__' not in p.parts} + need(actual == read(package / 'MANIFEST.json'), 'Dependency source manifest') + + +def add_native_arguments(parser): + selection = parser.add_mutually_exclusive_group(required=True) + selection.add_argument('--native', type=Path, help='One complete native replay, named gauge44') + selection.add_argument('--native-provider', action='append', metavar='PID=DIR', + help='Named complete native replay; repeat for mixed providers') + parser.add_argument('--dispatch', type=Path, help='JSON array of 72 [stage, replica, provider] rows') + + +def selected_native_directories(args): + if args.native is not None: + need(args.dispatch is None, 'Use named providers for explicit dispatch') + return {'gauge44': args.native.resolve()} + result = {} + for item in args.native_provider: + pid, separator, directory = item.partition('=') + need(separator and re.fullmatch(r'[a-z][a-z0-9_]*', pid) and pid not in result, + 'Unique simple provider names required') + result[pid] = Path(directory).resolve() + need(args.dispatch is not None, 'Explicit dispatch required for named providers') + return result + + +def selected_dispatch(args, providers): + rows = read(args.dispatch) if args.dispatch else [[s, r, 'gauge44'] for s in range(9) for r in range(8)] + need(type(rows) is list and len(rows) == 72, 'Exactly 72 dispatch rows required') + result = {} + for row in rows: + need(type(row) is list and len(row) == 3, 'Dispatch row shape') + stage, replica, pid = row + need(type(stage) is int and type(replica) is int and type(pid) is str + and 0 <= stage < 9 and 0 <= replica < 8 and pid in providers, 'Dispatch row domain') + need((stage, replica) not in result, 'Duplicate dispatch invocation') + result[stage, replica] = pid + need(set(result) == {(s, r) for s in range(9) for r in range(8)}, 'Complete dispatch invocation census') + need(set(result.values()) == set(providers), 'Every named provider must be used') + return result + + +def main(): + ap = argparse.ArgumentParser(description=__doc__) + for name in ('dependency', 'out'): + ap.add_argument('--' + name, type=Path, required=True) + add_native_arguments(ap) + ap.add_argument('--owners', type=Path, help='Explicit gzipped owner rows; defaults to the dependency map') + args = ap.parse_args() + dep, out = [getattr(args, name).resolve() for name in ('dependency', 'out')] + natives = selected_native_directories(args) + dispatch = selected_dispatch(args, natives) + owners_path = (args.owners or dep / 'data/OWNERS.json.gz').resolve() + need(owners_path.suffix == '.gz', 'Supply a gzipped JSON owner map') + owners_blob = owners_path.read_bytes() + owners_sha256 = hashlib.sha256(owners_blob).hexdigest() + need(not out.exists(), 'New output directory required') + need(not out.is_relative_to(dep) and not any(out.is_relative_to(n) for n in natives.values()), + 'Output must be separate') + verify_manifest(dep) + plan = read(dep / 'data/PLAN.json') + original = copy.deepcopy(plan) + need(set(original['provider_registry']) == {'gauge44'}, 'Pinned single-provider source geometry') + module_spec = importlib.util.spec_from_file_location('identity', dep / 'code/generated_identity.py') + identity = importlib.util.module_from_spec(module_spec) + module_spec.loader.exec_module(identity) + widths_by_provider, paid_by_provider = {}, {} + plan['provider_registry'] = {} + for pid, native in sorted(natives.items()): + result = read(native / 'RESULT.json') + need(result['status'] == 'PASS_COMPLETE_NATIVE_REPLAY_UNCHANGED_CHECKERS', 'Complete native replay required') + need(result['input_sha256']['dependency_manifest'] == sha(dep / 'MANIFEST.json'), 'Native dependency binding') + for relative, expected in read(native / 'RECEIPT.json')['artifacts'].items(): + need(sha(native / relative) == expected, 'Native output changed: ' + relative) + local = native / 'local' + canonical = read(local / 'CANONICAL-WORD.json.gz') + programs = read(local / 'LOCAL-PROGRAMS.json.gz') + checks = read(local / 'LOCAL-CHECKS.json') + need((canonical['v'], canonical['h'], canonical['R']) == (112, 9, 504), 'Unchanged native geometry') + desc = copy.deepcopy(original['provider_registry']['gauge44']) + widths = [len(canonical['frames'][canonical['final'][h]]) - len(canonical['frames'][canonical['start'][h]]) + for h in range(224, 728)] + need(canonical['ports'] == desc['ports'] and canonical['centers'] == desc['centers'], + 'Unchanged ports and centers') + need(len(widths) == 504 and all(type(w) is int and 0 < w <= 9 for w in widths), + 'Valid fresh native residual widths') + paid = Counter(event[-1] for event in programs['forward'] if event[0] in ('climb', 'center')) + need(paid == Counter(event[-1] for event in programs['backward'] if event[0] in ('climb', 'center')), + 'Both orientation profiles agree') + need(dict(paid) == {int(r): n for r, n in result['profile'].items()}, 'Independent native profile') + desc['artifact_semantic_sha256'] = identity.artifact_identities(local) + desc['artifact_sha256'] = {name: sha(local / name) for name in desc['artifact_sha256']} + desc['actual_paid_profile'] = dict(sorted(paid.items())) + desc['widths'] = widths + desc['orientation_program_sha256'] = {orientation: checks[orientation]['sha256'] for orientation in checks} + desc['directory'] = 'providers/' + pid + plan['provider_registry'][pid] = desc + widths_by_provider[pid], paid_by_provider[pid] = widths, paid + for call in plan['provider_calls']: + call['provider'] = dispatch[call['stage'], call['replica']] + call['local_program_sha256'] = plan['provider_registry'][call['provider']]['orientation_program_sha256'][call['orientation']] + need(len(plan['per_call_widths']) == 72, 'Complete per-call width inventory') + need({(c['stage'], c['replica']) for c in plan['per_call_widths']} == + {(s, r) for s in range(9) for r in range(8)}, 'Complete per-call width identities') + for call in plan['per_call_widths']: + call['widths'] = widths_by_provider[dispatch[call['stage'], call['replica']]].copy() + rows = json.loads(gzip.decompress(owners_blob)) + used = defaultdict(set) + helpers = defaultdict(set) + families = defaultdict(set) + calls = {call['time']: call for call in plan['provider_calls']} + need(set(calls) == set(range(72)), 'Complete invocation chronology') + stage_pair = {0: 0, 1: 0, 2: 0, 3: 1, 4: 1, 5: 2, 6: 2, 7: 3, 8: 3} + for row in rows: + need(all(type(row[k]) is int for k in ('time', 'helper', 'stage', 'replica', 'width', + 'owner_replica', 'child', 'port', 'offset', 'family', 'copy')), + 'Integer owner role fields') + time, helper = row['time'], row['helper'] + need(type(time) is int and time in calls and type(helper) is int and 0 <= helper < 504, + 'Owner role domain') + call = calls[time] + need((row['stage'], row['replica']) == (call['stage'], call['replica']) == tuple(plan['order'][time]), + 'Owner invocation identity') + need(row['width'] == widths_by_provider[call['provider']][helper], + 'Owner width equals the fresh native footprint') + replica, child, port, offset = [row[k] for k in ('owner_replica', 'child', 'port', 'offset')] + need(all(type(v) is int for v in (replica, child, port, offset)) + and 0 <= replica < 8 and 0 <= port < 112, 'Physical owner domain') + window_key = f'{replica},{child}' + need(window_key in plan['windows'], 'Known physical owner window') + capacity, times = plan['windows'][window_key] + need(time in times and 0 <= offset and offset + row['width'] <= capacity, + 'Owner footprint fits its invocation window') + pair, side = plan['pairs'][str(child)], plan['sides'][str(child)] + family = replica * 896 + (2 * pair + side) * 112 + port + need(row['family'] == family and row['copy'] == replica * 112 + port, 'Physical family identity') + need((replica, pair) != (row['replica'], stage_pair[row['stage']]), 'Owner does not alias active data') + need(helper not in helpers[time] and family not in families[time], 'Unique helper and family per invocation') + helpers[time].add(helper) + families[time].add(family) + key = replica, child, port + cells = set(range(row['offset'], row['offset'] + row['width'])) + need(not used[key] & cells, 'Nonoverlapping owned coordinates') + used[key].update(cells) + need(len(rows) == 36288 and all(helpers[t] == set(range(504)) for t in range(72)), + 'Every native helper has exactly one owner per invocation') + idle = Counter() + for key, (capacity, window) in plan['windows'].items(): + replica, child = map(int, key.split(',')) + for port in range(112): + occupied = used[replica, child, port] + need(occupied == set(range(len(occupied))) and len(occupied) <= capacity, 'Compacted owner prefix') + if len(occupied) < capacity: + idle[capacity - len(occupied)] += 1 + profile = Counter() + for call in calls.values(): + profile.update(paid_by_provider[call['provider']]) + profile.update(idle) + need(sum(rank * count for rank, count in profile.items()) == 520704, 'Global rank mass') + plan['profile'] = dict(sorted(profile.items())) + plan['assignment_sha256'] = owners_sha256 + need(all(plan[key] == original[key] for key in original + if key not in ('profile', 'provider_calls', 'provider_registry', 'per_call_widths', 'assignment_sha256')), + 'Inherited plan structure changed') + out.mkdir(parents=True) + (out / 'data').mkdir() + dump(out / 'data/PLAN.json', plan) + (out / 'data/OWNERS.json.gz').write_bytes(owners_blob) + old_spec = read(dep / 'data/SPEC.json') + spec = {key: copy.deepcopy(value) for key, value in old_spec.items() + if key not in ('data', 'providers', 'expected', 'name')} + spec.update(name='joint-frame-candidate', + data={'plan_sha256': sha(out / 'data/PLAN.json'), + 'owners_sha256': sha(out / 'data/OWNERS.json.gz')}, + providers={pid: {} for pid in sorted(natives)}, + dispatch=[[s, r, dispatch[s, r]] for s in range(9) for r in range(8)], + expected={'gain_baseline_kappa': old_spec['expected']['gain_baseline_kappa']}) + pivot_path = spec['pivot_swap']['recipe'] + (out / pivot_path).parent.mkdir(parents=True, exist_ok=True) + shutil.copyfile(dep / pivot_path, out / pivot_path) + need(sha(out / pivot_path) == spec['pivot_swap']['sha256'], 'Retained pivot recipe binding') + dump(out / 'data/SPEC.json', spec) + dump(out / 'REBINDING.json', {'status': 'PREPARED_FOR_UNCHANGED_GLOBAL_ADMISSION', + 'dependency_manifest_sha256': sha(dep / 'MANIFEST.json'), + 'dependency_plan_sha256': sha(dep / 'data/PLAN.json'), + 'native_receipt_sha256': {pid: sha(n / 'RECEIPT.json') for pid, n in natives.items()}, + 'plan_sha256': sha(out / 'data/PLAN.json'), 'owners_sha256': sha(out / 'data/OWNERS.json.gz'), + 'source_owners_sha256': sha(dep / 'data/OWNERS.json.gz'), + 'native_widths': widths_by_provider, + 'width_changes': {pid: [[h, old, new] for h, (old, new) in + enumerate(zip(original['provider_registry']['gauge44']['widths'], widths)) if old != new] + for pid, widths in widths_by_provider.items()}, + 'local_profiles': {pid: dict(paid) for pid, paid in paid_by_provider.items()}, + 'provider_counts': dict(Counter(dispatch.values())), 'idle_profile': dict(idle), 'global_profile': dict(profile), + 'changed_plan_fields': ['profile', 'provider_calls.provider', 'provider_calls.local_program_sha256', 'provider_registry', + 'per_call_widths.widths', 'assignment_sha256'], + 'scope': 'Data rebinding only. Complete independent native replay already passed. Discovery, strict global admission, independent owners/moments and outer checks are required separately.'}) + print('PREPARED_CANDIDATE', json.dumps(dict(profile))) + + +if __name__ == '__main__': + main() diff --git a/research/complex-rank7-end-pair/code/replay_native.py b/research/complex-rank7-end-pair/code/replay_native.py new file mode 100644 index 0000000000..fd7a9b6530 --- /dev/null +++ b/research/complex-rank7-end-pair/code/replay_native.py @@ -0,0 +1,184 @@ +"""Run unchanged native checks on an explicit raw complex supplier word.""" +import argparse +import gzip +import hashlib +import json +import os +from pathlib import Path +import subprocess +import sys +import time + + +def read(path): + raw = path.read_bytes() + return json.loads(gzip.decompress(raw) if path.suffix == '.gz' else raw) + + +def sha(path): + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def payload_sha(path): + return hashlib.sha256(gzip.decompress(path.read_bytes())).hexdigest() + + +def dump(path, data): + path.write_text(json.dumps(data, indent=2) + '\n') + + +def need(value, message): + if not value: + raise ValueError(message) + + +def cold_control_census(word): + meta = word['refactored_cleanup'] + registers = lambda gate: gate[1:3] if gate[0] == 'add' else gate[1:2] + entering = list(map(int, meta.get('entering_low_frame_ended_helpers', []))) + premix = word['A'][:meta['premix_gates']] + cold = list(map(int, meta['cold_low_frame_ended_helpers'])) + hyperplanes = [helper for helper in cold if len(word['helper_final'][str(helper)]) == 8] + absorptions = meta.get('forward_absorption_A_indices', []) + ended = set(map(int, word['helper_final'])) + tail = [(index, word['cleanup'][index], frame) for index, frame in word['early_cleanup']] + accumulators = set() + for position, (_, gate, frame) in enumerate(tail): + if (gate[0] == 'add' and gate[1] not in ended and gate[2] not in ended and len(frame) < 8 + and any(later[0] == 'add' and later[2] == gate[1] and later[1] in hyperplanes + for _, later, _ in tail[position + 1:])): + accumulators.add(gate[1]) + return {'common': 14, 'entering_ends': 3 * len(entering), + 'entering_premix': 3 * sum(any(helper in registers(gate) for gate in premix) for helper in entering), + 'premix_target_writes': 5 if meta.get('premix_target_writes', 0) else 0, + 'forward_absorptions': 7 if absorptions else 0, + 'shared_anchor_and_release': 5 if hyperplanes and absorptions else 0, + 'dimension_eight_ends': 3 * len(hyperplanes), 'factored_accumulators': 2 * len(accumulators)} + + +def main(): + ap = argparse.ArgumentParser(description=__doc__) + for name in ('ancestor-package', 'dependency', 'raw', 'out'): + ap.add_argument('--' + name, type=Path, required=True) + ap.add_argument('--expected-local-pins', type=Path) + ap.add_argument('--finalize-completed', action='store_true', + help='Validate existing successful stage logs and finalize their receipt without rerunning checks') + args = ap.parse_args() + need(__debug__, 'Assertions must remain enabled') + ancestor, dep, raw, out = [getattr(args, name).resolve() + for name in ('ancestor_package', 'dependency', 'raw', 'out')] + need(out.is_dir() if args.finalize_completed else not out.exists(), 'Use the required output directory state') + need(not any(out.is_relative_to(p) for p in (ancestor, dep)), 'Output must be outside source packages') + completed_stages = read(out / 'STAGES.json') if args.finalize_completed else [] + if not args.finalize_completed: + out.mkdir(parents=True) + else: + need(not (out / 'RESULT.json').exists() and not (out / 'RECEIPT.json').exists(), + 'Only incomplete receipt finalization may be resumed') + root = ancestor / 'vendor/main' + source = root / 'research/complex-k492-owner-repair/vendor/multicold' + pr635 = ancestor / 'vendor/pr635/research/complex-571-cold14-st2' + base = source / 'vendor/pr558' + parent = base / 'vendor/pr552' + routing = parent / 'complex-local/inputs/phase-baseline/CANONICAL-WORD.json.gz' + env = dict(os.environ, PYTHONDONTWRITEBYTECODE='1', PYTHONUTF8='1', PYTHONINTMAXSTRDIGITS='0', + MULTICOLD_SOURCE=str(source), GAIN_PR564_SOURCE=str(source)) + for key in ('PYTHONOPTIMIZE', 'WITNESS_SPEC', 'WITNESS_DISCOVER', 'WITNESS_RECORD', + 'XPARAM', 'EXTRAH', 'PAIRING_RANKS', 'DIAG', 'HYBBUDGET', 'PR635_CODE', 'SW4_PIN'): + env.pop(key, None) + stages = [] + inputs = {'raw_word_content': payload_sha(raw), 'raw_word_file': sha(raw), + 'ancestor_manifest': sha(ancestor / 'MANIFEST.json'), + 'dependency_manifest': sha(dep / 'MANIFEST.json')} + started = time.monotonic() + + def run(name, script, *arguments, portable=True, extra_env=None): + print('RUN', name, flush=True) + cmd = [sys.executable, '-B'] + ([str(source / 'code/run_portable.py')] if portable else []) + cmd += [str(script), *map(str, arguments)] + log = out / (name + '.log') + if args.finalize_completed: + need(len(stages) < len(completed_stages), 'Missing completed checker stage') + record = completed_stages[len(stages)] + need(record['name'] == name and record['command'] == cmd and record['exit_code'] == 0 + and record['script_sha256'] == sha(script) and record['log_sha256'] == sha(log), + 'Completed checker stage binding: ' + name) + stages.append(record) + print('VERIFIED_COMPLETED', name, flush=True) + return + before = time.monotonic() + with log.open('w') as stream: + result = subprocess.run(cmd, stdout=stream, stderr=subprocess.STDOUT, + env=dict(env, **(extra_env or {}))) + stages.append({'name': name, 'command': cmd, 'script_sha256': sha(script), + 'exit_code': result.returncode, 'seconds': time.monotonic() - before, + 'log_sha256': sha(log)}) + dump(out / 'STAGES.json', stages) + if result.returncode: + raise RuntimeError(name + ' failed:\n' + log.read_text()[-8000:]) + print('PASS', name, flush=True) + + run('ancestor-manifest', ancestor / 'verify_manifest.py', portable=False) + run('dependency-manifest', dep / 'verify_manifest.py', portable=False) + local = out / 'local' + run('independent-raw-audit', dep / 'independent/audit_local.py', '--word', raw, + '--main', root, '--output', out / 'INDEPENDENT-AUDIT.json', portable=False) + run('native', pr635 / 'code/hpe_audit_and_transport.py', '--raw', raw, + '--routing', routing, '--out', local) + run('ledgers', pr635 / 'code/hpe_emit_local.py', local) + run('local-replay', pr635 / 'code/hpe_audit_local.py', local) + run('wrappers', pr635 / 'code/hpe_adapters_local.py', local / 'CANONICAL-WORD.json.gz', + local / 'RESIDUAL-ADAPTERS.json', local / 'WRAPPER-CHECKS.json') + run('cold-end-controls', dep / 'construction/layers_p6n/layer_end_controls.py', raw, + routing, out / 'controls', extra_env={'PR635_CODE': str(pr635 / 'code')}) + run('phases', base / 'code/phases_full.py', local, + parent / 'complex-global/vendor531/vendor/clifford') + need(not args.finalize_completed or len(stages) == len(completed_stages), 'Complete stage census') + audit = read(out / 'INDEPENDENT-AUDIT.json') + need(audit['status'] == 'PASS_INDEPENDENT_EXACT_FORWARD_AND_DUAL_ENDPOINT_FRAMES_ENTRANCES_CONES' + and audit['checked_columns'] == 728 and audit['content_sha256'] == inputs['raw_word_content'], + 'Independent raw audit failed or bound to another input') + native = read(local / 'INDEPENDENT-LOCAL-REPLAY.json') + need(native['status'] == 'PASS_INDEPENDENT_LOCAL_SCALAR_FRAME_AND_WRAPPER_REPLAY' + and len(native['negative_controls_rejected']) == 25, 'Incomplete native controls') + for orientation in ('forward', 'backward'): + need(native['local'][orientation]['all_exact_columns'] == 728 + and native['local'][orientation]['private_work_erased'], 'Native column restoration') + need(native['paid_profiles'][orientation] == audit['local_profile'], 'Native paid profile mismatch') + wrapper = read(local / 'WRAPPER-CHECKS.json') + need(wrapper['status'] == 'PASS_RESIDUAL_WRAPPERS_ARE_EXACT', 'Residual wrapper failure') + control = read(out / 'controls/COLD-END-CONTROLS.json') + cold_census = cold_control_census(read(raw)) + need(control['status'] == 'PASS_COLD_END_RAW_WORD_CONTROLS' + and len(control['rejected']) == len(set(control['rejected'])) == sum(cold_census.values()), + 'Incomplete cold-end controls') + phase = read(local / 'CLIFFORD-REVIEW.json') + need(phase['status'] == 'PASS_NEW_WORD_EXACT_LOCAL_PHASE_RECIPES' + and phase['all_child_equalities_include_global_phase'] is True, 'Incomplete phase equality') + need(phase['canonical_word_sha256'] == sha(local / 'CANONICAL-WORD.json.gz') + and phase['recipe_sha256'] == sha(local / 'CLIFFORD-RECIPES.json'), 'Stale phase binding') + checks = read(local / 'LOCAL-CHECKS.json') + pins = {'canonical_sha256': payload_sha(local / 'CANONICAL-WORD.json.gz'), + 'program_sha256': {o: checks[o]['sha256'] for o in ('forward', 'backward')}, + 'clifford_recipes_sha256': sha(local / 'CLIFFORD-RECIPES.json')} + if args.expected_local_pins: + expected = read(args.expected_local_pins) + need(all(expected[k] == value for k, value in pins.items()), 'Nominated native pins differ') + inputs['expected_local_pins'] = sha(args.expected_local_pins) + need(payload_sha(raw) == inputs['raw_word_content'] and sha(raw) == inputs['raw_word_file'], + 'Raw input changed during native replay') + result = {'status': 'PASS_COMPLETE_NATIVE_REPLAY_UNCHANGED_CHECKERS', 'input_sha256': inputs, + 'profile': audit['local_profile'], 'phase_edges': phase['directed_edges'], + 'pins': pins, 'seconds': sum(stage['seconds'] for stage in stages), 'stages': stages, + 'cold_control_census': cold_census, 'cold_controls_rejected': len(control['rejected']), + 'finalized_from_completed_stages': args.finalize_completed, + 'scope': 'Fresh raw/native forward and dual columns, scalar/frame/cones, wrappers, 25 native controls, every applicable cold-end control, and every exact phase edge. Global admission and construction ancestry remain separate.'} + dump(out / 'RESULT.json', result) + artifacts = [p for p in out.rglob('*') if p.is_file() and p.name != 'RECEIPT.json'] + dump(out / 'RECEIPT.json', {'status': result['status'], + 'artifacts': {p.relative_to(out).as_posix(): sha(p) for p in artifacts}}) + print(result['status'], json.dumps(result['profile']), flush=True) + + +if __name__ == '__main__': + main() diff --git a/research/complex-rank7-end-pair/data/END-RECIPE.json b/research/complex-rank7-end-pair/data/END-RECIPE.json new file mode 100644 index 0000000000..612ee756ef --- /dev/null +++ b/research/complex-rank7-end-pair/data/END-RECIPE.json @@ -0,0 +1,28 @@ +{ + "schema": 1, + "input_sha256": "1e1d99ba7aab877d6b573c41f7030ee73de9a52fee51d0a822ddaae71251999f", + "ends": [ + [588, [256, 128, 96, 16, 8, 4, 2, 1], [256, 128, 96, 17, 9, 5, 3]], + [589, [256, 128, 96, 16, 8, 4, 2, 1], [256, 128, 96, 17, 9, 5, 3]] + ], + "B_frames": [ + [1018, [260, 130, 96, 20, 10, 1], [261, 131, 96, 20, 10]], + [1019, [258, 132, 96, 20, 10, 1], [259, 133, 96, 20, 10]], + [1050, [264, 137, 96, 24, 4, 3], [268, 137, 96, 24, 3]], + [1051, [265, 136, 96, 24, 4, 3], [265, 140, 96, 24, 3]], + [1130, [260, 130, 96, 20, 10, 1], [261, 131, 96, 20, 10]], + [1131, [258, 132, 96, 20, 10, 1], [259, 133, 96, 20, 10]], + [1162, [264, 137, 96, 24, 4, 3], [268, 137, 96, 24, 3]], + [1163, [265, 136, 96, 24, 4, 3], [265, 140, 96, 24, 3]] + ], + "early_cleanup": [ + [140, 140, [256, 128, 96, 16, 8, 4, 2, 1], [256, 128, 96, 17, 9, 5, 3]], + [141, 141, [256, 128, 96, 16, 8, 4, 2, 1], [256, 128, 96, 17, 9, 5, 3]] + ], + "expected": { + "output_sha256": "796a40505ed9dc38d64c5b7856a0908e70bd9f22cd869edf01ebe66ac02ab15a", + "local_profile": {"1": 2542, "2": 352, "3": 422, "4": 194, "5": 56, "8": 8}, + "local_rank_mass": 5632, + "width_inventory": {"4": 80, "5": 32, "7": 56, "8": 120, "9": 216} + } +} diff --git a/research/complex-rank7-end-pair/data/EXPECTED.json b/research/complex-rank7-end-pair/data/EXPECTED.json new file mode 100644 index 0000000000..df4c057c5c --- /dev/null +++ b/research/complex-rank7-end-pair/data/EXPECTED.json @@ -0,0 +1,42 @@ +{ + "kappa": "1661712108827881/1000000000000000000", + "kappa_decimal": "0.001661712108827881", + "baseline_kappa": "1661634653669567/1000000000000000000", + "gain": "38727579157/500000000000000000", + "complex_lower": "832238996031084233427/500000000000000000000000", + "bit_lower": "1733427039589844234749/1000000000000000000000000", + "global_profile": { + "1": 183024, + "2": 25344, + "3": 30384, + "4": 13968, + "5": 4032, + "8": 576, + "48": 2400 + }, + "baseline_word_sha256": "1e1d99ba7aab877d6b573c41f7030ee73de9a52fee51d0a822ddaae71251999f", + "word_sha256": "796a40505ed9dc38d64c5b7856a0908e70bd9f22cd869edf01ebe66ac02ab15a", + "owners_sha256": "02bde66a90b8ae9b0c4d8d563ca2218ad1de851fa6dec3d1abb5d3a30ca3dd2a", + "native_pins": { + "canonical_sha256": "d5988057b8d06e8ea7a430283d55d6e36c1602bc989007b70839a257500b4518", + "program_sha256": { + "forward": "0732bf8ab48f08b2d8f07c3c5d1109c12c149ea69bb2b14ba8847c9703876c08", + "backward": "2b918db2ec63a5503551f84023b6881196e2cc1511fd3e2b43be3b5b633b434d" + }, + "clifford_recipes_sha256": "9b39a953ab1912aa3f48a5bd438c7b38554a48dfc0d51faf47a8be25e7605e5d" + }, + "local_profile": { + "1": 2542, + "2": 352, + "3": 422, + "4": 194, + "5": 56, + "8": 8 + }, + "phase_edges": 2950, + "native_controls": 25, + "inherited_cold_controls": 89, + "strict_admission_controls": 69, + "bit_controls": 12, + "independent_owner_controls": 7 +} diff --git a/research/complex-rank7-end-pair/data/OWNER-FLOW.json.gz b/research/complex-rank7-end-pair/data/OWNER-FLOW.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..bcff36f310fafd500b5acaca2959377e7e4014d3 GIT binary patch literal 5262 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 U$}o7*;>SP#4T2I##ad$k0Cr(R=>Px# literal 0 HcmV?d00001 diff --git a/research/complex-rank7-end-pair/end_controls.py b/research/complex-rank7-end-pair/end_controls.py new file mode 100644 index 0000000000..91895fac5e --- /dev/null +++ b/research/complex-rank7-end-pair/end_controls.py @@ -0,0 +1,150 @@ +"""Reason-specific raw-auditor controls for both new dimension-seven ends. + +Prepared with OpenAI Codex assistance. Apache-2.0. +""" +import argparse +import copy +import gzip +import hashlib +import json +from pathlib import Path +import subprocess +import sys +import tempfile + + +WORD_SHA = '796a40505ed9dc38d64c5b7856a0908e70bd9f22cd869edf01ebe66ac02ab15a' +RECIPE = Path(__file__).resolve().parent / 'data/END-RECIPE.json' + + +def require(condition, message): + if not condition: + raise RuntimeError(message) + + +def cases(word, recipe): + result = [] + endpoint = dict(native='arbitrary-dirt endpoint', independent='all-column endpoint failure') + nonmonotone = dict(native="'nonmonotone'", independent='frame not monotone') + profile = dict(native='paid local profile differs from the reported local_profile', + independent='paid profile mismatch') + + def add(name, mutation, reasons): + mutant = copy.deepcopy(word) + mutation(mutant) + result.append((name, mutant, reasons)) + + def drop_gate(mutant, index): + mutant['cleanup'].pop(index) + mutant['early_cleanup'] = [[j - (j > index), frame] + for j, frame in mutant['early_cleanup'] if j != index] + + tails = {word['cleanup'][cleanup_index][1]: (index, cleanup_index, old, new) + for index, cleanup_index, old, new in recipe['early_cleanup']} + require(set(tails) == {588, 589}, 'changed tail helpers') + for q, old, new in recipe['ends']: + index, cleanup_index, old_tail, new_tail = tails[q] + require(word['helper_final'][str(q)] == new and word['early_cleanup'][index] == + [cleanup_index, new_tail], 'changed end and tail') + add(f'end-{q}-other-dim7', lambda w: w['helper_final'].__setitem__(str(q), new[:-1] + [1]), + dict(native='hpe cone pre-check (row / column)', independent='frame not monotone')) + add(f'end-{q}-drop-cleanup-gate', lambda w: drop_gate(w, cleanup_index), endpoint) + add(f'end-{q}-wrong-cleanup-coefficient', + lambda w: w['cleanup'][cleanup_index].__setitem__(3, 2 * w['cleanup'][cleanup_index][3]), endpoint) + add(f'end-{q}-cleanup-at-full', lambda w: w['early_cleanup'].pop(index), + dict(native='cleanup on non-FULL end', independent='full cleanup reads a low end')) + add(f'end-{q}-revert-tail-frame', lambda w: w['early_cleanup'][index].__setitem__(1, old_tail), nonmonotone) + add(f'end-{q}-removed-end', lambda w: w['helper_final'].pop(str(q)), profile) + for index, old, new in recipe['B_frames']: + require(word['B'][index][-1] == new, 'changed B frame') + reasons = nonmonotone if index in (1018, 1019, 1050, 1051) else profile + add(f'B-{index}-omitted-lowering', lambda w: w['B'][index].__setitem__(-1, old), reasons) + + def false_profile(mutant): + mutant['report']['local_profile']['1'] += 2 + mutant['report']['local_profile']['2'] -= 1 + + def false_widths(mutant): + mutant['report']['width_inventory']['7'] -= 1 + mutant['report']['width_inventory']['8'] += 1 + + add('false-profile-same-rank-mass', false_profile, profile) + # The independent raw auditor checks the reported width inventory. + add('false-width-inventory', false_widths, dict(independent='width inventory mismatch')) + require(len(result) == 22, 'targeted control count') + return result + + +def run_check(args, name, checker, word, expected=None): + payload = json.dumps(word, sort_keys=True, separators=(',', ':')).encode() + with tempfile.TemporaryDirectory(prefix=f'{name}-{checker}-', dir=args.output) as temporary: + root = Path(temporary) + path = root / 'WORD.json.gz' + path.write_bytes(gzip.compress(payload, compresslevel=9, mtime=0)) + command = [sys.executable, '-I', '-B'] + if checker == 'native': + command += [str(args.portable_runner), str(args.native_auditor), '--raw', str(path), + '--routing', str(args.routing), '--out', str(root / 'native')] + receipt = root / 'native/SCALAR-FRAME-AUDIT.json' + error_type = 'AssertionError:' + hash_key = 'input_content_sha256' + else: + receipt = root / 'independent.json' + command += [str(args.independent_auditor), '--word', str(path), '--output', str(receipt)] + if args.main is not None: + command += ['--main', str(args.main)] + error_type = 'RuntimeError:' + hash_key = 'content_sha256' + completed = subprocess.run(command, capture_output=True, text=True, timeout=120) + log = completed.stdout + completed.stderr + (args.output / f'{name}.{checker}.log').write_text(log, encoding='utf-8') + if expected is None: + require(completed.returncode == 0, f'{checker} rejected the positive control: {log[-1000:]}') + result = json.loads(receipt.read_text(encoding='utf-8')) + require(result[hash_key] == WORD_SHA, 'positive control content pin') + return dict(checker=checker, accepted=True, status=result['status']) + last_line = log.strip().splitlines()[-1] if log.strip() else '' + require(completed.returncode == 1 and last_line.startswith(error_type) and expected in last_line, + f'{name}: {checker} expected {expected!r}, got exit {completed.returncode}: {last_line}') + return dict(checker=checker, rejected=last_line) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--word', type=Path, required=True) + parser.add_argument('--recipe', type=Path, default=RECIPE) + parser.add_argument('--independent-auditor', type=Path, required=True) + parser.add_argument('--native-auditor', type=Path, required=True) + parser.add_argument('--portable-runner', type=Path, required=True) + parser.add_argument('--routing', type=Path, required=True) + parser.add_argument('--main', type=Path) + parser.add_argument('--output', type=Path, required=True) + args = parser.parse_args() + raw = gzip.decompress(args.word.read_bytes()) + require(hashlib.sha256(raw).hexdigest() == WORD_SHA, 'candidate content pin') + recipe = json.loads(args.recipe.read_text(encoding='utf-8')) + require(recipe['expected']['output_sha256'] == WORD_SHA, 'recipe output pin') + word = json.loads(raw) + args.output.mkdir(parents=True, exist_ok=True) + positive = [run_check(args, 'positive', checker, word) for checker in ('native', 'independent')] + rejected = [] + for name, mutant, reasons in cases(word, recipe): + checks = [run_check(args, name, checker, mutant, expected) for checker, expected in reasons.items()] + rejected.append(dict(name=name, checks=checks)) + print('rejected', name, flush=True) + report = dict(status='PASS_DIMENSION_SEVEN_END_PAIR_RAW_CONTROLS', content_sha256=WORD_SHA, + checked_helpers=[588, 589], positive_controls=positive, + mutations=22, raw_rejections=sum(len(case['checks']) for case in rejected), + rejected_controls=rejected, + checker_sha256={name: hashlib.sha256(path.read_bytes()).hexdigest() + for name, path in (('independent', args.independent_auditor), + ('native', args.native_auditor), + ('portable_runner', args.portable_runner))}, + scope='Supplemental controls for both dimension-seven ends, both tail gates and frames, all eight B ' + 'lowerings, paid profiles, and reported widths. Inherited controls are counted separately.') + (args.output / 'END-CONTROLS.json').write_text(json.dumps(report, indent=2) + '\n', encoding='utf-8') + print(report['status'], '22 mutants; 43 raw rejections', flush=True) + + +if __name__ == '__main__': + main() diff --git a/research/complex-rank7-end-pair/evidence/ASSEMBLY.json.gz b/research/complex-rank7-end-pair/evidence/ASSEMBLY.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..7370b8bf42b580da58d0f7133b6de590455f70e7 GIT binary patch literal 17898 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 (3, 11), 'Python 3.11+ with assertions enabled is required') + work = args.work.resolve() + need(not work.exists() and not work.is_relative_to(PACKAGE), 'Use a new external output directory') + work.mkdir(parents=True) + pins, expected = read(PACKAGE / 'SOURCES.json'), read(PACKAGE / 'data/EXPECTED.json') + environment = dict(os.environ, PYTHONDONTWRITEBYTECODE='1', PYTHONUTF8='1', PYTHONINTMAXSTRDIGITS='0') + for name in ('PYTHONOPTIMIZE', 'WITNESS_SPEC', 'WITNESS_DISCOVER', 'WITNESS_RECORD', + 'MULTICOLD_SOURCE', 'GAIN_PR564_SOURCE', 'SW4_PIN', 'PR635_CODE', + 'XPARAM', 'EXTRAH', 'PAIRING_RANKS', 'DIAG', 'HYBBUDGET'): + environment.pop(name, None) + stages = [] + started = time.monotonic() + + def run(name, command, binary_output=None): + print('RUN', name, flush=True) + begin = time.monotonic() + log = work / (name + '.log') + with log.open('wb') as stream: + if binary_output is None: + result = subprocess.run(list(map(str, command)), stdout=stream, stderr=subprocess.STDOUT, + env=environment) + else: + with binary_output.open('wb') as output: + result = subprocess.run(list(map(str, command)), stdout=output, stderr=stream, + env=environment) + stages.append(dict(name=name, exit_code=result.returncode, seconds=time.monotonic()-begin, + log_sha256=sha(log))) + dump(work / 'STAGES.json', stages) + if result.returncode: + raise RuntimeError(name + ' failed:\n' + log.read_text(errors='replace')[-6000:]) + print('PASS', name, flush=True) + return log.read_text(errors='replace') + + def python(name, script, *arguments): + return run(name, [sys.executable, '-B', script, *arguments]) + + repository = args.git_repository.resolve() if args.git_repository else work / 'source.git' + if args.git_repository is None: + run('initialize-source-cache', ['git', 'init', '--bare', repository]) + sources = {} + for row in pins['sources']: + number, commit, relative = row['pr'], row['commit'], row['path'] + if args.git_repository is None: + run(f'fetch-{number}', ['git', '-C', repository, 'fetch', '--no-tags', '--depth=1', + row['repository'], commit]) + run(f'check-commit-{number}', ['git', '-C', repository, 'cat-file', '-e', commit + '^{commit}']) + archive = work / f'source-{number}.tar' + run(f'archive-{number}', ['git', '-C', repository, 'archive', '--format=tar', commit, relative], + binary_output=archive) + destination = work / f'source-{number}' + extract_package(archive, destination, relative) + package = destination / relative + need(sha(package / 'MANIFEST.json') == row['manifest_sha256'], 'Pinned source manifest') + actual = {path.relative_to(package).as_posix(): sha(path) for path in package.rglob('*') + if path.is_file() and path != package / 'MANIFEST.json' and '__pycache__' not in path.parts} + manifest = read(package / 'MANIFEST.json') + need(actual == manifest, f'All source files match PR{number}') + sources[number] = package + ancestor, dependency, checker = [sources[number] for number in (741, 799, 777)] + root = ancestor / 'vendor/main' + native_source = root / 'research/complex-k492-owner-repair/vendor/multicold' + routing = native_source / 'vendor/pr558/vendor/pr552/complex-local/inputs/phase-baseline/CANONICAL-WORD.json.gz' + pr635 = ancestor / 'vendor/pr635/research/complex-571-cold14-st2' + baseline = work / 'baseline741' + python('complete-ancestor-replay', ancestor / 'verify.py', '--work', baseline) + + construction = work / 'baseline799-construction' + construction.mkdir() + base_word = construction / 'FULL-WORD.json.gz' + recipe = dependency / 'construction/jx/RECIPE-X4.json' + builder = dependency / 'construction/jx/build_jx.py' + python('rebuild-x4-word', builder, '--input', baseline / 'sw4/FULL-WORD.json.gz', + '--recipe', recipe, '--out', base_word) + x4 = read(recipe) + need(payload_sha(base_word) == x4['expected']['output_content_sha256'] == expected['baseline_word_sha256'], + 'Rebuilt X4 source word') + control_results = {} + for name, control in sorted(x4['controls'].items()): + log = python('x4-control-' + name, builder, '--input', baseline / 'sw4/FULL-WORD.json.gz', + '--recipe', recipe, '--control', name) + if 'rejection_expected' in control: + need('CONTROL PINNED' in log, 'Expected X4 construction rejection') + control_results[name] = {'rejected': control['rejection_expected']} + else: + need('OK ' + control['expected_sha'] in log, 'Expected X4 construction output') + control_results[name] = {'content_sha256': control['expected_sha']} + need(len(control_results) == 7, 'Complete predecessor construction control census') + dump(construction / 'CONTROLS.json', control_results) + + word = work / 'FULL-WORD.json.gz' + python('build-end-pair', PACKAGE / 'build_word.py', '--input', base_word, '--output', word) + need(payload_sha(word) == expected['word_sha256'], 'Minimal candidate word') + python('independent-point-audit', PACKAGE / 'audit_points.py', '--baseline', base_word, + '--word', word, '--output', work / 'POINT-AUDIT.json') + python('end-pair-controls', PACKAGE / 'end_controls.py', '--word', word, + '--independent-auditor', dependency / 'independent/audit_local.py', + '--native-auditor', pr635 / 'code/hpe_audit_and_transport.py', + '--portable-runner', native_source / 'code/run_portable.py', + '--routing', routing, '--output', work / 'end-controls') + owners = work / 'owners' + python('rebuild-owners', PACKAGE / 'build_owners.py', '--word', word, + '--plan', dependency / 'data/PLAN.json', '--out', owners) + need(payload_sha(owners / 'OWNERS.json.gz') == expected['owners_sha256'], 'Exact literal owner assignment') + native = work / 'native' + python('complete-native-replay', PACKAGE / 'code/replay_native.py', '--ancestor-package', ancestor, + '--dependency', dependency, '--raw', word, '--out', native) + native_result = read(native / 'RESULT.json') + need(native_result['pins'] == expected['native_pins'], 'Every proof-relevant native output') + admission = work / 'admission' + python('complete-global-admission', PACKAGE / 'code/admit_candidate.py', '--ancestor-package', ancestor, + '--ancestor-replay', baseline, '--dependency', dependency, '--checker-package', checker, + '--native', native, '--owners', owners / 'OWNERS.json.gz', '--out', admission) + admitted = read(admission / 'RESULT.json') + for field in ('kappa', 'kappa_decimal', 'complex_lower', 'bit_lower', 'global_profile', 'gain'): + need(admitted[field] == expected[field], 'Frozen admitted result: ' + field) + result = dict(status='PASS_COLD_RANK7_END_PAIR_COMPLETE_ADMISSION', + kappa=admitted['kappa'], kappa_decimal=admitted['kappa_decimal'], gain=admitted['gain'], + baseline_kappa=admitted['baseline_kappa'], global_profile=admitted['global_profile'], + sources=pins, word_sha256=payload_sha(word), owners_sha256=payload_sha(owners / 'OWNERS.json.gz'), + native_pins=native_result['pins'], seconds=time.monotonic()-started, stages=stages, + scope='Fresh pinned ancestor and X4 construction, minimal end recipe, independent point audit, ' + 'targeted controls, exact owner reconstruction, complete native and strict global admission. ' + 'The cited PR589 bit circuit is repriced. Inherited uniform and analytic assumptions remain.') + dump(work / 'RESULT.json', result) + outputs = ['RESULT.json', 'STAGES.json', 'POINT-AUDIT.json', 'FULL-WORD.json.gz', + 'baseline741/RESULT.json', 'baseline741/RECEIPT.json', 'baseline741/ANCESTRAL-LINK.json', + 'baseline799-construction/CONTROLS.json', 'owners/OWNERS.json.gz', + 'native/RESULT.json', 'native/RECEIPT.json', 'admission/RESULT.json', 'admission/RECEIPT.json'] + dump(work / 'RECEIPT.json', dict(status=result['status'], + artifacts={name: sha(work / name) for name in outputs}, + package_inputs={str(path.relative_to(PACKAGE)): sha(path) for path in PACKAGE.rglob('*') + if path.is_file() and '__pycache__' not in path.parts})) + print(result['status'], result['kappa_decimal'], flush=True) + + +if __name__ == '__main__': + main() From d71857cd0ae7824e935aac17327e4ec27f66322b Mon Sep 17 00:00:00 2001 From: Alexander Schwartzman Date: Tue, 13 Oct 2026 12:30:00 -0400 Subject: [PATCH 2/2] research: combine rank-seven helper ends with U8 --- research/complex-rank7-end-pair/NOTICE.md | 20 ++- research/complex-rank7-end-pair/PROOF.md | 22 ++- research/complex-rank7-end-pair/README.md | 100 ++++++------ research/complex-rank7-end-pair/SEARCH.json | 48 ++++-- research/complex-rank7-end-pair/SOURCES.json | 22 ++- .../complex-rank7-end-pair/audit_points.py | 6 +- .../complex-rank7-end-pair/build_owners.py | 2 +- research/complex-rank7-end-pair/build_word.py | 8 +- .../code/admit_candidate.py | 14 +- .../data/END-RECIPE.json | 10 +- .../complex-rank7-end-pair/data/EXPECTED.json | 35 +++-- .../data/OWNER-FLOW.json.gz | Bin 5262 -> 5260 bytes .../data/SELECTED942.json.gz | Bin 0 -> 4208 bytes .../complex-rank7-end-pair/end_controls.py | 2 +- .../evidence/ASSEMBLY.json.gz | Bin 17898 -> 17778 bytes .../evidence/END-CONTROLS.json | 2 +- .../evidence/POINT-AUDIT.json | 10 +- .../evidence/VALIDATION.json | 148 ++++++++++-------- research/complex-rank7-end-pair/reproduce.py | 33 +++- 19 files changed, 291 insertions(+), 191 deletions(-) create mode 100644 research/complex-rank7-end-pair/data/SELECTED942.json.gz diff --git a/research/complex-rank7-end-pair/NOTICE.md b/research/complex-rank7-end-pair/NOTICE.md index d4ef3c20a7..ace4da0b33 100644 --- a/research/complex-rank7-end-pair/NOTICE.md +++ b/research/complex-rank7-end-pair/NOTICE.md @@ -5,9 +5,10 @@ substantial OpenAI Codex assistance, including delegated research and review. The new code and research artifacts use the repository's Apache-2.0 license. No independent human peer review or full formal proof is claimed. -This contribution changes two helper ends in the retained PR799 construction +This contribution changes two helper ends in the retained PR869 U8 construction and supplies a new physical owner assignment. It builds on Jeremy Kothe's -(`jeremykothe2`) PR799 X4 assembly and its credited JointXF read exchanges, +(`jeremykothe2`) PR869 triangle-hybrid deliveries, credited to NewBArch, and +PR799 X4 assembly with its credited JointXF read exchanges, Chafik Boukhalfa's (`chafreaky`) PR741 frame coalescences and PR685 ownership work, icekylinx's Gauge44 construction, and the retained PR635 cold-end and residual-wrapper machinery. BlockInvert's entrance promotions, G44Pack's @@ -27,10 +28,13 @@ ancestry and DreamingOfClouds' transport. Douglas Colkitt's repository, integration, and retained analytic framework are also prerequisites. This notice supplements the original notices; it does not replace them. +The comparison snapshot is Jonathan Capalbo's (`jon314159`) PR942 selected +result, following Chafik Boukhalfa's PR890 and the PR858/869/870 lineage. +Its fixed-width all-replica bound does not cover the new width inventory. + The investigation and submission branch start at -`66849e1475c930fd7732b1a0067ffee7e1e95f60`. The final development and validation -snapshot is `f567884aeb8851b6e794af1184119a3bfbe1e631`, recorded as -`base_commit` in `SOURCES.json`; it selects PR799's conditional result. -Only the new research package is submitted from the earlier branch base. -The replayed code, source pins, and data are unchanged. No source from PR784 -is used. +`66849e1475c930fd7732b1a0067ffee7e1e95f60`. The final development and comparison +snapshot is `407d52ff15b2217b6e22bce44728b4c3907b6515`, which selects PR942. +`SOURCES.json` records both bases and all consumed source commits. Only the +new research package is submitted from the earlier branch base. No source +from PR784 is used. diff --git a/research/complex-rank7-end-pair/PROOF.md b/research/complex-rank7-end-pair/PROOF.md index 2fdeda52a5..9c4a299944 100644 --- a/research/complex-rank7-end-pair/PROOF.md +++ b/research/complex-rank7-end-pair/PROOF.md @@ -1,6 +1,6 @@ # The end pair and its complete cost -All indices below refer to PR799's pinned raw word. The recipe records both +All indices below refer to PR869's pinned U8 raw word. The recipe records both the old and new value at every changed position and checks the complete input and output content hashes. @@ -21,7 +21,7 @@ wrapper contract. The new end requires eight B-frame changes, at zero-based positions 1018, 1019, 1050, 1051, 1130, 1131, 1162, and 1163. The two early-cleanup -frames at entries 140 and 141 also become U. No scalar gate changes. The +frames at entries 148 and 149 also become U. No scalar gate changes. The independent point audit checks containment for every adjacent frame, every source and target boundary, the center interface, all paid jumps, and the unchanged scalar program. The unchanged native auditors independently derive @@ -56,7 +56,7 @@ capacity. The retained global auditor independently reconstructs the physical windows and checks the final assignment against the native helper widths. The complete unused-space profile is exactly `{48:2400}`. -Across all 72 calls, the global profile change from PR799 is +Across all 72 calls, the global profile change from the U8 construction is ``` ΔH_global = {1:-433, 2:+1008, 3:-577, 44:-1, 48:+4}. @@ -65,19 +65,25 @@ Across all 72 calls, the global profile change from PR799 is The rank mass does not change: `-433 + 2*1008 - 3*577 - 44 + 4*48 = 0`. The resulting mass is 520704, retaining the deficit 2560 and the same physical -geometry. At PR799's certified complex endpoint, the raw moment decreases by -approximately `0.11903590824390181`. That decimal is a diagnostic; admission -uses the two retained rational interval engines. +geometry. The certified global prefix bound is 257 bits, within the retained +512-bit allowance. The physical row coefficient is 16467, below 20161. +Admission checks both retained rational interval engines and the complete +precision and tape invoice. The native complex recurrence is accepted at -`b = 832238996031084233427 / 500000000000000000000000` +`b = 6659172436825204659 / 4000000000000000000000` and rejected at `b + 10^-24`. The complete bit profile retains its bad-residue surcharge. Both moment engines and all 47 outer inequalities certify ``` -κ = 1661712108827881 / 1000000000000000000. +κ = 166202617947539 / 100000000000000000. ``` +This exceeds the selected PR942 value by exactly +`65631761443 / 1000000000000000000`. PR942's all-replica bound fixes the +previous U8 profile and width inventory. The new helper ends change both, +so that bound does not exclude this construction. + The scalar program and its finite envelopes retain their source predicates. The new frames, wrapper ranks, local profile, owner map, global profile, moments, and outer witness are freshly admitted. This establishes a finite diff --git a/research/complex-rank7-end-pair/README.md b/research/complex-rank7-end-pair/README.md index a4b04232c5..9ff6a51c3e 100644 --- a/research/complex-rank7-end-pair/README.md +++ b/research/complex-rank7-end-pair/README.md @@ -1,32 +1,39 @@ -# Two rank-seven helper ends: conditional κ = 0.001661712108827881 +# U8 with two rank-seven helper ends: conditional κ = 0.00166202617947539 -This construction increases PR799's conditional κ from -`0.001661634653669567` to **`0.001661712108827881`**. The exact increase is -`38727579157 / 500000000000000000`, approximately **0.00466138%** of the -preceding κ. This compares asymptotic exponent savings, not measured runtime. +This construction gives **κ = 0.00166202617947539**, above the pinned selected +PR942 result, `0.001661960547713947`. The exact increase is +`65631761443 / 1000000000000000000`, approximately **0.00394906%** of that κ. +This compares asymptotic exponent savings, not measured runtime. -The change has two parts. Helpers 588 and 589 finish in dimension seven instead -of eight. Eight B frames and two early-cleanup frames change with those ends. -An explicit new owner assignment then combines the released space into -rank-48 residuals. All raw scalar gates, their order, the ports, the center -interface, and the 72-call schedule retain their PR799 values. +The construction combines PR869's U8 word with two smaller helper ends and +an explicit owner assignment. Helpers 588 and 589 finish in dimension seven +instead of eight. Eight B frames and two early-cleanup frames change with +those ends. The owner assignment combines the released space into rank-48 +residuals. All raw scalar gates and their order retain their U8 values. The +ports, center interface, physical geometry, and 72-call schedule retain their +PR799 values. -| Quantity | PR799 | This construction | +| Quantity | U8 before this change | This construction | | --- | ---: | ---: | | Local rank-one children | 2548 | 2542 | | Local rank-two children | 338 | 352 | -| Local rank-three children | 430 | 422 | -| Local rank-four / five / eight children | 194 / 56 / 8 | 194 / 56 / 8 | +| Local rank-three children | 446 | 438 | +| Local rank-four / five / eight children | 162 / 72 / 8 | 162 / 72 / 8 | | Helper width per call | 3778 | 3776 | | Global idle profile | `{1:1, 3:1, 44:1, 48:2396}` | `{48:2400}` | The complete global profile is -`{1:183024, 2:25344, 3:30384, 4:13968, 5:4032, 8:576, 48:2400}`. -Its rank mass is 520704. The certified complex endpoint is -`0.001664477992062168466854`; the retained PR589 bit endpoint is +`{1:183024, 2:25344, 3:31536, 4:11664, 5:5184, 8:576, 48:2400}`. +Its rank mass is 520704, with deficit 2560. The certified complex endpoint is +`0.001664793109206301164750`; the retained PR589 bit endpoint is `0.001733427039589844234749`. The complex supplier remains the limiting one. -The conservative complex calculation separately gives -`κ = 0.001661712105945928`. +The conservative calculation separately gives `κ = 0.001662026176592891`. + +The 72-call construction has a certified global prefix bound of 257 bits and +retains the 512-bit allowance. Its physical row coefficient is 16467, below +the retained limit 20161. The comparison result uses 333 calls and a 1024-bit +allowance. Its all-replica bound fixes the previous local profile and helper +widths; this construction changes both. From the repository root, use Python 3.11 or newer and Git: @@ -34,44 +41,43 @@ From the repository root, use Python 3.11 or newer and Git: python3 -B research/complex-rank7-end-pair/reproduce.py --work /tmp/rank7-end-pair ``` -Use a new output directory. The command fetches the three exact source commits -in `SOURCES.json` into that directory. It rebuilds the PR741 ancestry and PR799 -word, applies the twelve changed annotations, rebuilds the owner assignment, +Use a new output directory. The command fetches the four exact source commits +in `SOURCES.json`. It rebuilds the PR741 ancestry, PR799 word, and PR869 U8 +word; applies the twelve changed annotations; rebuilds the owner assignment; and runs complete native and global admission. No optimizer or Python package -installation is required. If a local repository already contains the pinned -commits, add `--git-repository /absolute/path/to/repository` to use its objects -without fetching. Source files are extracted into the output directory in -either case. +installation is required. If a local repository contains the pinned commits, +add `--git-repository /absolute/path/to/repository` to use its objects without +fetching. Source files are extracted into the output directory in either case. Expected final output: ```text -PASS_COLD_RANK7_END_PAIR_COMPLETE_ADMISSION 0.001661712108827881 +PASS_COLD_RANK7_END_PAIR_COMPLETE_ADMISSION 0.00166202617947539 ``` -The required checks include every 728-input column in both orientations, -all 2,950 phase edges, exact residual wrappers, 25 native controls, and the -89 applicable inherited cold-end controls. Dedicated controls cover the new -dimension-seven ends and their frame changes. The independent point audit -uses explicit subsets of the 512-point frame space. Owner checks cover all -36,288 roles, complete availability windows, distinct families per call, -capacity, and disjoint compact coordinate prefixes. Discovery is followed by -frozen strict admission, 69 admission controls, 12 bit-supplier controls, -seven independent owner controls, and both exact moment engines with all 47 -outer inequalities. `data/EXPECTED.json` pins the resulting word, programs, -phase recipes, owner map, profile, and κ. - -A complete cold run on Python 3.14.7 and macOS arm64 passed in 685 seconds. -`evidence/VALIDATION.json` records its environment, coverage, and input hashes. +The required checks include all 38 U8 construction controls, every 728-input +column in both orientations, all 2,950 phase edges, exact residual wrappers, +25 native controls, and the 89 applicable inherited cold-end controls. +Dedicated controls cover the new dimension-seven ends and their frame changes. +The independent point audit uses explicit subsets of the 512-point frame +space. Owner checks cover all 36,288 roles, complete availability windows, +distinct families per call, capacity, and disjoint compact coordinate prefixes. +Discovery is followed by frozen strict admission, 69 admission controls, +12 bit-supplier controls, seven independent owner controls, and both exact +moment engines with all 47 outer inequalities. `data/EXPECTED.json` pins +the resulting word, programs, phase recipes, owner map, profile, and κ. -`evidence/ASSEMBLY.json.gz` preserves the unchanged assembler's complete -output. Its historical descriptions and comparison labels refer to its -predecessors. The profile, moment endpoints, κ, and outer inequalities are -the computed results for this candidate. +`evidence/VALIDATION.json` records the final cold run's environment, coverage, +and input hashes. `evidence/ASSEMBLY.json.gz` preserves the unchanged +assembler's complete output. Its historical descriptions and comparison +labels refer to its predecessors. The profile, moment endpoints, κ, and +outer inequalities are the computed results for this candidate. -`PROOF.md` explains the end frames, the packing certificate, and the complete -cost change. `SEARCH.json` records how the finite search found this candidate. -Search optimality is not needed to verify the construction. +`PROOF.md` explains the end frames, packing certificate, and complete cost +change. `SEARCH.json` records the finite discovery and subsequent composition +with U8. Search optimality is not needed to verify the construction. +`data/SELECTED942.json.gz` preserves the selected-result snapshot used only +for the numerical comparison; its source commit and hash are in `SOURCES.json`. This is a finite conditional witness for `T(n) = O(n (log n)^(1-kappa))`. The inherited all-size compiler, diff --git a/research/complex-rank7-end-pair/SEARCH.json b/research/complex-rank7-end-pair/SEARCH.json index 70b3b11415..32d2ce2fac 100644 --- a/research/complex-rank7-end-pair/SEARCH.json +++ b/research/complex-rank7-end-pair/SEARCH.json @@ -42,11 +42,18 @@ }, "search_code_sha256": "88e905223d3691c00bef5e6873d6709273ab2bdf7b2142797448ebab6a390730", "search_word_content_sha256": "9f63de243f867e2c52212b18d2253059a3bc965db4a981ecf18b73d83969006c", - "final_minimal_word_content_sha256": "796a40505ed9dc38d64c5b7856a0908e70bd9f22cd869edf01ebe66ac02ab15a", - "rebinding": "The final word removes unrelated frame rechoices. Its helper widths and local profile are identical. The frozen flow and literal owners are unchanged.", + "rebinding": "The first minimal end-pair word removed unrelated frame rechoices while preserving the search profile and helper widths. Later U8 composition changes the local paid profile but retains the entire helper-width vector, frozen flow and literal owners.", "original_flow_content_sha256": "7ff3e4c2bbe9e0beb2592888de7db962fd34971a025be841c8f1711b5139f8f1", "owner_content_sha256": "02bde66a90b8ae9b0c4d8d563ca2218ad1de851fa6dec3d1abb5d3a30ca3dd2a", - "global_profile": { + "idle_profile": { + "48": 2400 + }, + "rank_mass": 520704, + "deficit": 2560, + "search_moment_delta_at_baseline_b": "-0.119035908243901811918210669949724217035275333404321692154", + "required_admission": "unchanged native local and strict global replay plus independent exact repricing", + "end_pair_only_minimal_word_content_sha256": "796a40505ed9dc38d64c5b7856a0908e70bd9f22cd869edf01ebe66ac02ab15a", + "search_global_profile": { "1": 183024, "2": 25344, "3": 30384, @@ -54,14 +61,7 @@ "5": 4032, "8": 576, "48": 2400 - }, - "idle_profile": { - "48": 2400 - }, - "rank_mass": 520704, - "deficit": 2560, - "search_moment_delta_at_baseline_b": "-0.119035908243901811918210669949724217035275333404321692154", - "required_admission": "unchanged native local and strict global replay plus independent exact repricing" + } }, "earlier_searches": [ { @@ -77,8 +77,30 @@ "result": "Local savings did not overcome global packing cost. The new end dimensions change the width inventory and escape that restriction." } ], - "final_raw_word_sha256": "796a40505ed9dc38d64c5b7856a0908e70bd9f22cd869edf01ebe66ac02ab15a", + "final_raw_word_sha256": "096ed4abee4bb02c0d6f03bb8191510e57f6b1fcd34e8644f4fd336254e46411", "final_owner_sha256": "02bde66a90b8ae9b0c4d8d563ca2218ad1de851fa6dec3d1abb5d3a30ca3dd2a", "admission_status": "PASS_STRICTLY_IMPROVED_KAPPA_UNCHANGED_ADMISSION", - "kappa": "1661712108827881/1000000000000000000" + "kappa": "166202617947539/100000000000000000", + "composition": { + "date": "2026-10-13", + "source_pr": 869, + "source_commit": "73e86f69bf9a391e3c334999f7bbe3825dc42759", + "method": "Apply the same end subspace and eight B frames to the pinned U8 word. Its eight new early tails move the two affected tail entries from 140/141 to 148/149. All 504 helper widths otherwise match the prior end-pair candidate.", + "new_search_required": false, + "independent_point_audit": "Exact twelve-annotation difference and local delta {1:-6,2:+14,3:-8}; U8 scalar gates unchanged.", + "owner_reuse": "The full per-helper width vector is identical, so the frozen integer flow and literal owner payload remain valid. All roles, windows, charts, and controls are rechecked.", + "new_global_profile": { + "1": 183024, + "2": 25344, + "3": 31536, + "4": 11664, + "5": 5184, + "8": 576, + "48": 2400 + }, + "selected_comparison_pr": 942, + "selected_comparison_kappa": "1661960547713947/1000000000000000000", + "scope": "PR942 all-replica bound fixes the previous U8 profile and helper widths; this construction changes both." + }, + "original_end_pair_only_kappa": "1661712108827881/1000000000000000000" } diff --git a/research/complex-rank7-end-pair/SOURCES.json b/research/complex-rank7-end-pair/SOURCES.json index 3688f6c816..44936224d9 100644 --- a/research/complex-rank7-end-pair/SOURCES.json +++ b/research/complex-rank7-end-pair/SOURCES.json @@ -1,6 +1,6 @@ { "schema": "complex-rank7-end-pair-sources/1", - "base_commit": "f567884aeb8851b6e794af1184119a3bfbe1e631", + "base_commit": "407d52ff15b2217b6e22bce44728b4c3907b6515", "sources": [ { "pr": 741, @@ -22,7 +22,25 @@ "commit": "eca5c317d8176401a1f71a5ea1e81384c2eab1e0", "path": "research/pr699-frame-retiming", "manifest_sha256": "e0102586186663b2a667768565f61db184638b370f68f0ea58dd673e523173ec" + }, + { + "pr": 869, + "repository": "https://github.com/CrocSwap/integer-mult-bounds.git", + "commit": "73e86f69bf9a391e3c334999f7bbe3825dc42759", + "path": "research/gauge44-barch", + "manifest_sha256": "ffcafdcb4693211fdb95d1b7b3f5bfc54f203aa0cd2cd9dbdcdad32f42104e17" } ], - "research_start_commit": "66849e1475c930fd7732b1a0067ffee7e1e95f60" + "research_start_commit": "66849e1475c930fd7732b1a0067ffee7e1e95f60", + "submission_branch_base_commit": "66849e1475c930fd7732b1a0067ffee7e1e95f60", + "comparison_snapshot": { + "pr": 942, + "artifact": "data/SELECTED942.json.gz", + "repository": "https://github.com/CrocSwap/integer-mult-bounds.git", + "commit": "407d52ff15b2217b6e22bce44728b4c3907b6515", + "path": "certificates/selected-result.json", + "source_content_sha256": "1d35283cb0ce3f8db1f285683933517f9e87475d295e2b6316399ad9928c81c3", + "audited_source_commit": "1960cfa919a0945d0ca4cb14ea96237000037903", + "scope": "Immutable selected-result snapshot for numerical comparison; no T37 construction or enlarged prefix allowance is used." + } } diff --git a/research/complex-rank7-end-pair/audit_points.py b/research/complex-rank7-end-pair/audit_points.py index 181f210f08..32459874b2 100644 --- a/research/complex-rank7-end-pair/audit_points.py +++ b/research/complex-rank7-end-pair/audit_points.py @@ -14,8 +14,8 @@ from pathlib import Path -BASE_SHA = '1e1d99ba7aab877d6b573c41f7030ee73de9a52fee51d0a822ddaae71251999f' -WORD_SHA = '796a40505ed9dc38d64c5b7856a0908e70bd9f22cd869edf01ebe66ac02ab15a' +BASE_SHA = '090fd574747fbf9628e70cb9beb792732914cfa52e1df147579fe4dbccc68c5a' +WORD_SHA = '096ed4abee4bb02c0d6f03bb8191510e57f6b1fcd34e8644f4fd336254e46411' RECIPE = Path(__file__).resolve().parent / 'data/END-RECIPE.json' @@ -129,7 +129,7 @@ def check_edits(baseline, candidate, recipe): require([q for q, _, _ in recipe['ends']] == [588, 589], 'end sites') require([i for i, _, _ in recipe['B_frames']] == [1018, 1019, 1050, 1051, 1130, 1131, 1162, 1163], 'B-frame sites') - require([i for i, _, _, _ in recipe['early_cleanup']] == [140, 141], 'tail sites') + require([i for i, _, _, _ in recipe['early_cleanup']] == [148, 149], 'tail sites') changes = [] for q, old, new in recipe['ends']: require(baseline['helper_final'][str(q)] == old and candidate['helper_final'][str(q)] == new, 'literal end edit') diff --git a/research/complex-rank7-end-pair/build_owners.py b/research/complex-rank7-end-pair/build_owners.py index 887d444d70..27c856f06d 100644 --- a/research/complex-rank7-end-pair/build_owners.py +++ b/research/complex-rank7-end-pair/build_owners.py @@ -358,7 +358,7 @@ def main(): flow, word, plan = map(read, (flow_path, args.word, args.plan)) parent = read(args.source_template) if args.source_template else None word_hash = hashlib.sha256(raw(args.word)).hexdigest() - assert word_hash == '796a40505ed9dc38d64c5b7856a0908e70bd9f22cd869edf01ebe66ac02ab15a' + assert word_hash == '096ed4abee4bb02c0d6f03bb8191510e57f6b1fcd34e8644f4fd336254e46411' assert flow['schema'] == 'frozen-rank7-owner-flow/1' owners = expand(flow, plan) report = audit(flow, owners, plan, word, parent, word_hash) diff --git a/research/complex-rank7-end-pair/build_word.py b/research/complex-rank7-end-pair/build_word.py index c7e10bd6d7..915610f40d 100644 --- a/research/complex-rank7-end-pair/build_word.py +++ b/research/complex-rank7-end-pair/build_word.py @@ -1,4 +1,4 @@ -"""Apply the pinned twelve-frame recipe to the retained PR799 word. +"""Apply the pinned twelve-frame recipe to the retained PR869 U8 word. Prepared with OpenAI Codex assistance. Apache-2.0. """ @@ -9,8 +9,8 @@ from pathlib import Path -BASE_SHA = '1e1d99ba7aab877d6b573c41f7030ee73de9a52fee51d0a822ddaae71251999f' -WORD_SHA = '796a40505ed9dc38d64c5b7856a0908e70bd9f22cd869edf01ebe66ac02ab15a' +BASE_SHA = '090fd574747fbf9628e70cb9beb792732914cfa52e1df147579fe4dbccc68c5a' +WORD_SHA = '096ed4abee4bb02c0d6f03bb8191510e57f6b1fcd34e8644f4fd336254e46411' RECIPE = Path(__file__).resolve().parent / 'data/END-RECIPE.json' @@ -28,7 +28,7 @@ def build(source, recipe): require([q for q, _, _ in recipe['ends']] == [588, 589], 'end sites') require([i for i, _, _ in recipe['B_frames']] == [1018, 1019, 1050, 1051, 1130, 1131, 1162, 1163], 'B-frame sites') - require([i for i, _, _, _ in recipe['early_cleanup']] == [140, 141], 'tail sites') + require([i for i, _, _, _ in recipe['early_cleanup']] == [148, 149], 'tail sites') for q, old, new in recipe['ends']: require(word['helper_final'][str(q)] == old, 'old helper end') word['helper_final'][str(q)] = new diff --git a/research/complex-rank7-end-pair/code/admit_candidate.py b/research/complex-rank7-end-pair/code/admit_candidate.py index 7cc802cce0..18c47e0e54 100644 --- a/research/complex-rank7-end-pair/code/admit_candidate.py +++ b/research/complex-rank7-end-pair/code/admit_candidate.py @@ -5,6 +5,7 @@ """ import argparse from fractions import Fraction +import gzip import hashlib import json import os @@ -19,7 +20,8 @@ def read(path): - return json.loads(path.read_text()) + raw = path.read_bytes() + return json.loads(gzip.decompress(raw) if path.suffix == '.gz' else raw) def sha(path): @@ -54,12 +56,18 @@ def main(): ap.add_argument('--' + name, type=Path, required=True) add_native_arguments(ap) ap.add_argument('--owners', type=Path, help='Specified gzipped owner rows for the fresh native widths') + ap.add_argument('--comparison-record', type=Path, required=True, + help='Pinned selected-result record used for the strict improvement comparison') args = ap.parse_args() ancestor, replay, dep, checker, out = [getattr(args, name).resolve() for name in ('ancestor_package', 'ancestor_replay', 'dependency', 'checker_package', 'out')] natives = selected_native_directories(args) dispatch = selected_dispatch(args, natives) need(__debug__, 'Assertions must remain enabled') + comparison_path = args.comparison_record.resolve() + comparison_sha = sha(comparison_path) + comparison = read(comparison_path) + need(Fraction(comparison['kappa']) == Fraction(comparison['decimal']), 'Comparison record value') need(not out.exists(), 'Use a new output directory') need(not any(out.is_relative_to(p) for p in (ancestor, replay, dep, checker, *natives.values())), 'Output must be separate from input artifacts and source packages') @@ -146,7 +154,7 @@ def run(name, script, *arguments): kappa = expected['kappa'] need(kappa == assembly['kappa'] == owner_audit['kappa'] == price['prices']['native']['outer_with_bit']['kappa'], 'Independent kappa witnesses disagree') - baseline_kappa = read(dep / 'data/SPEC.json')['expected']['kappa'] + baseline_kappa = comparison['kappa'] need(Fraction(kappa) > Fraction(baseline_kappa), 'A strictly improved kappa is required') need(len(owner_audit['negative_controls']) == 7 and owner_audit['roles'] == 36288, 'Independent owner census') for mode in ('native', 'conservative'): @@ -162,10 +170,12 @@ def run(name, script, *arguments): need(len(bit['rejected_controls']) == 12 and bit['derived_deficit'] == 10272, 'Bit controls') result = {'status': 'PASS_STRICTLY_IMPROVED_KAPPA_UNCHANGED_ADMISSION', 'kappa': kappa, 'kappa_decimal': assembly['kappa_decimal'], 'baseline_kappa': baseline_kappa, + 'comparison_record_sha256': comparison_sha, 'gain': str(Fraction(kappa) - Fraction(baseline_kappa)), 'complex_lower': assembly['complex_lower'], 'bit_lower': assembly['bit_lower'], 'global_profile': assembly['complex_profile'], 'seconds': time.monotonic() - started, 'stages': stages, 'scope': 'Finite conditional native exact-complex witness. Hash-verified reuse of a fresh ancestral replay; full changed-native and global admission. Cited PR589 bit circuit is repriced with its surcharge and controls. All inherited all-size and analytic-transfer assumptions remain.'} + need(sha(comparison_path) == comparison_sha, 'Comparison record changed during admission') dump(out / 'RESULT.json', result) retained = [p for p in out.rglob('*') if p.is_file() and p.name != 'RECEIPT.json'] dump(out / 'RECEIPT.json', {'status': result['status'], diff --git a/research/complex-rank7-end-pair/data/END-RECIPE.json b/research/complex-rank7-end-pair/data/END-RECIPE.json index 612ee756ef..c301e8d383 100644 --- a/research/complex-rank7-end-pair/data/END-RECIPE.json +++ b/research/complex-rank7-end-pair/data/END-RECIPE.json @@ -1,6 +1,6 @@ { "schema": 1, - "input_sha256": "1e1d99ba7aab877d6b573c41f7030ee73de9a52fee51d0a822ddaae71251999f", + "input_sha256": "090fd574747fbf9628e70cb9beb792732914cfa52e1df147579fe4dbccc68c5a", "ends": [ [588, [256, 128, 96, 16, 8, 4, 2, 1], [256, 128, 96, 17, 9, 5, 3]], [589, [256, 128, 96, 16, 8, 4, 2, 1], [256, 128, 96, 17, 9, 5, 3]] @@ -16,12 +16,12 @@ [1163, [265, 136, 96, 24, 4, 3], [265, 140, 96, 24, 3]] ], "early_cleanup": [ - [140, 140, [256, 128, 96, 16, 8, 4, 2, 1], [256, 128, 96, 17, 9, 5, 3]], - [141, 141, [256, 128, 96, 16, 8, 4, 2, 1], [256, 128, 96, 17, 9, 5, 3]] + [148, 148, [256, 128, 96, 16, 8, 4, 2, 1], [256, 128, 96, 17, 9, 5, 3]], + [149, 149, [256, 128, 96, 16, 8, 4, 2, 1], [256, 128, 96, 17, 9, 5, 3]] ], "expected": { - "output_sha256": "796a40505ed9dc38d64c5b7856a0908e70bd9f22cd869edf01ebe66ac02ab15a", - "local_profile": {"1": 2542, "2": 352, "3": 422, "4": 194, "5": 56, "8": 8}, + "output_sha256": "096ed4abee4bb02c0d6f03bb8191510e57f6b1fcd34e8644f4fd336254e46411", + "local_profile": {"1": 2542, "2": 352, "3": 438, "4": 162, "5": 72, "8": 8}, "local_rank_mass": 5632, "width_inventory": {"4": 80, "5": 32, "7": 56, "8": 120, "9": 216} } diff --git a/research/complex-rank7-end-pair/data/EXPECTED.json b/research/complex-rank7-end-pair/data/EXPECTED.json index df4c057c5c..083c78b951 100644 --- a/research/complex-rank7-end-pair/data/EXPECTED.json +++ b/research/complex-rank7-end-pair/data/EXPECTED.json @@ -1,36 +1,36 @@ { - "kappa": "1661712108827881/1000000000000000000", - "kappa_decimal": "0.001661712108827881", - "baseline_kappa": "1661634653669567/1000000000000000000", - "gain": "38727579157/500000000000000000", - "complex_lower": "832238996031084233427/500000000000000000000000", + "kappa": "166202617947539/100000000000000000", + "kappa_decimal": "0.00166202617947539", + "baseline_kappa": "1661960547713947/1000000000000000000", + "gain": "65631761443/1000000000000000000", + "complex_lower": "6659172436825204659/4000000000000000000000", "bit_lower": "1733427039589844234749/1000000000000000000000000", "global_profile": { "1": 183024, "2": 25344, - "3": 30384, - "4": 13968, - "5": 4032, + "3": 31536, + "4": 11664, + "5": 5184, "8": 576, "48": 2400 }, "baseline_word_sha256": "1e1d99ba7aab877d6b573c41f7030ee73de9a52fee51d0a822ddaae71251999f", - "word_sha256": "796a40505ed9dc38d64c5b7856a0908e70bd9f22cd869edf01ebe66ac02ab15a", + "word_sha256": "096ed4abee4bb02c0d6f03bb8191510e57f6b1fcd34e8644f4fd336254e46411", "owners_sha256": "02bde66a90b8ae9b0c4d8d563ca2218ad1de851fa6dec3d1abb5d3a30ca3dd2a", "native_pins": { - "canonical_sha256": "d5988057b8d06e8ea7a430283d55d6e36c1602bc989007b70839a257500b4518", + "canonical_sha256": "9c071e0491181435c2fcb6dc84343a6a878e38be5ece1545199af06b62310d3f", "program_sha256": { - "forward": "0732bf8ab48f08b2d8f07c3c5d1109c12c149ea69bb2b14ba8847c9703876c08", - "backward": "2b918db2ec63a5503551f84023b6881196e2cc1511fd3e2b43be3b5b633b434d" + "forward": "1acecc4bc9daaad1f68bfd65d87b6c14a12319695d23d2faf4e13c9f5efc9b37", + "backward": "53adb146aafd679ac18a3b7498b134c4e99f15a9b89a86f6a4df829a9e6a8168" }, - "clifford_recipes_sha256": "9b39a953ab1912aa3f48a5bd438c7b38554a48dfc0d51faf47a8be25e7605e5d" + "clifford_recipes_sha256": "dc9323bd5bde9d238688685fb15b25f15e8badeea328eddba7419fc2d5404bf7" }, "local_profile": { "1": 2542, "2": 352, - "3": 422, - "4": 194, - "5": 56, + "3": 438, + "4": 162, + "5": 72, "8": 8 }, "phase_edges": 2950, @@ -38,5 +38,6 @@ "inherited_cold_controls": 89, "strict_admission_controls": 69, "bit_controls": 12, - "independent_owner_controls": 7 + "independent_owner_controls": 7, + "u8_word_sha256": "090fd574747fbf9628e70cb9beb792732914cfa52e1df147579fe4dbccc68c5a" } diff --git a/research/complex-rank7-end-pair/data/OWNER-FLOW.json.gz b/research/complex-rank7-end-pair/data/OWNER-FLOW.json.gz index bcff36f310fafd500b5acaca2959377e7e4014d3..59cf38b88e8129f44df50363eb24c7fbf34f29f4 100644 GIT binary patch delta 5225 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 M4T2I##ad$k02snS4*&oF diff --git a/research/complex-rank7-end-pair/data/SELECTED942.json.gz b/research/complex-rank7-end-pair/data/SELECTED942.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..547cae7e92377cb9c20ae7947cbd454b806de6a6 GIT binary patch literal 4208 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 GBLD!bBtw}1 literal 0 HcmV?d00001 diff --git a/research/complex-rank7-end-pair/end_controls.py b/research/complex-rank7-end-pair/end_controls.py index 91895fac5e..9dacd8b285 100644 --- a/research/complex-rank7-end-pair/end_controls.py +++ b/research/complex-rank7-end-pair/end_controls.py @@ -13,7 +13,7 @@ import tempfile -WORD_SHA = '796a40505ed9dc38d64c5b7856a0908e70bd9f22cd869edf01ebe66ac02ab15a' +WORD_SHA = '096ed4abee4bb02c0d6f03bb8191510e57f6b1fcd34e8644f4fd336254e46411' RECIPE = Path(__file__).resolve().parent / 'data/END-RECIPE.json' diff --git a/research/complex-rank7-end-pair/evidence/ASSEMBLY.json.gz b/research/complex-rank7-end-pair/evidence/ASSEMBLY.json.gz index 7370b8bf42b580da58d0f7133b6de590455f70e7..9ec207f2db9a079ac8babdfce93d82e9b1b90a6c 100644 GIT binary patch literal 17778 zcmV)OK(@ahiwFP!00002|LvV?b7R+aroa1Fu=-Py>K6C?VwXQS9+hWGO2(CFrZSaE zu?~O(HX;yU0I*wf%Kv@dXC0C)_C@TrEvZ{NOhs;jz`;3tulrj2egFGcXJ=22r{Q#S zeDdqFCx86izy9mRAAa|L{_uH97ytabum0En{ruwdfBW6`1NpoJ@7eSN^qh0+EdN3pL_TE&v!m>u^N|~t6|Fr-Dl3d_TlNB%l*~$ zcKqgIyMH+zcxNfO`x;U#E#%;memzg_Z9fk$@aC7L+M{ZTX+M3a@95c_*Q%gv2trIhuZZ_y}D9;_Px~5S}3)LlAF`=rW|~){^1&3 zANK3bcGUI%TQBPmUjOthx{#huF9f|1^y$0bqkfM*$8!67;sdPh?eAH?XW#CAZTwpA z-^{N;o2Os@Y&W7Cc(GaOd6)Z}-Rb!1MlOe&%Q12F8t&hHyg4kN4~NU~;%dJdx3AuP zw}`(!TMyggc>8tQ6uojf+>G~ESnhYn@$h0eZC;EQZ-`opA@-8999m-zIsP*#W(=qO;r^EG)n_rb zoO=$T7T5GGRhC1~jh2)cbLc*06eq@b?n_IZ%_yZ8{egGu-wj>uvDKg#rCdR`nYCZ8 z)s|~>uC!jWewSR|-zDEIU6+0q--2t}Z@nwF;DhHM`cTjl%a*0?O3|0g8g%_ZKho>y zd$V7%R5j_py-CMp@w~n=1n+h2(27(iOSxS3A?f*^+A6*SBh>uf%GzSTKOIkp;rdO>IDT`z-`)D=hM z>|M8j<&cimoLj817Ok-qH_K7uh%F+}{&-hgkTvqsWvoqQTUh**&~=$eiK;Y8dvqQ? z?7=?x=ar~m+JinRwPBxX>$QCQWw0&k7Wri-Q=Xr^)!KY_M}v8fT=hiV2L)2C zWi5o4=SnRpwA1DU?Pn=IN}gq0dh$iy0T&@p=cS2Kq(Jc3s z*x`eut1MMl#3qx^O6k|sqpm3@;)|UB54~)Et;FOKWoW#djI=aAe~BASqH- zfNV8{S8tEnfr7|31s0NDnHFhr?_H`O-IX(Jq2V=jH&XZDs@z6*EVb+qX_7Wc+b5xv z^;Qgm=ZNwsdRbT1uZl?&Q#ft1?1sKZAL1+YxrDuoQV8GA%SX01f33{R91y^Ht$|h` zXuYJ@GIk2GV<$R7zneUiL{y3)<<8n5xj((nY1OKta=lG~qMQI5z((l5@@S-O(jZ5) znq@%sQ3ZiAAYGeMr3+P?sEbxYXa$)?zow)#PmWPhjpu9hA-+PN%lflkk*V=NpG|m8 zpQH|v>Ok{F=0S@p6_L4!k1Lfv6to8kJ(8i9TT?hI`y=by9hxb_)f724vTWHXEqx+; z%ZUwfPI50FF0-eYNgEL5zh&T?b|%VB>8jdmy)M;g3g2~oS+__iFQ1_}K%1_O>ZUvr z7g@a!W%uRxNgcdCWGXNF=yXp-x928HsEkf8$zjOVRIG_o3|xy|kUiCHB)pM4R4#f9 zeO~`_9{s1i|9`E{vU+kh+H6d&G*>=a>!RPZU^1RsS!t>^SAWsFuzQMf6wD+!GDnnY zVO*7GQW9AyvLvO{S^6pmh;a0(RHzXaDCUh45^aH0kE~0Ysc$FBc;dsa_zjnSub$gxlz%P0O^~Ry6W?K`!9EgUo!}S^hHSv zZc%!xyf-H4f>cS0_#VDCpf!r|pf&Ga+Qf-4KZv%UnmDs@M)g%nLLQBmi&|6Cx@eu-19wh zIP$R)oGkIxO-pqoNmJw(DJRJ9D1cFvFMCLg9{emmf1ypI zf~pAIlEtDV+oF1^HAdn6Ik0xj#A zEK5WgWXt4WCGIkgQJNvYDcdB6ri=6vWQHgkN5W(ZwT?8oT4_PX4x?J|p8AoJDf=X2 zbd)S2H?NFGwoYk!#yu;XD|BLH$fl@T%c!KqEMv1whJ;@3nsk(MwQMeNrJRZWE
zWs4gRd#=@)CHaT5o1rTBWrO8RCG?44#}Sob`V=CwZ4JSdT~#`&;7-wZCr4Gpl?y4D zURT&HQ>KpvrAl(y5>8oKSxua?WRP&YphAlAl>_Jl@|}UOT_P(xspy`#P@?A9brJBfSb4 z$tmkr>a0}Gtgg5Gjw-GMnv#+p6??91P?<)e3Z?8)E?ssW{pqu4{x~){k^#m@Dv${B zv;&=NO&cjg5h^N)z0eU6lh|lbS&dZAJ-A~OF-msWk|cX zVgv0dPhCdRAgLsmrQGNXwHTC0p+z7xRA`ZKB3(vOUOCg{BFm&tXr(Amp6e_Uk$@>q zq_U@+GE1aMb0v*-hmqXJBjU28vbV)FRr1#fxUt5%cVb`S8g7axKubg+)uX!#bm?Vf z1-@N*4Shiwbz0gyG-YNS384Z$p<6{uUyrs>|I>ZZUn?ZhbnxW1v^Yf7y0r8}52XK< z#aHg$C}tBunK7u+V^)qDJgz1xZBqI?tINk@_!Wv4Vn+#eCNsi7D&8sVxB_K~E(Ln+ zpq1w-g~>rHP(XXA9=AyOE0eM58pO2JTJ^GoKwIx*IAyNMz2yY>qlCCy`cDEU9VRMQ zGNjxt$y$^AD?pIM7n`q;;5gbh@*b!^N|0%qc@v@DXb+RF*-eo=$uTKTm&`hv@e)}@ zT+&;mrwTukzOXiWMNR5K&?7a95_TMpz6V3z3jqub0vc#uZ>O{%2dF2K4kXe6dYaUQ z8@)|Er(!!fok-$o@mWBPv~u)o@MFc#a{rOG2P`-(lD=&1z(DNGAOS@u*)+*^*Z;}t zDbaKF$@ldz_cte-Zu#%~p_q&7{c*$JX0J1QonO56-4DYJi#;v>&FRhqQP?jMd&z_} zfYBXF>QYRGC1wvad!V164lKs){^f;I5}QJelQWv)tw^Fv?~=B@#O|@ty(f$DG(2!M z{?T!(=`;5?!H4=gejdNpb{y6h$Kl0hcloAn7Ybf-o^y0L>-NuFxBu&b5=IF>L#Qz` zo93zS7pam}U?usUI4>~bMD0pipm$~)X5PGiGeZ2ZJIi$@_iPUbItDm!`pDt^fwdGUL7NRc;`m|L9Iwnq%I$6OKm<^65 zZ3-Yf!AxQzl<-BaA=1rY#!5=W6seQo*^rgOF;5SX@vP4A2*w>`s2PlMjF>Z9>e>{N z^oWh^oxu!du;l|7QdLxgeln&N73efwoLP6ttc0DBMt!X`MG_w@?vf>Ut_BlQPFvB` zX1*gL?Q)3$uchxInzLh9QXmHSqy_qFeM<7~>De%8ADObSKv5r16sD+37C~M~T0+B! z&`!xE14L3Y=J@5X6bH)BIMWT(wKCUH6&un#WhPKwPb)jC%O{z5y+?4Cv95~d=iqD( z&gP%j_2)sgK$&mns0IE;vPXDSh&`kMbY?q)8`Z)#%dsWOPWE>8L9-8Eqz`l@U zkQC(_Ii4&9~r`|_|jr!>?B7^L)xTN*JLJ7 zqT1wsyc}JN94clgz41?P2k51HM2j9rRqWu6=j^=%oa0cvm^sixH3m>C9-A@Fr2lxP zSUKIoOf)K}=r}PL%jr|D!+8#l!+0}Al)y`wmFCk|nz;ry`f2L-%&JYlYY&p#ichU4{dv)%6=PTJXy zr8kD=m}P5q-pQZl2Sq9z@tf`2$7J7LSER@NQ2;W*$9cbgGJiCy(MPLBmp8*%toB!%-EbO@ zoVER)kvj^}+8tItg#dUPfG~h_Ye#abcHV|ICHPsC_Z-NXg_>Nc_M)TW3@&GEdR=1R zQVUw7uI$Qe87lIxT?#?L?P#4a#mVw+w(MHASlGl+c?@0KMMc zg5IVTve%NXYP$qL8Kt>mn3VdPzLIhrxxAGIC4V{cv@KW}oyt9Rd7zzHW&qQ`ani<7 ztqaINGZ2)LL((E72U?IMmt#f<7cfzJ*a<2J7|f_!FCbABJICzJk{L9ao&lg92@ddT zl6DY>19DKmuO2un-6yAXhjF=AM0mVeuQ%V!A>r)L=56`Vkns9Bxcb}ua+-X208XjT zg_dpknw*U`q1MJEQS(|CncDs+qoLjA!thAQ7M|gJv_-7S}z8IMjs)?JTca^vu zIVQjc<%(jI3j$58*3>{B26PzGnGC9y_AzJ~N|(=YEUa$O>o#a`X(hEhGVly9$=>VH zGi_9T7bj>zlTQYHFGtWp81x1uPiK~e4wAH{{Q*QhF^|-`_DBAduC*i$Uzm7wUnDqk zEvYFCY4+4Z+5F;%EVqFMF&G(rLikD zt2SK#W;AB8AYgr>L(sBI(ux)@~V@(~f>Mo`Q%raT6lElftAV*rr>INJoWH)Dc^U$5mZ z0CT@<&_W{hw(XK3h!FG`wMlkH>QFh@4^BRy-Znl6A%}btNU8}Y9&NKCVjN70=vHN| z6pB|R00gbF3J979$P%As^8i3fN?w7C#yH9^Adn5nV8heRW|KM#7>xtLW^5AJ-gNsz zOs0GKn08j?Lr#x*%!W1@!hArID)0rx;`a*hp*F(FS~f|5B!L_NFz{dp_Q_-PfA}J) zyD>uPnPuDXIMNaz72z-H5kT{1!eZhIuAt;x>sW1GN1D*-;*%5=26o^r3ZO3Xyba7+ z$*a~yo74+9Nu5Ib2;03KSRH&2AhfI=1uhXdimqZtnmdhTZBG=exY6{e>f! z33$u#kZv%KG8Oajke^`AL;qrQ_q(XH;Bf$#F9((QbJsrnJoif9c70q#Oz?O>{aTUn2(OEs?3ZYU49|pi6#JVxor8Xz@|a0fr(`C zLA(GuJAuCiSV(ckw*;k&QN<8tIA*4$u)Q+btlIz>gw15#NP8>T9)&41fOc`Spn(?S zfHA;+eF{4lh{+>3r!b!YJBnKK9H0=%L;=cM&B`UbxxOUekD#KFgh;mJP-F)|jV?wB zg$1Tg0pSW!Kqgvc*j`)@%dc-a4d(=JPVnY!`H%!} z*ec$99G4FVMQJc%6AM;LHnc%E5jasn_$i-I2#aMeiDWQaAOQygK_V{MY=Y}<0iA_x zGL3{-U?-CvG$4<(UX2CP4#^kFY}Gb-Hy8k5r3k>n8wClF*bQPZi}gr6^zE>RY1O)o z`~m{*U@AgnDE%oI;z$QT#ul!0<2Zqv(!)bQa0BYNHl}iP!?E{)(27GSIH69NQWD0E z%0V@(w1JFI%s7pR3<`~aU#E4F*m@&8A_r8Ef+ObkCH%_ENW}nWuGDRzKP4z7*7n>8 z3nlB^!n?AocupC2W{{biHh0h{Gm~B!r4u3?;0J*+sF0@;qr(hV zETKp864FGDOu5vV>xL%+(y<8q{w;%?#qy9mczlIIKoI%i7=fh3xWxjS!*fU+jF71E zwF=y{p~=qkkmW%Kpg4t`0IaEIkqyjJ+FLyUOI*OJ!ZXSDN{}on*52qIB$kB*FO&~h ze>AW|PDDtmMd(uE2q6clF_|GATJl9HfyfJ5H9WqD-om(X*e{@|WEC9O(_iHC6&1^P zXmi=%WHg@=n8*Crq;n6aJ>C&FO8Ctu&&Knk@@cc){S5T(V!gjPOtT^o&`4sac}PvD z&2sq_d?QTj8%U{twFDxKIw=S-CzD#6w|2z$}Fi#%E4V*I6+W$`PuFv>$4< zvXFva0{_gWB zGojY)(5gTW%cKKchYXEgw}wz7wc)Q;&cqrP&h){P+l*n+F=J3I_&^2Gk^R?6Ox+7Q7cDQfH_U#s`kwR|-G+CO1CH7O3Ny@WP|s#HZ2m)^rl1e$q6~?Q zAoMW`y0THs$t=U>HE~^0#tM{_v0xbIqU#vIY=*TBVx$N`2u4NQT{t{wWWvUCqg%qz zu;u3xih$RlA;KAcD`|T|OUh(D+QzV1&9W2^hZyzoLYBw6Ss{^r3orr+OIU5w0u?Jq zO4B*Ai3!4i2BRM%+BNW6y_$fTZB&vHn6Z+}0?##tIt8o~y<9ZvVme~Z+Gd_E9R^-v zk|>kfsePJ%)(;}rqd`fv9Y$MISjvyU-B$~AI|ac8&a|U{s-nrLa(zA0c={3@P@ps#iISfK>(1`cBJ_>Qh+ptWEBkPZUGS8 zGh7?mVLp(4p7Bo8UqX(FDCtFc$|z7tl7wNps)AP=SX09(@rgha@; zXkS?itWrfP9Hmx>Lga#329t!vp+VYsOnDEc=4d&ap(4}|MkE+1UQvA4$|UOuV_Cdx z8(}-0)H$r+3S7rMHgj%^i=!*TePoFbz;QS|`Nn-WzScmlMG0mY4&RQ4xA`I&W9m-SZ#sfT4l9?;*rOxL zAirX$zQa4hxS`$>EKKv{rx{n`2;Cx?cc3Opv#-EuTBnK}M++M9OvWqOw+R0y07ZykG)}jkG?I$aU&@dYiNw%Vy&rWWI7m z4ev@lF=3(TJz5wjdG|IV*RXF)U=Se7wh^ut>t$kjWtVHUISIKB=A)oGHN-cgLE(Ok z=$FnS9Y`}3$sRD_o5+5dQOnjN^h}AGeo<#6$im?mpd2~{7yEp;;FCREu(;WNeV_Kt z9%=SS^Uo{g_``5>JZ^^F#cVGdU*fMXUFDkui*DI`N^#R)KG&9tq} zdT)}>MzN78K^dA(!o#sJ$xmWl)meGZQ%lcg%RLndU+In%j)_Tx3Xr5E57gkHlCLBb z%*H0lEOcuUOv()6GH$|Y09n6EYNJ0x8ZSdPjjuM65-Bqd0lnn#8Fj`$hfP9E`XZ}N z6);nIt~3&CrngX3#3{CJc{+smt$E z_lK|F@JF7iF$IA}JBeC@q=&{OLq^QyI_qXrV51a9qn1K9?Qff9rMzf|Md=@7zUft3 zL6HR^CZR>92!n;B>?OZtClILOb)Jt%C0MqOB)QZmNFCZZs+hL?qmHbE%FU<>L*L+M%M%c!61*dO96RFB5v}J`Z7u<=qvOh$g@jnj(iqU_@KAG7ywRB^ z&C-@84h=FvK^~|ardq;=dOOg)$#t3?HV8<>TnhYTOMz0jKflQ@u3t`v{TArQf1gxx zH-2-vxIAoDcRKo~@vy%bPs4-X7vFi|X16&_FWhsOU+q`p_H7rx`__rDcHFJ5_nRGq zB>y=sPb0`fr{@>@EeFmI%jd)4a=iPN{nh4lf(;f9^!vZcQ{QZvK-p|B?9N}iq)f}J zySo4O!(sZ<#pSTsSs?ux!)d*L{>%sa!Y8Luw@AVC_NpH- zod-B$7t0Wr6f4r2NKgv6q}#lR>!FO&qSeYThBjSzv%9`Iy}IfxvHSkzj)K$8Y9hHE z!n*YlL3YC;kHikkAuPgrRnu5TrNxW98W!vIu_nf?4uqTaS`n zUA_!utss(&Jq=6guggOl^ukEmyH5AuZoA9PZakh}?I~SBq%F=BLC#H!NLG zOPQe|FT+Bgl&Fo_E!IrXYf)rMmwBjZ8JELqsV|GmS2{iE#P#)dGagXZNeuwVY`%i;Q*GeDQ);n~&A_Vmm;>BsLBMXzoJG7sxzTPiQ><4`2cb(#HY zz2as@7naMq@NtpK-6yX`Dd*~9FihD+lnk}39bTk`3Gz4&Zr$8!Azv&FB8nXPtFuYN zG@b@F?I1-zAKNoM;j?R*!e^(O-MBjEzvmC-?d}*N#%Q}=pkkh@jLM}}t0gHEsYYG* zwIa5)Vwb^dS;MO7-gWnP7f|fKx?e;6{zAX#i=W>8z8aUZZU?N}@igpMo)Yi>y4+uX zdvO?cU%#??{M4sE&_8eg^&j@Xf4-miJIK(jE>2Uv7d-YtWbx9RMkep}KjFc8_qZ!eB|NV6ut-^ga4-RxwG zciQf=I}!ZN+3ES_cs3l5g$}xA&6t{&r`Q2>5xr%^7JqI zcAE2li*LV^%lmb?Gq10$OSLgBZ*WS?19s-F&+}hUFq^JNbs*Azh!j@}^@7ebeOL+Z zZCdp=khNlLHw+YTnv3c7{tme9w@BG~*d8AfGwlZTKLz6oGc)BrjyrR1i>ik2WhYCU362?+sx)h;<76t;OcA>F-L)0UpH5z{e3*Y%<`p=xmMK7zODBf^NZlnIw7aU!VtEC` z?<-=>%8rdO5GB)~7BH#$VIuZG#wf6J?i$u5Mn`(Gr+l}`_-lmhHdKDQpgk0c2a-lz zuQIgS?2xj4eSb-NAA1J$OX3(s=KP(_x&oKR5DGOSC34YQe?bQ0Z*R{&;M?nuYtImK zg%*#9*Mo92otM5Uqrx!sDU{JUx3inose{|dPEtrP4N*tcH z+OSLQ=OukyJ=Isj5lGn!gP6e%lliF+3RV-ap;*BVEDA>%IGn)x(R4@vt$5mzjiMW^ z9fo2$#|LQx(wSnOoEZYfGl89ogfu|MNE{0%3n@W~zqyWo&Iu*6VDJl*`dYWm` zS{C4ARclBPY--VIs-dfagPTlfDa*lXSuHuzNHVB8S$>Y0Xv63-=&$FrYChdbfmc$^ z5HurUhSbO5H_V>LW^~4=XoxVa(rDp!yu87gNn06t#-l3ssRlSipWm8R^k~@vVyPUN z8K6T?tJ~QXX*XIElTI!ufYPQ=fB^zkiP<(?2N)p*@|;L(SRm<^|MVCAHFcrtPkWcv zWwtpX7Pp4?FxPbAn0$*&zmcYME-x7HoFVpNa+7+&G1(uPmHf z!)I0caWs}Y$5A{}KpuRIz`?!*j|^@5#@RTulcT5fH5f7kMiR>u^tOWq1 zZvDj0!M#QobNULK_Q-a`ifAemqX13SasfB0Q%(uV{oH@v)W-n1ubrU=hth)?$N}?g zNP~vY%*kcc4qR%^i*xL!(LmKA0@p$m#Z~Bw(bexZ&m)%}I6Ozh*)7*$z6`Ehg<5u4 zN8dq1o5`_E#tUkv_Ml)ED^1Zxt$@Q$9F@cYa&F1KB4E7}$2?{9r)F@Yr{w{s1_=6> zwwtdhI%mlM3Fi<9aTHkC4cMN5cY9pj$yz!)$~jX|+AtOwmj*f+XD68rw8LObMUaGY zqLi~B9F-+MqZMv6$xH$zrWrZR8f+kev!Biabp6plfgA&0c9g^pk8v`D`7gl7mHZ~s zV;~Nq!_r%k#xueL#uyW}GA|9pvt%7e&f9Zb#nVl70LNh@=$HccW`oNdBgQD9 zxIpFCFnj|)5wOH$u6Slo63nUa29zB*5RB#-ZXX{nY*V6;lJFu72I7do6{a%4@n=aa zMa*RI_JDaRK+v~EJMss1U?TWqB$d$u;D9@}#|CN*w*k}PG7aUh}R-7la={8rX zoS%t(P@Eaof(gK8S2+1rfPj@l0bW67(J%;#&Gmydz)&|(i4hP-uF82;=DL9T;$%Z% z8iaWWz#p@rG9n%c;0+L92<{b+FvJ1Q2ww>L3xhs}sw-iY069aF1c?C<1H&+3pp#UF z%JNizqBhzYUu2|-xzfbkN2G%u=*ogbkeM!Tozf6PrZU|&!pPx1OeIJ4nE>JHWEIr_ zw9maE8O%R_GXqF+5u6~p`> zKavhowXYKyfg%o~N*HSz$8;nMaTNhlLxF-(OFOJ@vz*x=kZJGMX2>28 zDRIojsNTtmn1crb2BiSXh65`F`C>epk~&36iCLyFsaOG-;+Q{>M>6Zw!9XpbmS$fG zU>zOn%y2oGI>)-IVai1VKqH*Z1spOX5@7nbG8kF`0>}YyRq%)ka2t9R3X2FVDosd^ zQ*zF&-1g38&cW3nas!i9K{m%qbQM2K^~X^p$3q7|Y@>mNb3%s$v6dNg1_A6ci&`T{ zbWdJu$=NvItBF14_#U9U&0b>m5ah40VD{9&h_9*|iGnL7} ztO<}hC*r-qgE_*cPSLd5SgVB3&i^qf<1BPDgi8;*g9$_Th)sY*tl8viw;H=0_=KCa zRZe+JTq^L`obn^IA>K1MzywAM_{vPTfWgV3Q;;NR=QZg0th@xGADlO|n2|zLJI+og z1E;X=62v_eoD2yD6#~K7nnKOyrkJJWNP29ZL#NIrDD^i$u^|AWe`N<&nbeptQ=|1Z zX%&0Jvj!3|M9*M4u&3|Pf*6dScmDY}v}1B6Mjy1BXf5Yd<;P1^W@Y#Ym4U#>6afHZ z<9B3-so6)kZkV@{eZ%BKUk2l02Bh00fcXy%|?=np}laFn?oSQK=e6?!q|=kHhXJ( z!5Z0MC}?0RaGD-qlZh%bn%)B85NL%NBw9t2z*DhKFeu-kB}t_-P%e$Liyf|W8pyyA z0sEYcY}Pp4q^Ql&R;mp6`aF9E_sK^b#230_6tN zQyc^GFe=$BJJfK%I&yANVVH-4N)`g(VesJ`4wYj{9`DIeJ**+bsCYUsuY#d!O=x5s zMa7TJD)FhQ#9Xd+TwIR(tMN2ppa&Qk<`I=yLFQd} zEJyj`Vzs|A3gIJXAHQe1i!TH=v%o)?;D6#^2uQka;(DpZVhvLo#4+H`c;M!WQG0oB zTu^i!;gM;;gG00f2a1*<)rmC@5I=p5a#*l%66Z`H`vM69jA(uZK#MjYD1zPP;E zSaW;{$gYXgnb7-ygaw%lNLet*07UCtKor4Sf(NKsSq#uSmK>6M1SCKvSppP5 z06oGAZn7YWg$NcLNRUN~p)@p4iL3xrSasvZ&cvCJ1_To$K@FjS&@BLH2of;_tFFQn z0m^_R*hs{{nS5srZC0s|UZoD>a({s7X1(5gGY4z4FPeAZVX$_~#l2rnefmUOBxej_ zH;)ps=fGcvHxB?xh9)8E#FN0QZK&n|RKk~KBb9VcWa8oZ>(OyskDdnHpAqX`0djJ( z>l4mSXJ^4pbBu?uteoW2?~rmsUm1Z}^+s>z0n?=C2;wz_VKAX_&@a$7GMZ|eq+v!T z!x|3#9wc&EH^@0j?O)1pAwX_cu;y?I1L!D^;X(dnv)XjJ67+g6-w?TPtsr8wE+MRyu1zA;+try|rSUEpHDLkx|G{;3(njB?Cdp zWD52^IQzgG^HHG$A;FRPcBqvV_LdaJU&>qCFm9`~+|f+H{_@ zJW97XDU@+M4O0drSpjl6$pZ8Yzhid5zdFP11K$@OU3jpqd&#{)Pzco{YSW}s4aoc0 zjic8fYf)nalFlaVnb-;D2B4USsZncR?Z`81fzl?JT4|~}mVBbzhG}VB^)UB27#VeESY3>Pj4dq5ot5Jd zZ<%;$A?Sr1*_oY4kO~7G7Lleh@gLghd-(^DCcOKYc#NV^A9ZQ!h?hq1m7EBrrK@*UIhTa!g zHK-Y~k#;(R_^!B=YSSj%5S(eSt8(%jKz1p)&Fyx;Tp?Wvg zcAhjo#ut1!TwM(c;TGG?ZX6C%YcxFCRUNn6yTkLtZe^gbP#C|Z-vfG_f6Ezx0s;4Y zM&L)9Nr1>$YVSZeVCV?Lg2y8s=*c`e)1+YB0&%OWX;*+Ltk~(u;H$J2^mC8fKxHAJ zfiRYlA_rzF1LBjExB7@}a{sADlcUSpPkFiJlLg$#z0BTxg;yaQk? zD+}2-x%s2+%|;DuwDZNVy?~=~v%8!#t2wipci~}XHEb0MK8`eImjg@HL(50JOQzrr z_djuWit6yO6$W_Sdcm@QDh-}VCi;MOTtNxB6ln?3R0WJUvd`TJ${EP7kj`gTR6#VT zrUk?mOe?-FSgFo1Rj~p_1D_$()=op-J{@HMTwGS4jp8VPe2VOvhkQE{m^u)%soYU~ zWXQB&b^@UbeBhB_JTMyCp@fD(%rIq$eK2dDGz14KIb$IR*1@`l&>6JtiYYhu<@kDY zV+aFOBr=4=u|!gxC=&5yRu(=JBPZ!HgtB_?9uGBM^S2D+5==6Oo1o(c|JX5r3z3c1 zOd^VpFWquf1s6DV(qr?d5@W4nWmr}3q&^GA7MwrT=<*_d7gTPAjc5Wp0t9cs%4b99 zaj;M@2V9LebE0CC*MKvIsapuSsgV-%v8XsaNUPCc5*)3W0m>`eRQ#v)>iD#7Q9V%| z5a$)XFJe<39U^qL0xlTI--ljlK-|!`8!gyHM(80~(&d zjM6e`F$58<+6kR*sdSI%6fO=#zd%PB0!K1i)P<&MCHV4G2qe@Ec0O2bC^{+hqdEx> zGlszeQzHS?3QmVtacQm?(?cSHn-B}7Q5jN;OcD-KDN<()8$_WHAW|*B6?bq2Ig<*x zBt-z|jJd%AZz%pRP`D-sZ^lQLY=;#FLcGz5YEe}?-qfHZgc+Glry>F`luzAA?m9I9 z@DDpDj%0E=1TW1zFBLe-K8_+ov9WLXRsku7&Qn6^%)v|ReM`SLlA{vb&WZMmU)FLmLteXHWuz@g$NX= zG8mgN8!a^l(v0uZLK=&?Ici+Gu`6K1xIg;u>`1X%ErAPVrvja+gA0U8x1I>=87N)# zZnY)|cxR2 z^1+x2t&m=`u0pBsTohxAqwEFAy7W#qUYGPtZNLvDi$sNA9;x#XT4I~7AXs#kF;NnV zl!r{f!OXVukghvX&5Iot;J~N zh$tWHp&bRt9dqXyAOe*d>N1F7%vz*Mz(I^gIg!YvH>;&mx$IV#rjvx7=@bMIdH6PI z7t6Fz9Bq6;AEaKLaRAKr=&}>5P^J_>D+9wOb%OSVs3{VZ;oUf1O2@;XXrrm5^|AB^ zLSB}@$Ue!sXav*XqUmI0lECh!Da3R1L8@^#b{L}(KZ&mKc5@mJ(yZfh*bava zn=m)+x*udxD0qF?uWpv7i#vX0DshUb&O^Qjq1LB&%WG|+3%Q;0bd5<`0&GH;T+VmM;7a_EXexJ>>!VZGpN=~5Fj((y#m=NkRTIX3v} zEUwZc8^OJ}lImQIyVDy=#5P1+OEO~KHX}C7hz&ox!|1njfy1}s;jLZ-9^N{Q!!ZgJ z;r65A9vJ3sR-x%usVk7vD{7%E6)k8Z>GZIolkF=ngH+FvC$PJNo1#SdHRG4fqBw+AtzJ!Vi=vc%K5s#qY5LRG)44P`01!g($+I^lu|Ac1H z7dP9l?~|?Bo6O$im*Y+TFx(uEn_+h`95$!tSL123d|d&QugaK`OK0ko#d6&SQB1dr zn~gzgcNxuNoQsNQ!7ejL7}8X&ViFVbC7fwaaCr2SR{rsir+#1=WaFAEkdKbyuEJNh~FNREK3F=quoMY>L7e1|yb)iex9PsZ7J(RtR414`09GOK9Y= zkW6TD%#Oor9I7kU`GiH8fo-_8<%B&+w*<4>2|j(0(wGf&Ck}8h=gROP**?8o>f2P* z8LFV{MCeiJ_%R77Po$@|A{|{IW!Nw$Q$D7yol%EOLXGI?LtW-xJSEtc|JJdrpJHnyOwBwX;QBn|LgdLqpoKuNqKCJO6 zmEBewW%$RO>WmB%vdFT>G@Wmd8cD9;yytAHR#yv%Q-h|_5llBTWmKAUPx>R*EXH51 z4>S8`P7cQgGkd@aqB7a?ky!1Zi2jqA(j)N#LYQfDs`9c{wB@vqoU!EtaIPb|$u=kO zPpi{qJ9Q!F*o~i?p<{b@v4LeK!ln7TQn!L1`@vK*(*UfJzOE83Dp02x$(>4R7%$On zWkX~N!D9Hic=m}D&wh2w!~SHs-<=NoE%0^!K55u){N{9VdDyJ(RPImXVSh26h6led zzVpJ(ZgZMmxM%P^F89~gruzMUx7q-ZH*C*#0}~Zz<2S?d^z4=a^6cg2v>T7dvtfN2 z4`r&0gd-D2zM6T|9ib42N%o?Y#!@SP32)tRvbpDmw{%dd~WIs4uuw+#bMYjpPyY0H@ENCJ2!`M^=vU5H^;kYu-i>ZziwA& z_h#!Evs!24ZgqTWA61sQ-7IxC!**N4*~{nq?f7i}a;N)WZI0K&NnbP^M!V?#IIdW) z=VvF~kUpeeZ*(Wa?o$7{8V~%B)}eKKzT?fcuB{9G9cz=%uJzuN657?-zewiJ6pyTa zbG8}}TH%#_U^TAoR=)bX@WqQ~U;e}Lc>4Rlf2yau-VV#n?$W+i*Glo#wfAeiBHj9p z{-|f?GSjWvrl0Aho84i2u^C^okiXk*pB*=UnjUAf9S=|W*OiuKJ1oZS`PI#7SZD#J zh1NF@+s&VbX(^|rQ7pARd%i!ObU#neuC=Qhmi7EJTu*y3NYcJl)^c{zE*;k<2Upt1 zv*CEWxwh3nd%f{&e>hv;=qtV)huzt7oI0p>2cJFp)t`U${{aC( J6Z~XI0RRzRu`vJu literal 17898 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