voxsum-qwen35-0.8b-harness — the checkpoint the harness needs
Published in response to the VoxSumDroid field report of 2026-08-03, whose headline was
correct: the published harness could not be run against any published weights. The
harness prompts require a harness-trained checkpoint and only the one-shot v2 NOTES
fine-tune existed, so running them together reproduced exactly the failure
agentic/contract.py documents — correct content emitted as header-less bullets, discarded
by the parser, five empty sections after 50 minutes of compute.
Files
| file | size | notes |
|---|
voxsum-qwen35-0.8b-harness-Q4_K_M.gguf | 529 MB | for llama.cpp |
| safetensors + tokenizer | 1.5 GB | for reconversion |
Trained on the v2 contract — byte-identical to the published Prompts.kt. This matters:
an earlier checkpoint trained on the v1 contract emits the v2 worked examples (遙控器 /
淑芬 / 建宏) as though they were meeting content, in 4 of 5 sections. That checkpoint is not
published.
Verified before publishing
eval/verify_harness_ckpt.py, 6 held-out chunks, zh and en:
| check | result |
|---|
strict (Kotlin ^([A-Z]+):$) parseable | 6/6 |
| output only the tolerant parser could save | 0/6 |
| contract example leakage | 0/6 |
bullets carrying [m:ss] | 6/6 |
| anchors present in that chunk's own transcript | 6/6 |
The second row is the one that matters most, and it is why this gate exists. The Python
reference parser (agentic/harness.py::parse_notes) recovers header-less bullets into
SUMMARY; the Kotlin NotesParser did not. Evaluations run through the Python path therefore
scored output that yields nothing on device. That is the whole explanation for the
contradictory tables in the field report's §6.
MUST READ: two runtime requirements
1. Apply the chat template. MeetingAgent.generateBlocking(prompt, maxTokens) passes a
bare instruction. That is correct for .litertlm (the bundle carries its template and the
runtime applies it) and silently wrong for a direct llama.cpp tokenize — the model continues
the transcript instead of answering. Use --jinja, or wrap with the model's template
yourself. The field report lost a 49-minute device run to this.
2. Disable thinking, or read reasoning_content. Qwen3.5 emits its answer inside a
thinking block by default; message.content comes back empty and it looks like a failed
generation. Use --reasoning-format none on the server, or send
chat_template_kwargs: {"enable_thinking": false}, or fall back to reasoning_content
when content is empty. This cost a run during verification of this very checkpoint.
Honest performance note
This checkpoint did not beat single-pass in our testing. Judged on 12 stratified long
meetings with a teacher judge:
| configuration | inversions |
|---|
| shipped single-pass Qwen3.5-0.8B | 6.2% |
| this harness-trained checkpoint | 33.3% |
So it unblocks running the harness as designed, but the field report's own decision — keep
the harness architecture (chunking, typed memory, dedup, caps, deterministic merge) and
drive it with the app's v2 NOTES prompt per chunk — is better supported by the evidence than
the prompt set it replaces.
Use this checkpoint if you want the harness contract exactly as published. Use single-pass
prompts inside the harness architecture if you want the better measured result.
Eval table provenance (field report §6)
The two tables disagreed because they measure different things. Stating both precisely:
| source | checkpoint | mode | eval set | date | result |
|---|
HARNESS_README.md | single-pass 0.8B | harness prompts, Python tolerant parser | 16 meetings, pre-vcsum_full, unstratified | 2026-08-01 | faith 4.75, faith<=2 6.2% |
contract.py header | harness-trained 0.8B | harness prompts | 12 meetings, vcsum_full, 6 zh / 6 en | 2026-08-02 | 33.3% inversions |
The README row is not reproducible on device: it depended on the tolerant parser rescuing
header-less output. It is being removed rather than corrected, because the configuration it
describes does not work in the deployed runtime.