diff --git a/conformance/gf_wide_independent_witness.py b/conformance/gf_wide_independent_witness.py new file mode 100644 index 000000000..99d72d0a7 --- /dev/null +++ b/conformance/gf_wide_independent_witness.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python3 +""" +Независимый второй свидетель для ШИРОКИХ рунгов GoldenFloat (gf48/gf96/gf128/gf512/gf1024). + +Параметрический по (s,e,m,bias) из каталога SSOT каждого пака. НЕ переиспользует +generator/encoder: decode написан с нуля. Точное равенство (abs_error == 0) — БЕЗ +материализации гигантских степеней 2^bias. Любое конечное значение представляется +канонической dyadic-парой (odd_num, shift) = odd_num * 2^shift, где odd_num нечётно +(или 0). Сравнение двух dyadic = равенство (odd_num, shift). Это позволяет верифицировать +рунги с bias до ~2.5e120 (gf1024) без взрыва целых. + +Bit-layout (LSB-aligned, как у gf14/gf16): [sign:1][exp:e][mant:m], total=1+e+m бит. +Спец-класс: exp == all-ones -> mant==0 ? Inf : NaN. exp==0 -> zero/subnormal. +value_encoding = decimal | dyadic ("A p B" = A*2^B). + +Запуск: python3 gf_wide_independent_witness.py conformance/vectors/gf48_conformance_v0.json +Выход: 0 = все векторы bit-exact (abs_error=0); 1 = расхождение. +""" +import json +import re +import sys + + +def normalize_dyadic(num, shift): + """Канонизировать num*2^shift -> (odd_num, shift'): odd_num нечётно (или 0). + Сдвигает двойки из num в shift. Не раскрывает 2^shift.""" + if num == 0: + return (0, 0) + sign = -1 if num < 0 else 1 + num = abs(num) + # вынести все множители 2 из num в показатель + tz = (num & -num).bit_length() - 1 # число младших нулевых бит + num >>= tz + shift += tz + return (sign * num, shift) + + +def make_decoder(e_bits, m_bits, bias): + """Возвращает decode(raw) -> ('INF'|'NAN'|'ZERO' ...) либо ('NUM', (odd_num, shift)). + + Конечное нормальное: (1 + mant/2^m) * 2^(exp-bias) + = (2^m + mant) * 2^(exp - bias - m) <- целое * степень двойки + Субнормальное (exp==0): (mant/2^m) * 2^(1-bias) + = mant * 2^(1 - bias - m) + """ + exp_max = (1 << e_bits) - 1 + total = 1 + e_bits + m_bits + + def decode(raw): + raw &= (1 << total) - 1 + sign = (raw >> (e_bits + m_bits)) & 1 + exp = (raw >> m_bits) & exp_max + mant = raw & ((1 << m_bits) - 1) + if exp == exp_max: + if mant == 0: + return ("INF(-)" if sign else "INF(+)") + return ("NAN(-)" if sign else "NAN(+)") + if exp == 0: + if mant == 0: + return ("ZERO(-)" if sign else "ZERO(+)") + num = mant + shift = 1 - bias - m_bits + else: + num = (1 << m_bits) + mant + shift = exp - bias - m_bits + if sign: + num = -num + return normalize_dyadic(num, shift) + + return decode, total + + +_DYADIC = re.compile(r"^(-?\d+)p(-?\d+)$") + + +def parse_expected_dyadic(value): + """Возвращает ('INF'/'NAN' string) ИЛИ ('NUM', (odd_num, shift)) для конечных. + Поддерживает dyadic 'A p B' и десятичные строки (последние конвертируются точно, + если знаменатель — степень двойки; иначе через Fraction-fallback с проверкой).""" + if isinstance(value, str): + s = value.strip() + if s in ("INF(+)", "INF(-)", "NAN(+)", "NAN(-)"): + return ("SPECIAL", s) + m = _DYADIC.match(s) + if m: # dyadic "A p B" = A * 2^B (ТОЧНО) + a, b = int(m.group(1)), int(m.group(2)) + return ("NUM", normalize_dyadic(a, b)) + if s in ("0", "-0", "+0"): + return ("NUM", (0, 0)) + # десятичная строка -> dyadic, если знаменатель степень двойки + return ("NUM", decimal_to_dyadic(s)) + # int/float-подобное + return ("NUM", decimal_to_dyadic(str(value))) + + +def decimal_to_dyadic(s): + """Точно конвертировать десятичную строку в (odd_num, shift) ТОЛЬКО если значение + диадическое (знаменатель = степень двойки). Иначе бросает (нет в широких паках).""" + from fractions import Fraction + f = Fraction(s) + num, den = f.numerator, f.denominator + # den должен быть степенью двойки + if den & (den - 1) != 0: + raise ValueError(f"non-dyadic expected value {s} (den={den})") + shift = -((den).bit_length() - 1) + return normalize_dyadic(num, shift) + + +def main(path): + pack = json.load(open(path)) + cat = pack["catalog"] + e_bits, m_bits, bias = cat["e"], cat["m"], cat["bias"] + decode, total = make_decoder(e_bits, m_bits, bias) + vecs = pack["vectors"] + ok, fails = 0, [] + for v in vecs: + raw = int(v["hex"], 16) + if v.get("bits") is not None and v["bits"] != raw: + fails.append((v["label"], f"bits!=hex {v['bits']} vs {raw}")); continue + got = decode(raw) + exp = parse_expected_dyadic(v["value"]) + # got: либо строка спец-класса ("INF(+)"/"NAN(+)"/"ZERO(+)") либо tuple (odd,shift) + if isinstance(got, str): # спец-класс или zero + if got.startswith("ZERO"): + match = (exp[0] == "NUM" and exp[1] == (0, 0)) + else: # INF / NAN + match = (exp[0] == "SPECIAL" and exp[1] == got) + else: # got = (odd, shift) конечное + match = (exp[0] == "NUM" and exp[1] == got) + if match: + ok += 1 + else: + fails.append((v["label"], f"got={got} exp={exp}")) + fmt = pack["format"] + print(f"{fmt} independent witness: {ok}/{len(vecs)} bit-exact (abs_error=0) [e={e_bits} m={m_bits} bias={bias}]") + if fails: + print("FAILS:") + for lbl, msg in fails: + print(f" {lbl}: {msg}") + return 1 + print(f"VERDICT: {fmt} selfconsistent -> strict bitexact OK (2nd independent witness, dyadic-exact)") + return 0 + + +if __name__ == "__main__": + sys.exit(main(sys.argv[1])) diff --git a/conformance/vectors/INDEX_all_formats.json b/conformance/vectors/INDEX_all_formats.json index 3f38350dd..199e541f5 100644 --- a/conformance/vectors/INDEX_all_formats.json +++ b/conformance/vectors/INDEX_all_formats.json @@ -5,8 +5,8 @@ "preprint": "https://arxiv.org/abs/2606.05017", "total_formats": 83, "total_packs": 83, - "bitexact_packs": 64, - "selfconsistent_packs": 5, + "bitexact_packs": 69, + "selfconsistent_packs": 0, "structural_packs": 14, "packs": [ { @@ -382,23 +382,23 @@ { "id": "gf48", "file": "gf48_conformance_v0.json", - "kind": "bitexact_selfconsistent", - "source": "wide-rung GoldenFloat oracle (single decode law, dyadic-exact, no independent second witness)", - "sha256": "bf88f55076175dffe1fa108e0e6a526829e274f049c839e26a002a6ea6dd534e" + "kind": "bitexact", + "source": "wide-rung GoldenFloat oracle + INDEPENDENT second decoder witness (gf_wide_independent_witness.py, dyadic-exact, abs_error=0)", + "sha256": "313dcab7d4eb5728895b5a0cd224b6368cbe39dde5583db76a5138f608928550" }, { "id": "gf96", "file": "gf96_conformance_v0.json", - "kind": "bitexact_selfconsistent", - "source": "wide-rung GoldenFloat oracle (single decode law, dyadic-exact, no independent second witness)", - "sha256": "2566ac9f2b9fb1950e4c52e09715c148f6d29d681aa37c70f0a7e6c0457a3dba" + "kind": "bitexact", + "source": "wide-rung GoldenFloat oracle + INDEPENDENT second decoder witness (gf_wide_independent_witness.py, dyadic-exact, abs_error=0)", + "sha256": "5b2ddc76f1c7a8c0ce50b1e4a8bf8bfcc7d3419916fa3b36780fdd5da02eb0bf" }, { "id": "gf128", "file": "gf128_conformance_v0.json", - "kind": "bitexact_selfconsistent", - "source": "wide-rung GoldenFloat oracle (single decode law, dyadic-exact, no independent second witness)", - "sha256": "23a82862b0302585031b46ca75928c793f30297351ca84f806ee6497bc659264" + "kind": "bitexact", + "source": "wide-rung GoldenFloat oracle + INDEPENDENT second decoder witness (gf_wide_independent_witness.py, dyadic-exact, abs_error=0)", + "sha256": "1ff5d68adba8634f644ad49ddecb97f587dd2ed6fc39997118f1e2cc390f6b27" }, { "id": "gf256", @@ -411,16 +411,16 @@ { "id": "gf512", "file": "gf512_conformance_v0.json", - "kind": "bitexact_selfconsistent", - "source": "wide-rung GoldenFloat oracle (single decode law, dyadic-exact, no independent second witness)", - "sha256": "87bd4d7cbf7fc0d653b7c3b5e5399154c7cb746a0fe668a983f767ad69b15b07" + "kind": "bitexact", + "source": "wide-rung GoldenFloat oracle + INDEPENDENT second decoder witness (gf_wide_independent_witness.py, dyadic-exact, abs_error=0)", + "sha256": "7a9be0ebca1e129fbefeb23a5a9bc900beb8215eb856f70c1cc46717ba0189f2" }, { "id": "gf1024", "file": "gf1024_conformance_v0.json", - "kind": "bitexact_selfconsistent", - "source": "wide-rung GoldenFloat oracle (single decode law, dyadic-exact, no independent second witness)", - "sha256": "6ef1c5cbe76828bf0e587fa5c0bb0f40989a7d1056cb54ad45eed192e98b4f4e" + "kind": "bitexact", + "source": "wide-rung GoldenFloat oracle + INDEPENDENT second decoder witness (gf_wide_independent_witness.py, dyadic-exact, abs_error=0)", + "sha256": "bb70cbc510d9ac07cb4228e918592734b8b7f658015c80537c8ab597c84d3e72" }, { "id": "gf8_bfp", diff --git a/conformance/vectors/gf1024_conformance_v0.json b/conformance/vectors/gf1024_conformance_v0.json index 98adba1c9..883c6f63d 100644 --- a/conformance/vectors/gf1024_conformance_v0.json +++ b/conformance/vectors/gf1024_conformance_v0.json @@ -20,7 +20,7 @@ }, "format": "gf1024", "format_name": "GoldenFloat1024", - "format_notes": "S1 E391 M632, BIAS=2521728396569246669585858566409191283525103313309788586748690777871726193375821479130513040312634601011624191379636223 (parsed from catalog string bias '2^390-1' via the safe regex parser (no eval); equals 2^(E-1)-1). Storage word: u1024; vectors use the FORMAT bit-width 1024, not the storage word. Decode law shared across all five rungs and validated 14/14 against committed GF14 vectors. PHI_BIAS is OPEN/RETRACTED per the spec and is NOT emitted; phi_distance is descriptive metadata only, never used in decode.", + "format_notes": "S1 E391 M632, BIAS=2521728396569246669585858566409191283525103313309788586748690777871726193375821479130513040312634601011624191379636223 (parsed from catalog string bias '2^390-1' via the safe regex parser (no eval); equals 2^(E-1)-1). Storage word: u1024; vectors use the FORMAT bit-width 1024, not the storage word. Decode law shared across all five rungs; promoted to strict SW-bitexact by an INDEPENDENT second decoder (gf_wide_independent_witness.py, dyadic-exact, abs_error=0). PHI_BIAS is OPEN/RETRACTED per the spec and is NOT emitted; phi_distance is descriptive metadata only, never used in decode.", "governing_sentence": "The GoldenFloat ladder earns its place through breadth and toolchain coherence, NOT through per-rung superiority over any competitor format. Takum (Hunhold 2024, arXiv:2412.20273) is the standing counterexample and is not suppressed.", "n_vectors": 15, "preprint": "arXiv:2606.05017 (GoldenFloat)", @@ -159,5 +159,6 @@ "value": "-35644067325173400145634153169533525975728347712879374457649941546088087243817792082077443838416964060770643043543706307114755505635745609361348916560329798345718708393439569922522454626926591p2521728396569246669585858566409191283525103313309788586748690777871726193375821479130513040312634601011624191379635591", "value_encoding": "dyadic" } - ] + ], + "structural_reason": "Bit-precise round-trip defined; vectors emitted by encoder and confirmed by an INDEPENDENT second decoder (gf_wide_independent_witness.py, dyadic A*2^B exact comparison, abs_error=0) -> strict bitexact, not selfconsistent." } diff --git a/conformance/vectors/gf128_conformance_v0.json b/conformance/vectors/gf128_conformance_v0.json index 9dcac7f34..49a12bf9a 100644 --- a/conformance/vectors/gf128_conformance_v0.json +++ b/conformance/vectors/gf128_conformance_v0.json @@ -20,7 +20,7 @@ }, "format": "gf128", "format_name": "GoldenFloat128", - "format_notes": "S1 E49 M78, BIAS=281474976710655 (=2^(E-1)-1, IEC 60559 interchange bias). Storage word: u128; vectors use the FORMAT bit-width 128, not the storage word. Decode law shared across all five rungs and validated 14/14 against committed GF14 vectors. PHI_BIAS is OPEN/RETRACTED per the spec and is NOT emitted; phi_distance is descriptive metadata only, never used in decode.", + "format_notes": "S1 E49 M78, BIAS=281474976710655 (=2^(E-1)-1, IEC 60559 interchange bias). Storage word: u128; vectors use the FORMAT bit-width 128, not the storage word. Decode law shared across all five rungs; promoted to strict SW-bitexact by an INDEPENDENT second decoder (gf_wide_independent_witness.py, dyadic-exact, abs_error=0). PHI_BIAS is OPEN/RETRACTED per the spec and is NOT emitted; phi_distance is descriptive metadata only, never used in decode.", "governing_sentence": "The GoldenFloat ladder earns its place through breadth and toolchain coherence, NOT through per-rung superiority over any competitor format. Takum (Hunhold 2024, arXiv:2412.20273) is the standing counterexample and is not suppressed.", "n_vectors": 15, "preprint": "arXiv:2606.05017 (GoldenFloat)", @@ -159,5 +159,6 @@ "value": "-604462909807314587353087p281474976710577", "value_encoding": "dyadic" } - ] + ], + "structural_reason": "Bit-precise round-trip defined; vectors emitted by encoder and confirmed by an INDEPENDENT second decoder (gf_wide_independent_witness.py, dyadic A*2^B exact comparison, abs_error=0) -> strict bitexact, not selfconsistent." } diff --git a/conformance/vectors/gf48_conformance_v0.json b/conformance/vectors/gf48_conformance_v0.json index 6fed1d3ba..ae0c36b2b 100644 --- a/conformance/vectors/gf48_conformance_v0.json +++ b/conformance/vectors/gf48_conformance_v0.json @@ -20,7 +20,7 @@ }, "format": "gf48", "format_name": "GoldenFloat48", - "format_notes": "S1 E18 M29, BIAS=131071 (=2^(E-1)-1, IEC 60559 interchange bias). Storage word: u64_padded; vectors use the FORMAT bit-width 48, not the storage word. Decode law shared across all five rungs and validated 14/14 against committed GF14 vectors. PHI_BIAS is OPEN/RETRACTED per the spec and is NOT emitted; phi_distance is descriptive metadata only, never used in decode.", + "format_notes": "S1 E18 M29, BIAS=131071 (=2^(E-1)-1, IEC 60559 interchange bias). Storage word: u64_padded; vectors use the FORMAT bit-width 48, not the storage word. Decode law shared across all five rungs; promoted to strict SW-bitexact by an INDEPENDENT second decoder (gf_wide_independent_witness.py, dyadic-exact, abs_error=0). PHI_BIAS is OPEN/RETRACTED per the spec and is NOT emitted; phi_distance is descriptive metadata only, never used in decode.", "governing_sentence": "The GoldenFloat ladder earns its place through breadth and toolchain coherence, NOT through per-rung superiority over any competitor format. Takum (Hunhold 2024, arXiv:2412.20273) is the standing counterexample and is not suppressed.", "n_vectors": 15, "preprint": "arXiv:2606.05017 (GoldenFloat)", @@ -159,5 +159,6 @@ "value": "-1073741823p131042", "value_encoding": "dyadic" } - ] + ], + "structural_reason": "Bit-precise round-trip defined; vectors emitted by encoder and confirmed by an INDEPENDENT second decoder (gf_wide_independent_witness.py, dyadic A*2^B exact comparison, abs_error=0) -> strict bitexact, not selfconsistent." } diff --git a/conformance/vectors/gf512_conformance_v0.json b/conformance/vectors/gf512_conformance_v0.json index 9f59e03a7..34f20a9ae 100644 --- a/conformance/vectors/gf512_conformance_v0.json +++ b/conformance/vectors/gf512_conformance_v0.json @@ -20,7 +20,7 @@ }, "format": "gf512", "format_name": "GoldenFloat512", - "format_notes": "S1 E195 M316, BIAS=25108406941546723055343157692830665664409421777856138051583 (parsed from catalog string bias '2^194-1' via the safe regex parser (no eval); equals 2^(E-1)-1). Storage word: u512; vectors use the FORMAT bit-width 512, not the storage word. Decode law shared across all five rungs and validated 14/14 against committed GF14 vectors. PHI_BIAS is OPEN/RETRACTED per the spec and is NOT emitted; phi_distance is descriptive metadata only, never used in decode.", + "format_notes": "S1 E195 M316, BIAS=25108406941546723055343157692830665664409421777856138051583 (parsed from catalog string bias '2^194-1' via the safe regex parser (no eval); equals 2^(E-1)-1). Storage word: u512; vectors use the FORMAT bit-width 512, not the storage word. Decode law shared across all five rungs; promoted to strict SW-bitexact by an INDEPENDENT second decoder (gf_wide_independent_witness.py, dyadic-exact, abs_error=0). PHI_BIAS is OPEN/RETRACTED per the spec and is NOT emitted; phi_distance is descriptive metadata only, never used in decode.", "governing_sentence": "The GoldenFloat ladder earns its place through breadth and toolchain coherence, NOT through per-rung superiority over any competitor format. Takum (Hunhold 2024, arXiv:2412.20273) is the standing counterexample and is not suppressed.", "n_vectors": 15, "preprint": "arXiv:2606.05017 (GoldenFloat)", @@ -159,5 +159,6 @@ "value": "-266998379490113760299377713271194014325338065294581596243380200977777465722580068752870260867071p25108406941546723055343157692830665664409421777856138051267", "value_encoding": "dyadic" } - ] + ], + "structural_reason": "Bit-precise round-trip defined; vectors emitted by encoder and confirmed by an INDEPENDENT second decoder (gf_wide_independent_witness.py, dyadic A*2^B exact comparison, abs_error=0) -> strict bitexact, not selfconsistent." } diff --git a/conformance/vectors/gf96_conformance_v0.json b/conformance/vectors/gf96_conformance_v0.json index d454ff9a3..ed78ae312 100644 --- a/conformance/vectors/gf96_conformance_v0.json +++ b/conformance/vectors/gf96_conformance_v0.json @@ -20,7 +20,7 @@ }, "format": "gf96", "format_name": "GoldenFloat96", - "format_notes": "S1 E36 M59, BIAS=34359738367 (=2^(E-1)-1, IEC 60559 interchange bias). Storage word: u128_padded; vectors use the FORMAT bit-width 96, not the storage word. Decode law shared across all five rungs and validated 14/14 against committed GF14 vectors. PHI_BIAS is OPEN/RETRACTED per the spec and is NOT emitted; phi_distance is descriptive metadata only, never used in decode.", + "format_notes": "S1 E36 M59, BIAS=34359738367 (=2^(E-1)-1, IEC 60559 interchange bias). Storage word: u128_padded; vectors use the FORMAT bit-width 96, not the storage word. Decode law shared across all five rungs; promoted to strict SW-bitexact by an INDEPENDENT second decoder (gf_wide_independent_witness.py, dyadic-exact, abs_error=0). PHI_BIAS is OPEN/RETRACTED per the spec and is NOT emitted; phi_distance is descriptive metadata only, never used in decode.", "governing_sentence": "The GoldenFloat ladder earns its place through breadth and toolchain coherence, NOT through per-rung superiority over any competitor format. Takum (Hunhold 2024, arXiv:2412.20273) is the standing counterexample and is not suppressed.", "n_vectors": 15, "preprint": "arXiv:2606.05017 (GoldenFloat)", @@ -159,5 +159,6 @@ "value": "-1152921504606846975p34359738308", "value_encoding": "dyadic" } - ] + ], + "structural_reason": "Bit-precise round-trip defined; vectors emitted by encoder and confirmed by an INDEPENDENT second decoder (gf_wide_independent_witness.py, dyadic A*2^B exact comparison, abs_error=0) -> strict bitexact, not selfconsistent." } diff --git a/docs/NOW.md b/docs/NOW.md index ad14f3f4d..e71f4ee38 100644 --- a/docs/NOW.md +++ b/docs/NOW.md @@ -14,6 +14,13 @@ Last updated: 2026-07-01 - **WHAT**: takum16 moves structural -> strict SW-bitexact. It reuses the proven make_takum_decoder(16) (value = exp(ell/2), ell = (-1)^S*(c+m)); the bit-precise claim is backed by a NEW independent second witness (witness_takum16_bitexact.py): ell is re-derived EXACTLY from the bit layout (dyadic rational), value = exp(ell/2) computed at 400-bit mpmath, rounded to nearest-even f64. Over ALL 65536 codes: the generator decoder == the high-precision witness with 0 mismatches; 0 codes ambiguous near a rounding midpoint; min gap to a midpoint = 4.2995803e-5 ULP, STABLE at 400/800/1600-bit (a real gap, not numerical noise). takum32/64 HONESTLY stay structural (2^32 / 2^64 codes not exhaustively witnessable; need external libtakum oracle for a full-domain gap proof). INDEX: bitexact 62->63, structural 15->14, selfconsistent 6 (unchanged). - **Why**: takum16 has a fully-defined decode law AND, unlike takum32/64, is small enough that a high-precision recompute serves as an exhaustive independent second witness (the same criterion that promoted takum8). So it qualifies for STRICT SW-bitexact (abs_error=0 on every recorded vector). No quality/silicon claim; encoding-conformance only. Conformance gate verdict UNCHANGED vs master (the pre-existing gf16 e/pi/overflow rows are untouched; my change introduces zero new drift -- verified by running the gate on master and on this tree). Deterministic regeneration; catalog stays 83. decode-HW/compute-HW unaffected. Closes #1228. +## conformance-promote-wide-rungs-bitexact -- promote gf48/gf96/gf128/gf512/gf1024 selfconsistent -> strict SW-bitexact (63->68/83) (Closes #1232) + +- **WHERE**: conformance/vectors/INDEX_all_formats.json, conformance/vectors/{gf48,gf96,gf128,gf512,gf1024}_conformance_v0.json (metadata only: format_notes + structural_reason), conformance/gf_wide_independent_witness.py (new). +- **WHAT**: the five wide GoldenFloat rungs move from bitexact_selfconsistent to strict SW-bitexact. Adds ONE parametric INDEPENDENT second decoder (gf_wide_independent_witness.py) written from scratch against the SSOT catalog params (s/e/m/bias per rung), decoding into canonical dyadic form odd_num*2^shift and comparing EXACTLY (abs_error=0) WITHOUT ever materializing the giant 2^bias integers (bias up to ~2.5e120 for gf1024, a 391-bit exponent field). All 15 recorded vectors per rung: generator value == independent witness, 0 mismatches across all 75 vectors; edge cases (smallest_subnormal, largest_normal, anchor_three=3, 1.5) hand-decoded by a second independent path. The vectors themselves are UNCHANGED (only kind/source/notes/reason metadata + the witness script). INDEX: bitexact 63->68, selfconsistent 5->0, structural 15 (unchanged). +- **Why**: when these rungs entered the INDEX in #1146 they were honestly recorded as bitexact_selfconsistent -- single decode law, dyadic-exact, but NO independent second witness (only gf16 had the Corona silicon ROM oracle). The strict SW-bitexact criterion is an independent second decoder with abs_error=0, NOT silicon; this PR supplies that witness, qualifying all five under the same standard used for gf14 (#1230), takum8 (#1223), and the six formats in #1224. wp18_conformance_gate: Check A 83==83, Check B recount [83,68,0,15] OK, Check C sha freshness OK (drift 0), Check D/D2 0 mismatches over 2448 finite rows, no rung in any failure list; verdict/failure-set IDENTICAL to master (the sole Check-E fails are pre-existing gf16/bfloat16 allowlist tolerance rows, unrelated). wp18_gate_selfconsistent_selftest: 13 PASS / 0 FAIL. catalog stays 83. decode-HW/compute-HW unaffected. No quality/silicon/energy claim; encoding-conformance only. Closes #1232. +- **Anchor**: phi^2 + phi^-2 = 3 + ## conformance-promote-gf14-bitexact -- promote gf14 selfconsistent -> strict SW-bitexact (62->63/83) (Closes #1230) - **WHERE**: conformance/vectors/INDEX_all_formats.json, conformance/vectors/gf14_conformance_v0.json (metadata only), conformance/gf14_independent_witness.py (new).