#!/usr/bin/env python3
"""pentagon-weight3-check.py -- the self-check of the pinned pack vendor_row05_weight3/ beside this file: the weight-3
(O(eps)) arm of the one-loop massless pentagon of the mpl-suite page (row 5) -- the ten scripts as run, the 70
auxiliary-mass-flow outputs they consumed and the seven receipts they produced -- pinned by sha256 in-code, their
cross-references verified against each other, the goal-40 / goal-60 pair floors of the two fit receipts re-derived from
the outputs, and the weight-two constrained count re-derived from the pack's own alphabet with the pack's own count.py.

pentagon-evaluate.py (beside this file) gains no O(eps) tier from this pack: this pack does not implement the published
exact-in-d form of the D = 6-2eps pentagon (Kozlov and Lee, JHEP 02 (2016) 021, arXiv:1512.01165; the pentagon to higher
orders: Del Duca, Duhr, Glover, Smirnov, JHEP 01 (2010) 042, arXiv:0905.0097; Kniehl, Tarasov, Nucl. Phys. B 833 (2010)
298); the boxes' O(eps) coefficients enter the fit from the outputs.

THE PACK (vendor_row05_weight3/; README.md there names every file):
  arm/        alphabet.py (the 21-letter alphabet by object), count.py (the constrained symbol counts: weight 3 over the
              21 letters 9261 -> 2205 -> 601 -> 100 -> 1; weight 2 over the 16-letter subalphabet 256 -> 80 -> 41 -> 4),
              symbol_extract.py (the unique parity-odd weight-3 symbol: 40 terms in 8 cyclic orbits), oeps_fit.py (the
              O(eps) value fit at 13 points, 3 held out to 60 digits), d6_symbol_fit.py (the symbol realised as a one-fold
              integral, fitted to the D = 6 pentagon at 12 chamber points, 3 held out to 45 digits), make_points_configs.py
              and make_chamber_points.py (the points, filed before any run), oracle_batch.sh, scoped_body.sh and
              launch_scoped.sh (how the runs were launched).
  samples/    the 70 outputs: 13 points x (d0 = 4, 6) x (goal 40, 60) = 52, 8 chamber points x d0 = 6 x 2 goals = 16,
              the symmetric point (-1, -1, -1, -1, -1) x d0 = 6 x 2 goals = 2.
  receipts/   alphabet_item64.json, COUNT_ITEM64.json, SYMBOL_ITEM64.json, POINTS.json, POINTS_CHAMBER.json,
              FIT_ITEM64.json, D6FIT_ITEM64_sqrtD_dps45.json.
Eight scripts and five receipts carry re-cut constants (the directories of the machine they ran on -> names beside the
file; nothing else); README.md states both sha256s for every such file, and the RECORD table below carries the sha256 of
the bytes as run so that the receipts' own PRODUCER / file pins (which name the bytes as run) can be verified here.

WHAT RUNS (python3 + mpmath; sympy + python-flint for the count):
  [pins]        every pack file hashed and compared with PINS before anything else (mismatch -> exit 3, missing -> exit 4,
                by name);
  [cross-pins]  the seven receipts' PRODUCER.sha256 == the scripts as run; the six receipt-to-receipt sha256 pins; the 76
                sample sha16s named by the two fit receipts == the samples' sha256 prefixes;
  [census]      the receipts' headline figures printed from the objects (key paths given);
  [pair floors] every goal-40 / goal-60 agreement the fit receipts store per point (FIT: 13 points x 4 figures at the fit's
                dps; D6FIT: 12 points x 1 at its dps) re-derived from the outputs with the same measure and compared;
  [count]       the weight-two constrained counts (the 16-letter subalphabet and the full 21-letter alphabet), the six
                evaluation points, the dlog ranks, the point-count convergence and the box-symbol control re-derived
                with arm/count.py from receipts/alphabet_item64.json and compared with COUNT_ITEM64.json (about a
                second); --w3 adds the weight-three parity-odd count 9261 -> 2205 -> 601 -> 100 -> 1 (about a minute).

THE I_5 ARM (--i5; default off, the legs above do not run under it): at the withheld Euclidean point (v1, ..., v5) =
(-1, -2, -3, -4, -5), against the two auxiliary-mass-flow runs of the massless five-propagator family (goals 40 and 60;
the same bytes as samples/p00_d4_g40.json / p00_d4_g60.json of the pack; the data under vendor_row5_i5/, README.md
there; every file pinned in PINS_I5, exit 3 / exit 4 by name), two objects: the sum of box functions S = sum_i B_i (what
the row's weight-two fit recovered with unit weights; the secondary tier of pentagon-evaluate.py; NOT the pentagon) and
the pentagon's closed form, the BDK v-form of pentagon-evaluate.py (Laurent coefficients eps^-2, eps^-1, eps^0):
  [pins] [cross-pins]  the eleven files; the outputs == the pack's two samples; the reference block's provenance sha256s
                == the vendored objects; the receipts' pins among themselves; one point throughout;
  [closed form]  B_i = Li2(1 - v_i/v_{i+2}) + Li2(1 - v_i/v_{i+3}) + log^2(v_{i+2}/v_{i+3})/2 re-evaluated here against
                the prediction receipt's dps-180 strings (S and the five B_i: the S value of record, filed when the
                served script presented S as I_5);
  [measure] [BDK] [boxes]  the two bubbles against the exact Gamma form, the pentagon against -(1/2) sum_a c_a box_a with
                the Cayley coefficients by object (eps^-2..eps^0; eps^1 is the D = 6 pentagon term, not covered), each
                one-mass box divided by r_Gamma / (s t) to its pole checks and its box function B_a, the sum of the five
                against the S value of record;
  [pair]        the goal-40 / goal-60 agreement per target and order; the reportable count = min(the pair floor over the
                eight targets and eps^-2..eps^0, the sum of B against the S value of record, that value's dps-120 /
                dps-180 pair) against the bar (certified_digits_pair_floor of the reference block); the planted-digit control;
  [pentagon]    the v-form's three Laurent coefficients (r_Gamma expanded, no e^{eps gamma_E}) against the goal-60
                [1,1,1,1,1] entry, each order to at least min(dps - 10, that order's goal-40 / goal-60 pair digits), and
                against the reduction -(1/2) sum_a c_a box_a; S against the pentagon's eps^0 (printed: no digit shared);
  [pySecDec]    the third route's eps^0 value against the goal-60 leg, from the reference block;
  [record]      every figure above against ITEM49_COMPARE.json, at the record's dps 130 only (--i5-dps elsewhere runs
                the arm and names the comparison NOT RUN, exit 5; below bar + 10 the gate is NOT RUN by name as well).
  --i5-point refuses by name (exit 2) any point but the record's; --i5-mutate must exit 1 by name; --i5 does not combine
  with --w3, --no-count or --mutate (refused by name, exit 2).

EXIT CODES: 0 PASS; 1 FAIL by name (a cross-pin, a pair floor, a count, the I_5 gate, or --mutate / --i5-mutate); 2 a
refusal by name (the I_5 arm outside its domain or combined with a weight-3 option); 3 a pack file's bytes differ
from its pin; 4 a pack file is missing; 5 a leg NOT RUN by name (the count: sympy / python-flint not importable; the
I_5 arm's gate or record comparison at a dps other than the record's) -- never PASS with a leg skipped: pass --no-count
to run the pins, the cross-pins, the census and the pair floors alone (exit 0 then says so).

CLI:
  python3 pentagon-weight3-check.py                # pins, cross-pins, census, pair floors, the weight-two count
  python3 pentagon-weight3-check.py --w3           # + the weight-three parity-odd count (about a minute)
  python3 pentagon-weight3-check.py --no-count     # without sympy / python-flint
  python3 pentagon-weight3-check.py --mutate       # one digit of one output changed in memory: must FAIL by name (exit 1)
  python3 pentagon-weight3-check.py --i5           # the I_5 arm at the withheld point (-1,-2,-3,-4,-5), dps 130 (seconds)
  python3 pentagon-weight3-check.py --i5 --i5-dps 40   # the arm at a lower precision: the gate and the record comparison NOT RUN by name (exit 5)
  python3 pentagon-weight3-check.py --i5 --i5-mutate   # one digit of the vendored S string of record changed in memory: must FAIL by name (exit 1)
"""

import argparse
import hashlib
import importlib.util
import json
import os
import sys
import time

import mpmath as mp

sys.stdout.reconfigure(line_buffering=True)

HERE = os.path.dirname(os.path.abspath(__file__))
PACK = os.path.join(HERE, "vendor_row05_weight3")

# sha256 of every file of the pack as shipped (relative to vendor_row05_weight3/)
PINS = {
    "PACK_MANIFEST.sha256": "5d23719352d38fc8357017569c67876b49551afbd9fcc739c5ce6e803a0df6c8",
    "README.md": "eaaf776f10b4d7678e22054fc0a0c04f7b1eecf577f4ac27eb87d06230d8575d",
    "arm/alphabet.py": "5198020c3aaf83a577deba8da90dedc52b5bff1fcf0699721ed4df105085a54b",
    "arm/count.py": "33402468e23df2b635b675a4d76ab9f765b97ac9d8aa9d8acb352f3c5366b787",
    "arm/d6_symbol_fit.py": "d861f8d6fc563392454baa54553ddd73d429edd115fa869aabd32936d32c88ed",
    "arm/launch_scoped.sh": "1482ec893241c9b2dc308425d5983bee7a88934d9e080dc0504ba0c188e17a7f",
    "arm/make_chamber_points.py": "a0dc0fa3ba2138c52af2253f76198a9c076fc0fc41c559f97a8f731bb2f0d319",
    "arm/make_points_configs.py": "6b20c280b18e64afacc4895b72acc6420a3315da6d077cdde5679a57426710c3",
    "arm/oeps_fit.py": "7ebfd6df2eca040429f3a36843cb01e7ad989a692c37cdec8843c1f64f4ccd9e",
    "arm/oracle_batch.sh": "e43b320a662b9dc17c5aab5f0372b333b5e76aec0655a08a590bcdb46f71395a",
    "arm/scoped_body.sh": "17170fafff3caf2c464a93f7bb478d80d0ce107caf4722991dcbbcccff4342c1",
    "arm/symbol_extract.py": "d00d4bc88e9ef355cd25de70a27295de17b442a80cac645ad09ab5522e686d4b",
    "receipts/COUNT_ITEM64.json": "12891dcd974bbd984562bbe12c35e1580737fc60d593ba7f87ef6910b3b6b8bd",
    "receipts/D6FIT_ITEM64_sqrtD_dps45.json": "646a4dd2796415af6e68ea43ffab463d9a72ef2fe39bd45b087cafce842ff01e",
    "receipts/FIT_ITEM64.json": "167e48ff159d71d0a98560c075e26e4f95f2c8b3a01bbcca5f329ddfd84270bf",
    "receipts/POINTS.json": "e983846cb58d342b8e03b7adbbe15012d7a8529b1fb207905001330ca265380f",
    "receipts/POINTS_CHAMBER.json": "97adf9d5e54fb4d3cd3593f4a83bc413d8496a964f52fe7deccadd89710b9e7d",
    "receipts/SYMBOL_ITEM64.json": "1411cd10c0337cf63063d40aa5c3b5f44ea5bfcd834b20846a3b2687bcbdaff8",
    "receipts/alphabet_item64.json": "36fef2099011fae74e493bd98ca1d7e09490581db5ad2623d1acbb7944e685fb",
    "samples/c01_d6_g40.json": "b546933de41e8b13ade373a8509b0836f5626295937f2a94ebf1a70042d71039",
    "samples/c01_d6_g60.json": "4e26cd7455198ff50077cc31dbfad5f291d1cd51b9b6fac669c760a3a9e91585",
    "samples/c02_d6_g40.json": "5cbce465c53799070f92b37c360492ff046677bd921dbd3011095f9fc5c376ab",
    "samples/c02_d6_g60.json": "035c7ec29885d7367489a111fe1a402ac921811ea2d2cf45e0757157b2bd79b8",
    "samples/c03_d6_g40.json": "7f645eb6a20f0b4719831aa55aa92d239bdd3cf1bb8dc706c089398e9bed386a",
    "samples/c03_d6_g60.json": "0b63c14d9c0a3f8a69d28292a15af5c18ccfbbd9cf3dc5c29fce29ae2bea023b",
    "samples/c04_d6_g40.json": "522bf1b4d20de7cfbdb1dd66b3d579d9344ed81bf4dd6b4e2404be9a0a37a982",
    "samples/c04_d6_g60.json": "6def4d493531e587c9e21443218b1630b3769b76a96558779b83fd9695c48047",
    "samples/c05_d6_g40.json": "e58256d39b530326a71af5b94da06343d8846176f1c9d499e2c4b0fd16380c32",
    "samples/c05_d6_g60.json": "bbbe2b8571da20176823e3066222ed4e5b8b13dd57b9ef1d8fe9b2b62e189749",
    "samples/c06_d6_g40.json": "9603b223daaed359c6f48582075c0f0ba55afde5be0cd76f554748128d7c484d",
    "samples/c06_d6_g60.json": "a0c0b0ae2773e419624c5671be9bd15203787420a98fa1bc3efeffb1bf1f5897",
    "samples/c07_d6_g40.json": "2049eb3080a2b436f4b442acae2386f7c7f9033228760c84fe1bb38cc5975e1c",
    "samples/c07_d6_g60.json": "8cdfb608b4bc06956290c52e6185771bb6fea7fc5211408c8554c788803b594c",
    "samples/c08_d6_g40.json": "567376f3996336cad019f72c4e74d5846c52ec9368c38461aa647fbd4b7bb07b",
    "samples/c08_d6_g60.json": "1cde30e25e2cda57e7574c8d2cfe44e6bdf9df20a76f23c512caed23df2ea42e",
    "samples/p00_d4_g40.json": "a08883b6d9ec31c92863ef0bc7b3eadb5f76ab650e0dc822b4587cd139a17b36",
    "samples/p00_d4_g60.json": "f0cfaabb57de4f310e08974301d0b0ffbc03cf60edad3487acb509d2691d5320",
    "samples/p00_d6_g40.json": "3e97052d4dceb45c8449594cd2c8d582cb67ebd286e3c637348646c2de79c20e",
    "samples/p00_d6_g60.json": "f2d872cb10d1e1cf95c6536d8f6488f80c98a5cf98597f0cef7673799ab4b2f5",
    "samples/p01_d4_g40.json": "7ef07da699248b44cd9ba08258c7ba87e4492f52d62a13878f9e256ba283227e",
    "samples/p01_d4_g60.json": "329af5e674d5cb6b5065f0ae6eb3137c11d0b1a4b43f81292d6000659be4c7d2",
    "samples/p01_d6_g40.json": "eeb27df2b70ff5bd9c7d23c46ab860c02790a6734ca82d77d6000b4dad042e80",
    "samples/p01_d6_g60.json": "62d4dba1e269bde0efda093db0c6aa97d1202190cae442db7f38b1869c04ef80",
    "samples/p02_d4_g40.json": "5ed89d2b81964a20cdcbf560ded09b28b73e658d8d93ff133b01073d14502b20",
    "samples/p02_d4_g60.json": "bf51886324b057f7a47dba67278bf83457785db272a5044ac05a6027944cf463",
    "samples/p02_d6_g40.json": "7cd00455d76e09ef7dcee7757107165b44531d443cc4848851814acb52e1045f",
    "samples/p02_d6_g60.json": "01a1fe9957be867642ddf0f9765aeb1ee9bcb1947d696f9f995e255d85cd39ea",
    "samples/p03_d4_g40.json": "87b9dd662726c9fc2f0fc2be23379ccfeaf0f4f762547817689a8e06e84d392c",
    "samples/p03_d4_g60.json": "0f04ee710014e90f50f362046f07dbe3a1533b92da53691e6a2368e05b18344b",
    "samples/p03_d6_g40.json": "ce5fba869c90ec4f6b62fd0052efdfaaff9d489fffb9e7f33b6cd8f425fc4b61",
    "samples/p03_d6_g60.json": "65bc0f224f8b36edde679f0f49b5e8a5cd8f11d0d796eb801c5ac137649d28a0",
    "samples/p04_d4_g40.json": "a18a2ae0f96941cc9a835de86d2eb8ab29f89b1d91a6ad7118973d552614a3bd",
    "samples/p04_d4_g60.json": "2ad6660a82ffcbf407ee6dc3c236c29541f48ace7a5e9bc6107267a857bba87e",
    "samples/p04_d6_g40.json": "7b3f3db9c8cc137167230fa113bdd99b435f6aac39181116837ae77ec3378395",
    "samples/p04_d6_g60.json": "d29f381921753c1fbb3f275d14abec67d254fc8e3ade6bdcf1fa60f34044f9dd",
    "samples/p05_d4_g40.json": "d0412ecba524384800f73bd51e4a8f17cb23be0b041422ec5e2d53619c1a2e57",
    "samples/p05_d4_g60.json": "7fe247e2a7420f930a90c92c1a10866208269685f79f1d89bc867289098242ba",
    "samples/p05_d6_g40.json": "a2de3db6ac95bca8ea5414e5a7266ce35a39912f3770573db73426e7838570e9",
    "samples/p05_d6_g60.json": "b67b42aa6f2b0ec5cec907854e40f7603a46c3166fc7a9e8a6c678ef6f3a51c9",
    "samples/p06_d4_g40.json": "56285167ac2c65f3fa684903a7505449438915115e37c4385c2c2f0cde1f4168",
    "samples/p06_d4_g60.json": "67e0018c57145117396b7225c2ada87b4c436e5613f21833883abfca1d28cdbf",
    "samples/p06_d6_g40.json": "fe60dbafb1d21f97927e5253fabdbc4846f97c53b98a50bd66481aee240e75fe",
    "samples/p06_d6_g60.json": "502a528d1a888e9f9f4617cc74da6e39e3154906ea61dcf5596321d7358341f1",
    "samples/p07_d4_g40.json": "47a7f9090b20cd12e74dca7dd5944b0e2b662551b50b6bfe9ac48ddbf9dbdcd7",
    "samples/p07_d4_g60.json": "a1ccc6027134d3af85296c68117aaa0baf59aea2db492fc0294205883866ddd0",
    "samples/p07_d6_g40.json": "af1925abb1aea47d9d49f28a8d098f1803b54fbc52da8f09ca6718f2cfb81a29",
    "samples/p07_d6_g60.json": "12341f23517eb571771ba5a5c16c2dca18887147f28309b146f78b62a7f0003a",
    "samples/p08_d4_g40.json": "c328f9265ace3ea6f935ecee2cf2a604444c2963d1e27ac33d8eae0e63749076",
    "samples/p08_d4_g60.json": "578b9fbceb620b06baa2669d25aac32b0d49b43f6a2eb839200dd72fc86d10c5",
    "samples/p08_d6_g40.json": "bd7f89e975f9635a859f0614d45c3592548825a84c0c49509be1c72a6b9bd228",
    "samples/p08_d6_g60.json": "1a2895c34d3f1b00347839d231adaac7ef64d2656c194729c45a212305289325",
    "samples/p09_d4_g40.json": "33b85b956427b43e4bccc5c25f63a2a76c21ffc4b2e49352dd9d064b7b5fcdb3",
    "samples/p09_d4_g60.json": "e4208537645aa0f40266edf9fbccb89565b9e9f2539267eca7957309f4d1ad0a",
    "samples/p09_d6_g40.json": "e6d78ef9793de0e3cd45e34d30a0f989dfc82ca6e9cedecd97b85ca8711bddea",
    "samples/p09_d6_g60.json": "ffc06a3d30c2352b9d3aadac46447f6b559b9639923b2903e97216bf2e674965",
    "samples/p10_d4_g40.json": "9f7ed2c44f9e4297e0deb2bfb30a327a106cdc0f1bc4c7edd2017a965e6b0b10",
    "samples/p10_d4_g60.json": "60fef5dca75e073ec0c7dab4a1022af53a9a245e914e4b4c9da04f3c302227ed",
    "samples/p10_d6_g40.json": "88101ebd7ca0b8abf4dbaff01c9ab314f99e6f9b707f320a46c2a9468f593427",
    "samples/p10_d6_g60.json": "2d177c731bab6970ca430c3d4c6d88389310ae96831d5eabcc7f6e60ae488d4f",
    "samples/p11_d4_g40.json": "5e841c993d086faeb7d0697c2229ddeb08f7148ea76dd608e00dbab40c79f051",
    "samples/p11_d4_g60.json": "20ac6c5709406bfa0165c9d542d4f1a56da8c49136c1089b3478f84d0151d646",
    "samples/p11_d6_g40.json": "0492b8eb63f9e13bb4aa4ad0aa7f4b6de97481f6db7924682bd6be6299bb99f8",
    "samples/p11_d6_g60.json": "c8a1f1f0cc8954df05317b1b79727a171d3cb7aac50c998d7a5e0c1a9655d8ef",
    "samples/p12_d4_g40.json": "d3837dfc57898a82f3d85abcf123b4ae1354e276ecd0300f8b118b06000b69ad",
    "samples/p12_d4_g60.json": "a747bf79fbb61fe9a599b5e6ba5f388112ae138af2885187e9147e10a43ad594",
    "samples/p12_d6_g40.json": "19c03abc708f803778ac26d5de091cd0e0dc034a5efbbf30926ea64a487bc203",
    "samples/p12_d6_g60.json": "c506698d738a050f8b91c049e46c8ea3ce2503ae70081d69c116757ba420a2a3",
    "samples/s00_d6_g40.json": "3c6cf101c6b7af53028398d5fbe79003f115e910dbb9ba31b623c2d1ac66ddda",
    "samples/s00_d6_g60.json": "2fba84da53203a6a12635f470365cc1f366511a05b07c2b1cab1ef5b5d30dccf"
}

# sha256 of the bytes as run, for every vendored script, output and receipt (== PINS where the file is byte-identical)
RECORD = {
    "arm/alphabet.py": "eb9b8f9ffe3224fc6e45598a69e616068bcf99e6d74d58c23c4bc9c3d67b4905",
    "arm/count.py": "e7d4e11165c4aabde959688d08c61bf18118dc3be774139049f18a99999cfa8e",
    "arm/d6_symbol_fit.py": "b8bc5e14c1fbb661d0483ea7d755d78bced29b4096b301c4a8d23ad285c6e33b",
    "arm/launch_scoped.sh": "a96d6172d0353cebbcd00f478308bc59ad05f00027d1e270f549770e1b638e9b",
    "arm/make_chamber_points.py": "a0dc0fa3ba2138c52af2253f76198a9c076fc0fc41c559f97a8f731bb2f0d319",
    "arm/make_points_configs.py": "2bc9b2842451b911c91050ee3197d20e79b48fb4662c7b0ff9d133e35e82657d",
    "arm/oeps_fit.py": "a7bf429401938b5de6c1a53c325a9e6c1fe796321c333e64ca5c4eeba02a5bb8",
    "arm/oracle_batch.sh": "ad4a9417ae0a767d814a90c68ebe38c0dcf1008d1018ee79078d0aebbff2eb08",
    "arm/scoped_body.sh": "17170fafff3caf2c464a93f7bb478d80d0ce107caf4722991dcbbcccff4342c1",
    "arm/symbol_extract.py": "12072e633807ad5491a492747bee6a184b596d0bc700aae9d3e39b12e2a77bf9",
    "receipts/COUNT_ITEM64.json": "ff2a55dc3e09a5708ef1a0fe916abe776d5ae52221fa8af4646e9f2d1675be89",
    "receipts/D6FIT_ITEM64_sqrtD_dps45.json": "646a4dd2796415af6e68ea43ffab463d9a72ef2fe39bd45b087cafce842ff01e",
    "receipts/FIT_ITEM64.json": "545df54f1216b98c6da663ff331569a6c2ea2839c329afed6ca2e9f8a18b0c9f",
    "receipts/POINTS.json": "7ae96a4155869ee7c67e6178d700071e9d899df408bcc82a2160c58c60696208",
    "receipts/POINTS_CHAMBER.json": "cf8c4865bb27a33ba771eef04609990049abacb7c7dddb50caa896a2169f1965",
    "receipts/SYMBOL_ITEM64.json": "1411cd10c0337cf63063d40aa5c3b5f44ea5bfcd834b20846a3b2687bcbdaff8",
    "receipts/alphabet_item64.json": "9ae43e2559684279bb802dcf8a531337713f36c9f0c29679b4e211e394e8a686",
    "samples/c01_d6_g40.json": "b546933de41e8b13ade373a8509b0836f5626295937f2a94ebf1a70042d71039",
    "samples/c01_d6_g60.json": "4e26cd7455198ff50077cc31dbfad5f291d1cd51b9b6fac669c760a3a9e91585",
    "samples/c02_d6_g40.json": "5cbce465c53799070f92b37c360492ff046677bd921dbd3011095f9fc5c376ab",
    "samples/c02_d6_g60.json": "035c7ec29885d7367489a111fe1a402ac921811ea2d2cf45e0757157b2bd79b8",
    "samples/c03_d6_g40.json": "7f645eb6a20f0b4719831aa55aa92d239bdd3cf1bb8dc706c089398e9bed386a",
    "samples/c03_d6_g60.json": "0b63c14d9c0a3f8a69d28292a15af5c18ccfbbd9cf3dc5c29fce29ae2bea023b",
    "samples/c04_d6_g40.json": "522bf1b4d20de7cfbdb1dd66b3d579d9344ed81bf4dd6b4e2404be9a0a37a982",
    "samples/c04_d6_g60.json": "6def4d493531e587c9e21443218b1630b3769b76a96558779b83fd9695c48047",
    "samples/c05_d6_g40.json": "e58256d39b530326a71af5b94da06343d8846176f1c9d499e2c4b0fd16380c32",
    "samples/c05_d6_g60.json": "bbbe2b8571da20176823e3066222ed4e5b8b13dd57b9ef1d8fe9b2b62e189749",
    "samples/c06_d6_g40.json": "9603b223daaed359c6f48582075c0f0ba55afde5be0cd76f554748128d7c484d",
    "samples/c06_d6_g60.json": "a0c0b0ae2773e419624c5671be9bd15203787420a98fa1bc3efeffb1bf1f5897",
    "samples/c07_d6_g40.json": "2049eb3080a2b436f4b442acae2386f7c7f9033228760c84fe1bb38cc5975e1c",
    "samples/c07_d6_g60.json": "8cdfb608b4bc06956290c52e6185771bb6fea7fc5211408c8554c788803b594c",
    "samples/c08_d6_g40.json": "567376f3996336cad019f72c4e74d5846c52ec9368c38461aa647fbd4b7bb07b",
    "samples/c08_d6_g60.json": "1cde30e25e2cda57e7574c8d2cfe44e6bdf9df20a76f23c512caed23df2ea42e",
    "samples/p00_d4_g40.json": "a08883b6d9ec31c92863ef0bc7b3eadb5f76ab650e0dc822b4587cd139a17b36",
    "samples/p00_d4_g60.json": "f0cfaabb57de4f310e08974301d0b0ffbc03cf60edad3487acb509d2691d5320",
    "samples/p00_d6_g40.json": "3e97052d4dceb45c8449594cd2c8d582cb67ebd286e3c637348646c2de79c20e",
    "samples/p00_d6_g60.json": "f2d872cb10d1e1cf95c6536d8f6488f80c98a5cf98597f0cef7673799ab4b2f5",
    "samples/p01_d4_g40.json": "7ef07da699248b44cd9ba08258c7ba87e4492f52d62a13878f9e256ba283227e",
    "samples/p01_d4_g60.json": "329af5e674d5cb6b5065f0ae6eb3137c11d0b1a4b43f81292d6000659be4c7d2",
    "samples/p01_d6_g40.json": "eeb27df2b70ff5bd9c7d23c46ab860c02790a6734ca82d77d6000b4dad042e80",
    "samples/p01_d6_g60.json": "62d4dba1e269bde0efda093db0c6aa97d1202190cae442db7f38b1869c04ef80",
    "samples/p02_d4_g40.json": "5ed89d2b81964a20cdcbf560ded09b28b73e658d8d93ff133b01073d14502b20",
    "samples/p02_d4_g60.json": "bf51886324b057f7a47dba67278bf83457785db272a5044ac05a6027944cf463",
    "samples/p02_d6_g40.json": "7cd00455d76e09ef7dcee7757107165b44531d443cc4848851814acb52e1045f",
    "samples/p02_d6_g60.json": "01a1fe9957be867642ddf0f9765aeb1ee9bcb1947d696f9f995e255d85cd39ea",
    "samples/p03_d4_g40.json": "87b9dd662726c9fc2f0fc2be23379ccfeaf0f4f762547817689a8e06e84d392c",
    "samples/p03_d4_g60.json": "0f04ee710014e90f50f362046f07dbe3a1533b92da53691e6a2368e05b18344b",
    "samples/p03_d6_g40.json": "ce5fba869c90ec4f6b62fd0052efdfaaff9d489fffb9e7f33b6cd8f425fc4b61",
    "samples/p03_d6_g60.json": "65bc0f224f8b36edde679f0f49b5e8a5cd8f11d0d796eb801c5ac137649d28a0",
    "samples/p04_d4_g40.json": "a18a2ae0f96941cc9a835de86d2eb8ab29f89b1d91a6ad7118973d552614a3bd",
    "samples/p04_d4_g60.json": "2ad6660a82ffcbf407ee6dc3c236c29541f48ace7a5e9bc6107267a857bba87e",
    "samples/p04_d6_g40.json": "7b3f3db9c8cc137167230fa113bdd99b435f6aac39181116837ae77ec3378395",
    "samples/p04_d6_g60.json": "d29f381921753c1fbb3f275d14abec67d254fc8e3ade6bdcf1fa60f34044f9dd",
    "samples/p05_d4_g40.json": "d0412ecba524384800f73bd51e4a8f17cb23be0b041422ec5e2d53619c1a2e57",
    "samples/p05_d4_g60.json": "7fe247e2a7420f930a90c92c1a10866208269685f79f1d89bc867289098242ba",
    "samples/p05_d6_g40.json": "a2de3db6ac95bca8ea5414e5a7266ce35a39912f3770573db73426e7838570e9",
    "samples/p05_d6_g60.json": "b67b42aa6f2b0ec5cec907854e40f7603a46c3166fc7a9e8a6c678ef6f3a51c9",
    "samples/p06_d4_g40.json": "56285167ac2c65f3fa684903a7505449438915115e37c4385c2c2f0cde1f4168",
    "samples/p06_d4_g60.json": "67e0018c57145117396b7225c2ada87b4c436e5613f21833883abfca1d28cdbf",
    "samples/p06_d6_g40.json": "fe60dbafb1d21f97927e5253fabdbc4846f97c53b98a50bd66481aee240e75fe",
    "samples/p06_d6_g60.json": "502a528d1a888e9f9f4617cc74da6e39e3154906ea61dcf5596321d7358341f1",
    "samples/p07_d4_g40.json": "47a7f9090b20cd12e74dca7dd5944b0e2b662551b50b6bfe9ac48ddbf9dbdcd7",
    "samples/p07_d4_g60.json": "a1ccc6027134d3af85296c68117aaa0baf59aea2db492fc0294205883866ddd0",
    "samples/p07_d6_g40.json": "af1925abb1aea47d9d49f28a8d098f1803b54fbc52da8f09ca6718f2cfb81a29",
    "samples/p07_d6_g60.json": "12341f23517eb571771ba5a5c16c2dca18887147f28309b146f78b62a7f0003a",
    "samples/p08_d4_g40.json": "c328f9265ace3ea6f935ecee2cf2a604444c2963d1e27ac33d8eae0e63749076",
    "samples/p08_d4_g60.json": "578b9fbceb620b06baa2669d25aac32b0d49b43f6a2eb839200dd72fc86d10c5",
    "samples/p08_d6_g40.json": "bd7f89e975f9635a859f0614d45c3592548825a84c0c49509be1c72a6b9bd228",
    "samples/p08_d6_g60.json": "1a2895c34d3f1b00347839d231adaac7ef64d2656c194729c45a212305289325",
    "samples/p09_d4_g40.json": "33b85b956427b43e4bccc5c25f63a2a76c21ffc4b2e49352dd9d064b7b5fcdb3",
    "samples/p09_d4_g60.json": "e4208537645aa0f40266edf9fbccb89565b9e9f2539267eca7957309f4d1ad0a",
    "samples/p09_d6_g40.json": "e6d78ef9793de0e3cd45e34d30a0f989dfc82ca6e9cedecd97b85ca8711bddea",
    "samples/p09_d6_g60.json": "ffc06a3d30c2352b9d3aadac46447f6b559b9639923b2903e97216bf2e674965",
    "samples/p10_d4_g40.json": "9f7ed2c44f9e4297e0deb2bfb30a327a106cdc0f1bc4c7edd2017a965e6b0b10",
    "samples/p10_d4_g60.json": "60fef5dca75e073ec0c7dab4a1022af53a9a245e914e4b4c9da04f3c302227ed",
    "samples/p10_d6_g40.json": "88101ebd7ca0b8abf4dbaff01c9ab314f99e6f9b707f320a46c2a9468f593427",
    "samples/p10_d6_g60.json": "2d177c731bab6970ca430c3d4c6d88389310ae96831d5eabcc7f6e60ae488d4f",
    "samples/p11_d4_g40.json": "5e841c993d086faeb7d0697c2229ddeb08f7148ea76dd608e00dbab40c79f051",
    "samples/p11_d4_g60.json": "20ac6c5709406bfa0165c9d542d4f1a56da8c49136c1089b3478f84d0151d646",
    "samples/p11_d6_g40.json": "0492b8eb63f9e13bb4aa4ad0aa7f4b6de97481f6db7924682bd6be6299bb99f8",
    "samples/p11_d6_g60.json": "c8a1f1f0cc8954df05317b1b79727a171d3cb7aac50c998d7a5e0c1a9655d8ef",
    "samples/p12_d4_g40.json": "d3837dfc57898a82f3d85abcf123b4ae1354e276ecd0300f8b118b06000b69ad",
    "samples/p12_d4_g60.json": "a747bf79fbb61fe9a599b5e6ba5f388112ae138af2885187e9147e10a43ad594",
    "samples/p12_d6_g40.json": "19c03abc708f803778ac26d5de091cd0e0dc034a5efbbf30926ea64a487bc203",
    "samples/p12_d6_g60.json": "c506698d738a050f8b91c049e46c8ea3ce2503ae70081d69c116757ba420a2a3",
    "samples/s00_d6_g40.json": "3c6cf101c6b7af53028398d5fbe79003f115e910dbb9ba31b623c2d1ac66ddda",
    "samples/s00_d6_g60.json": "2fba84da53203a6a12635f470365cc1f366511a05b07c2b1cab1ef5b5d30dccf"
}

# ---------------------------------------------------------------------------------------------------------------------
# THE I_5 ARM (--i5): the sum of box functions S and the pentagon's v-form at the withheld point (-1, -2, -3, -4, -5) against the auxiliary-mass-flow
# pair (goals 40 / 60); the data under vendor_row5_i5/ (README.md there), pinned below.  Default off: nothing above runs
# differently without --i5.  The algebra is the record's comparison, carried here line for line (the BDK normalisation
# applied by object: the measure pin on the bubbles, the Cayley coefficients from the Gram-type matrix S, each one-mass box
# divided by r_Gamma / (s t) to its pole checks and its box function).
I5DIR = os.path.join(HERE, "vendor_row5_i5")
I5_POINT = ("-1", "-2", "-3", "-4", "-5")
I5_DPS_RECORD = 130
PINS_I5 = {
    "ITEM49_COMPARE.json": "63ebd9a97d01b8b4b1f6e0ff1f48248d3e35a1817256b021d226d1aa8da4f7e1",
    "PREDICTION_ITEM49.json": "c3a7426a9ecf443bd931232a0ad7d7be12f85915673dedab548a6846ebc7d176",
    "README.md": "f9deb1853bd5cd5c09a12d2b4b4b4f7dd2ae88d6eb08f2e49fba29447b71714c",
    "RECORD_COPIES.sha256": "e73131509b3494208fd9a257ecdccdbebb48880fb3e4c06dcd7e2331772dae7a",
    "amflow_config_g40.json": "14e21ea4a115e1ca46d3ba503c16e2776b2e4a1ad524bf77cfa700a80dfd495a",
    "amflow_config_g60.json": "fd7030dc105d26f9e7da32f5c756d244de89c81b618cd56c8231cd0604c912f5",
    "amflow_out_g40.json": "a08883b6d9ec31c92863ef0bc7b3eadb5f76ab650e0dc822b4587cd139a17b36",
    "amflow_out_g60.json": "f0cfaabb57de4f310e08974301d0b0ffbc03cf60edad3487acb509d2691d5320",
    "pentagon-reference-data.json": "8b02c73247ce632ff737a1113921f03ad2c865f00f9a019b950d387cf7e5a512",
    "psd_build_pentagon.py": "832a299dfe9ef538a5f516af6d09029f729c74dd865c687aa01230106e8eedf8",
    "psd_out_e9.json": "b0b6b63ef33221fb3a91e67a32ce9c844ed5e9938f1c72abc040556d1ea4e15d",
}
# the two outputs are the same bytes as two of the pack's samples (asserted at run time against PINS)
I5_PACK_TWINS = {"amflow_out_g40.json": "samples/p00_d4_g40.json", "amflow_out_g60.json": "samples/p00_d4_g60.json"}


def i5_refuse(msg):
    print(f"REFUSED by name: {msg} (exit 2)")
    return 2


def i5_same_point(s):
    """True when the five comma-separated rationals equal the record's point."""
    from fractions import Fraction
    try:
        got = [Fraction(x.strip()) for x in s.split(",")]
    except (ValueError, ZeroDivisionError):
        return False
    return len(got) == 5 and got == [Fraction(x) for x in I5_POINT]


def i5_series_div(num, den, lo, hi):
    """Laurent series num (dict order -> mpf, from lo) divided by a Taylor series den (list den[0..]) -> dict order lo..hi."""
    out = {}
    for n in range(lo, hi + 1):
        s = num.get(n, mp.mpf(0))
        for k in range(1, n - lo + 1):
            s -= den[k] * out[n - k]
        out[n] = s / den[0]
    return out


def i5_arm(args, t0):
    fails = []
    tol = 1e-6
    dps = int(args.i5_dps)
    print(f"[I5] the I_5 arm: the sum of box functions S and the pentagon's v-form at the withheld point ({', '.join(I5_POINT)}) against the auxiliary-mass-flow pair (goals 40 / 60), dps {dps} (the record's {I5_DPS_RECORD})")

    # [pins]
    missing = [r for r in sorted(PINS_I5) if not os.path.exists(os.path.join(I5DIR, r))]
    if missing:
        for r in missing:
            print(f"[pins] MISSING: vendor_row5_i5/{r}")
        print(f"OVERALL FAIL: {len(missing)} file(s) of vendor_row5_i5/ missing (exit 4)")
        return 4
    data = {}
    bad = []
    for r in sorted(PINS_I5):
        b = open(os.path.join(I5DIR, r), "rb").read()
        data[r] = b
        h = sha256_bytes(b)
        if h != PINS_I5[r]:
            bad.append(r)
            print(f"[pins] MISMATCH: vendor_row5_i5/{r} sha256 {h[:16]}... != pinned {PINS_I5[r][:16]}...")
    if bad:
        print(f"OVERALL FAIL: {len(bad)} file(s) of vendor_row5_i5/ differ from their pins (exit 3)")
        return 3
    print(f"[pins] {len(PINS_I5)} files of vendor_row5_i5/ verified by sha256 (the two outputs, the two configurations, the reference block, the two receipts, the pySecDec fixture and output, README.md, RECORD_COPIES.sha256)")

    REF = json.loads(data["pentagon-reference-data.json"])
    CMP = json.loads(data["ITEM49_COMPARE.json"])
    PRED = json.loads(data["PREDICTION_ITEM49.json"])
    CFG = {g: json.loads(data[f"amflow_config_g{g}.json"]) for g in (40, 60)}
    prov = REF["provenance"]

    # [cross-pins]
    xp = []
    for name, twin in I5_PACK_TWINS.items():
        xp.append((f"{name} == vendor_row05_weight3/{twin}", sha256_bytes(data[name]) == PINS[twin]))
    xp.append(("provenance amflow_out_g40 == the vendored output", prov["amflow_out_g40"] == PINS_I5["amflow_out_g40.json"]))
    xp.append(("provenance amflow_out_g60 == the vendored output", prov["amflow_out_g60"] == PINS_I5["amflow_out_g60.json"]))
    xp.append(("provenance amflow_config_g40 == the vendored configuration's original bytes", prov["amflow_config_g40"] == CFG[40]["vendored_from"]["sha256"]))
    xp.append(("provenance amflow_config_g60 == the vendored configuration's original bytes", prov["amflow_config_g60"] == CFG[60]["vendored_from"]["sha256"]))
    xp.append(("provenance psd_out_e9 == the vendored pySecDec output", prov["psd_out_e9"] == PINS_I5["psd_out_e9.json"]))
    xp.append(("provenance psd_build_pentagon.py == the fixture's original bytes (its header line)", prov["psd_build_pentagon.py"] in data["psd_build_pentagon.py"].decode().split("\n")[1]))
    xp.append(("ITEM49_COMPARE.json out_files sha256 == the vendored outputs", CMP["out_files"]["40"]["sha256"] == PINS_I5["amflow_out_g40.json"] and CMP["out_files"]["60"]["sha256"] == PINS_I5["amflow_out_g60.json"]))
    xp.append(("ITEM49_COMPARE.json prediction_receipt sha256 == PREDICTION_ITEM49.json's original bytes", CMP["prediction_receipt"]["sha256"] == PRED["vendored_from"]["sha256"]))
    xp.append(("the reference block's S value of record (served_I5_dps180) == the prediction receipt's", REF["served_I5_dps180"] == PRED["two_precision_pair"]["dps180"]["I5"]))
    xp.append(("the reference block's goal-60 sum of B == ITEM49_COMPARE.json's", REF["amflow_sum_B_goal60"] == CMP["I5"]["amflow_sum_B"]))
    xp.append(("the reference block's bar == the integer part of the record's reportable count", int(REF["certified_digits_pair_floor"]) == int(CMP["reportable_digits"]["value"])))
    pts = [tuple(d["point"][k] for k in ("v1", "v2", "v3", "v4", "v5")) for d in (REF, PRED)] + [tuple(CFG[g]["amf_options"]["blackbox"]["numeric_values"][k] for k in ("v1", "v2", "v3", "v4", "v5")) for g in (40, 60)]
    xp.append(("the point of the reference block, the prediction receipt and both configurations == the arm's", all(p == I5_POINT for p in pts)))
    xp_ok = sum(1 for _, ok in xp if ok)
    for label, ok in xp:
        if not ok:
            fails.append(f"cross-pin: {label}")
    print(f"[cross-pins] {xp_ok} of {len(xp)}: the outputs are the pack's p00_d4 samples byte for byte; the reference block's provenance sha256s name the vendored objects (the configurations and the fixture by their original bytes); the receipts pin each other; one point throughout")
    sib = os.path.join(HERE, "pentagon-evaluate.py")
    sib_sha = sha256_bytes(open(sib, "rb").read()) if os.path.exists(sib) else None
    print(f"[sibling] pentagon-evaluate.py beside this file: {sib_sha[:16] + '...' if sib_sha else 'absent'}; the prediction of record was filed against {PRED['served_sha256'][:16]}... "
          + ("(the same bytes)" if sib_sha == PRED["served_sha256"] else "(different bytes: pentagon-evaluate.py has moved since the prediction was filed -- informational; S is re-evaluated below from its formula)"))

    if args.i5_mutate:
        s = PRED["two_precision_pair"]["dps180"]["I5"]
        k = 25
        PRED["two_precision_pair"]["dps180"]["I5"] = s[:k] + str((int(s[k]) + 1) % 10) + s[k + 1:]
        print(f"[mutate] digit {k} of the vendored S string of record (PREDICTION_ITEM49.json, dps 180) changed in memory (this run MUST exit nonzero)")

    mp.mp.dps = dps
    v = [mp.mpf(REF["point"][k]) for k in ("v1", "v2", "v3", "v4", "v5")]
    I5_served = mp.mpf(PRED["two_precision_pair"]["dps180"]["I5"])
    B_served = [mp.mpf(x) for x in PRED["two_precision_pair"]["dps180"]["B"]]
    idx = [tuple(t["indices"]) for t in CFG[40]["integrals"]]
    if idx != [tuple(t["indices"]) for t in CFG[60]["integrals"]]:
        fails.append("the two configurations name different target lists")
    outs = {g: parse_out(json.loads(data[f"amflow_out_g{g}.json"])) for g in (40, 60)}
    R = {k: {o: c[0] for o, c in d.items()} for k, d in outs[60].items()}
    im_max = max(abs(c[1]) for d in outs[60].values() for c in d.values())

    # [closed form] the documented form of pentagon-evaluate.py, re-evaluated here
    B_cf = []
    for i in range(5):
        a, b, c = v[i], v[(i + 2) % 5], v[(i + 3) % 5]
        B_cf.append(mp.polylog(2, 1 - a / b) + mp.polylog(2, 1 - a / c) + mp.log(b / c) ** 2 / 2)
    d_cf = min(dig(B_cf[i], B_served[i]) for i in range(5))
    d_cf_I5 = dig(sum(B_cf), I5_served)
    need = dps - 10
    print(f"[closed form] B_i = Li2(1 - v_i/v_(i+2)) + Li2(1 - v_i/v_(i+3)) + log^2(v_(i+2)/v_(i+3))/2, S = sum_i B_i (the sum of box functions -- the weight-two fit's object, NOT the pentagon; re-evaluated here at dps {dps}): "
          f"the five B_i vs the prediction receipt's dps-180 strings >= {d_cf:.1f} digits, S {d_cf_I5:.1f} digits (need >= {need}); S = {mp.nstr(sum(B_cf), 40)}")
    if d_cf < need:
        fails.append(f"closed form: a B_i re-evaluated here vs the vendored dps-180 string {d_cf:.1f} d < {need}")
    if d_cf_I5 < need:
        fails.append(f"closed form: S re-evaluated here vs the vendored S string of record {d_cf_I5:.1f} d < {need}" + (" (mutated in memory)" if args.i5_mutate else ""))

    # [measure] the two massless bubbles vs Gamma(eps) Gamma(1-eps)^2 / Gamma(2-2eps) (-v)^-eps per order (e * Bub is regular)
    def bub(vv):
        return lambda e: mp.gamma(1 + e) * mp.gamma(1 - e) ** 2 / mp.gamma(2 - 2 * e) * (-vv) ** (-e)
    pin_min = None
    for key, vv in (((1, 0, 1, 0, 0), v[0]), ((0, 1, 0, 0, 1), v[4])):
        tay = mp.taylor(bub(vv), 0, 5)
        ser = {n: tay[n + 1] for n in range(-1, 4)}
        for n in sorted(R[key]):
            if n in ser:
                d = dig(R[key][n], ser[n])
                pin_min = d if pin_min is None else min(pin_min, d)

    # [BDK] pentagon = -(1/2) sum_a c_a box_a + O(eps), c_a = sum_b (S^-1)_ab, S_ab = -(1/2) (q_a - q_b)^2
    def inv(a, b):
        a, b = sorted((a, b))
        d = (b - a) % 5
        if d in (0, 1, 4):
            return mp.mpf(0)
        if d == 2:
            return v[a]
        return v[(a + 3) % 5]
    S = mp.matrix(5, 5)
    for a in range(5):
        for b in range(5):
            S[a, b] = -inv(a, b) / 2
    Sinv = S ** -1
    cay = [sum(Sinv[a, b] for b in range(5)) for a in range(5)]
    boxes = {a: tuple(1 if j != a else 0 for j in range(5)) for a in range(5)}
    pent = (1, 1, 1, 1, 1)
    bdk = {}
    for n in range(-2, 2):
        rhs = -sum(cay[a] / 2 * R[boxes[a]][n] for a in range(5))
        bdk[n] = dig(R[pent][n], rhs)
    cay_ok = [mp.nstr(x, 30) for x in cay] == list(REF["bdk_cayley_c"])
    if not cay_ok:
        fails.append("the Cayley coefficients differ from the reference block's bdk_cayley_c")

    # [boxes] box a (propagator a removed) -> the closed form's index i = (a - 1) mod 5: M^2 = v_i, channels v_(i+2), v_(i+3)
    rG = lambda e: mp.gamma(1 + e) * mp.gamma(1 - e) ** 2 / mp.gamma(1 - 2 * e)
    rG_t = mp.taylor(rG, 0, 6)
    B_amf, sig_all, pole_d, B_d = [None] * 5, [None] * 5, [None] * 5, [None] * 5
    for a in range(5):
        i = (a - 1) % 5
        M2, s, t = v[i], v[(i + 2) % 5], v[(i + 3) % 5]
        num = {n: R[boxes[a]][n] * s * t for n in R[boxes[a]]}
        g = i5_series_div(num, rG_t, -2, 1)
        sigma = g[-2] / 2
        Ls, Lt, LM = mp.log(-s), mp.log(-t), mp.log(-M2)
        chk_m1 = -2 * sigma * (Ls + Lt - LM)
        B = ((Ls ** 2 + Lt ** 2 - LM ** 2) - mp.pi ** 2 / 3 - g[0] / sigma) / 2
        B_amf[i], sig_all[i] = B, mp.mpf(mp.nstr(sigma, 30))  # the record reads sigma back from its 30-digit string (exactly +-1 here)
        pole_d[i] = min(dig(abs(sigma), 1), dig(g[-1], chk_m1))
        B_d[i] = dig(B, B_served[i])
    I5_amf = sum(B_amf)
    d_I5 = dig(I5_amf, I5_served)
    d_ref_string = dig(I5_amf, mp.mpf(REF["amflow_sum_B_goal60"]))

    # the pentagon per order from the served B (the BDK form, sigma from the boxes)
    def pent_pred(e):
        tot = mp.mpf(0)
        for a in range(5):
            i = (a - 1) % 5
            M2, s, t = v[i], v[(i + 2) % 5], v[(i + 3) % 5]
            e2Fbox = sig_all[i] * (2 * ((-s) ** (-e) + (-t) ** (-e) - (-M2) ** (-e)) - e ** 2 * (2 * B_served[i] + mp.pi ** 2 / 3))
            tot += -cay[a] / 2 * rG(e) / (s * t) * e2Fbox
        return tot
    pt = mp.taylor(pent_pred, 0, 3)
    pent_cf = {n: dig(R[pent][n], pt[n + 2]) for n in (-2, -1, 0)}
    print(f"[measure] the two bubbles vs the exact Gamma form, eps^-1..eps^3: >= {pin_min:.1f} digits;  [BDK] Cayley c = ({', '.join(mp.nstr(x, 6) for x in cay)}) == the reference block's: {'yes' if cay_ok else 'NO'}; "
          f"pentagon vs -(1/2) sum_a c_a box_a: eps^-2 {bdk[-2]:.1f}, eps^-1 {bdk[-1]:.1f}, eps^0 {bdk[0]:.1f} digits (eps^1 {bdk[1]:.1f}: not covered, the D = 6 pentagon term); max imaginary part {mp.nstr(im_max, 3)}")
    print(f"[boxes] each one-mass box divided by r_Gamma / (s t): the pole checks (g_-2 / 2 = +-1, g_-1 = -2 sigma (L_s + L_t - L_M)) >= {min(pole_d):.1f} digits; "
          f"the box functions B_1..B_5 from the goal-60 eps^0 coefficients vs the served B_i: {', '.join(f'{d:.1f}' for d in B_d)} digits; the pentagon per order from the served B_i vs the goal-60 leg: {', '.join(f'eps^{n} {pent_cf[n]:.1f}' for n in (-2, -1, 0))}")
    print(f"[sum B] the sum of the five box functions from the goal-60 boxes = {mp.nstr(I5_amf, 40)} vs the S value of record (dps 180): {d_I5:.2f} digits; vs the reference block's 70-digit string {d_ref_string:.1f}")

    # [pair] goal 40 vs goal 60 per target and order; the reportable count with its members
    pair = {}
    for k in idx:
        pair[k] = {n: dig(outs[40][k][n][0], outs[60][k][n][0]) for n in sorted(outs[60][k]) if n in outs[40][k]}
    pair_floor = min(min(d[n] for n in (-2, -1, 0) if n in d) for d in pair.values())
    d_pair_served = float(PRED["two_precision_pair"]["agree_digits_120_vs_180"])
    members = {"the goal-40 / goal-60 pair floor over the 8 targets x eps^-2..eps^0": pair_floor, "the sum of B (goal 60) vs the S value of record": d_I5, "that value's dps-120 / dps-180 pair": d_pair_served}
    reportable = min(members.values())
    bar = int(REF["certified_digits_pair_floor"])
    s = PRED["two_precision_pair"]["dps180"]["I5"]
    pos = 25
    planted = s[:pos] + str((int(s[pos]) + 1) % 10) + s[pos + 1:]
    d_planted = dig(I5_amf, mp.mpf(planted))
    print(f"[pair] goal 40 vs goal 60 per target (eps^-2, eps^-1, eps^0): " + "; ".join(f"{list(k)} {pair[k][-2]:.1f} / {pair[k][-1]:.1f} / {pair[k][0]:.1f}" if -2 in pair[k] else f"{list(k)} - / {pair[k][-1]:.1f} / {pair[k][0]:.1f}" for k in idx))
    gate_run = dps >= bar + 10
    verdict = "PASS" if reportable >= bar else "FAIL"
    print(f"[I5 gate] reportable = min({', '.join(f'{k} {d:.2f}' for k, d in members.items())}) = {reportable:.2f} digits; bar {bar} (the reference block's certified_digits_pair_floor) -> "
          + (verdict if gate_run else f"NOT RUN by name: every member is capped by the working dps {dps} < bar + 10 = {bar + 10}"))
    print(f"[control] the S string of record with digit {pos} changed: the sum of B agrees with it to {d_planted:.1f} digits -> {'FAIL by name: planted digit detected' if d_planted < 30 else 'CONTROL BROKEN'}")
    if gate_run and reportable < bar:
        fails.append(f"I5 gate: reportable {reportable:.2f} d < bar {bar}" + (" (mutated in memory)" if args.i5_mutate else ""))
    if d_planted >= 30:
        fails.append("the planted-digit control did not fail")

    # [pentagon] the BDK v-form (the closed form of pentagon-evaluate.py; r_Gamma expanded, no e^(eps gamma_E)): its three Laurent
    # coefficients vs the goal-60 [1,1,1,1,1] entry and vs the reduction -(1/2) sum_a c_a box_a; S vs the pentagon's eps^0
    r1, r2 = -mp.euler, mp.euler ** 2 / 2 - mp.pi ** 2 / 12
    vf = {-2: mp.mpf(0), -1: mp.mpf(0), 0: mp.mpf(0)}
    for j in range(5):
        Rj = 1 / (v[(j - 2) % 5] * v[(j - 1) % 5] * v[j])
        Lx = mp.log(((-v[(j - 2) % 5]) * (-v[(j - 1) % 5]) * (-v[j])) / ((-v[(j + 1) % 5]) * (-v[(j + 2) % 5])))
        fin = 2 * mp.polylog(2, 1 - v[(j + 3) % 5] / v[(j + 1) % 5]) + 2 * mp.polylog(2, 1 - v[j] / v[(j + 2) % 5]) - mp.pi ** 2 / 6
        vf[-2] += Rj
        vf[-1] += Rj * (r1 - Lx)
        vf[0] += Rj * (r2 - r1 * Lx + Lx ** 2 / 2 + fin)
    vf_d = {n: dig(vf[n], R[pent][n]) for n in (-2, -1, 0)}
    vf_red = {n: dig(vf[n], -sum(cay[a] / 2 * R[boxes[a]][n] for a in range(5))) for n in (-2, -1, 0)}
    vf_need = {n: min(dps - 10, pair[pent][n]) for n in (-2, -1, 0)}
    d_S_pent = dig(I5_amf, R[pent][0])
    print(f"[pentagon] the v-form (the closed form of pentagon-evaluate.py) = {', '.join(f'eps^{n} {mp.nstr(vf[n], 30)}' for n in (-2, -1, 0))}; vs the goal-60 [1,1,1,1,1] entry: "
          + ", ".join(f"eps^{n} {vf_d[n]:.1f} (need >= {vf_need[n]:.1f})" for n in (-2, -1, 0)) + " digits; vs the reduction -(1/2) sum_a c_a box_a: "
          + ", ".join(f"eps^{n} {vf_red[n]:.1f}" for n in (-2, -1, 0)) + f" digits; S vs the pentagon's eps^0: {d_S_pent:.2f} digits (S is not the pentagon)")
    for n in (-2, -1, 0):
        if vf_d[n] < vf_need[n]:
            fails.append(f"pentagon: the v-form at eps^{n} agrees with the goal-60 leg to {vf_d[n]:.1f} d < {vf_need[n]:.1f}")

    # [pySecDec] the third route, from the reference block (values at double precision; agreement re-derived)
    P = REF["pysecdec_eps0"]
    d_psd = dig(mp.mpf(P["psd_re"]), mp.mpf(P["amflow_g60_re"]))
    within = abs(mp.mpf(P["psd_re"]) - mp.mpf(P["amflow_g60_re"])) <= 3 * abs(mp.mpf(P["psd_err_re"]))
    print(f"[pySecDec] eps^0 {P['psd_re']} +/- {P['psd_err_re']} vs the goal-60 leg {P['amflow_g60_re']}: {d_psd:.2f} digits (the reference block's {P['agree_d']:.2f}), within 3 error bars: {'yes' if within else 'NO'} (the reference block's {'yes' if P['within_bar'] else 'no'})")
    if abs(d_psd - float(P["agree_d"])) >= tol or within != bool(P["within_bar"]):
        fails.append("pySecDec: the re-derived agreement or the bar verdict differs from the reference block")

    # [record] every figure against ITEM49_COMPARE.json (the record's dps only)
    rec_state = None
    if dps == I5_DPS_RECORD:
        F = CMP["floors"]
        mine = [("served_two_precision_pair_d", d_pair_served), ("goal40_vs_goal60_pair_floor_d_over_targets_and_orders_-2..0", pair_floor), ("measure_pin_min_d", pin_min),
                ("bdk_reduction_min_d_orders_-2..0_(eps^1_excluded_by_the_D=6_term)", min(bdk[n] for n in (-2, -1, 0))), ("box_pole_checks_min_d", min(pole_d)), ("per_box_B_min_d", min(B_d)),
                ("I5_sum_B_amflow_vs_served_d", d_I5), ("pentagon_closed_form_min_d_orders_-2..0", min(pent_cf.values()))]
        n_ok, n_all, worst = 0, 0, 0.0

        def cmpf(label, got, want):
            nonlocal n_ok, n_all, worst
            n_all += 1
            diff = abs(float(got) - float(want))
            worst = max(worst, diff)
            if diff < tol:
                n_ok += 1
            else:
                fails.append(f"record: {label} re-derived {float(got):.6f} vs the receipt's {float(want):.6f}" + (" (mutated in memory)" if args.i5_mutate else ""))
        for key, got in mine:
            cmpf(f"floors.{key}", got, F[key])
        for n in (-2, -1, 0, 1):
            cmpf(f"bdk_reduction eps^{n}", bdk[n], CMP["bdk_reduction_pentagon_vs_minus_half_sum_c_box"][str(n)]["agree_d"])
        for i in range(5):
            cmpf(f"boxes.B_{i+1}.B_agree_d", B_d[i], CMP["boxes"][f"B_{i+1}"]["B_agree_d"])
        for k in idx:
            for n, d in pair[k].items():
                cmpf(f"pair {list(k)} eps^{n}", d, CMP["pair_goal40_vs_goal60"][str(list(k))][str(n)])
        for n in (-2, -1, 0):
            cmpf(f"pentagon_closed_form eps^{n}", pent_cf[n], CMP["pentagon_closed_form_per_order"][str(n)]["agree_d"])
        cmpf("planted_digit_control.agree_d_vs_planted", d_planted, CMP["planted_digit_control"]["agree_d_vs_planted"])
        cmpf("reportable_digits.value", reportable, CMP["reportable_digits"]["value"])
        if mp.nstr(im_max, 5) != CMP["floors"]["max_imag_part_amflow"]:
            fails.append("record: max imaginary part differs")
        if mp.nstr(I5_amf, 70) != CMP["I5"]["amflow_sum_B"]:
            fails.append("record: the 70-digit sum-of-B string differs from ITEM49_COMPARE.json's")
        rec_state = f"{n_ok} of {n_all} figures agree (largest difference {worst:.1e}); the 70-digit sum-of-B string {'==' if mp.nstr(I5_amf, 70) == CMP['I5']['amflow_sum_B'] else '!='} the receipt's"
        print(f"[record] re-derived here vs ITEM49_COMPARE.json at the record's dps {dps}: {rec_state}")
    else:
        print(f"[record] NOT RUN by name: the comparison with ITEM49_COMPARE.json needs the record's dps {I5_DPS_RECORD} (this run: {dps})")

    print(f"\ntimings [s]: TOTAL {time.time() - t0:.2f}")
    if fails:
        print(f"OVERALL FAIL: {'; '.join(fails)}")
        return 1
    if not gate_run or rec_state is None:
        print(f"OVERALL: the I_5 arm's pins, cross-pins, closed form, measure, BDK, boxes and controls OK; " + ("the gate" if not gate_run else "") + (" and " if not gate_run and rec_state is None else "") + ("the record comparison" if rec_state is None else "") + f" NOT RUN by name at dps {dps} (exit 5)")
        return 5
    print(f"OVERALL PASS (the I_5 arm at ({', '.join(I5_POINT)}): the goal-40 / goal-60 pair floor {reportable:.2f} digits, bar {bar}; the pentagon's v-form vs the goal-60 leg {' / '.join(f'{vf_d[n]:.2f}' for n in (-2, -1, 0))} digits at eps^-2 / eps^-1 / eps^0; the sum of box functions S vs its value of record {d_I5:.2f} digits)")
    return 0

PENT = (1, 1, 1, 1, 1)
BOXES = [tuple(1 if j != a else 0 for j in range(5)) for a in range(5)]


def sha256_bytes(b):
    return hashlib.sha256(b).hexdigest()


def dig(a, b):
    """relative digits of agreement, the fit scripts' measure (identical -> the working dps)."""
    a, b = mp.mpf(a), mp.mpf(b)
    if a == b:
        return float(mp.mp.dps)
    ref = max(abs(a), abs(b))
    return float(-mp.log10(abs(a - b) / ref)) if ref != 0 else float(mp.mp.dps)


def ball_mid(s):
    """the midpoint of one printed value: '[X +/- E]' -> X; a plain decimal -> itself; '[+/- E]' -> 0."""
    s = s.strip()
    if s.startswith("["):
        s = s[1:-1]
    mid = s.split("+/-")[0].strip()
    return mp.mpf(mid) if mid else mp.mpf(0)


def laurent(entry):
    return {int(c["order"]): (ball_mid(c["value"]["re"]), ball_mid(c["value"]["im"])) for c in entry["coefficients"]}


def parse_out(obj):
    return {tuple(r["integral"]["indices"]): laurent(r) for r in obj["result"]}


def main():
    ap = argparse.ArgumentParser(description="Row 05: the weight-3 arm pack vendor_row05_weight3/ -- pins, cross-pins, census, pair floors, the weight-two count")
    ap.add_argument("--no-count", action="store_true", help="skip the count re-derivation (no sympy / python-flint needed); the verdict names the skip")
    ap.add_argument("--w3", action="store_true", help="also re-derive the weight-three parity-odd count (about a minute)")
    ap.add_argument("--mutate", action="store_true", help="change one digit of one output in memory; the run must exit 1 by name")
    ap.add_argument("--i5", action="store_true", help="the I_5 arm: the withheld point (-1,-2,-3,-4,-5) against the auxiliary-mass-flow pair vendored under vendor_row5_i5/ (pins, cross-pins, the sum of box functions S re-evaluated, the box functions from the goal-60 leg, the pentagon's v-form per order, the goal-40 / goal-60 pair floor against the bar); the weight-3 legs do not run")
    ap.add_argument("--i5-dps", type=int, default=I5_DPS_RECORD, help="working precision of the I_5 arm (default 130, the record's; the record comparison runs there only)")
    ap.add_argument("--i5-point", default=None, help="five comma-separated rationals; anything but the record's point (-1,-2,-3,-4,-5) is refused by name (exit 2)")
    ap.add_argument("--i5-mutate", action="store_true", help="one digit of the vendored S string of record changed in memory; the run must exit 1 by name")
    args = ap.parse_args()
    if (args.i5_point is not None or args.i5_mutate) and not args.i5:
        return i5_refuse("--i5-point and --i5-mutate belong to the I_5 arm: pass --i5")
    if args.i5 and (args.w3 or args.no_count or args.mutate):
        return i5_refuse("--i5 does not combine with --w3, --no-count or --mutate (the weight-3 legs do not run under the arm)")
    if args.i5 and args.i5_point is not None and not i5_same_point(args.i5_point):
        return i5_refuse(f"the I_5 arm holds reference data at ({', '.join(I5_POINT)}) only; the point {args.i5_point} is outside its domain")
    if args.i5 and args.i5_dps < 20:
        return i5_refuse(f"--i5-dps {args.i5_dps} below 20")
    t0 = time.time()
    fails = []

    print("pentagon weight-3 pack  vendor_row05_weight3/  (row 5: the O(eps) arm -- scripts as run, 70 outputs, 7 receipts; pentagon-evaluate.py gains no O(eps) tier here)")

    # [pins]
    data = {}
    missing = [r for r in sorted(PINS) if not os.path.exists(os.path.join(PACK, r))]
    if missing:
        for r in missing:
            print(f"[pins] MISSING: vendor_row05_weight3/{r}")
        print(f"OVERALL FAIL: {len(missing)} pack file(s) missing (exit 4)")
        return 4
    bad = []
    for r in sorted(PINS):
        b = open(os.path.join(PACK, r), "rb").read()
        data[r] = b
        h = sha256_bytes(b)
        if h != PINS[r]:
            bad.append(r)
            print(f"[pins] MISMATCH: vendor_row05_weight3/{r} sha256 {h[:16]}... != pinned {PINS[r][:16]}...")
    if bad:
        print(f"OVERALL FAIL: {len(bad)} pack file(s) differ from their pins (exit 3)")
        return 3
    sub = {}
    for r in PINS:
        sub[r.split("/")[0] if "/" in r else r] = sub.get(r.split("/")[0] if "/" in r else r, 0) + 1
    verb = sum(1 for r in RECORD if RECORD[r] == PINS[r])
    recut = sorted(r for r in RECORD if RECORD[r] != PINS[r])
    print(f"[pins] {len(PINS)} pack files verified by sha256: " + ", ".join(f"{k} {v}" for k, v in sorted(sub.items()))
          + f"; of the {len(RECORD)} vendored files {verb} are byte-identical to the bytes as run and {len(recut)} carry re-cut constants ({', '.join(recut)})")

    if args.i5:
        return i5_arm(args, t0)

    if args.mutate:
        r = "samples/p10_d4_g60.json"
        obj = json.loads(data[r])
        for e in obj["result"]:
            if tuple(e["integral"]["indices"]) == PENT:
                for c in e["coefficients"]:
                    if int(c["order"]) == 1:
                        s = c["value"]["re"]
                        k = 25
                        c["value"]["re"] = s[:k] + str((int(s[k]) + 1) % 10) + s[k + 1:]
        data[r] = json.dumps(obj).encode()
        print(f"[mutate] digit {k} of the goal-60 eps^1 pentagon value at p10 ({r}) changed in memory (this run MUST exit nonzero)")

    # receipts
    R = {os.path.basename(r): json.loads(data[r]) for r in PINS if r.startswith("receipts/")}
    A, CNT, SYM = R["alphabet_item64.json"], R["COUNT_ITEM64.json"], R["SYMBOL_ITEM64.json"]
    P, PC, FIT, D6 = R["POINTS.json"], R["POINTS_CHAMBER.json"], R["FIT_ITEM64.json"], R["D6FIT_ITEM64_sqrtD_dps45.json"]

    # [cross-pins]
    xp_ok, xp_n = 0, 0
    for rname, script in (("alphabet_item64.json", "alphabet.py"), ("COUNT_ITEM64.json", "count.py"), ("SYMBOL_ITEM64.json", "symbol_extract.py"),
                          ("FIT_ITEM64.json", "oeps_fit.py"), ("D6FIT_ITEM64_sqrtD_dps45.json", "d6_symbol_fit.py"),
                          ("POINTS.json", "make_points_configs.py"), ("POINTS_CHAMBER.json", "make_chamber_points.py")):
        xp_n += 1
        pr = R[rname]["PRODUCER"]
        if pr["script"] == script and pr["sha256"] == RECORD["arm/" + script]:
            xp_ok += 1
        else:
            fails.append(f"cross-pin: {rname} PRODUCER {pr['script']} {pr['sha256'][:16]} != arm/{script} as run {RECORD['arm/' + script][:16]}")
    n_prod = xp_ok
    rr = [("SYMBOL_ITEM64.json alphabet_sha256", SYM["alphabet_sha256"], "receipts/alphabet_item64.json"),
          ("SYMBOL_ITEM64.json count_sha256", SYM["count_sha256"], "receipts/COUNT_ITEM64.json"),
          ("D6FIT symbol_sha256", D6["symbol_sha256"], "receipts/SYMBOL_ITEM64.json"),
          ("D6FIT alphabet_sha256", D6["alphabet_sha256"], "receipts/alphabet_item64.json"),
          ("FIT_ITEM64.json points_file.sha256", FIT["points_file"]["sha256"], "receipts/POINTS.json"),
          ("COUNT_ITEM64.json alphabet_file.sha256", CNT["alphabet_file"]["sha256"], "receipts/alphabet_item64.json")]
    rr_ok = 0
    for label, got, target in rr:
        if got == RECORD[target]:
            rr_ok += 1
        else:
            fails.append(f"cross-pin: {label} {got[:16]} != {target} as run {RECORD[target][:16]}")
    s_fit_n = s_fit_ok = 0
    for pid, rec in FIT["per_point"].items():
        for k, h16 in rec["files"].items():
            s_fit_n += 1
            key = f"samples/{pid}_{k}.json"
            if key in PINS and PINS[key].startswith(h16):
                s_fit_ok += 1
            else:
                fails.append(f"cross-pin: FIT per_point {pid} names {key} as {h16}, the pack has {PINS.get(key, 'no such file')[:16]}")
    s_d6_n = s_d6_ok = 0
    for pid, rec in D6["per_point"].items():
        for g, h16 in rec["sha"].items():
            s_d6_n += 1
            key = f"samples/{pid}_d6_{g}.json"
            if key in PINS and PINS[key].startswith(h16):
                s_d6_ok += 1
            else:
                fails.append(f"cross-pin: D6FIT per_point {pid} names {key} as {h16}, the pack has {PINS.get(key, 'no such file')[:16]}")
    print(f"[cross-pins] receipts' PRODUCER sha256 == the scripts as run: {n_prod} of {xp_n}; receipt-to-receipt sha256 pins: {rr_ok} of {len(rr)}; "
          f"sample sha16s named by FIT_ITEM64.json: {s_fit_ok} of {s_fit_n}, by D6FIT: {s_d6_ok} of {s_d6_n}")

    # [census]
    st = {s["label"]: s for s in CNT["stages"]}
    w3o, w3e, w2a = st["w3_A21_odd"], st["w3_A21_even"], st["w2_A16_record_subalphabet"]
    so = SYM["w3_odd_Z5"]
    fo, bdk = FIT["fit_Oeps"], FIT["bdk_dimension_shift"]
    ho = {k: v for k, v in fo["held_out"].items() if k in FIT["held_out"]}
    ctrl = {k: v for k, v in fo["held_out"].items() if k in FIT["control_points"]}
    d6h = D6["held_out"]
    print("[census] alphabet: %d letters (%s) [alphabet_item64.json n_letters, letters_in_order]" % (A["n_letters"], ", ".join(A["letters_in_order"])))
    print("         weight 3 over the 21 letters, parity-odd: %d raw -> %d first entry -> %s integrability (mod two primes) -> %s parity-odd (over Q) -> %s under Z5 (rank %s of %d orbit unknowns over Q) [COUNT_ITEM64.json stages w3_A21_odd]"
          % (w3o["raw"], w3o["first_entry"], w3o["after_integrability_modp"], w3o["after_parity"]["count_Q"], w3o["after_Z5"]["count_Q"], w3o["after_Z5"]["rank_Q"], w3o["after_Z5"]["unknowns"]))
    print("         weight 3 parity-even: %s after parity (mod p) -> %s under Z5; weight 2 over the 16-letter subalphabet: %d -> %d -> %s -> %s under Z5; the five box symbols in the constrained space: %d of 5, their sum Z5-invariant: %s [stages w3_A21_even, w2_A16_record_subalphabet]"
          % (w3e["after_parity"]["count_modp"], w3e["after_Z5"]["count_Q"], w2a["raw"], w2a["first_entry"], w2a["after_integrability_modp"], w2a["after_Z5"]["count_Q"],
             sum(1 for x in w2a["control_boxes"]["B_i_in_constrained_space"] if x), "yes" if w2a["control_boxes"]["sum_B_Z5_invariant"] else "no"))
    print("         the unique symbol: %d terms in %d Z5 orbits, coefficients %s, parity pattern %s, %d distinct weight-2 right factors, last letters %s, integrability residual on the full symbol %s [SYMBOL_ITEM64.json w3_odd_Z5]"
          % (so["n_terms"], so["n_orbit_terms"], so["coefficient_set"], so["parity_pattern_counts"], so["distinct_weight2_right_factors"], so["distinct_last_letters"], so["integrability_verified_on_full_symbol_max_residual"]))
    fl_ = lambda x: int(x)  # digit counts are floored, as the receipts' prose floors them
    print("         O(eps) value fit: %d points in fit, rank %d, condition number %s, coefficients %s integer to %d digits (floor over %d), in-fit residual %d digits; held out %s: agreement %d digits, reportable %d digits (floors over %d); control %s: agreement %d, reportable %d [FIT_ITEM64.json fit_Oeps]"
          % (fo["n_in_fit"], fo["rank"], fo["condition_number"], fo["coefficients"], fl_(min(fo["coefficients_nearest_integer_d"])), len(fo["coefficients_nearest_integer_d"]), fl_(fo["in_fit_residual_min_d"]),
             " ".join(ho), fl_(min(v["agree_d"] for v in ho.values())), fl_(min(v["reportable_d"] for v in ho.values())), len(ho), " ".join(ctrl), fl_(min(v["agree_d"] for v in ctrl.values())), fl_(min(v["reportable_d"] for v in ctrl.values()))))
    print("         dimension shift: rho nearest integer %d, integer to %d digits, constant across the %d points to %d digits; box reduction at eps^-2..eps^0 %d digits; pair floors over the points: eps^1 pentagon %.2f, D=6 pentagon eps^0 %.2f; max imaginary part %s; D=6 leading orders %s [bdk_dimension_shift]"
          % (bdk["rho_nearest_integer"], fl_(bdk["rho_is_integer_d"]), FIT["n_points_complete"], fl_(bdk["rho_constant_across_points_min_d"]), fl_(bdk["min_bdk_orders_-2..0_d"]), bdk["min_floor_P1"], bdk["min_floor_P6_0"], bdk["max_imag_part"], bdk["P6_leading_orders"]))
    print("         planted digit (position %d of %s): %.1f digits -> %s; foreign point rc %d [controls]" % (FIT["controls"]["planted_digit"]["digit_pos"], FIT["controls"]["planted_digit"]["point"], FIT["controls"]["planted_digit"]["agree_d_vs_planted"], FIT["controls"]["planted_digit"]["verdict"], FIT["controls"]["foreign_point"]["rc"]))
    print("         D=6 symbol-function fit (norm %s, dps %d): %d points in fit, held out %s: agreement %d digits, reportable %d digits (floors over %d); rank %d, condition number %s, symbol coefficient %s, pi^2 coefficient over pi^2 %s, constant %s; Z5 control identical (%d); %d points refused by name; planted digit %.1f digits -> %s [D6FIT_ITEM64_sqrtD_dps45.json]"
          % (D6["norm"], D6["dps"], len(D6["in_fit"]), " ".join(d6h), fl_(min(v["agree_d"] for v in d6h.values())), fl_(min(v["reportable_d"] for v in d6h.values())), len(d6h), D6["fit"]["rank"], D6["fit"]["condition_number"],
             D6["fit"]["coefficients"][0], D6["fit"]["kappa_over_pi2"], D6["fit"]["coefficients"][2], int(D6["z5_control"]["identical_d"]), len(D6["refused_points"]), D6["controls"]["planted_digit"]["agree_d_vs_planted"], D6["controls"]["planted_digit"]["verdict"]))
    print("         points: %d in POINTS.json (%d sample, %d control) + %d chamber points + the symmetric point; outputs listed by the fit receipts: %d + %d" % (len(P["points"]), sum(1 for q in P["points"] if q["role"] == "sample"), sum(1 for q in P["points"] if q["role"] != "sample"), len(PC["points"]), s_fit_n, s_d6_n))

    # [samples]
    outs = {}
    kinds = {}
    for r in sorted(PINS):
        if not r.startswith("samples/"):
            continue
        obj = json.loads(data[r])
        stem = os.path.basename(r)[:-5]
        pid, d0, g = stem.split("_")
        outs[(pid, int(d0[1:]), int(g[1:]))] = obj
        key = (obj["options"]["d0"], len(obj["result"]), tuple(sorted(set(int(c["order"]) for e in obj["result"] for c in e["coefficients"]))))
        kinds[key] = kinds.get(key, 0) + 1
    im_nonzero = sum(1 for obj in outs.values() for e in obj["result"] for c in e["coefficients"] if c["value"]["im"].strip() not in ("0", "0.0"))
    print("[samples] %d outputs: " % len(outs) + "; ".join("d0 = %s: %d files, %d integrals, orders eps^%d..eps^%d" % (k[0], n, k[1], k[2][0], k[2][-1]) for k, n in sorted(kinds.items())) + f"; imaginary parts not printed as 0: {im_nonzero}")

    # [pair floors]
    mp.mp.dps = int(FIT["dps"])
    pf_n = pf_ok = 0
    worst = 0.0
    mine = {}
    for pid in [q["id"] for q in P["points"]]:
        R4 = {g: parse_out(outs[(pid, 4, g)]) for g in (40, 60)}
        R6 = {g: parse_out(outs[(pid, 6, g)]) for g in (40, 60)}
        fl = lambda R, k, n: dig(R[40][k][n][0], R[60][k][n][0])
        mine[pid] = {"floor_P1": fl(R4, PENT, 1), "floor_P0": fl(R4, PENT, 0), "floor_boxes1": min(fl(R4, b, 1) for b in BOXES), "floor_P6_0": fl(R6, PENT, 0)}
        rec = FIT["per_point"][pid]
        for k in ("floor_P1", "floor_P0", "floor_boxes1", "floor_P6_0"):
            pf_n += 1
            diff = abs(mine[pid][k] - float(rec[k]))
            worst = max(worst, diff)
            if diff < 1e-9:
                pf_ok += 1
            else:
                fails.append(f"pair floor {k} at {pid}: re-derived {mine[pid][k]:.3f} vs the receipt's {float(rec[k]):.3f}" + (" (mutated in memory)" if args.mutate and pid == "p10" else ""))
    min_p1 = min(v["floor_P1"] for v in mine.values())
    min_p6 = min(v["floor_P6_0"] for v in mine.values())
    mp.mp.dps = int(D6["dps"])
    d6_n = d6_ok = 0
    for pid, rec in D6["per_point"].items():
        R6 = {g: parse_out(outs[(pid, 6, g)]) for g in (40, 60)}
        f = dig(R6[40][PENT][0][0], R6[60][PENT][0][0])
        d6_n += 1
        if abs(f - float(rec["floor_P6_0"])) < 1e-9:
            d6_ok += 1
        else:
            fails.append(f"D6FIT pair floor at {pid}: re-derived {f:.3f} vs the receipt's {float(rec['floor_P6_0']):.3f}")
    print("[pair floors] re-derived from the outputs with the receipts' own measure: FIT %d of %d figures agree (13 points x floor_P1, floor_P0, floor_boxes1, floor_P6_0 at dps %d; largest difference %.1e); min over the points: eps^1 pentagon %.2f (receipt %.2f), D=6 pentagon eps^0 %.2f (receipt %.2f); D6FIT %d of %d (12 points x floor_P6_0 at dps %d)"
          % (pf_ok, pf_n, int(FIT["dps"]), worst, min_p1, bdk["min_floor_P1"], min_p6, bdk["min_floor_P6_0"], d6_ok, d6_n, int(D6["dps"])))
    if abs(min_p1 - bdk["min_floor_P1"]) >= 1e-9 or abs(min_p6 - bdk["min_floor_P6_0"]) >= 1e-9:
        fails.append("pair floor minima differ from bdk_dimension_shift.min_floor_P1 / min_floor_P6_0")

    # [count]
    count_state = "NOT RUN (--no-count)"
    if not args.no_count:
        t1 = time.time()
        try:
            import sympy as sp
            import flint  # noqa: F401
            spec = importlib.util.spec_from_file_location("weight3_count", os.path.join(PACK, "arm", "count.py"))
            C = importlib.util.module_from_spec(spec)
            spec.loader.exec_module(C)
        except Exception as e:  # a missing module, by name
            count_state = f"NOT RUN ({type(e).__name__}: {e})"
            C = None
        if C is not None:
            import random
            v, rat, Delta, odd = C.build_letters(A)
            extra = {}
            for k, orb in enumerate(A["odd_search"]["Z5_orbits"][1:]):
                for j, a in enumerate(orb):
                    extra[f"X{k+1}_{j+1}"] = sp.sympify(a)
            names21 = list(rat) + ["Delta5"] + list(odd)
            names16 = list(rat) + ["Delta5"]
            names31 = names21 + list(extra)
            zmap = dict(A["Z5_letter_map"])
            for k, orb in enumerate(A["odd_search"]["Z5_orbits"][1:]):
                for j in range(5):
                    zmap[f"X{k+1}_{j+1}"] = f"X{k+1}_{(j + 1) % 5 + 1}"
            random.seed(6464)
            pts = []
            while len(pts) < 6:
                pt = [random.randint(-40, 40) for _ in range(5)]
                sb = dict(zip(v, pt))
                if any(e.subs(sb) == 0 for e in rat.values()):
                    continue
                dl = Delta.subs(sb)
                if dl == 0 or sp.sqrt(abs(dl)).is_rational:
                    continue
                if any(a.subs(sb) ** 2 == dl for a in list(odd.values()) + list(extra.values())):
                    continue
                pts.append(pt)
            DL = [C.dlogs_at_point(v, rat, Delta, odd, extra, pt) for pt in pts]

            def dlog_rank(names):
                rows = []
                for n in names:
                    row = {}
                    c = 0
                    for (D, delta) in DL:
                        for comp in D[n]:
                            row[c] = comp.x
                            row[c + 1] = comp.y
                            c += 2
                    rows.append({k: val for k, val in row.items() if val != 0})
                return C.rows_to_fmpq(rows, 10 * len(DL)).rank()

            def wedges(names, npts):
                out = []
                for (D, delta) in DL[:npts]:
                    Wp = {}
                    for a in range(len(names)):
                        for b in range(len(names)):
                            if a != b:
                                Wp[(a, b)] = C.wedge(D[names[a]], D[names[b]])
                    out.append(Wp)
                return out
            F = [0, 1, 2, 3, 4]
            cmp_ok, cmp_n = 0, 0

            def check(label, got, want):
                nonlocal cmp_ok, cmp_n
                cmp_n += 1
                if got == want:
                    cmp_ok += 1
                else:
                    fails.append(f"count: {label} re-derived {got} vs the receipt's {want}")
            check("evaluation points", pts, CNT["points"])
            indep = {"A16": dlog_rank(names16), "A21": dlog_rank(names21), "A31": dlog_rank(names31)}
            check("dlog ranks over Q", indep, CNT["dlog_rank_over_Q"])
            conv = []
            for npts in (2, 3, 4, 5):
                _, _, rows = C.integrability_rows(names21, F, None, wedges(names21, npts), 2)
                conv.append({"npts": npts, "rank_modp": C.rank_modp(rows, 5 * 21 * 21)})
            check("point-count convergence (weight 2, A21)", conv, CNT["point_convergence_w2_A21"])
            stages = [("w2_A16_record_subalphabet", names16, 2, +1), ("w2_A21", names21, 2, +1)]
            if args.w3:
                stages.append(("w3_A21_odd", names21, 3, -1))
            lines = []
            for label, names, w, par in stages:
                stage, words, idx, rows = C.count_stage(names, F, [n for n in names if n.startswith("W") or n.startswith("X")], {k: zmap[k] for k in names}, wedges(names, 4), w, par, label)
                want = st[label]
                for key in ("raw", "first_entry", "after_integrability_modp", "rank_modp_two_primes", "integrability_rows"):
                    check(f"{label}.{key}", stage[key], want[key])
                for blk in ("after_parity", "after_Z5"):
                    for key in ("unknowns", "rank_modp", "rank_Q", "count_modp", "count_Q", "n_rows"):
                        check(f"{label}.{blk}.{key}", stage[blk][key], want[blk][key])
                ctrl_s = ""
                if w == 2:
                    ix = {n: k for k, n in enumerate(names)}
                    B = C.box_symbols(names)
                    ok = []
                    for Bi in B:
                        vec = {idx[k]: c for k, c in Bi.items()}
                        res = max((abs(sum(row.get(k, 0) * c for k, c in vec.items())) for row in rows), default=0)
                        ok.append(res == 0)
                    sig = {ix[k]: ix[zmap[k]] for k in names}
                    Bsum = {}
                    for Bi in B:
                        for k, c in Bi.items():
                            Bsum[k] = Bsum.get(k, 0) + c
                    Bsh = {(sig[a], sig[b]): c for (a, b), c in Bsum.items()}
                    cb = {"B_i_in_constrained_space": ok, "sum_B_Z5_invariant": all(Bsum.get(k, 0) == Bsh.get(k, 0) for k in set(Bsum) | set(Bsh)), "B_i_word_counts": [len(b) for b in B]}
                    check(f"{label}.control_boxes", cb, want["control_boxes"])
                    ctrl_s = "; boxes in the space %d of 5, sum Z5-invariant %s" % (sum(1 for x in ok if x), "yes" if cb["sum_B_Z5_invariant"] else "no")
                lines.append("%s: %d raw -> %d first entry -> %s integrability (mod p) -> %s parity (over Q) -> %s under Z5%s == receipt %d / %d / %s / %s / %s"
                             % (label, stage["raw"], stage["first_entry"], stage["after_integrability_modp"], stage["after_parity"]["count_Q"], stage["after_Z5"]["count_Q"], ctrl_s,
                                want["raw"], want["first_entry"], want["after_integrability_modp"], want["after_parity"]["count_Q"], want["after_Z5"]["count_Q"]))
            count_state = "%d of %d figures agree" % (cmp_ok, cmp_n)
            print("[count] re-derived with arm/count.py from receipts/alphabet_item64.json (%.1f s): the %d evaluation points == the receipt's; dlog ranks over Q %s; convergence of the weight-2 integrability rank with 2..5 points %s" % (time.time() - t1, len(pts), indep, [c["rank_modp"][0] for c in conv]))
            for l in lines:
                print("        " + l)
            print("        %s" % count_state)
        else:
            print(f"[count] {count_state}: install sympy and python-flint (the arm's own requirements) or pass --no-count")
    else:
        print("[count] NOT RUN (--no-count): the weight-two constrained count is not re-derived in this run")

    print(f"\ntimings [s]: TOTAL {time.time() - t0:.2f}")
    if fails:
        print(f"OVERALL FAIL: {'; '.join(fails)}")
        return 1
    if count_state.startswith("NOT RUN (") and not args.no_count:
        print(f"OVERALL: pins, cross-pins, census and pair floors OK; the count {count_state} (exit 5)")
        return 5
    print("OVERALL PASS" + (" (pins, cross-pins, census, pair floors; the count NOT RUN by --no-count)" if args.no_count else ""))
    return 0


if __name__ == "__main__":
    sys.exit(main())
