{"credit":"Taylor (gtmcknight), github.com/gtmcknight/amm-sim@4812a6382311624e1506aca131ca35c378f930d9 research/solved: the solved policy, replica and production U1 tables that LEAN and QLX5 are built on. Audited exact port: api.imd.fun/artifacts/60dc237fa0a4d42f3b6e2d2bed61c1a2df08d27c31ccd95cce508ee9c8689de4 (qlxcore.py sha256 701dbfd1175fee7d129de92db21b1ddc78645796c422b29d8efba2eda501ab00); audit: 362fb97f041087bf3548c302af4c0f82d2537d6a6c0157a95ac06d0cb70a5ce4; QLX5 + rows: 1ef80bfb6d6791b877b1f4048a5e63cf2ae54153e6e8763ae3f8ab13132dfb15 (QLX5 source sha256 e183e5bc3fb794b7067703b10a7da9920267aa5f4caa968e16ca101b02338f40); kit identity-md-launches/goal-3178-build-shared-evaluation-kit@45e7563d1a29ffca9d608fdf60c90bf2624d2d01.","item":"b3-speed/cython","where":"replica_parity","metric":"Cython-compiled QLX5 port minus untouched control port, final edge per seed (numeric parity error, explicitly NOT strategy gain)","gain_vs_base":0.0,"se":0.0,"n":64,"seeds":[10010512,10010575],"gain_note":"mean over seeds 10010512..10010575 of (Cython edge - control edge) for QLX5 (default knobs); every per-seed difference is exactly 0 (64/64 bit-identical f64, float.hex compared); LEAN (split=0) also 64/64. Not a strategy gain; the policy is unchanged.","source_sha256":"3d28cffd8e4fe258e412c9e42f7be7b8f590a719e1267293704af5c0f53d3e93","source_hash_scope":"SHA256 of qlxhot.py, the accelerated (Cython-compiled) policy source generated by mkcy.py from qlxcore.py 701dbfd1...; reproduced byte-identically by the rebuild from the embedded payload","hashes":{"qlxcore_py_control":"701dbfd1175fee7d129de92db21b1ddc78645796c422b29d8efba2eda501ab00","qlxhot_py":"3d28cffd8e4fe258e412c9e42f7be7b8f590a719e1267293704af5c0f53d3e93","qlxcore_cy_py":"7e1d0d75ab5f315f03a1f74185aed0351dbed9bc7e871ddf0c5a145bd4d8aa72","qlxhot_pxd":"1aafacd66dcdb3d253cacc04503bbbbed0e64bf9fb8be5d0176a4c9de30382cc","qlxhot_c_cython_3_1_4":"3ec6cc3133036121548f2321debfe83bba43227206a0f513b1d30cc0e5c64844","qlxhot_so_build1":"a25edbf7416693d816be1bac88622a7489eaba051810d9fc7ec63b0bd725a502","qlxhot_so_rebuild_from_payload":"34426a416400ba621ed3e634ab98fcfb10d9554526ce7003b1a5f55d3baf49d3","enginecore_f_py_unchanged":"60af56a7570fabd603c6374d38a38f88b3c35a8f1e8192f588769460a96bfcfd","enginecore_f_py_copied":"60af56a7570fabd603c6374d38a38f88b3c35a8f1e8192f588769460a96bfcfd","qlx_tables_json":"8c6d33c5c1024bc23593f46123aad1712c0cc8af3f4a118c5875258f9d7b81a6","payload_tar":"e8be7a7b49f00b3736ceb610ae4fc265c28da7dce5ae569f0b4879c7ee6f4dcf","payload_files":{"cyqlx/cyport/README.md":"340caff3753743de65f9a937b6db2fafab93304e11ecaf3fde6797d867424994","cyqlx/cyport/mkcy.py":"7ec78c6c5b4ecc5c43cd27d9e0719c873a2fcf83831012e5bd52fc198d11a4b8","cyqlx/cyport/qlxhot.pxd":"1aafacd66dcdb3d253cacc04503bbbbed0e64bf9fb8be5d0176a4c9de30382cc","cyqlx/cyport/build_cy.sh":"d944378efac6ee1c9aeadb7ab736daa647ceae72fdb78e19135e8a26b9b5745c","cyqlx/cyport/requirements-cython.txt":"ade5e8020e4f16a9c41854ec0eb0f3f10ac2760de93e29e8d2555fbb132d1705","cyqlx/cyport/qlxhot.diff":"13d182d656dbdb8bb1b6338cc1b47574a07a2f162d868732b9a94ce2a8699a1a","cyqlx/cyport/qlxcore_cy.diff":"d9b90984a0829f46b412b40428182c069eb15b22f341bfb1cb131708ad17fd80","cyqlx/tools/exacttest.py":"7020b87d434a37d08d463812c6563a522038a93437310e22c4af928660e2a923","cyqlx/tools/parbench.py":"44ae0acd84bbaef2b60c9969cc41223322f0ec262aa7fdd742126a6b80876dd2","cyqlx/tools/prof.py":"f5f107ad965a2c2ea6be3700fe716e2a6d02509b1a51570f5799865aa7c224ba"},"cython_wheel":"9def7c41f4dc339003b1e6875f84edf059989b9c7f5e9a245d3ce12c190742d9","setuptools_wheel":"062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922","artifact_60dc237f_input":"60dc237fa0a4d42f3b6e2d2bed61c1a2df08d27c31ccd95cce508ee9c8689de4","artifact_362fb97f_audit":"362fb97f041087bf3548c302af4c0f82d2537d6a6c0157a95ac06d0cb70a5ce4","artifact_1ef80bfb_rows":"1ef80bfb6d6791b877b1f4048a5e63cf2ae54153e6e8763ae3f8ab13132dfb15","qlx5_source":"e183e5bc3fb794b7067703b10a7da9920267aa5f4caa968e16ca101b02338f40"},"advance":true,"advance_reason":"All 64 old-seed runs (and the 64 LEAN runs) are bit-identical to the untouched control in final edge and normalizer edge, every callback (inputs, returned bid/ask wads) and the full policy state after every callback match (1,417,005 callbacks, 0 mismatches), and the median paired wall-clock throughput gain is +54.0% (>= 20%).","speedup":{"median_wall":1.5397,"cpu_total":1.5422,"median_throughput_gain":0.5397,"runs_per_core_s":{"control":1.662,"cython":2.563},"note":"8 worker processes (multiprocessing Pool(8), fork after Numba compile in the parent), every worker warmed on both implementations, then 6 rounds alternating order (control first in rounds 0,2,4; cython first in 1,3,5) over the same 32 seeds 10010512..10010543, QLX5 default knobs, no logging. Paired wall per round; cpu = sum of per-run process_time."},"timings":{"seeds":[10010512,10010543],"workers":8,"rounds":[{"order":["control","cython"],"control_wall_s":2.6509,"control_cpu_s":20.1796,"control_edges_sha":"cb137db2f3815c4e","cython_wall_s":1.6707,"cython_cpu_s":12.7828,"cython_edges_sha":"cb137db2f3815c4e","speedup_wall":1.5867},{"order":["cython","control"],"cython_wall_s":1.6421,"cython_cpu_s":12.5206,"cython_edges_sha":"cb137db2f3815c4e","control_wall_s":2.493,"control_cpu_s":18.9986,"control_edges_sha":"cb137db2f3815c4e","speedup_wall":1.5182},{"order":["control","cython"],"control_wall_s":2.4963,"control_cpu_s":19.0455,"control_edges_sha":"cb137db2f3815c4e","cython_wall_s":1.6193,"cython_cpu_s":12.3803,"cython_edges_sha":"cb137db2f3815c4e","speedup_wall":1.5416},{"order":["cython","control"],"cython_wall_s":1.6238,"cython_cpu_s":12.4112,"cython_edges_sha":"cb137db2f3815c4e","control_wall_s":2.5002,"control_cpu_s":19.0883,"control_edges_sha":"cb137db2f3815c4e","speedup_wall":1.5397},{"order":["control","cython"],"control_wall_s":2.5012,"control_cpu_s":19.0421,"control_edges_sha":"cb137db2f3815c4e","cython_wall_s":1.6148,"cython_cpu_s":12.4054,"cython_edges_sha":"cb137db2f3815c4e","speedup_wall":1.5489},{"order":["cython","control"],"cython_wall_s":1.6331,"cython_cpu_s":12.4245,"cython_edges_sha":"cb137db2f3815c4e","control_wall_s":2.5011,"control_cpu_s":19.1509,"control_edges_sha":"cb137db2f3815c4e","speedup_wall":1.5315},{"order":["control","cython"],"control_wall_s":2.5085,"control_cpu_s":19.1144,"control_edges_sha":"cb137db2f3815c4e","cython_wall_s":1.6295,"cython_cpu_s":12.4516,"cython_edges_sha":"cb137db2f3815c4e","speedup_wall":1.5394},{"order":["cython","control"],"cython_wall_s":1.6325,"cython_cpu_s":12.4928,"cython_edges_sha":"cb137db2f3815c4e","control_wall_s":2.5135,"control_cpu_s":19.3982,"control_edges_sha":"cb137db2f3815c4e","speedup_wall":1.5397}],"median_speedup_wall":1.5397,"median_control_wall_s":2.50115,"median_cython_wall_s":1.631,"median_throughput_gain":0.5397000000000001,"speedup_cpu":1.5421931886908076,"edges_equal_every_round":true},"first_divergence":null,"parity":{"compared":"untouched qlxcore.py (control) vs qlxcore_cy.py + compiled qlxhot (Cython), same process pool, same enginecore_f.py, same qlx_tables.json; per run: float.hex of edge and normalizer edge, the counters (calls, firsts, arbs, tell_pos, tries, hits, guard_shifts, m0), and per callback the logged tuple (initializing, is_buy, ax, ay, t, rx, ry, bid_wad, ask_wad) together with the policy state after it (m, v, sp, r, px, py, fb, fa, t, cnt, syn, m0 and counters), digested per callback and as one sha256 per run","QLX5":{"runs":64,"edge_bit_equal":64,"callbacks_compared":708923,"callback_mismatches":0,"state_hash_equal":64,"counters_equal":64,"first_divergence":null,"engine_row_rounded_equal":64,"max_abs_vs_engine_row":4.870904604103998e-07,"mean_edge":547.1956689694701,"parity_error_mean":0.0,"sha256_all_runs":{"control":"ec380bbfc9ada0e2de2dafdd180bc5234d718534acb516ae8dd6059c783cd68c","cython":"ec380bbfc9ada0e2de2dafdd180bc5234d718534acb516ae8dd6059c783cd68c"},"seeds":[10010512,10010575]},"LEAN":{"runs":64,"edge_bit_equal":64,"callbacks_compared":708082,"callback_mismatches":0,"state_hash_equal":64,"counters_equal":64,"first_divergence":null,"engine_row_rounded_equal":64,"max_abs_vs_engine_row":4.909534254693426e-07,"mean_edge":547.1625643085824,"parity_error_mean":0.0,"sha256_all_runs":{"control":"e1bf5b497a1dce42361f78eb7bfad14e925dca437871a77e67573cd38c690ad9","cython":"e1bf5b497a1dce42361f78eb7bfad14e925dca437871a77e67573cd38c690ad9"},"seeds":[10010512,10010575]}},"engine_rows_check":"As a sanity check only (no engine run here): both implementations round to the saved 6-decimal engine rows of 1ef80bfb on 64/64 seeds for QLX5 and LEAN (max |port - row| 4.9e-7, the row rounding).","exact_arithmetic_tests":{"what":"each policy helper of compiled qlxhot vs the untouched qlxcore function on random Python ints (seeded random.Random(20261111)), incl. negatives, values far beyond 2^64 (up to 2^300 for tdiv/mul/divi), out-of-domain inputs; results compared as (value, type) and exceptions as (type, message)","results":{"tdiv":{"n":20000,"mismatches":0,"control_exceptions":0},"mul":{"n":20000,"mismatches":0,"control_exceptions":0},"divi":{"n":20000,"mismatches":0,"control_exceptions":0},"ln":{"n":20000,"mismatches":0,"control_exceptions":0},"exp":{"n":20000,"mismatches":0,"control_exceptions":189},"root":{"n":20000,"mismatches":0,"control_exceptions":0},"pdf":{"n":20000,"mismatches":0,"control_exceptions":0},"cdf":{"n":20000,"mismatches":0,"control_exceptions":0},"trunc":{"n":5000,"mismatches":0,"control_exceptions":0},"lt_msb":{"n":20000,"mismatches":0,"control_exceptions":0},"rn":{"n":20000,"mismatches":0,"control_exceptions":0},"binade":{"n":20000,"mismatches":0,"control_exceptions":0},"ulp_over_grid_wad":{"n":20000,"mismatches":0,"control_exceptions":0},"lt_round":{"n":20000,"mismatches":0,"control_exceptions":0},"lt_wad":{"n":20000,"mismatches":0,"control_exceptions":0},"lt_div_wad":{"n":20000,"mismatches":0,"control_exceptions":0},"lt_gamma":{"n":20000,"mismatches":0,"control_exceptions":1066},"lt_pre":{"n":20000,"mismatches":0,"control_exceptions":7799},"lt_grid":{"n":20000,"mismatches":0,"control_exceptions":0},"lt_tell":{"n":5000,"mismatches":0,"control_exceptions":0},"q_r":{"n":20000,"mismatches":0,"control_exceptions":0},"q_d":{"n":20000,"mismatches":0,"control_exceptions":0},"q_w":{"n":20000,"mismatches":0,"control_exceptions":0},"q_hit_x":{"n":5000,"mismatches":0,"control_exceptions":0},"lerp":{"n":20000,"mismatches":0,"control_exceptions":0},"clip":{"n":20000,"mismatches":0,"control_exceptions":0},"surf":{"n":5000,"mismatches":0,"control_exceptions":0},"edge_cases":{"n":360,"mismatches":0},"compiled_function_types":["builtin_function_or_method"],"total_mismatches":0,"total_cases":480360},"compiled_types_note":"compiled helpers are builtin_function_or_method (cpdef in the .so), confirming the compiled module was the one tested"},"profile":{"control_one_seed_10010514":"cProfile: 0.998 s profiled, Policy.swap cumulative 0.979 s (98%) -> the policy, not the core, is the workload; top tottime: mul (1.32M calls), surf, ln, lerp (0.59M), exp, tdiv (0.63M), fees, cdf, update. Unprofiled wall for 10010513: 0.52 s.","why_cython":"the hot cost is Python call overhead of tiny integer helpers; cpdef over object args removes the frame/dispatch cost while every arithmetic op is still CPython PyLong arithmetic."},"implementation":{"method":"One implementation: Cython 3.1.4 compiles qlxhot.py (all policy code of qlxcore.py, text unchanged) with an augmenting qlxhot.pxd declaring the 28 integer helpers (tdiv, mul, divi, ln, exp, root, pdf, cdf, trunc, lt_msb, rn, _at_least, binade, ulp_over_grid_wad, lt_round, lt_wad, lt_div_wad, lt_gamma, lt_pre, lt_grid, lt_tell, q_r, q_d, q_w, q_hit_x, lerp, surf, clip) as cpdef with Python object arguments and results. No C integer types anywhere, infer_types=False, language_level=3, binding=False. Policy stays a regular Python class (same methods, attributes, knobs). qlxcore_cy.py is the original callback/run section verbatim, importing Policy from qlxhot. enginecore_f.py, RNG, exp call sites, float order, U1 tables, policy rules and knobs untouched.","source_patch_qlxhot_diff":"--- src/qlxcore/qlxcore.py\t1970-01-01 00:00:00.000000000 +0000\n+++ cybuild/qlxhot.py\t2026-11-11 01:11:05.049682649 +0000\n@@ -1,3 +1,4 @@\n+# cython: language_level=3\n # Credit: Taylor (gtmcknight), github.com/gtmcknight/amm-sim@4812a6382311624e1506aca131ca35c378f930d9 research/solved.\n # The solved policy (Gaussian filter, fee rule, qm tables, exact-arithmetic arb/retail tell) is Taylor's; LEAN and\n # QLX5 are the IdentityMD contracts built on it (A/a79a3606, A/1ef80bfb); the split test rule is A/8b18deed (mku.py).\n@@ -24,10 +25,7 @@\n import os\n from math import isqrt\n \n-import numpy as np\n-from numba import njit, objmode\n \n-import enginecore_f as ec\n \n CREDIT = 'Taylor (gtmcknight), github.com/gtmcknight/amm-sim@4812a6382311624e1506aca131ca35c378f930d9 research/solved'\n U = 10 ** 18\n@@ -613,39 +611,3 @@\n         return fb, fa\n \n \n-# ---------------------------------------------------------------- the policy on the engine-faithful core\n-_POL = [None]\n-_LOG = [None]\n-\n-\n-def _py_callback(initializing, is_buy, axh, axl, ayh, ayl, t, rxh, rxl, ryh, ryl):\n-    pol = _POL[0]\n-    ax = (int(axh) << 64) | int(axl); ay = (int(ayh) << 64) | int(ayl)\n-    rx = (int(rxh) << 64) | int(rxl); ry = (int(ryh) << 64) | int(ryl)\n-    if initializing:\n-        b, a = pol.init(rx, ry)\n-    else:\n-        b, a = pol.swap(bool(is_buy), ax, ay, int(t), rx, ry)\n-    if _LOG[0] is not None:\n-        _LOG[0].append((bool(initializing), bool(is_buy), ax, ay, int(t), rx, ry, b, a))\n-    return b, a\n-\n-\n-@njit\n-def callback(initializing, is_buy, ax, ay, t, rx, ry, state):\n-    with objmode(b='int64', a='int64'):\n-        b, a = _py_callback(initializing, is_buy, ax[0], ax[1], ay[0], ay[1], t, rx[0], rx[1], ry[0], ry[1])\n-    return b, a\n-\n-\n-def run(seed, T=None, n_steps=10000, log=None, trace=False, **knobs):\n-    \"\"\"One engine-faithful run of the policy alone against the 30 bps normalizer -> edge and counters.\"\"\"\n-    pol = Policy(T, **knobs)\n-    _POL[0] = pol; _LOG[0] = log\n-    try:\n-        r = ec.run(int(seed), n_steps=n_steps, callback=callback, state=np.zeros(1, np.int64), trace=trace)\n-    finally:\n-        _POL[0] = None; _LOG[0] = None\n-    out = dict(steps=r['steps'], events=r['events']) if trace else {}\n-    return dict(out, seed=int(seed), edge=r['edge'], normalizer_edge=r['normalizer_edge'], calls=pol.calls, firsts=pol.firsts,\n-                arbs=pol.arbs, tell_pos=pol.tell_pos, tries=pol.tries, hits=pol.hits, guard_shifts=pol.guard, m0=pol.m0)\n","qlxhot_pxd":"# Credit: Taylor (gtmcknight), github.com/gtmcknight/amm-sim@4812a6382311624e1506aca131ca35c378f930d9 research/solved.\n# Augmenting declarations for qlxhot.py: every argument and result is a Python object (arbitrary-precision int),\n# never a C integer; cpdef only turns module-internal calls into direct C calls.\ncpdef object tdiv(object a, object b)\ncpdef object mul(object a, object b)\ncpdef object divi(object a, object b)\ncpdef object ln(object x)\ncpdef object exp(object x)\ncpdef object root(object x)\ncpdef object pdf(object x)\ncpdef object cdf(object x, object density)\ncpdef object trunc(object m, object v, object lo, object hi, object z_floor)\ncpdef object lt_msb(object x)\ncpdef object rn(object num, object den)\ncpdef object _at_least(object w, object e)\ncpdef object binade(object w)\ncpdef object ulp_over_grid_wad(object paid, object before, object after, object floor_shift)\ncpdef object lt_round(object n, object s)\ncpdef object lt_wad(object m, object e)\ncpdef object lt_div_wad(object d, object e, object G)\ncpdef object lt_gamma(object f)\ncpdef object lt_pre(object w)\ncpdef object lt_grid(object m, object e, object k0, object G, object ax, object wide)\ncpdef object lt_tell(object px, object py, object fee, object ax, object ay, object cy, object buy, object budget=*, object lo_bits=*, object hi_bits=*, object wide=*)\ncpdef object q_r(object n)\ncpdef object q_d(object a, object b)\ncpdef object q_w(object w)\ncpdef object q_hit_x(object pw, object rx, object ry, object fee, object buy, object m0, object nc, object QK=*, object QG=*, object QKE=*, object QGE=*)\ncpdef object lerp(object a, object b, object f)\ncpdef object surf(object t, object pw, object p2, object k, object tt, object jm, object imax)\ncpdef object clip(object x, object a, object b)\n","qlxcore_cy_py":"# Credit: Taylor (gtmcknight), github.com/gtmcknight/amm-sim@4812a6382311624e1506aca131ca35c378f930d9 research/solved.\n# The solved policy (Gaussian filter, fee rule, qm tables, exact-arithmetic arb/retail tell) is Taylor's; LEAN and\n# QLX5 are the IdentityMD contracts built on it (A/a79a3606, A/1ef80bfb); the split test rule is A/8b18deed (mku.py).\n\"\"\"qlxcore: the LEAN and QLX5 contracts on the engine-faithful core (enginecore_f.py = enginecore.py of A/2ad2abf4\nwith rand_distr's fdlibm exp/log, see mkcore.py).\n\nThe contracts are fixed-point WAD integer programs (int256), not float programs: ln, exp, pdf, cdf, the filter, the\nQPL1 table lookup and the binary64-in-integers tell and split test.  A float port differs from them by ~1e-11 in a\nfee, which moves a retail fill by far more than one ulp and so re-rolls the exact-arithmetic tell.  This file\ntherefore transcribes the contract statement by statement in Python integers (Solidity signed division truncates\ntoward zero: tdiv), and plugs it into enginecore.kernel through a Numba objmode callback.  The engine side\n(RNG, router, arbitrage, k recomputed from rounded reserves, truncated WAD callback inputs) is the core.\n\nEvery structural constant is a knob (KNOBS: name, default = the QLX5 contract's value, meaning).  Policy(split=0)\nis LEAN; the default is QLX5.\n\nAPI\n  T = load_tables()                         # qlx_tables.json beside this file (mktables.py makes it from the .sol)\n  r = run(seed, T, **knobs)                 # {'seed','edge','calls','tries','hits', ...}\n  pol = Policy(T, **knobs); pol.init(xw, yw); pol.swap(is_buy, axw, ayw, t, rxw, ryw) -> (bid_wad, ask_wad)\n\"\"\"\nimport numpy as np\nfrom numba import njit, objmode\n\nimport enginecore_f as ec\nimport qlxhot\nfrom qlxhot import *  # noqa: F401,F403  (compiled policy: Policy, load_tables, KNOBS, ...)\nfrom qlxhot import CREDIT, Policy\n\n\n# ---------------------------------------------------------------- the policy on the engine-faithful core\n_POL = [None]\n_LOG = [None]\n\n\ndef _py_callback(initializing, is_buy, axh, axl, ayh, ayl, t, rxh, rxl, ryh, ryl):\n    pol = _POL[0]\n    ax = (int(axh) << 64) | int(axl); ay = (int(ayh) << 64) | int(ayl)\n    rx = (int(rxh) << 64) | int(rxl); ry = (int(ryh) << 64) | int(ryl)\n    if initializing:\n        b, a = pol.init(rx, ry)\n    else:\n        b, a = pol.swap(bool(is_buy), ax, ay, int(t), rx, ry)\n    if _LOG[0] is not None:\n        _LOG[0].append((bool(initializing), bool(is_buy), ax, ay, int(t), rx, ry, b, a))\n    return b, a\n\n\n@njit\ndef callback(initializing, is_buy, ax, ay, t, rx, ry, state):\n    with objmode(b='int64', a='int64'):\n        b, a = _py_callback(initializing, is_buy, ax[0], ax[1], ay[0], ay[1], t, rx[0], rx[1], ry[0], ry[1])\n    return b, a\n\n\ndef run(seed, T=None, n_steps=10000, log=None, trace=False, **knobs):\n    \"\"\"One engine-faithful run of the policy alone against the 30 bps normalizer -> edge and counters.\"\"\"\n    pol = Policy(T, **knobs)\n    _POL[0] = pol; _LOG[0] = log\n    try:\n        r = ec.run(int(seed), n_steps=n_steps, callback=callback, state=np.zeros(1, np.int64), trace=trace)\n    finally:\n        _POL[0] = None; _LOG[0] = None\n    out = dict(steps=r['steps'], events=r['events']) if trace else {}\n    return dict(out, seed=int(seed), edge=r['edge'], normalizer_edge=r['normalizer_edge'], calls=pol.calls, firsts=pol.firsts,\n                arbs=pol.arbs, tell_pos=pol.tell_pos, tries=pol.tries, hits=pol.hits, guard_shifts=pol.guard, m0=pol.m0)\n","build_script":"#!/usr/bin/env bash\n# Credit: Taylor (gtmcknight), github.com/gtmcknight/amm-sim@4812a6382311624e1506aca131ca35c378f930d9 research/solved.\n# Usage: build_cy.sh QLXCORE_DIR OUTDIR CYTHON_SITE   (CYTHON_SITE: pip --target dir with cython==3.1.4, setuptools==80.9.0)\nset -euo pipefail\nhere=$(cd \"$(dirname \"$0\")\" && pwd); src=$(cd \"$1\" && pwd); mkdir -p \"$2\"; out=$(cd \"$2\" && pwd); site=$(cd \"$3\" && pwd)\npython3 -I \"$here/mkcy.py\" \"$src/qlxcore.py\" \"$out\"\ncp \"$here/qlxhot.pxd\" \"$out/\"; cp \"$src/enginecore_f.py\" \"$src/qlx_tables.json\" \"$out/\"\ncd \"$out\" && CC=\"${CC:-gcc}\" LDSHARED=\"${LDSHARED:-gcc -shared}\" PYTHONPATH=\"$site\" python -c \"\nfrom Cython.Build import cythonize\nfrom setuptools import setup, Extension\nsetup(name='qlxhot', script_args=['build_ext', '--inplace'],\n      ext_modules=cythonize([Extension('qlxhot', ['qlxhot.py'])], compiler_directives=dict(language_level=3, infer_types=False, binding=False), annotate=False, quiet=True))\n\" > build.log 2>&1 || { cat build.log; exit 1; }\nrm -rf build; ls -la \"$out\"; sha256sum \"$out\"/qlxhot.py \"$out\"/qlxcore_cy.py \"$out\"/qlxhot.pxd \"$out\"/qlxhot.c \"$out\"/qlxhot*.so\n","pinned_dependencies":"# Credit: Taylor (gtmcknight), github.com/gtmcknight/amm-sim@4812a6382311624e1506aca131ca35c378f930d9 research/solved.\n# Build-only pins (the kit venv supplies python 3.12.16, numpy 2.5.4, numba 0.68.1, llvmlite 0.50.0). Install:\n#   PIP_NO_INDEX=0 python -m pip install --require-hashes --target CYTHON_SITE -r requirements-cython.txt\ncython==3.1.4 --hash=sha256:9def7c41f4dc339003b1e6875f84edf059989b9c7f5e9a245d3ce12c190742d9\nsetuptools==80.9.0 --hash=sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922\n","toolchain":"kit venv python 3.12.16 (python-build-standalone), numpy 2.5.4, numba 0.68.1, llvmlite 0.50.0; gcc 13.3.0 (CC=gcc, LDSHARED=\"gcc -shared\"; the standalone python sysconfig names clang, which is not installed here); flags from sysconfig (-O3)."},"payload_encoding":"base64(zlib(tar)); members cyqlx/cyport/{README.md, mkcy.py, qlxhot.pxd, build_cy.sh, requirements-cython.txt, qlxhot.diff, qlxcore_cy.diff}, cyqlx/tools/{exacttest.py, parbench.py, prof.py}","decode":"python3 -I -c \"import json,base64,zlib,io,tarfile,sys; tarfile.open(fileobj=io.BytesIO(zlib.decompress(base64.b64decode(json.load(open(sys.argv[1]))['payload_zb64'])))).extractall(sys.argv[2], filter='data')\" result.json OUTDIR","rebuild":["kit: curl -sSL https://github.com/identity-md-launches/goal-3178-build-shared-evaluation-kit/archive/45e7563d1a29ffca9d608fdf60c90bf2624d2d01.tar.gz | tar xz -C test/scratch/kitsrc; bash .../setup_fast.sh --platform linux-x86_64 --cache \"$PWD/test/scratch/cache\" --scratch \"$PWD/test/scratch/runtime\"; . test/scratch/runtime/env.sh","control: extract code_zb64 of 60dc237f into test/scratch (qlxcore/), then cd qlxcore && python3 -I mktables.py ROWS_1ef80bfb.json qlx_tables.json (sha256 8c6d33c5c1024bc23593f46123aad1712c0cc8af3f4a118c5875258f9d7b81a6)","decode this payload (decode above) into test/scratch/cyp","PIP_NO_INDEX=0 python -m pip install --require-hashes --target test/scratch/cypkgs -r test/scratch/cyp/cyqlx/cyport/requirements-cython.txt","bash test/scratch/cyp/cyqlx/cyport/build_cy.sh test/scratch/qlxcore test/scratch/cyout test/scratch/cypkgs   (prints sha256 of qlxhot.py 3d28cffd..., qlxcore_cy.py 7e1d0d75..., qlxhot.c 3ec6cc31...)","checks: python -B cyqlx/tools/exacttest.py QLXCORE_DIR CYOUT 20000; python -B cyqlx/tools/parbench.py QLXCORE_DIR CYOUT ROWS_1ef80bfb.json 6","use: sys.path.insert(0, CYOUT); import qlxcore_cy as qlxcore  # Policy(T, **knobs), run(seed, T, **knobs), load_tables(), KNOBS as before"],"rebuild_verified":"Payload decoded into an empty dir and rebuilt with build_cy.sh: qlxhot.py, qlxcore_cy.py, qlxhot.c byte-identical to the measured build; exacttest (24,360 cases) 0 mismatches; seed 10010575 edge 0x1.d9178d89e9aadp+8, 8848 callbacks, equal to control.","limitations":["Speed only for the policy: the engine core (enginecore_f.kernel, Numba) and the objmode callback bridge are unchanged; the policy remains CPython big-int arithmetic, so the gain (~1.54x) is from removing Python call overhead, not from faster arithmetic. Still about 2.56 runs per core-second, far from the float fast replica.","The .so is not bit-reproducible across builds (build paths embedded: sha256 a25edbf7... first build vs 34426a41... rebuild), but the generated C (qlxhot.c) is byte-identical; it is CPython 3.12 / linux x86_64 specific and needs gcc and the Python headers.","Numba on-disk cache hazard: enginecore_f.kernel is cache=True and its index pickles the callback by module. A process that imports both qlxcore and qlxcore_cy from the same enginecore_f.py path writes a qlxcore_cy entry into that cache, and a later process importing only qlxcore then fails loading it (ModuleNotFoundError: qlxcore_cy). Observed here after the paired benchmark; with separate NUMBA_CACHE_DIR per implementation both run and agree. Use a separate NUMBA_CACHE_DIR (or a separate copy of enginecore_f.py) for the Cython build.","Parity verified for the default knobs (QLX5) and split=0 (LEAN) only, on the 64 old seeds 10010512..10010575; other knob values are covered only by the helper-level exact tests (the code paths are the same compiled source). Benchmark on 32 seeds, 8 workers, this host only.","No engine run, no fresh E seed (10,200,000+), no P/Q/T/F/G/E gate, no tuning, no Solidity or leaderboard change, nothing submitted. The audited implementation is not replaced: qlxcore_cy is an alternative import beside the untouched qlxcore.py."],"engine_work":{"fresh_seeds_from_10200000":0,"engine_runs":0,"leaderboard_submissions":0},"payload_zb64":"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"}