Repository navigation
PMAT-3430 Phases 3-4: three ggml enums become one (M1 complete) - #3621
Merged
Merged
Conversation
|
§13.11 rung 1 — quorum shadow verdict Shadow mode: this records a verdict and merges nothing. A refusal |
#3430 Q1-c claims Phases 3-4 are behaviour-preserving: no crate accepts an id or a name it refused before. This makes that a measurement instead of a promise. 12 tests, all written against UNCHANGED code and all green on it now. They must pass UNCHANGED after the re-exports and admission functions land, with ONE edit named in advance (below). serve, 7 boundaries — the id sweep is 0..=255 at every one, because the property is about what is REFUSED as much as what is accepted and a sweep over the admitted set alone cannot see a widening: gguf/dtype.rs apr_qtype_to_dtype (+ its refusal names the id), apr_dtype_to_byte infer/mod.rs qtype_to_dtype_str apr/mod.rs the dtype_byte arm of TensorEntry::from_binary — exercised through the REAL parser with a minimal entry, not a re-typed copy of the expression, which would pass while the real path changed apr/special_tokens MappedAprModel::dtype_to_qtype apr/dequant dtype_to_ggml_qtype, which deliberately admits LESS than the enum knows (F32/F16/BF16 -> None) compute, 1 boundary — from_u32 over 0..=255, plus all 15 rows of block geometry and the partial-block rounding, since compute is the only one of the three enums that carried sizes and the extraction agreed with it exactly core, 0 boundaries — measured, not assumed: nothing in core turns an integer or a string into a GgmlType. Its whole exposure is ONE exhaustive match, GgufTensor::byte_size, snapshotted here at 24 (dtype, elements) points Each lives in a #[cfg(test)] child module of the boundary's own module, so the private items are reachable without widening anything; the only non-test edits in this commit are four `mod` lines. THE ONE ROW EXPECTED TO MOVE, named now so the diff cannot hide it: core sizes Q4_1 at 18 bytes/block where upstream says 20 AND core's own shape.rs already says 20. A second test asserts that disagreement DIRECTLY, so it cannot be fixed by accident; Phase 3 deletes that test and moves one row in the case table, 54 -> 60, in the same commit. Refs #3430 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ow checkable The ticket's headline. `crates/aprender-serve` (16 ids), `crates/aprender-core` (12) and `crates/aprender-compute` (15) each declared their own ggml tensor-type enum; a fourth private table, QTYPE_LABELS (13 rows, #3405), named the same ids again. All four are gone. The tree now holds ONE definition: $ grep -rnE '^\s*pub enum (GgmlType|GgmlQuantType)\b' crates/*/src crates/aprender-quant/src/ggml_type.rs:140:pub enum GgmlType { BEHAVIOUR IS PRESERVED, AND THAT IS MEASURED, NOT ASSERTED. Phase 1's 12 characterization tests were written against the unchanged code and sweep every boundary over ids 0..=255. All of them pass UNCHANGED through this commit, with exactly the two edits named in advance: - compute: `GgmlType::from_u32(x)` -> `from_u32(x)`, because an inherent method cannot follow a type defined in another crate. The admitted SET is untouched — still exactly 15 ids, now stated once in `const ADMITTED`. - core: the Q4_1 row, below. Each crate keeps its own admitted set, stated once and enforced at every boundary, because the leaf knows all 35 live ggml types and no crate may start accepting an id it used to refuse: compute ADMITTED[15] + `from_u32`, at its one GGUF parse boundary serve ADMITTED[16] + `admitted_from_id` / `admitted_from_name`, at all SEVEN boundaries (gguf/dtype x2, infer, apr/mod's from_binary arm, apr/special_tokens, apr/dequant, and the loader test that mirrors the predicate) core none, and none is needed — measured: nothing in core turns an integer or a string into a GgmlType THE ONE VALUE THAT CHANGES, AND THE COUNT THE COLLAPSE IS WORTH. core sized Q4_1 at 18 bytes per block where ggml says 20 (2 x f16 for scale AND min, plus 16 nibble bytes) and where core's OWN other size table, format/gguf/shape.rs, already said 20. Two tables in one crate disagreeing, and the wrong one was the one nothing called — `export_tensors_to_gguf` sizes tensors with data.len(), so no GGUF was ever written wrong by it. A unit test had asserted the 18-byte value since it was written, pinning the defect. So the honest ledger for this collapse: four tables -> one, ONE wrong value removed (Q4_1) and one omission (QTYPE_LABELS had no row for Q8_1, so a refusal printed `qtype 9`). The larger find is not in this diff: measuring against the extracted table is what exposed `ggml_dtype_element_size`, a FIFTH id-indexed table, wrong in 10 of 31 rows including BF16 at 0.375 B/elem instead of 2.0 — that is #3583, deliberately not folded in here. QTYPE_LABELS's replacement goes through `from_id`, never `TRAITS[id]`: it takes an arbitrary u32 from a file and a raw index would panic for any id >= 43. It is also deliberately NOT filtered by the admitted set — it is a diagnostic, and naming id 21 in a refusal beats printing `qtype 21`. GUARD: scripts/check_one_ggml_type_enum.sh, green on this tree, with a 15-row case table (a re-export, a commented-out definition, GgmlTypeError, GgufValue, QuantType and a private enum all correctly NOT matched) and a zero-match arm that FAILS rather than passing vacuously. Mutation: re-adding a second definition to compute turns it RED naming both files; restoring turns it GREEN. guard_tree discovers it automatically via `git ls-files 'scripts/check_*.sh'`, so committing it is what wires it. Verified: 30,168 tests across serve+core+quant (nextest, ci profile) and 3,514 in compute, all passing; `cargo check --workspace --all-targets` clean; clippy -D warnings clean on all four crates; fmt clean. Refs #3430, #3421, #3583 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The falsifier met, the 12 characterization tests that make behaviour preservation a measurement, the one value that changed and why it was never reachable, and an honest count of what the collapse was worth. Refs #3430 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
noahgift
force-pushed
the
PMAT-3430-m1-phases-3-4
branch
from
September 20, 2026 18:39
5e329db to
5420b7e
Compare
Member
Author
|
quorum-review (AD-04): three PASS — agreed (auto_merge: checked=true was_armed=false disarmed=false) {
"ticket": "PMAT-3430",
"head": "5420b7e982a47ab1073870efb04aedce7e22ea86",
"width": 3,
"executor": "agy",
"agreed": true,
"auto_merge": {
"checked": true,
"was_armed": false,
"disarmed": false,
"note": "auto-merge not armed"
},
"lanes": [
{
"lane": 1,
"verdict": "PASS",
"findings": 5
},
{
"lane": 2,
"verdict": "PASS",
"findings": 0
},
{
"lane": 3,
"verdict": "PASS",
"findings": 4
}
]
} |
gemini-3.1-pro-high, gemini-3.1-pro-low, gemini-3.6-flash-high — each model measured from its own agy log, none in the author's family, no dissent. One round: the Pro variants and 3.6-flash returned a verdict object first time, where 3.8/3.7-flash-high had returned none in five of six lane-runs on #3581. Refs #3430, #3562 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
noahgift
enabled auto-merge
September 20, 2026 18:50
This was referenced Sep 20, 2026
PMAT-3587 (nextest half): [profile.ci] fail-fast = false — 3 of 6 verdicts discarded, measured
#3626
Merged
Merged
guyernest
pushed a commit
to guyernest/aprender
that referenced
this pull request
Sep 29, 2026
…0 theorem was false where the generator reaches (paiml#3631) * PMAT-3627 step 1 (RED): the input that killed paiml#3621, as a committed regression case RED FIRST. Only the regression test lands; the proptest, the contract and the header are untouched. On THIS commit: test regression_3627_scale_invariance_in_the_eps_dominated_regime ... FAILED 3627 regression: sign*y[1]=-1.414158 vs y_scaled[1]=-1.1461217, diff=0.26803625 Input: data = [0.0, -0.15964308], alpha = 0.012254778. alpha^2 * mean(x^2) = 1.91e-6, eps = 1e-6 (RMSNorm::without_affine, group_norm.rs:275). Ratio 1.91: the eps term is not negligible and RMSNorm(alpha*x) != sign(alpha)*RMSNorm(x), by design of eps. The numbers were re-derived in f64 independently of the CI log and match to six digits; the eps>0 identity y_scaled = sign(a)*y*sqrt((m+eps)/(m+eps/a^2)) predicts -1.146122 with relative error 2e-16. The implementation is right; the assertion was wrong. Refs paiml#3627, paiml#3621 Pmat-Ticket: PMAT-3627 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * PMAT-3627 step 2 (GREEN): assert the eps>0 scale-invariance property, not the eps=0 theorem Same regression case as the RED commit, now green, plus the proptest, the contract and the file's header. THE PROPERTY. With eps in the denominator, RMSNorm(a*x) = sign(a) * RMSNorm(x) * sqrt((m+eps) / (m+eps/a^2)), m = mean(x^2), exactly (re-derived in f64: relative error 2e-16 on the killing input). The eps=0 theorem RMSNorm.rms_scale_zero_eps is the k -> 1 limit and is false whenever a^2*m is comparable to eps. The proptest and the regression case now assert the eps>0 form with a relative tolerance of 1e-4 -- testing what the implementation computes, in every regime the generator reaches -- and the guessed `tol = 0.05 if |alpha| < 0.1` branch is gone. Option 1 from the issue, chosen over the precondition: it is the stronger property and excludes nothing. regression_3627_... ok prop_scale_invariance x 20 runs, fresh seed each 20/20 ok MUTATION (k := 1, the eps=0 form restored) RED: rel=0.18953769 -- the 19% the whole rmsnorm suite 12 passed, 0 failed The regression case also pins y_scaled[1] = -1.146122 and k = 0.810462, so it is anchored to the incident's numbers, not only to the identity. THE CONTRACT. RN-INV-005's formal now states the eps>0 property (carries Sigma symbols: forall, ne, sqrt, arrows), and its Lean notes say precisely which regime the eps=0 theorem covers. FALSIFY-RN-002 names both tests and the mutation. pv validate clean; cargo test -p aprender-contracts --lib 1666/1666 (sigma armed). The edit adds no file and no triple, so census/graph/README are unchanged -- checked by regenerating. THE HEADER. This file said "DO NOT EDIT -- regenerate with `pv probar --binding`". That is false: the in-tree pv probar emits seven `#[ignore = "no binding available"]` stubs for this contract and cannot produce these bodies, which came from the pre-monorepo generator (20dda94, 2026-02-18). Obeying the header would have replaced five real property tests with seven ignored stubs. This is a declared HAND EDIT, and the header now says so; the issue's "regenerated, no hand edit" item was withdrawn on that measurement. The same false header stands on ~50 other tests/contracts/ files: paiml#3630. RETRIES ARE THEATER FOR PROPERTY TESTS. nextest [profile.ci] retries = 2 replayed the case proptest persisted to proptest-regressions/ on TRY 1, so TRY 2 and 3 failed in 0.005 s each: three tries, one failure. A retry cannot un-persist a counterexample. Refs paiml#3627, paiml#3621, paiml#3630 Pmat-Ticket: PMAT-3627 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * PMAT-3627: register the ticket (fragment + aggregate) so the AD-04 quorum can run docs/roadmaps/entries/PMAT-3627.yaml hand-entered from issue paiml#3627 (title, done_when as notes), roadmap.yaml regenerated by make roadmap-aggregate. quorum-review.sh refuses unless `pmat work status PMAT-3627` resolves, and the item existed only as a GitHub issue. Four roadmap guards rc=0. No renumbering, no separate PR. Pmat-Ticket: PMAT-3627 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * PMAT-3627: AD-04 quorum receipt — 3/3 PASS, three independent lanes docs/audits/quorum-PMAT-3627.json from quorum-review.sh --base origin/main --pr 3631, executor agy, width 3, models gemini-3.1-pro-high / gemini-3.8-flash-high / gemini-3.7-flash-high, none in the author's family. Independence inspected: every lane file has zero references to a sibling lane, $WORK or the .lanes/ dir. Dissent: none. Pmat-Ticket: PMAT-3627 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
guyernest
pushed a commit
to guyernest/aprender
that referenced
this pull request
Sep 29, 2026
…dicts discarded, measured (paiml#3626) * PMAT-3587 nextest half, step 1 (RED): the guard that refuses a fail-fast [profile.ci] RED FIRST. Only the guard lands; .config/nextest.toml is untouched, so on this commit: $ bash scripts/check_nextest_ci_profile_no_fail_fast.sh FAIL .config/nextest.toml: [profile.ci].fail-fast = True -- a failing test cancels every test still queued and their verdicts are discarded rc=1 $ bash scripts/check_nextest_ci_profile_no_fail_fast.sh --self-test ok rows 1-9 (every polarity: false / true / absent / wrong profile / no profile / false-in-a-comment / the string "false" / unparseable / missing file) FAIL row 10 the real .config/nextest.toml is RED rc=1 Row 10 is deliberate: the case table judges the real config too, so a red tree cannot hide behind green fixtures. paiml#3616 landed --no-fail-fast as the default for the explicit-command runner. The workspace-test shards run under nextest's OWN profile, where fail-fast = true still stands, and that is the half the operator's "on the shard" most plausibly meant. The behaviour, measured on a 6-test probe whose 2nd test fails (~60 ms), the rest 400-550 ms, -j 2 -- not read from docs: fail-fast = true Summary 3/6 tests run: 2 passed, 1 failed Cancelling due to test failure: 1 test still running fail-fast = false Summary 6 tests run: 5 passed, 1 failed (still rc 100) (key absent) Summary 3/6 tests run -- nextest's DEFAULT is fail-fast ON So an absent key is RED, not neutral, and the guard says so. The tree's own number for this class is the prior instance, not tonight's: "nextest fail-fast hid every other dark failure: 7 rounds for 4 tests." Tonight's 11,757 on paiml#3621 were NOT this -- that log reads `Cancelling due to signal`, nextest's wording for receiving SIGTERM itself, which fail-fast does not govern; the probe above produced fail-fast's actual wording, `Cancelling due to test failure`, and the two are distinct. Those 11,757 are a receipt row (a signal-killed shard must read as Unknown), filed separately. The guard reads the key STRUCTURALLY (tomllib, [profile.ci], the bool) and runs no build tool, so guard_tree.sh --no-cargo picks it up with two rows and no ci.yml step is needed. Its first draft's header comment named the build tool with a space after it and matched CARGO_RE on its own -- a substring test satisfied by the documentation of the thing it looks for, in a guard written the day that class was named. Refs paiml#3587, paiml#3616, paiml#3621, paiml#3607 Pmat-Ticket: PMAT-3587 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * PMAT-3587 nextest half, step 2 (GREEN): [profile.ci] fail-fast = false One line in .config/nextest.toml, plus the comment that says why. Same guard as the RED commit, unchanged: now `run` PASS and `--self-test` 10/10. Every workspace-test shard runs `cargo nextest run --profile ci`, so this is the setting they inherit. A red shard now still measures every test it was going to measure, and the Summary line counts them -- which is exactly when the data is most wanted. The failure is still a failure (rc 100); it is just no longer the only thing the shard knows. nextest re-reads the config cleanly (`cargo nextest show-config version` rc 0). Not touched: ci.yml:497's comment "[profile.ci]: retries=0, fail-fast" -- a workflow file, and already stale on retries (paiml#2616). It now drifts on both keys; noted in the PR body rather than edited here. Refs paiml#3587, paiml#3616 Pmat-Ticket: PMAT-3587 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * PMAT-3587: register the ticket (fragment + aggregate) so the AD-04 quorum can run docs/roadmaps/entries/PMAT-3587.yaml hand-entered from issue paiml#3587, roadmap.yaml regenerated by make roadmap-aggregate. Four roadmap guards rc=0. Pmat-Ticket: PMAT-3587 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * PMAT-3587: AD-04 quorum receipt for paiml#3626 — 3/3 PASS, three independent lanes docs/audits/quorum-PMAT-3587.json, executor agy, width 3, judged at head 0981864, author model claude-opus-5, lane models gemini-3.1-pro-high / gemini-3.7-flash-high / gemini-3.6-flash-high (the trio ruled for everyone tonight after 3.8-flash's silences, paiml-implement#311). Three distinct conversation ids, verdicts via structured_output, zero sibling-lane or $WORK references. Dissent: none. First attempt. Pmat-Ticket: PMAT-3587 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(guard): the nextest fail-fast guard read a missing tomllib as "the config is RED" -- ENV is never 1 Measured on intel-clean-room-6 (paiml#3626, guard-tree job 106169486109, head 2be40b4): Traceback (most recent call last): File "<stdin>", line 1, in <module> ModuleNotFoundError: No module named 'tomllib' FAIL (rc=1) and the self-test on the same runner: rows 1, 8, 10 FAIL, rows 2-7 "ok" -- because those rows WANTED rc=1 and a dead interpreter delivers rc=1 too. tomllib is python 3.11+; the runner's python3 is older; lambda's is 3.13, which is why every local run was green. The `import tomllib` sat at module level, outside the try, so the import error was never classified: an environment death was reported as a code defect, on a guard that exists to stop verdicts being discarded. Reproduced locally against the old guard with /usr/bin/python3.10 -S (no tomllib, no tomli): identical traceback, `FAIL (rc=1)`. What changes (all in scripts/check_nextest_ci_profile_no_fail_fast.sh): - Readers, in order: tomllib, tomli, then a purpose-built reader for the ONE question this guard asks (under [profile.ci], what is fail-fast?). The reader refuses -- ENV rc=2, never a guess -- anything outside its scope: multi-line strings, values continuing past the line, dotted keys, top-level keys, duplicate tables, [[profile.ci]] as an array of tables, a fail-fast value it cannot type. The real .config/nextest.toml (inline tables, [[...overrides]], sub-tables) judges GREEN through it: `NEXTEST_GUARD_PYTHON=python3.10 NEXTEST_GUARD_FORCE_FALLBACK=1` -> `reader=purpose-built reader`, rc=0. - The judge SAYS its verdict (a `VERDICT ok|FAIL|ENV` line). The shell accepts rc 0/1 only with that line; rc=1 without it -- a traceback before the first statement, a SyntaxError on an old python, no python3 at all (rc=127) -- is ENV rc=2 naming the interpreter and $RUNNER_NAME. A BaseException catch-all inside the judge classifies the rest as ENV too. - Self-test: 10 -> 30 rows. The case table runs twice, once per reader (NEXTEST_GUARD_FORCE_FALLBACK=1 sets sys.modules['tomllib'] = sys.modules['tomli'] = None so the imports fail for real, not a flag that skips around them); three refusal rows for the purpose-built reader; two death rows (/bin/false as the interpreter, a missing interpreter) that want ENV 2; two new table rows (false under [[profile.ci.overrides]] only -> RED; the real file's shape -> PASS). Passes under python 3.13.1 and 3.10.12 on this box. Mutants, each turning the self-test RED (baseline PASSED 30 rows): M1 rc=1 accepted with no VERDICT line row 28 rc=1 (wanted 2) M2 purpose-built reader removed 10 rows M3 multi-line string opener skipped, not refused 1 row (fixture: `note = """title"`, which a quote-count check passes) M4 [[profile.ci]] read as the profile 1 row M5 the string "false" typed as the bool 1 row M6 judge always returns 0 21 rows M8 continuation lines not refused 1 row M7 (library reader: a list profile.ci not refused explicitly) SURVIVES and is equivalent by construction: the catch-all classifies the AttributeError as the same ENV 2. Kept for the message it gives. Gates on the tree: bashrs-gate PASS (354 files), pipe-into-grep-q 75/75, hardcoded paths delta +0, apr pinned OK; the guard's --help still says self-test, so guard_tree runs both rows; no `cargo ` substring, so it stays inside the --no-cargo run. AD-04: docs/audits/quorum-PMAT-3587.json was judged at head 0981864 with diff_sha256 428d6936d2f8478c7de2da67b93566df08a18f2f43eb78ba6314027eff16a772. This commit MOVES diff_sha256 (the guard is inside the judged diff); the receipt is left as judged, per the cop's ruling that a fix on the same intent stands on it and says so here. New value: 41cdea8a2e887122bfa3e3d2ec8d37166ae1b52a88532d3f21f980e0e24e71c9. Refs paiml#3587 paiml#3626 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * PMAT-3587: AD-04 quorum receipt round 2 for paiml#3626 at 3df1c64 — 3/3 PASS Round 1 (0981864, diff_sha256 428d6936…) attested a diff that the tomllib fix (0464c2d) replaced; the cop disarmed on that ground. Round 2 judges the merge head 3df1c64 against origin/main (diff_sha256 e54d3397…): lanes gemini-3.1-pro-high / gemini-3.1-pro-low / gemini-3.6-flash-high, PASS/PASS/PASS. Independence: lane 1 ran `--self-test` itself, lane 3 ran the guard against its own fixture under NEXTEST_CONF_OVERRIDE, lane 2 read only; no lane transcript reads a sibling lane file (lane-3's one match is the receipt named as a diff item, not a verdict). Refs paiml#3587 paiml#3626 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is the half of #3430 that makes its title true. #3581 landed the leaf and the upstream-extracted
TRAITS[43]; this collapses the three enums into it.The falsifier, met
#3430's acceptance criterion is "exactly 1 ggml tensor-type enum definition under
crates/*/src":Four declarations of one fact are gone: serve's
GgmlQuantType(16 ids), core'sGgmlType(12), compute'sGgmlType(15), andQTYPE_LABELS— the private 13-row table #3405 added while three enums of it already existed.Behaviour preservation is measured, not asserted
Phase 1 wrote 12 characterization tests against unchanged code, and all 12 pass unchanged through Phases 3-4. That is the whole argument that this is safe, and the only part of it a reviewer can check without re-deriving the boundaries by hand.
gguf/dtype×2,infer,apr/mod'sfrom_binarydtype arm,apr/special_tokens,apr/dequant, the loader test mirroring the predicateGgmlType(dtype, elements)points throughbyte_sizeThe id sweep is 0..=255 and not "the interesting ids" because the property is about what is refused as much as what is accepted, and a sweep over the admitted set cannot see a widening.
Exactly two edits to those tests, both named in advance: compute's
GgmlType::from_u32(x)→from_u32(x)(an inherent method cannot follow a foreign type; the admitted set is untouched), and core'sQ4_1row below.Each crate keeps its own admitted set
The leaf knows all 35 live ggml types. No crate may start accepting an id it used to refuse — that is how a loader begins decoding bytes it has no kernel for.
compute→ADMITTED[15];serve→ADMITTED[16]withadmitted_from_id/admitted_from_nameat all seven boundaries;core→ none, and none is needed.The one value that changes
core sized
Q4_1at 18 bytes/block; ggml says 20, and core's ownformat/gguf/shape.rsalready said 20 — two tables in one crate disagreeing. It was never reachable:export_tensors_to_ggufusesdata.len(), andbyte_size()has no non-test caller. A unit test had asserted the 18 since it was written — a test pinning a defect.Phase 1 anticipated it, asserted the disagreement directly so it could not be fixed by accident, and instructed its own deletion once fixed. Both happened in one commit: two expectations moved (36→40, 54→60), the companion test went, and the other 22 assertions passed untouched — evidence that delegation changed one value, not twelve.
What the collapse was worth, counted honestly
Four tables → one; one wrong value removed and one omission (
QTYPE_LABELShad noQ8_1row, so a refusal printedqtype 9). That is smaller than the collapse deserves credit for, and the reason matters: the big find is not in this diff. Measuring in-tree tables against the extracted one is what exposedggml_dtype_element_size, a fifth id-indexed table, wrong in 10 of 31 rows including BF16 at0.375B/elem instead of2.0— which makes the #2569 truncation check fail-open on BF16 GGUFs. That is #3583, deliberately not folded in.The guard
scripts/check_one_ggml_type_enum.sh— green here, 15-row case table (a re-export, a commented-out definition,GgmlTypeError,GgufValue,QuantTypeand a private enum all correctly not matched), and a zero-match arm that fails rather than passing vacuously. Mutation: re-adding a second definition to compute turns it RED naming both files; restoring turns it GREEN.guard_treediscovers it viagit ls-files 'scripts/check_*.sh', so committing it is what wires it. Its root comes from$0, notgit rev-parse— the container refuses the bind-mounted tree (#3586).Verification
Net -35 lines while adding a 111-line guard.
The stop condition did not fire
I said before starting that if a boundary's behaviour could not be preserved I would stop and surface it rather than widen an admitted set to make a test pass — and that under automatic publishing, widening would be a fabricated green feeding a release. It did not come up: all 12 snapshots passed unchanged, and both edits to them were named before the work began. The admitted sets were reproduced from measured behaviour, not chosen.
Receipt:
docs/audits/impl-PMAT-3430-phases-3-4-receipt.md.keep-open: #3421 is the epic, #3431 is M2 (not started), #3583 is the fifth table this work exposed and is deliberately separate; #3430 itself is closed by this PR.
Closes #3430
🤖 Generated with Claude Code