Repository navigation
PP-QUANT-001 M1: one #[repr(u32)] GgmlType (43 rows: 35 live + 8 Removed) + TRAITS[43] below core/compute/serve — ggml enums 3 → 1 #3430
Description
⚠ FALSIFIER SUPERSEDED (operator ruling 2026-09-20, amended same day). The falsifier below — agreement with existing core/compute/serve values — is unsatisfiable (core
Q4_118 bytes/block vs upstream 20;Q8_136 upstream bystatic_assertvs 40 in-tree). Replaced by: for every live row i,TRAITS[i].{blck_size,type_size}equals the value extracted from ggml at the pin resolved by reference (scripts/llama_pin.tomlbuild_commit, resolved at run time — never a literal sha anywhere, including in a strike-through), the extraction output is a checked-in fixture recording the sha it read, a test assertsfixture.sha == build_commit, and mutation of any one row turns the test RED. Upstream ggml is the oracle; in-tree enums are the defendant.Title numbers verified 2026-09-20 by re-extraction at whatever
scripts/llama_pin.tomlbuild_commitresolves to: 35 live + 8 Removed = 43 slots (GGML_TYPE_COUNT = 43). No longer[U]; no title correction needed. Full ruling, amendment and extraction method in the comments.
Parent: #3421 · Slot: 0.69.0 must-carry.
Mechanism: three independent enums name ggml tensor types and disagree — serve GgmlQuantType 16 ids, core GgmlType 12 (the import path; no Q5_0/Q5_1/Q2_K/Q3_K/Q5_K), compute GgmlType 15 — against 35 live ids at llama.cpp 3173a5647. #3405 added a fourth private table (QTYPE_LABELS, 13 rows).
Fix: one closed enum + const TRAITS: [QuantTraits; 43] {name, blck_size, type_size, family} in the lowest common workspace dependency, or a new zero-dep leaf crate if none exists (then it joins clean-room + publish order). The three enums become re-exports. GGUF metadata value-type ids (UINT32/STRING/INT32/ARRAY) are a separate enum — a different id space.
Falsifier: exactly 1 ggml tensor-type enum definition under crates/*/src; TRAITS (block, bytes) equals gguf-py GGML_QUANT_SIZES for every shared id.
Ĵ: 24 turns [A] — borrowed; estimate.sh aprender pools 0 of 47 ledger rows today, so there is no measured basis.
Plan + evidence: #3427 · design discussion: #3418 · spec PR: #3420
🤖 Generated with Claude Code
Carried from the PMAT-3427 receipt (operator decision 2026-09-17) — PLAN PHASE FIRST, no code until the plan quorum is 3/3.
The design quorum for Q1 (one #[repr(u32)] GgmlType, 43 rows, TRAITS[43], homed in the lowest common workspace dep or a zero-dep leaf crate) and X1 (ordering Q1 → T1/T2 → Q2 → Q3) runs inside this ticket's own plan phase. Inputs, all in docs/audits/impl-PMAT-3427-receipt.md (draft PR #3447), measured on origin/main @ 7eb81a531:
- Table S — 43 spec ids (35 live + 8 removed) × serve / core / compute presence; 13 live ids named by no aprender enum.
- Table E — 38
Ggml*/Quant*/GgufValue*enums: 3 merge, 10 merge-candidate, 1 keep, 24 "keep?". The plan must resolve every one of the 24 tomergeorkeep(concept). - Table B — 53 raw-integer qtype fields/params (24 fields, 29 params; serve 34, core 8, apr-cli 7, cbtop 2, compute 1, train 1).
- Dispatch sites — 231 at file:line in 28 files (151 arm/ref, 54
.qtypecompare, 24match, 2 bare-integer). The 558-line bare-integer upper bound stays[U]; classifying it is PP-QUANT-001 M2: reconciliation gate —GgmlTypevs the vendoredggml.hid list at a pinned sha; exhaustive matches, no_ =>#3431's first task, not this ticket's. - Home crate for
GgmlType: derive fromcargo treeper consumer crate (core, compute, serve), not from memory. - X1 stands on measurement: T∩B = 14 of 34 serve rows (41 %, file-level) > the 20 % falsifier ⇒ T1 before Q2.
Post the verdict grid on PR spec(PP-QUANT-001): quant-type dispatch consolidation — design, contract, Phase 0 gate #3420.
Activity
PMAT-3427: Table S sized Q8_1 from gguf-py (40); the C struct at the …
noahgift commentedon Sep 17, 2026
Falsifier correction (my wording was unmeetable) — 2026-09-17. This ticket's body says
TRAITS(block, bytes) must equal gguf-pyGGML_QUANT_SIZESfor every shared id. That cannot be met: at llama.cpp3173a5647gguf-py gives Q8_1 = 40 (4 + 4 + 32) while ggml's C struct is 36 (static_assert(sizeof(block_q8_1) == 2*sizeof(ggml_half) + QK8_1),ggml/src/ggml-common.h)[X], verified. Found by this ticket's own plan session.Read the falsifier as:
TRAITS(block, bytes) equals the Cstatic_assertsizes inggml-common.hat the pinned sha for every live id; gguf-py is a second source, and every id where the two disagree is listed by name with both values (today: Q8_1) rather than silently resolved. Table S in the PMAT-3427 receipt took itstype_sizecolumn from gguf-py and is corrected for Q8_1 only — the other 34 rows are not yet re-checked against C; that is Phase 2 of this ticket.This does not touch the open design ruling on objection classes A/B (posted on #3421).
noahgift commentedon Sep 20, 2026
RULING (operator, 2026-09-20) — PMAT-3430 M1
Recorded verbatim. Lane A is unblocked; no fifth quorum round.
One clause needs a correction before it can be executed — clause 2's sha
The ruling makes the pinned llama.cpp sha the oracle, so every number in M1's fixture is extracted from whatever that sha resolves to. It does not resolve here. Measured on the release tree:
d1d3c3396scripts/llama_pin.tomlbuild_commit,pinned_on = 2026-09-15,pin_expiry = 2026-12-01, 216 references in-tree39173bcacevidence/parity/thresholds.yaml)3173a5647(the ruling's)grep -rlover the repo returns nothingI am not substituting a sha into the ruling by inference: the whole point of clause 2 is that the oracle is named, and an oracle resolved by guessing is not an oracle. The implementer needs one line back: is the oracle
d1d3c3396(the pin of record), or a deliberate new pin? If it is a new pin, note that bumping the comparator invalidates every ratio measured against the old one —llama_pin.tomlsays so itself, and that is a decision with a named cost rather than a bump.Second-order finding, independent of the answer: two comparator pins are live in-tree at once — 216 references to
d1d3c3396and 124 to39173bcac. Some committed artifacts are therefore measured against a superseded oracle. That deserves its own row regardless of how clause 2 resolves.What proceeds now, unblocked
#[repr(u32)] GgmlType(43 rows: 35 live + 8 Removed) +TRAITS[43]below core/compute/serve — ggml enums 3 → 1 #3430's original falsifier is superseded by clause 3 and must not be implemented as written.GgmlTypevs the vendoredggml.hid list at a pinned sha; exhaustive matches, no_ =>#3431 is now scoped by clause 4: every disagreement is a row with upstream value, in-tree value, call sites, and a NEVER-WORKED / REGRESSION verdict measured on the v0.68.1 binary, not inferred.#[repr(u32)] GgmlType(43 rows: 35 live + 8 Removed) +TRAITS[43]below core/compute/serve — ggml enums 3 → 1 #3430 → PMAT-3427: PP-QUANT-001 slice M is 0.69.0 must-carry — measured tables, fix-diff Pareto, the queue #3447 → docs(release): APR-RELEASE-001 has no must-carry section onmain— land §1.5 (must-carry rows; T-0 waits; > 72 h andon) #3446, epic EPIC: PP-QUANT-001 — quant-type dispatch, Phase 0/1 (0.69 train) #3421. This is Band 0 of EPIC: release train 0.69.0 — COMPLETE Qwen usability on pure CUDA (all 0.68.x folded in) #3080 and it gates T-0.Refs #3080, #3430, #3431, #3421, #3562
noahgift commentedon Sep 20, 2026
AMENDMENT (operator, 2026-09-20) — clause 2 of the M1 ruling, recorded verbatim
2b is now measured — the ticket's numbers hold.
[U]cleared.Extracted from the pinned checkout at
/home/noah/src/llama.cpp-d1d3c3396(git rev-parse HEAD→d1d3c3396aa1…, matchingllama_pin.tomlbuild_commit), fromggml/include/ggml.h:Q4_2, 5Q4_3, 31Q4_0_4_4, 32Q4_0_4_8, 33Q4_0_8_8, 36IQ4_NL_4_4, 37IQ4_NL_4_8, 38IQ4_NL_8_8GGML_TYPE_COUNT = 43, ids 0…42, and 35 + 8 = 43 ✓So
43 rows: 35 live + 8 Removedis confirmed at the pin. No title correction is needed and the count can stop being[U].Method note, because it nearly went the other way. A first pass with a one-line grep returned 44/41/3 and looked like a disagreement. It was wrong twice: it counted
GGML_TYPE_COUNTas a type, and it classified a commented row as live whenever the comment did not contain the word "removed" (// GGML_TYPE_Q4_0_4_8 = 32,says nothing). Reading the enum settled it. Worth stating because clause 3's fixture will be generated by a command, and a sloppy extractor produces a fixture that is confidently wrong on exactly these rows — the commented block at 31–33 and 36–38 is the trap.Four live types are recent —
MXFP4(39),NVFP4(40),Q1_0(41),Q2_0(42). Whether in-tree carries them at all is part of clause 4's reconciliation, and aNEVER-WORKEDverdict is the likely shape there rather thanREGRESSION.What clause 3's committed extraction command must do
enum ggml_typefromggml/include/ggml.hat the resolved pin, taking commented rows asRemovedby position, not by comment wording.blck_size/type_sizefrom ggml's own type-traits table, not from the header comment, and not from any in-tree value.2a generalises, and there is already a ticket for the general case
2a — an artifact derived from the pin records the pin, and a test asserts they match, so a bump's cost surfaces in the bump PR — is exactly the mechanism #3563 asks for repo-wide, where two comparator pins are live at once (216 references to
d1d3c3396, 124 to the earlier39173bcac). The TRAITS fixture should be the first artifact built to this shape, and #3563's guard should be written as the general form of it rather than as a separate idea.Refs #3080, #3430, #3431, #3452, #3563
noahgift commentedon Sep 20, 2026
done_when
(Fixed heading, written by the cop for tab 2 — see #3452 for the full chain definition, which governs this row.)
This is the implementation half of the ruled M1 plan. Its
done_whenis #3452's, in full — the falsifier, the oracle-by-reference rule, the derived row counts (35 live + 8 Removed = 43, verified atd1d3c3396, no longer[U]), the by-position Removed classification, and fix-or-refuse per type.Two things specific to this ticket:
TRAITS[43]lives inaprender-quant(settled, clause 1), and the fixture + its sha assertion ship in the same PR as the table — not as a follow-up. A table without its falsifier is the thing the four quorum rounds were about.STOP conditions and the fresh-worktree rule: as #3452.
noahgift commentedon Sep 20, 2026
M1's leaf is up: #3581 — the ruling executed, with the extraction and the mutation proof
Clauses 1–6 with amendment 2'/2a/2b.
trueno_quant::GgmlType(35 live variants) +TRAITS[43], every number extracted from ggml at the pin by a committed command, fixture recording its sha, six mutations RED and every control GREEN. Behaviour unchanged: nothing imports the leaf yet, and serve's 16 strings / compute's 15 sizes are asserted identical.Two corrections to the ruling's premises, both measured
1. Clause 3 says "Q8_1 upstream is 36 by static_assert vs 40 in-tree (pre-f16 layout)". There is no 40 in-tree. Every in-tree Q8_1 size is already 36 —
aprender-compute'sblock_bytes,aprender-core'sshape.rs:230, and the GPU dp4a kernels. The 40 came from gguf-py, via Table S of the PMAT-3427 receipt, which is a document, not code. So clause 5's fix-or-refuse has no Q8_1 case at all, and the extraction (which reads the C table) simply gives 36.2. Clause 5 has no Q4_1 case either, for a different reason.
GgufTensor::byte_sizereally does sizeQ4_1at 18 where upstream says 20 — but it has no non-test caller in the workspace:export_tensors_to_ggufsizes tensors withtensor.data.len(). No GGUF was ever written wrong by it, and there is no load path for a refusal to sit on. Core's other size table (shape.rs) has always said 20, so the defect is two tables in one crate disagreeing rather than a wrong loader.Clause 5 therefore ships with no refusal, stated rather than silently skipped. If #3431's reconciliation finds a wrong size on a real load path, that type gets clause 5's treatment there.
The defect that matters, for #3431's table (clause 4)
aprender-core::ggml_dtype_element_size(format/safetensors.rs) is wrong in 10 of its 31 rows. From index 16 the table is written in the order of its own comment —… I8, I16, BF16, I32, I64, F64, IQ1_M— instead of ggml id order (24 I8, 25 I16, 26 I32, 27 I64, 28 F64, 29 IQ1_M, 30 BF16), and the IQ rows carry values belonging to no type at all.type_size/blck_size)unwrap_or(4.0))Verdict NEVER-WORKED, with a user-visible consequence.
list_tensors_ggufuses this table for the #2569 truncation check: BF16 at 0.375 instead of 2.0 is a 5.3× under-estimate, so a truncated BF16 GGUF passes the extent check — fail-open — andapr tensorsprints a size 5.3× too small. The IQ rows err the other way and would reject an intact file as truncated.PMAT-869 corrected four K-quant rows of this same table in 2026-06 and stopped there. The audit-lags-main pattern, and the reason the whole table is being re-derived rather than patched row by row.
It is not fixed in #3581: the fix is a lookup into
TRAITS, which is what #3581 creates, and doing both at once would make the leaf's "changes no behaviour" claim unverifiable. It lands next, with theQ4_1row, before Phases 3–4.Disposition of #3452
Its plan (v4) and the four-round quorum history are the provenance for this work and are cited by the receipt; nothing in them is contradicted except where the ruling superseded the falsifier and where §6 above corrects a premise. It carries no code and can merge or close on tab 1's call — #3581 does not depend on it.
Refs #3430, #3421, #3431, #3452, #3563
noahgift commentedon Sep 20, 2026
Note for tab 2's first read — two literal shas remain below the fold, in the pre-existing ticket text:
3173a5647and7eb81a531. They are in the original body written before the oracle-by-reference rule, not in the falsifier or the banner, and I have left them rather than silently rewriting someone else's ticket text.Neither is authority. The oracle is
scripts/llama_pin.tomlbuild_commit, resolved at run time.3173a5647is the struck literal from the original ruling — it resolves nowhere in this tree. If the implementation grep finds either string, that is the literal-a-grep-will-find problem the rule exists to prevent; delete them in the M1 PR rather than working from them.PMAT-3430: the extractor's case table asked git where it was, and CI'…
PMAT-3430: quorum verdict 3/3 on 9bbcaa4 (AD-04)
PMAT-3430: one new contract obliges two derived artifacts — regenerat…
PMAT-3430: the case table must run where the code runs — awk, not pyt…
PMAT-3430: receipt §6a — what adding ONE contract file actually cost
PMAT-3430 Phase 1: characterize all 9 boundaries BEFORE touching them
PMAT-3430 Phases 3-4: three ggml enums become one, and the count is n…
PMAT-3430 Phases 3-4: receipt
PMAT-3430 Phases 3-4: quorum verdict 3/3 on 5420b7e (AD-04)
PMAT-3430 M1: one ggml tensor-type table, extracted from upstream rat…
PMAT-3430 Phases 3-4: three ggml enums become one (M1 complete) (paim…