The export is clean now, and I checked it by content rather than existence. At 16f37ff6 all 168 byte counts agree, norms.f32 matches its declared c236ddbc, embeddings.f16 matches bdf74048. Nothing is broken.
Three things survive that. The last one cuts against my own previous message.
The manifest never moved.
8dc46000 index.json oid 6c08ec90... 56/168 files agree
cae77c3d index.json oid 6c08ec90...
b0471c76 index.json oid 6c08ec90...
16f37ff6 index.json oid 6c08ec90... 168/168 files agree
Same blob, four commits, eight minutes. export_complete: true was written in the first chunk, before 112 of the files it describes existed. A per-matrix sha256 does not catch this, because whatever integrity fields you add ship in the commit that opens the window, not the one that closes it. Anyone cloning during those eight minutes gets a manifest vouching for files that are not there yet.
Which makes it an ordering problem rather than a hashing one. Push assets first and the manifest last, and the window closes on its own with no flag to tighten.
You have both of those fixes in flight already, and the ordering one is the gap. The seam got fixed by re-push at 11:31:39. The SOTA export then went out the same way ten hours later.
8dc46000 21:26:59 index.json, export_complete true
cae77c3d 21:29:26
b0471c76 21:31:22
16f37ff6 21:34:54 last matrices land
Same shape, after the lesson. Which is why I think it is push order rather than integrity fields.
The card declares a checkpoint that has never been on the Hub, and the byte count is why nothing caught it.
I walked quantal_model.safetensors across all 20 commits. Three distinct contents, one size.
834dc609...0998 08-11 05:12:58 .. 08-11 12:34:18 the 3.2862 winner
2d54a10f...5c4c 08-12 03:17:50 .. now the 1.6998 continued-train
69af3001...0409 declared in card + index.json never published
989,099,518 bytes all three
metadata.epochs is 10 with val_loss null beside a card saying epoch 21 and 0.5597, so the declared one is the SOTA checkpoint and the published one is its predecessor. Nobody is stuck. But the ternary export cannot be re-derived from anything published, which is the one job checkpoint_sha256 has.
That size is not a weak signal, it is a constant. Two different runs landed on the same 989,099,518 and the declared third claims it too, because the tensor names, shapes and dtype are fixed by the architecture and only the values move. A byte count cannot separate those three even in principle.
Which is the argument for your fix #2, one file to the left. index.json already carries a checkpoint hash and it already disagrees with the blob beside it. The assets block is the counter-example in the same file: norms.f32 declares c236ddbc and embeddings.f16 declares bdf74048, and both match their blob exactly. Two of your three integrity fields work today. The third has never matched.
On the 168 dropped norms, my evidence was weak and your card supplies the rebuttal.
I said those per-projection norm.weight tensors "were trained" because no element sits at exactly 1.0. That does not hold up. AdamW at weight decay 0.1 moves every parameter off init whether or not it ever sees a gradient. At your schedule, batch 8, 21 epochs, cosine 5e-5 to 5e-6, I get about 0.86 for a parameter with no gradient at all. Observed mean is 0.8945 over 245,760 elements. Location proves nothing.
Spread does. Uniform multiplicative decay from a constant init maps ones to one number, with zero spread.
per-projection norm.weight, within-tensor sd
q 0.0319 k 0.0307 o 0.0281 v 0.0197
up 0.0148 gate 0.0140 down 0.0131
per-tensor means across the 168: 0.8619 .. 0.9797
q_proj mean-of-means 0.9431 down_proj 0.8824
All 168 have internal spread, and it is organised by projection type rather than by depth. The three attention projections carry roughly twice the MLP three, with v between. Decay cannot make that shape.
Then I checked the benign reading, that the norm is folded into the export's per-group scales and nothing is lost. It is not.
m000 = layers.23.mlp.up_proj, scales [4864 out][14 groups of 64 in]
mean group profile 1.0000 x 14 sd across rows 0.0002
norm group means 0.9962 .. 1.0047
Pearson r 0.117 (m002: 0.241)
The scales carry no structure on the input axis, which is the only axis the norm lives on. 4852 of 4864 rows have all 14 group scales identical, so group_size: 64 is nominal in this file and the norm is not in it anywhere.
Which leaves one thing I cannot settle from outside, and it is not the dilemma I posed last time.
Your card now says the Rust runner reproduces the forward to 1e-5, golden logits, identical argmax. The runner cannot see these tensors, the format has no slot for them. So the training forward is not using them either, and the card is self-consistent with itself and with your gate.
But then nothing in the deployed forward gave them that structure.
The card says continued-train, and the prior runs are 3.2862 and 11.34. If per-projection RMSNorm was live before deployed-forward QAT, these are frozen gains from that regime, decaying quietly through every run since, and 1.04 MB of the checkpoint is archaeology rather than weights. That would explain the shape and cost nothing.
Has crates/ternary ever read a per-projection gain, or has that path never existed?