Repository navigation
EPIC: release train 0.68.2 (interrupt) — Qwen3 CPU+GPU verification, P0 #3477
Description
Release train 0.68.2 (interrupt) — Qwen3 CPU + GPU support, P0
Why this exists / relation to the 06x cadence (docs/specifications/06x-release-schedule.md): that spec's only
stated Qwen priorities are F/G — Qwen2.5-Coder-7B parity and its fine-tune story. Qwen3 was never an operator-declared
priority row, so under §1.1 ("scope that is not on the platform rides the next train") every Qwen3 ticket has drifted
forward release over release with no floor. This milestone is an explicit operator override of that drift, inserted
ahead of 0.69.0/0.70.0, per the 2026-09-18 decision: the next release ships Qwen3 CPU+GPU verification, full stop.
Investigation — how Qwen3 support ended up NOT in v0.68.1 (summary; full trail in ticket comments):
-
Dense Qwen3 (
Qwen3ForCausalLM) has no current proof it runs at all. The only historical verifications
(Qwen3 GPU inference produces garbage output (architecture not supported) #479, qualify: Qwen3-4B self-test failures (Q4_K_M and Q8_0) #308, closed 2026-02/03) predate the entire monorepo consolidation and multiple forward-path bug classes
found since (Q5_K layout fix, 8 Qwen3.5-forward defects). Nothing re-checked it. This wasn't "deprioritized" —
it was undiscovered: P0: dense Qwen3 (Qwen3ForCausalLM) has no current proof it runs — last verification is 7 months stale and CI never covers it #3413 (P0) was filed 2026-09-17, the day after the 0.68.0 train closed, while
investigating the adjacent Qwen3.5 ticket. It could not have ridden 0.68.1 because the gap wasn't known to exist
until 0.68.0 had already shipped. It landed on milestone 0.69.0 by default (the only open train when filed), not
by any prioritization decision. -
Qwen3.5 CPU (CPU: Qwen3.5 / Qwen3.8 hybrid GGUFs are refused entirely — no fallback exists #3091) DID get an explicit no-slip commitment for 0.68 (operator ruling 2026-09-15, row 68-Q1
of the 0.68.0 epic EPIC: release train 0.68.0 — 06x-release-schedule.md §3 (0.68.0) #3079) and a PR landed (feat(qwen35): Qwen3.5 / Qwen3.8 hybrid GGUFs run on the CPU — apr run + apr chat (#3091) #3114/CPU: Qwen3.5 / Qwen3.8 hybrid GGUFs are refused entirely — no fallback exists #3091 merge). But the fix was incomplete:tensor_byte_size
only handles 11 quant-type ids, and real downloaded quantizations (UD-IQ2_XXS, UD-IQ4_XS) crash with an
unhandled-type refusal. The ticket's true state was hidden by three wrongful auto-closes — GitHub misparsed
the literal string "no-close: CPU: Qwen3.5 / Qwen3.8 hybrid GGUFs are refused entirely — no fallback exists #3091" in unrelated PR bodies as a closing keyword (tracked separately as GitHub parses 'no-close: #N' as 'close: #N' — #3091 was closed twice by PRs whose bodies said no-close (D0 of the pmat 3.41.0 run); #3351 carries the same line for #3347 #3400,
a real GitHub/tooling defect). Operator triage caught this 2026-09-17, reopened it, and rescoped it to depend on
PP-QUANT-001 M4:tensor_byte_sizeand ONE refusal site readTRAITS— closes the #3091-reopen / #3341 class for all 35 ids at once #3432 (the quant-dispatch fix), which was itself slotted as 0.69.0 "must-carry" — so CPU: Qwen3.5 / Qwen3.8 hybrid GGUFs are refused entirely — no fallback exists #3091 landed on 0.70.0,
two trains past where it was originally committed. -
Qwen3.5 GPU (GPU: implement Gated DeltaNet / SSM inference for Qwen3.5 / Qwen3.8 hybrid GGUFs #3090) and the umbrella feature ticket feat: Qwen3.5 (qwen35) SSM/Gated Delta Net inference support #3038 never received any no-slip ruling — they
simply lost every capacity contest against the F/G-prioritized Qwen2.5-Coder work under the train's hard PR
budget (8-20 PRs per 60h train, §1.2 of the schedule spec) and rode 0.70.0 by drift, same as P0: dense Qwen3 (Qwen3ForCausalLM) has no current proof it runs — last verification is 7 months stale and CI never covers it #3413 would have. -
Root mechanism common to both families:
tensor_byte_size/ quant-type dispatch has no single source of
truth (ARCH: quant-type dispatch is duplicated across ~30 files with no single source of truth — propose a dedicated consolidation release #3418, EPIC EPIC: PP-QUANT-001 — quant-type dispatch, Phase 0/1 (0.69 train) #3421/EPIC: Inference dispatch & architecture consolidation (dedicated cycle) #3423) — the same class of gap that broke CPU: Qwen3.5 / Qwen3.8 hybrid GGUFs are refused entirely — no fallback exists #3091 on real files is why nothing here has
a durable regression gate. PP-QUANT-001 M4:tensor_byte_sizeand ONE refusal site readTRAITS— closes the #3091-reopen / #3341 class for all 35 ids at once #3432 is the concrete fix.
Net effect: Qwen3 was never actually rejected from 0.68.1 — it was never on the manifest to begin with,
because (a) the dense-Qwen3 gap was discovered one day too late, and (b) the one Qwen3.5 commitment that did exist
was quietly undone by a tooling bug and only really diagnosed after 0.68.1 had already shipped.
Scope — P0, must land in 0.68.2
| Issue | What | Depends on |
|---|---|---|
| #3413 | Dense Qwen3 (Qwen3ForCausalLM) CPU + GPU verification — run real Qwen3-4B/8B GGUF on both, record evidence, add a qwen-story rung |
none — pure verification |
| #3091 | Qwen3.5/3.8 CPU: stop refusing valid real-world quant types (IQ2_XXS, IQ4_XS, …) | #3432 |
| #3432 | tensor_byte_size reads TRAITS instead of hand-maintained 11-arm match — unblocks #3091 for all 35 quant ids at once |
pulled forward from 0.69.0 must-carry |
| #3090 | Qwen3.5/3.8 GPU: implement Gated DeltaNet / SSM inference (currently unimplemented, refuses cleanly) | none — new work |
| #3038 | Umbrella: Qwen3.5 SSM/GDN inference support — tracks #3090/#3091 to closure | superseded in practice by #3090/#3091; kept open as the closing ticket |
Acceptance
- P0: dense Qwen3 (Qwen3ForCausalLM) has no current proof it runs — last verification is 7 months stale and CI never covers it #3413: dated, hostnamed, commit-pinned CPU and GPU evidence that dense Qwen3 produces coherent multi-token
output, or a filed concrete defect if it doesn't;qwen3.yamlgets an explicitis_supported_cpu/gpupair - PP-QUANT-001 M4:
tensor_byte_sizeand ONE refusal site readTRAITS— closes the #3091-reopen / #3341 class for all 35 ids at once #3432 merged, CPU: Qwen3.5 / Qwen3.8 hybrid GGUFs are refused entirely — no fallback exists #3091 verified fixed on the real UD-IQ2_XXS/UD-IQ4_XS repro files (not just the synthetic fixture) - GPU: implement Gated DeltaNet / SSM inference for Qwen3.5 / Qwen3.8 hybrid GGUFs #3090: Qwen3.5/3.8 GPU inference (Gated DeltaNet on CUDA) lands — the non-goal option is withdrawn. Decision 2026-09-19: Noah selected "GPU required — build GPU: implement Gated DeltaNet / SSM inference for Qwen3.5 / Qwen3.8 hybrid GGUFs #3090 now". Proof:
apr qaGolden Output GPU passes on lambda (sm_89) and gx10 (sm_121), and the qwen35-0.8b-q4km rung of contracts/model-capability-ladder-v1.yaml is green for cuda on both hosts (QHF-GPU-008 / QE2E-DEV-008, contracts(qwen35-gpu): GDN-on-device obligations + cuda claimed on the Qwen3.5 ladder rung — RED until #3090's path is measured on both hosts (#3477) #3502). Bump PR release: 0.68.2 #3498 stays disarmed and its CHANGELOG [0.68.2] paragraph must be rewritten before it re-arms - ONT-4c1: model receipts as SHACL focus nodes — extract:gguf + extract:apr-model, ladder rungs resolve to per-host receipts; shapes: every required rung green on both silicons (cc 8.9 + 12.1) #3508 ONT-4c1: ladder rungs are SHACL focus nodes resolving to the tracked per-host receipts;
pv lint --gate shapesRED when a required rung lacks a green receipt on cc 8.9 and 12.1 (operator 2026-09-19: 0.68.2 requirement) - ONT-4b2: extract:code + extract:lean into contracts.nt (symbol/ and world/ roots), vendored W3C SHACL-Core cases, make oracle differential (release gate) #3509 ONT-4b2: code + lean extractors, W3C SHACL-Core cases,
make oracledifferential at the release gate (operator 2026-09-19: 0.68.2 requirement) - 0.68.2 HARD REQUIREMENT: full Qwen3.5 support at every DENSE size — 0.8B/2B/4B/9B/27B on CPU+CUDA on both ladder hosts (re-scoped from all sizes; 35B-A3B post-0.70) #3510 ALL DENSE Qwen3.5 SIZES (operator 2026-09-19, re-scoped same day: "ONLY up to 27B"): 0.8B/2B/4B/9B/27B on both hosts, CPU+CUDA green in the ladder receipts; 35B-A3B → Qwen3.5-35B-A3B (hybrid Gated DeltaNet + routed MoE): CPU reference forward + CUDA path + ladder rung on both hosts (UD-IQ4_XS 17.5 GB) #3512 (0.71.0); 122B/397B not filed; QE2E-INV-001 asserts Qwen3.5-9B ∈ [9.0B, 9.2B] but the repo's own 9b descriptor sums to 8.209B — the descriptor declares no DeltaNet tensors #3346 fixed
- closing comment here: what shipped, what slipped (if anything), evidence paths, v0.68.2 tag instant
🤖 Generated with Claude Code
Activity
noahgift commentedon Sep 18, 2026
Measured 2026-09-18 — Alfredo's "it doesn't work", reproduced on two hosts
Binaries pinned via
. scripts/apr_bin.shfrom a worktree atorigin/main4a538dd, built--features cuda. The published crates.io 0.68.1 installed with--features cudabehaves identically on every cell (lambda-vector). Control: Qwen2.5-Coder-1.5B Q4_K_M runs on CUDA cleanly on both hosts, no divergence — so nothing below is a box/driver problem.--gpu--gpurunandchat)--gpuapr qaQwen3-1.7Bapr qaQwen3.5-0.8BFinding A — dense Qwen3 on GPU is broken and hidden (#3413, now a reproduced defect, not a process gap). The same wrong argmax (25) at the same position on sm_89 and on Blackwell means a deterministic logic defect in the CUDA qwen3 forward, not precision or silicon. The parity guard catches it and falls back to CPU, so a user sees "works but slow" and a benchmark sees a 12–15× GPU speedup on garbage.
apr qais the only surface that names it, andapr qaon a dense Qwen3 is in no CI lane. Likely locus: the per-head QK RMSNorm that dense Qwen3 adds over Qwen2.5 (crates/aprender-serve/src/cuda/executor/layers/rope.rs::apply_qk_norm, run inside the trueno#243 manual graph, 535 kernels). Not yet root-caused op-by-op.Finding B — Qwen3.5 hybrid runs on CPU but the tooling still refuses it (#3091 / #3432).
apr run/apr chatare correct on Q4_K_M;apr qa,apr checkand the parity refusal still callrealizar::gguf::unsupported_architecture_reasonand print the pre-#3114 message. The UD-IQ2_XXS / UD-IQ4_XS crash in #3091 is untested here (no such quant on either host).Finding C — the contracts that should have caught A are proved against the wrong object. Detail in #3413. In short:
qk-norm-v1FALSIFY-QKN-006 compares CPU to a "GPU reference simulation", KANI-QK_NOR-008 "GPU kernel matches CPU reference" is a Kani harness (Kani cannot execute a CUDA kernel),apr-cpu-vs-gpu-output-parity-v1hasQA gate: not defined, andqwen3-e2e-verification-v1QW3E-BND-005 assertscoverage(qwen3_contracts) = 1.0while none of its 7 obligations mentions a backend. All four are green today.Acceptance addendum for this train (proposed — falsifiable, per host)
apr qa <dense Qwen3 Q4_K_M>Golden Output PASS on GPU on sm_89 and on GB10, with the argmax-25 mutation (revert the fix) turning it RED. Ships as a CI leg on the GPU runners, not a nightly.apr run --gpuon dense Qwen3 emits no "diverges … falling back to CPU" line, and the decode runs on the GPU (trace line or throughput ≥ the ACVGOP-INV-010 floor, not "device: GPU" by intent).apr qa <Qwen3.5 Q4_K_M>Capability Match PASS on CPU (PP-QUANT-001 M4:tensor_byte_sizeand ONE refusal site readTRAITS— closes the #3091-reopen / #3341 class for all 35 ids at once #3432 collapsesqa_capability.rs:98,parity_refusal.rs:157,ptx_map.rs:441onto the one predicate the loader honours).Provable-contract work required for full GPU support
contracts/qk-norm-v1.yamlapply_qk_normon device on the Qwen3-1.7B layer-0 q/k of a fixed prompt, compare toRMSNorm::forwardper head, cosine ≥ 0.9999. Mark KANI-QK_NOR-008strategy: not_applicable(CUDA) so L4/L5 stop counting it as proved. Bind it to a#[contract]onapply_qk_norm— today the only bindings are the two loaders andforward_cached.rs(CPU).contracts/apr-cpu-vs-gpu-output-parity-v1.yamlqa_gate: not defined; ACVGOP-INV-002 "greedy first-token argmax identical" is exactly what fails and nothing runs it on qwen3qa_gatethat names theapr qaGolden-Output GPU check and a per-architecture model ladder (qwen2,qwen3,qwen3moe,llama,phi3) — one small Q4_K_M per arch. Add FALSIFY-CPU-GPU-015: "dense Qwen3 pos-1 argmax on CUDA == CPU"; mutate by skippingapply_qk_norm.contracts/qwen3-e2e-verification-v1.yamlcoverage = 1.0is self-declaredQW3E-PAR-008(invariant):forall p in probe positions ≥ 1: argmax_gpu(p) == argmax_cpu(p) ∧ cos ≥ 0.95pergpu-cpu-parity-gate-v2; addQW3E-DEV-009(liveness): decode ran on the selected device (no fallback line). Point QW3E-BND-005 atpv coverageoutput, not a literal 1.0.contracts/model-families/qwen3.yamlverified_on:rows{host, cc, backend, sha, receipt}thatqwen3_5.yamlalready has, filled by the CI leg in acceptance 1.contracts/qwen35-hybrid-forward-v1.yaml,qwen35-e2e-verification-v1.yamlQHF-GPU-008"GDN recurrent state on device equals CPU state per layer per token (L∞ ≤ 1e-3 fp32)" andQE2E-DEV-008"no[qwen35: … runs on the CPU]notice when--gpuis honoured".contracts/quant-dispatch-v1.yaml(#3432, unlanded)apr qaon aqwen35GGUF must not print "NEITHER the CPU nor the GPU backend".SHACL / ONT-001 rows required (v4.4,
entity:+shape:blocks in the YAML;.ttlis a generated export)Today 0 of 1818 contracts carry
entity:/shape:, and the validator (ontology/shapes.rs, ONT-4b) has not landed in aprender (#3269, 0.70.0). These rows are therefore authored now, gated when ONT-4b lands — they must not be claimed as passing before that.contracts/model-qwen3-1p7b-q4km-gguf.yaml—entity: {type: gguf, ref: <sha256>},shape.closed: true, properties:model:arch in [qwen3];model:tensorwithpattern "^blk\\.[0-9]+\\.attn_q_norm\\.weight$"minCount =model:layerCount, same forattn_k_norm;model:headDim= 128;model:parityReceipt minCount 1, resolves: receiptper backend (cuda-sm89,cuda-cc120,cpu). The missing receipt is what makes today's state a SHACL violation rather than an unanchored claim.contracts/model-qwen35-0p8b-q4km-gguf.yaml— same shape family withmodel:arch in [qwen35],model:tensorpattern^blk\.[0-9]+\.ssm_a$minCount ≥ 1,model:hybridLayout(attention/GDN interleave) present,model:parityReceiptforcpunow andcuda-*when GPU: implement Gated DeltaNet / SSM inference for Qwen3.5 / Qwen3.8 hybrid GGUFs #3090 lands.type: gguf(SHACLtargetClass, R-19 inherits down): every GGUF a release claims to support carries ≥ 1model:parityReceiptwhosebackendis in the release's declared backend set. This is the shape that turns the Docs: publish a GPU-vs-CPU model architecture support table (no user-facing doc exists today) #3077 support table from prose into a validated projection.apply_qk_normand the GDN forward:entity: {type: code, ref: realizar::cuda::executor::layers::rope::apply_qk_norm},ont:binds minCount 1, resolves: symbol(so the contract-to-kernel binding above becomes a census fact),ont:validUnder class ont:Worldnaming{cc: [89, 120]}.pc_shape): a planted GGUF projection withattn_q_normabsent must be rejected by shape 1; a planted receipt withbackend: cpuonly must fail shape 3 for a release that declarescuda. Without these the shapes are theater (memory: "a gate never green on its own target is not a gate").Ledger: probe logs on lambda-vector under the session scratchpad, on gx10 under
~/probe/; worktrees~/src/aprender-qwen3-probeon both hosts at 4a538dd.noahgift commentedon Sep 18, 2026
Process piece landed as a PR: #3479 — model capability ladder.
contracts/model-capability-ladder-v1.yaml+scripts/model_ladder.sh(per-host runner) +scripts/check_model_ladder.sh(declared dogfood gate, 13-case self-test) + a T-2 Models row in APR-RELEASE-001 §4. Receipts at 4a538dd from lambda and gx10 are committed and the gate is RED on both (qwen3/cuda fell back + golden gibberish; qwen35 capability_match refused) with the control rung green — the 0.68.2 train cannot cut until #3413 and #3432 turn those rows green. The unit of release evidence is now (architecture, backend, silicon), never "a model ran".noahgift commentedon Sep 18, 2026
✅ #3479 merged to main 2026-09-18T12:46Z — the T-2 Models row is live:
scripts/check_model_ladder.shis a declared dogfood gate and is RED on both hosts until #3413 (qwen3/cuda) and #3432 (qwen35 capability_match) land. Before the 0.68.2 cut: rerunbash scripts/model_ladder.shon lambda and gx10 at the cut sha and commit the receipts.noahgift commentedon Sep 18, 2026
Coordination state 2026-09-18 ~13:15Z (assistant session). Fix branch
PMAT-3477-qwen3-cuda-qk-norm(head 83f85a1, unpushed) measured on lambda via the ladder: qwen3-1.7bapr qagolden_output on GPU now PASSES (qk-norm-in-graph works) butapr run --gpufalls back on it AND on the qwen2.5 control — the new batched-prefill F2 validator rejects on cosine alone (one case argmax 29 == 29 still fell back); it must apply gpu-cpu-parity-gate-v2's per-position rule. qwen3-8b golden GPU still gibberish at that head. qwen35: two more refusal sites beyond the loader —apr qacapability_match (ladder side fixed by #3481: cpu-only rungs skip it) andapr qatensor_contract via rosetta.validate → transformer.rs:91, a hard exit-5 abort with no report. Side PRs: #3480 contracts co-evolution (qk-norm-v1/parity/qwen3-e2e, 3/3 quorum, armed), #3481 ladder cpu-only rung. T-2 preflight dogfood on main e6dad31 in progress: red so far = model-ladder (by design), version-unpublished (pre-bump), andmake coverage-check(cause not yet read).noahgift commentedon Sep 18, 2026
Preview receipt on the fix branch head 8edf3bf, gx10 (GB10 cc 12.1,
apr --version= 8edf3bf): model ladder 4/4 GREEN — qwen2-1.5b cpu+cuda, qwen3-1.7b cpu+cuda, qwen3-8b cpu+cuda, qwen35-0.8b cpu. First green four-rung receipt since the gate existed. Lambda counterpart pending the final head (#3484 will fold #3480/#3482/#3485 per the one-queue-entry decision). Not the counted run: that happens once on the final head on both hosts.PMAT-3477: model-capability-ladder receipts at 9275872 — lambda 4090 …
alfredodeza commentedon Sep 18, 2026
Reopened — operator ruling (2026-09-18): GPU (#3090) is a MUST for this interrupt, not an optional non-goal
This epic auto-closed 2026-09-18T12:45Z as a side effect of a merged PR's
Closes #3477text, not from a check against the acceptance list below. At that moment #3090 had not
shipped and had not yet even received its "dated non-goal" disposition — that comment
landed on #3090 afterward. No one signed off that closing was correct. Reopening to
replace the mechanical close with an actual decision.
The acceptance line that created the ambiguity:
That "or" was written into this epic by the operator and is being read literally as
permission to defer GPU. It is withdrawn as of this comment: for this interrupt, GPU
is required, not optional. The reason to run this as an interrupt in the first place —
jumping Qwen3 ahead of the normal train queue under §1.1 of the schedule spec — was that
Qwen3 GPU support has been drifting for trains with no floor. Letting it defer again inside
the one release built specifically to stop that drift defeats the interrupt's purpose.
Acceptance checklist — measured state, 2026-09-18 ~15:30Z
apply_qk_normfrom replay; batched prefill applies no QK-norm at all). Fix on branchPMAT-3477-qwen3-cuda-qk-norm, open PR #3484, still OPEN, not merged — CI run in progress at time of writing.tensor_byte_sizereads TRAITS)Ruling
main, scoped explicitly toQHF-GPU-008/QE2E-DEV-008from the contract table already written in this epic's earlier comment,apr qaGolden Output GPU PASS on sm_89 and GB10 as the gate.Closes #3477, treat that as a bug to fix (drop the closing keyword from PR bodies referencing this epic; useRefs #3477instead), not as a real close.🤖 Generated with Claude Code
27 remaining items
feat(cuda): wire IQ4_NL through the executor — whitelist still SHUT (#…
feat(dogfood): model capability ladder — T-2 proves every (architectu…
fix(ladder): a rung that claims only the CPU is not asked whether the…
PMAT-3477: 0.68.2 — Qwen3 CUDA QK-norm restored in the graph and the …
fix(guard): R-2 close-issue guard now fails closed on the paiml#3400 …
contracts(qwen35-gpu): GDN-on-device obligations + cuda claimed on th…
ci: ONT-4/ONT-4b gate tests were dark — wire relations + shapes gate …
ci: guard_tree reads GitHub with the job token, not the runner's shar…
ci(pack): workspace-test as a 3-shard matrix across intel/gx10/yoga w…
PMAT-3508 / ONT-4c1: model receipts as focus nodes — extract:gguf + e…
PP-LLAMA-001 row 2: the perf002 prefill-path probe, with refusals tha…
docs(CLAUDE.md): withdraw the "always ask before `make publish`" chec…
docs(release): v0.68.2 T-5 reconcile receipt + train ledger record (p…
release(0.69.1): batch 1 — 20 receipted rows + 3 combination fixes, o…
release: merge back v0.69.3 into main (paiml#4338)