PR #83 — fix(quant): harden the campaign pipeline — wrong-name container races, an unproved token identity, and three silent-waste loops
Adversarial review of the whole qwen38-w5nl64 pipeline (convert → calib → kldref → score, plus the corpus builder/re-chunker/pusher and the fp8 stacker). Every fix below is a
defect that either destroys hours silently or produces a number that is not the number
claimed; cosmetics and style were left alone.
Stacks on #82 (both touch scripts/frank-archon.env's neighbourhood); merge #82 first.
Defects found and fixed
correctness — a KLD reference that scores different tokens than the corpus holds
rechunk-kld-corpus.py wrote each window as text (tok.decode(window)) and asserted only
window lengths, while its own docstring promises "a record's windows concatenate back to that
record's own token sequence, unchanged". Decode→encode is not identity in general, so the
reference could be recorded against a token sequence the parent corpus never held — and the KLD
gate's whole meaning is that both sides score the same positions. Now every window is
re-encoded and the tool refuses on any mismatch.
make-calib-corpus.py crashed the entire build on any .json in the repo that is not a
content-keyed JSONL: the "has a content key" test was a substring match on the raw line, and a
list-shaped document raised TypeError. Non-conforming lines are now skipped.
make-calib-corpus.py advanced the KLD cursor by 2 per consumed fragment, so half the KLD
pool was never used. Now +1.
silent waste — rounds that cannot finish, taps that cannot fill
calib-push.py looped up to --max-roundswithout ever checking that the tap grew. That is
exactly today's failure mode: a wrongly-pointed or read-only tap stops recording while the
engine keeps answering 200, and the driver re-pushes the whole 10 M-token corpus per round.
Now: bytes sealed per round are compared, a round with zero stored bytes aborts, and a round
with zero accepted prompts aborts.
calib-push.py divided by a possibly-zero elapsing time, hard-coded the served model id
(frank-archon) although the rig serves qwen4exp-qwen38-w5nl64, and recomputed the corpus'
char count every round. Fixed; --model and --tap-dir are now parameters.
races and false receipts — the runner and the converter
run-qwen38-bf16.sh's restore() started production without removing the rig container. --rm only fires when podman itself exits, so a killed run leaves conmon alive holding the
GPUs and the service reports active while its engine starves — measured today, and it needed
a manual podman rm -f qwen38-bf16. restore() now removes the container first.
run-qwen38-bf16.sh: the calib tap directory is now proven writable before the boot (a typo'd
path used to auto-create an empty dir and burn the run), and RADIANCE_CALIB_TOKENS is
overridable (it was a magic 12 M inside the argv).
run-qwen38-bf16.sh: the score's read-only-reference guard compared strings, so .../kld-ref/../kld-ref/x.json slipped past it and then mounted the reference dir writable.
Now also compared as resolved paths.
convert-qwen38-w5nl64.sh: --arm / --target-count with no value died on set -u's
"unbound variable"; an existing qwen38-convert-<arm> container (a killed run) was only
discovered after the plan phase; and a rad-convert that exited 0 without writing the
artifact produced an arithmetic error instead of a receipt failure. All three refuse early with
the fix named.
stack-qwen38-official-fp8.py: the verifier used bare assert, so python3 -O would have
skipped byte verification entirely; a PLE HD that the 128-lane pack cannot express was a
warning and the stack continued. Both are hard failures now.
speed — the corpus build
make-calib-corpus.py re-tokenized each fragment on every pass of a loop that cycles the pool
up to 40 times, and re-tokenized the entire KLD corpus a second time just to print kld_scored_positions. Counts are computed once per fragment and the scored total is
accumulated during generation.
Verification
./tests/run.sh — 576 tests, 0 failures (see the job log in the PR comment).
python3 -m py_compile on all four tools; bash -n on both scripts; shellcheck -S warning
clean for both scripts.
calib-push.py --help and an import-level exercise of the new tap_bytes() (empty dir → 0,
one 100-byte file → 100, absent dir → 0).
Not changed, on purpose
convert-qwen38-w5nl64.sh's expert_opts single-quoted $CALIB is correct: the recipe reader
expands it from the container environment (-e CALIB=/data/calib), which shellcheck cannot see.
The arms stay sequential: three concurrent converts would each write ~141 GiB against one
volume — the peak-disk law, not a bug.
Refactor (second commit)
The three corpus tools now share scripts/qwen38_common.py: tokenizer load, one n_tokens, JSONL read/write, atomic writer, refuse(). make-calib-corpus.py's
170-line main() with three nested closures is now classify / split_pools / fragment_text / build_frags / pack_class / emit_calib / emit_kld / manifest; rechunk-kld-corpus.py's main is validate / cut / rechunk around
a Window record, so the round-trip proof is one testable function; calib-push.py
grew parse_args / load_prompts / push_round.
Parity was measured on dankserver against the pre-refactor scripts at the same seed:
identical records in identical order for calib.jsonl and kld.jsonl, identical
manifest, byte-identical re-chunked corpus (md5 e824e67d3acbffe2b6cb2b1c50853457).
The only byte-level change is JSON escaping — write_jsonl emits literal UTF-8,
which the re-chunker already did; the parsed records do not move.
# PR #83 — fix(quant): harden the campaign pipeline — wrong-name container races, an unproved token identity, and three silent-waste loops
Adversarial review of the whole `qwen38-w5nl64` pipeline (`convert` → `calib` → `kldref` →
`score`, plus the corpus builder/re-chunker/pusher and the fp8 stacker). Every fix below is a
defect that either **destroys hours silently** or **produces a number that is not the number
claimed**; cosmetics and style were left alone.
**Stacks on #82** (both touch `scripts/frank-archon.env`'s neighbourhood); merge #82 first.
## Defects found and fixed
### correctness — a KLD reference that scores different tokens than the corpus holds
- `rechunk-kld-corpus.py` wrote each window as **text** (`tok.decode(window)`) and asserted only
window lengths, while its own docstring promises "a record's windows concatenate back to that
record's own token sequence, unchanged". Decode→encode is not identity in general, so the
reference could be recorded against a token sequence the parent corpus never held — and the KLD
gate's whole meaning is that both sides score *the same positions*. Now every window is
re-encoded and the tool refuses on any mismatch.
- `make-calib-corpus.py` crashed the entire build on any `.json` in the repo that is not a
content-keyed JSONL: the "has a content key" test was a substring match on the raw line, and a
list-shaped document raised `TypeError`. Non-conforming lines are now skipped.
- `make-calib-corpus.py` advanced the KLD cursor by **2** per consumed fragment, so half the KLD
pool was never used. Now `+1`.
### silent waste — rounds that cannot finish, taps that cannot fill
- `calib-push.py` looped up to `--max-rounds` **without ever checking that the tap grew**. That is
exactly today's failure mode: a wrongly-pointed or read-only tap stops recording while the
engine keeps answering 200, and the driver re-pushes the whole 10 M-token corpus per round.
Now: bytes sealed per round are compared, a round with zero stored bytes aborts, and a round
with zero accepted prompts aborts.
- `calib-push.py` divided by a possibly-zero elapsing time, hard-coded the served model id
(`frank-archon`) although the rig serves `qwen4exp-qwen38-w5nl64`, and recomputed the corpus'
char count every round. Fixed; `--model` and `--tap-dir` are now parameters.
### races and false receipts — the runner and the converter
- `run-qwen38-bf16.sh`'s `restore()` started production **without removing the rig container**.
`--rm` only fires when podman itself exits, so a killed run leaves conmon alive holding the
GPUs and the service reports `active` while its engine starves — measured today, and it needed
a manual `podman rm -f qwen38-bf16`. `restore()` now removes the container first.
- `run-qwen38-bf16.sh`: the calib tap directory is now proven writable before the boot (a typo'd
path used to auto-create an empty dir and burn the run), and `RADIANCE_CALIB_TOKENS` is
overridable (it was a magic 12 M inside the argv).
- `run-qwen38-bf16.sh`: the score's read-only-reference guard compared strings, so
`.../kld-ref/../kld-ref/x.json` slipped past it and then mounted the reference dir writable.
Now also compared as resolved paths.
- `convert-qwen38-w5nl64.sh`: `--arm` / `--target-count` with no value died on `set -u`'s
"unbound variable"; an existing `qwen38-convert-<arm>` container (a killed run) was only
discovered *after* the plan phase; and a `rad-convert` that exited 0 without writing the
artifact produced an arithmetic error instead of a receipt failure. All three refuse early with
the fix named.
- `stack-qwen38-official-fp8.py`: the verifier used bare `assert`, so `python3 -O` would have
skipped byte verification entirely; a PLE `HD` that the 128-lane pack cannot express was a
warning and the stack continued. Both are hard failures now.
### speed — the corpus build
- `make-calib-corpus.py` re-tokenized each fragment on every pass of a loop that cycles the pool
up to 40 times, and re-tokenized the entire KLD corpus a second time just to print
`kld_scored_positions`. Counts are computed once per fragment and the scored total is
accumulated during generation.
## Verification
- `./tests/run.sh` — 576 tests, 0 failures (see the job log in the PR comment).
- `python3 -m py_compile` on all four tools; `bash -n` on both scripts; `shellcheck -S warning`
clean for both scripts.
- `calib-push.py --help` and an import-level exercise of the new `tap_bytes()` (empty dir → 0,
one 100-byte file → 100, absent dir → 0).
## Not changed, on purpose
- `convert-qwen38-w5nl64.sh`'s `expert_opts` single-quoted `$CALIB` is correct: the recipe reader
expands it from the container environment (`-e CALIB=/data/calib`), which shellcheck cannot see.
- The arms stay sequential: three concurrent converts would each write ~141 GiB against one
volume — the peak-disk law, not a bug.
## Refactor (second commit)
The three corpus tools now share `scripts/qwen38_common.py`: tokenizer load, one
`n_tokens`, JSONL read/write, atomic writer, `refuse()`. `make-calib-corpus.py`'s
170-line `main()` with three nested closures is now `classify` / `split_pools` /
`fragment_text` / `build_frags` / `pack_class` / `emit_calib` / `emit_kld` /
`manifest`; `rechunk-kld-corpus.py`'s `main` is `validate` / `cut` / `rechunk` around
a `Window` record, so the round-trip proof is one testable function; `calib-push.py`
grew `parse_args` / `load_prompts` / `push_round`.
Parity was measured on dankserver against the pre-refactor scripts at the same seed:
identical records in identical order for `calib.jsonl` and `kld.jsonl`, identical
manifest, byte-identical re-chunked corpus (md5 `e824e67d3acbffe2b6cb2b1c50853457`).
The only byte-level change is JSON escaping — `write_jsonl` emits literal UTF-8,
which the re-chunker already did; the parsed records do not move.
---
cwd: /home/blank/.omp/wt/wt-20261027-142335-6d1fc1f · session: 01a17f3f-3e2e-7509-aef8-be516c27cf98
PR #81's pool half measured inert the day it deployed: the 66,560 boot printed the
same elastic 26.73 GiB / experts 20.72 / kv cache 5.64 / vram_weights 24.30 as the
49,152 boot and opened the pool with 0 B used, and the qwen38-w5nl64 rig moved
vram_kv 269.99 -> 271.25 MiB (window still 7,436 tokens: its 95.37 GiB n-gram table
claim decides, not the pool). The step half stays. Tests: 576 ok / 0 fail.
Adversarial review of the campaign pipeline. Correctness: rechunk-kld-corpus.py wrote
each window as text and asserted only lengths, so a KLD reference could score a
different token sequence than the corpus holds — every window is now re-encoded and
the tool refuses on mismatch; make-calib-corpus.py no longer crashes on a .json that
is not a content-keyed JSONL, and its KLD cursor advanced by 2 per fragment (half the
pool unused). Silent waste: calib-push.py now aborts when the tap sealed nothing or
no prompt was accepted, instead of re-pushing 10M tokens per round; div-by-zero gone,
served model id parameterised. Races: run-qwen38-bf16.sh restore() removes the rig
container before starting production (today's orphan held the GPUs while the service
reported active), the calib tap dir is proven writable, the score ro-guard resolves
paths; convert-qwen38-w5nl64.sh refuses a missing --arm value, an existing
qwen38-convert-<arm> container, and a zero-exit convert that wrote no artifact.
stack-qwen38-official-fp8.py: bare asserts in verify() (skipped under -O) and a
non-128-lane PLE HD that only warned are hard failures. Speed: fragment token counts
computed once, KLD scored positions accumulated instead of a second full re-encode.
Tests: 576 ok / 0 fail.
dank
changed title from fix(quant): harden the campaign pipeline — token identity, tap progress, runner races to fix(quant): harden the campaign pipeline, then refactor its corpus tools onto one module2026-10-29 15:26:08 -07:00
The three corpus tools now share scripts/qwen38_common.py: tokenizer load with the
venv guidance, one n_tokens (so a KLD count cannot drift from the corpus it scores),
JSONL read/write, an atomic writer, and refuse(). make-calib-corpus.py's 170-line
main() with three nested closures became classify / split_pools / fragment_text /
build_frags / pack_class / emit_calib / emit_kld / manifest; its magic numbers are
named constants. rechunk-kld-corpus.py's main became validate / cut / rechunk around
a Window record, so the round-trip proof sits in one function that can be tested
without a tokenizer. calib-push.py grew parse_args / load_prompts / push_round, and
a malformed corpus now refuses with a line number instead of raising KeyError.
Parity, measured on dankserver against the pre-refactor scripts at the same seed:
calib.jsonl and kld.jsonl carry identical records in identical order, the manifest
is identical, and the re-chunked corpus is byte-identical (md5 e824e67d...). The one
byte-level change is JSON escaping — write_jsonl emits literal UTF-8, which is what
the re-chunker already wrote; the parsed records do not move.
dank
merged commit da5eb968f9 into main2026-10-29 15:29:34 -07:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
PR #83 — fix(quant): harden the campaign pipeline — wrong-name container races, an unproved token identity, and three silent-waste loops
Adversarial review of the whole
qwen38-w5nl64pipeline (convert→calib→kldref→score, plus the corpus builder/re-chunker/pusher and the fp8 stacker). Every fix below is adefect that either destroys hours silently or produces a number that is not the number
claimed; cosmetics and style were left alone.
Stacks on #82 (both touch
scripts/frank-archon.env's neighbourhood); merge #82 first.Defects found and fixed
correctness — a KLD reference that scores different tokens than the corpus holds
rechunk-kld-corpus.pywrote each window as text (tok.decode(window)) and asserted onlywindow lengths, while its own docstring promises "a record's windows concatenate back to that
record's own token sequence, unchanged". Decode→encode is not identity in general, so the
reference could be recorded against a token sequence the parent corpus never held — and the KLD
gate's whole meaning is that both sides score the same positions. Now every window is
re-encoded and the tool refuses on any mismatch.
make-calib-corpus.pycrashed the entire build on any.jsonin the repo that is not acontent-keyed JSONL: the "has a content key" test was a substring match on the raw line, and a
list-shaped document raised
TypeError. Non-conforming lines are now skipped.make-calib-corpus.pyadvanced the KLD cursor by 2 per consumed fragment, so half the KLDpool was never used. Now
+1.silent waste — rounds that cannot finish, taps that cannot fill
calib-push.pylooped up to--max-roundswithout ever checking that the tap grew. That isexactly today's failure mode: a wrongly-pointed or read-only tap stops recording while the
engine keeps answering 200, and the driver re-pushes the whole 10 M-token corpus per round.
Now: bytes sealed per round are compared, a round with zero stored bytes aborts, and a round
with zero accepted prompts aborts.
calib-push.pydivided by a possibly-zero elapsing time, hard-coded the served model id(
frank-archon) although the rig servesqwen4exp-qwen38-w5nl64, and recomputed the corpus'char count every round. Fixed;
--modeland--tap-dirare now parameters.races and false receipts — the runner and the converter
run-qwen38-bf16.sh'srestore()started production without removing the rig container.--rmonly fires when podman itself exits, so a killed run leaves conmon alive holding theGPUs and the service reports
activewhile its engine starves — measured today, and it neededa manual
podman rm -f qwen38-bf16.restore()now removes the container first.run-qwen38-bf16.sh: the calib tap directory is now proven writable before the boot (a typo'dpath used to auto-create an empty dir and burn the run), and
RADIANCE_CALIB_TOKENSisoverridable (it was a magic 12 M inside the argv).
run-qwen38-bf16.sh: the score's read-only-reference guard compared strings, so.../kld-ref/../kld-ref/x.jsonslipped past it and then mounted the reference dir writable.Now also compared as resolved paths.
convert-qwen38-w5nl64.sh:--arm/--target-countwith no value died onset -u's"unbound variable"; an existing
qwen38-convert-<arm>container (a killed run) was onlydiscovered after the plan phase; and a
rad-convertthat exited 0 without writing theartifact produced an arithmetic error instead of a receipt failure. All three refuse early with
the fix named.
stack-qwen38-official-fp8.py: the verifier used bareassert, sopython3 -Owould haveskipped byte verification entirely; a PLE
HDthat the 128-lane pack cannot express was awarning and the stack continued. Both are hard failures now.
speed — the corpus build
make-calib-corpus.pyre-tokenized each fragment on every pass of a loop that cycles the poolup to 40 times, and re-tokenized the entire KLD corpus a second time just to print
kld_scored_positions. Counts are computed once per fragment and the scored total isaccumulated during generation.
Verification
./tests/run.sh— 576 tests, 0 failures (see the job log in the PR comment).python3 -m py_compileon all four tools;bash -non both scripts;shellcheck -S warningclean for both scripts.
calib-push.py --helpand an import-level exercise of the newtap_bytes()(empty dir → 0,one 100-byte file → 100, absent dir → 0).
Not changed, on purpose
convert-qwen38-w5nl64.sh'sexpert_optssingle-quoted$CALIBis correct: the recipe readerexpands it from the container environment (
-e CALIB=/data/calib), which shellcheck cannot see.volume — the peak-disk law, not a bug.
Refactor (second commit)
The three corpus tools now share
scripts/qwen38_common.py: tokenizer load, onen_tokens, JSONL read/write, atomic writer,refuse().make-calib-corpus.py's170-line
main()with three nested closures is nowclassify/split_pools/fragment_text/build_frags/pack_class/emit_calib/emit_kld/manifest;rechunk-kld-corpus.py'smainisvalidate/cut/rechunkarounda
Windowrecord, so the round-trip proof is one testable function;calib-push.pygrew
parse_args/load_prompts/push_round.Parity was measured on dankserver against the pre-refactor scripts at the same seed:
identical records in identical order for
calib.jsonlandkld.jsonl, identicalmanifest, byte-identical re-chunked corpus (md5
e824e67d3acbffe2b6cb2b1c50853457).The only byte-level change is JSON escaping —
write_jsonlemits literal UTF-8,which the re-chunker already did; the parsed records do not move.
cwd: /home/blank/.omp/wt/wt-20261027-142335-6d1fc1f · session: 01a17f3f-3e2e-7509-aef8-be516c27cf98
fix(quant): harden the campaign pipeline — token identity, tap progress, runner racesto fix(quant): harden the campaign pipeline, then refactor its corpus tools onto one module