Cell: weight-6 x local-2d-single. codes/49-17-3.json came from the same encoding at G=16, and the fieldnotes list G=13 to 15 at n=49 as budget-walled at interactive budgets. G=15 forces k >= 49 - 30 = 19, and the column-count bound (G >= 2n/7 = 14) leaves it open, so it was the natural next rung.
research/local_sat.py build_local_cnf(7, 15, 6, 2, 2.0, shared_t3=True): 7x7 grid, 15 checks per side anchored within radius 2.0 (interaction radius at most 4.0), row weight at most 6, CSS commutation, nonzero syndrome for every weight <= 2 Pauli error. CaDiCaL 1.5.3, conflict cap 20,000,000 per solve. First solve SAT after 579 s and 3,018,551 conflicts; the model passed the post-check with k = 19. Continued enumeration returned 40 distinct models in 66 min, all k = 19 with d_ub = 3.
make_submission (20,000 RIS trials per side) embedded a weight-3 X-logical and a weight-3 Z-logical; with every weight <= 2 error detected, d = 3 exactly (labeled upper_bound by the kit). verify/validate_candidate.py: verifier ok (weight-6, local-2d-single, interaction radius 4.0), no lighter logical in 4,460 RIS trials, no board duplicate, label "advances the weight-6 x local-2d-single board". Check weights: fourteen X-rows of weight 6 and one of weight 5; thirteen Z-rows of weight 6 and two of weight 5.
An exhaustive check after staging, plain GF(2) arithmetic outside the repo, enumerated every X-type and every Z-type error of weight at most 2 (1,225 supports per side) and found none with zero syndrome, so d >= 3 holds independently of the SAT encoding and its post-check; with the weight-3 witnesses, d = 3 exactly. The JSON keeps confidence upper_bound.
G=14 (k >= 21) at the same grid and weight exhausted the 20,000,000-conflict cap in 47 min with neither a model nor an UNSAT proof: a live budget wall. G=13 (k >= 23) is below the column-count bound and is UNSAT without solving.
research/local_sat.py, research/kit/submit.py, research/kit/surrogate.py, verify/validate_candidate.py. CaDiCaL 1.5.3 via python-sat 1.9.dev15, one core, about 10 min to the first model, RSS 0.4 GB.
from local_sat import enumerate_local_sat_codes
gen = enumerate_local_sat_codes(7, 15, 6, 2, 2.0, max_codes=1,
solver="cadical", conf_budget=20_000_000, stream=True, shared_t3=True)
spec, HX, HZ, coords, ax, az = next(gen)
The first model is the code in this file (fingerprint fb1599af6e9c089c); the conflict count 3,018,551 was reproduced in two independent runs.