The 2026-10-09 wire aliases become the service names everywhere: systemd units, serve scripts, env files and FRANK_* variables, deploy-plan/deploy-remote service keys, container names, Prometheus job names + alert rules, Grafana dashboard queries, bats seams, runbook filenames, homepage/AGENTS lore, and historical prose. Rollback tags renamed in lockstep. Residue in the tree: zero. Retired frank-medium/small/npu names are history and stay. Known casualty: scripts/patches/*.patch context lines were rewritten; those retired-era vLLM-fork patches no longer apply byte-exact.
12 KiB
type, title, description, tags, timestamp
| type | title | description | tags | timestamp | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| reference | frank-dragoon on Dankclaw — ROCmFPX llama.cpp, Qwen3.8-27B Q8_0_ROCMFPX_AGENT + MTP (retired) | The retired frank-dragoon runbook — the kingjones30/ROCmFPX llama.cpp fork (pinned commit, gfx1151) serving kingjones777's Q8_0_ROCMFPX_AGENT GGUF, a ftype-115 file no other loader can read, with the repo's own MTP-Q4_0 head, f16 KV, and the BF16 projector. Measured MTP-vs-none A/B, the client contract, and the rollback state as of 2026-10-03. |
|
2026-10-02 |
frank-dragoon — ROCmFPX Q8_0_ROCMFPX_AGENT + MTP (gfx1151, retired)
RETIRED 2026-10-03 — superseded by frank-dragoon-rocmfpx-q6agent-uncensored-mtp: Frank swapped to the uncensored Q6_0_ROCMFPX_AGENT file (protected heads, one rung down), which measures 27.6–28.1 t/s at a deeper prompt than this file's 17.0. This runbook stays live as the rollback reference and the trap catalogue; the payload it documents remains on disk at
/home/dank/models/kingjones-Qwen3.8-27B-ROCmFP4-STRIX-MTP/.Cut over 2026-10-02 from frank-dragoon-gufo-qwen38-27b (Q4_K_XL, ~15 t/s) on two requests from Frank: highest quality that runs, and one full context. It delivered 8.39 bpw weights — two quant rungs above what gufo could load — at 17.0 t/s, so quality was not bought with speed.
The capability that forced this whole shape is a GGUF tensor type:
GGML_TYPE_Q8_0_ROCMFPX(103). It exists in exactly one loader on this host, so the runtime was decided by the file, not by preference.
Identity
| Host / device | Dankclaw (192.168.0.143), Radeon 8060S iGPU gfx1151, ~114 GiB GTT aperture |
| Endpoint | http://192.168.0.143:7770 — alias frank-dragoon, /v1 OpenAI surface |
| Runtime | kingjones30/ROCmFPX llama.cpp fork @ 36e9acd40e10a87cd3c3ef8ec734668757dc8520, built by scripts/build-rocmfpx.sh → /home/dank/GitPackages/kingjones-ROCmFPX/build/bin/llama-server |
| Unit | root systemd frank-dragoon.service (scripts/frank-dragoon.service), User=dank, Restart=always |
| Serve script | scripts/serve-frank-dragoon.sh (owns the argv), tunables scripts/frank-dragoon.env |
| Weights | /home/dank/models/kingjones-Qwen3.8-27B-ROCmFP4-STRIX-MTP/Qwen3.8-27B-Q8_0_ROCMFPX_AGENT.gguf — 28,214,425,952 B, sha256 f3ef2bdbf56e244f… |
| Draft | …/mtp-Qwen3.8-27B-Q4_0.gguf — 1,680,271,648 B, sha256 051a1764cff8c4f3… |
| Projector | …/mmproj-Qwen3.8-27B-BF16.gguf — 931,145,888 B, sha256 de2a4986… |
| Fetch | scripts/download-frank-dragoon-kingjones.sh (-f, byte-count + LFS sha256 verified, --verify-only, token never on the command line) |
| Seam | tests/frank_dragoon_unit.bats (19 tests: payload gates, deployer/serve parity, spec block, KV dtype, sweep identity) |
Why this file, and why only this runtime
kingjones777/Qwen3.8-27B-ROCmFP4-STRIX-MTP-GGUF ships several rungs. Parsed
headers of the two candidates:
| File | ftype | Tensor mix | Output-head tensors at plain Q8_0 | Card MTP acceptance |
|---|---|---|---|---|
Qwen3.8-27B-Q8_0_ROCMFPX_AGENT.gguf |
115 | 353 F32 + 187 Q8_0 + 311 type-103 | 187 | 0.953 |
Qwen3.8-27B-Q8_0_ROCMFPX.gguf |
111 | 2 Q8_0 + type-103 | 2 | 0.911 |
Two consequences, both measured off the header rather than guessed:
- Quality. The AGENT routing variant keeps the output-head (and other routing-sensitive) tensors at plain Q8_0 instead of folding them into the ROCmFPX kernel layout — 187 vs 2 — so the logits the sampler reads are the highest-precision tensors in the file. It is also the card's MTP-tuned variant, so it is the faster drafter base at the same time.
- The runtime is forced. Type 103 is a private extension: stock llama.cpp
and gufo both fail at load (
unknown tensor type). Verified on the host before deploying — the bake-off was not a horse race, it was a lock-in check.
The build identity matters as much as the fork. The 2026-08-25 ROCmFPX
builds read this file and then died in ggml_compute_forward_set_rows — the
exact failure documented in kingjones-q8agent-rocmfpx when this payload was
first attempted on Dankclaw and routed to Dankserver as
frank-medium-rocmfpx instead. scripts/build-rocmfpx.sh therefore checks
the commit out by SHA and refuses to build anything else; the pin is
load-bearing, not tidiness.
Shape and budget
One session, the model's full native window, unquantized KV:
| Dial | Value | Why |
|---|---|---|
--ctx-size |
262,144 | "one full context" — the native window, no rope scaling |
--parallel |
1 | one conversation, all memory to it |
| KV dtype | f16 (both K and V) | ~64 KiB/token → ~16 GiB; free inside a 114 GiB aperture, so there is no reason to pay a quant |
--fit off |
on | the auto-fitter would silently resize the window we asked for |
--flash-attn on |
on | required for the long-window attention path to fit |
--direct-io |
on | bypasses page cache for the 26 GiB weight stream (mmap is disabled by it — deliberate) |
--ctx-checkpoints 16 |
16 | slot state for checkpoint/rollback |
--cache-ram 8192 + --cache-idle-slots |
8 GiB | prompt cache; verified a repeat pass over the same 6k prompt replays in 0.5 s |
--jinja |
on | without it chat_template_kwargs are silently ignored |
--reasoning on --reasoning-format deepseek --reasoning-budget -1 |
thinking in its own channel, unbounded |
Measured steady state (production, one model copy resident):
mem_info_gtt_used 63.1 GiB of the ~114 GiB aperture, mem_info_vram_used
0.17 / 2.0 GiB (the iGPU's dedicated carve-out is a stub; everything real lives
in GTT). llama-server RSS 2.1 GiB. Boot to /health 200: 16 s — the fastest
endpoint bring-up in the fleet, because there is no engine compile step.
Speculative decode — measured, not assumed
--spec-type draft-mtp --model-draft <mtp-Qwen3.8-27B-Q4_0.gguf>
--spec-draft-n-max 4 --spec-draft-n-min 0 --spec-draft-p-min 0.0
--spec-draft-device ROCm0 --spec-draft-ngl 99
MTP in llama.cpp is a property of the file, not of the flags: the head is a
trained tensor set (nextn_predict_layers = 1 in this repo's head, arch
qwen35, 65 blocks) and the draft context runs on the main model's weights, so
there is no second 26 GiB copy in memory. See the fleet law in
AGENTS.md → llama.cpp serving.
A/B, 2026-10-02 — same session, temp 0, 2,202-token prompt, 512 tokens,
cache_prompt: false, frank-dragoon.service stopped for every scratch arm (the
benchmarking law), baseline arm stripped of --model-draft and every
--spec-* flag:
| Arm | Decode t/s (2 runs) | Prefill t/s | Draft acceptance |
|---|---|---|---|
| MTP, n-max 4 (deployed) | 17.00 / 17.14 | 350.6 / 324.9 | 0.462 (mean acceptance length ≈ 1.86) |
| no draft | 7.60 / 7.66 | 381.8 / 381.0 | — |
+123 % decode for an 8–15 % prefill tax. Notes that matter before someone re-litigates this:
- Acceptance here (0.462) is nowhere near the card's 0.953. The card measures its own short, repetitive text; this is a 2.2k-token prose prompt. Treat the card's number as a file property, not a throughput promise.
n-max 4is where the gain was measured; 2 and 8 are unmeasured. The gufo-era law applies in spirit — never rank spec settings on a self-predictable corpus.- End-to-end on the chat path is slower than the
/completionnumber because thinking tokens are included: a 2,253-token chat prompt generating 512 tokens took 43.8 s wall (11.7 t/s end-to-end) — that is the cost of an unbounded reasoning budget, not a regression in decoding.
Client contract (live-verified 2026-10-02)
| Behavior | Observation |
|---|---|
| Model id | /v1/models → frank-dragoon |
| Tools | native: get_weather → {"city": "Seattle"} in tool_calls |
| Thinking | in reasoning_content (llama.cpp field — not vLLM's reasoning); models.yml sets reasoningContentField accordingly |
reasoning_effort |
accepts only xhigh, medium, low; anything else is HTTP 500 (the template raises, it does not clamp). models.yml folds high/max → xhigh |
| Sampling | server defaults = the card's thinking recipe (temp 1.0, top_p 0.95, top_k 20, min_p 0, presence 0), mirrored in the harness extraBody |
| Vision | the BF16 projector loads (loaded multimodal model); a red square answers Red (usage: 75 prompt / 71 cached) |
| Prompt cache | second pass over the same 6k prompt: 0.5 s wall |
Three traps, all hit for real:
content: nullwhen reasoning eats the budget. With--reasoning-parser-style separation, a request whosemax_tokensis consumed entirely by thinking returnsmessage.content = None. A bench client that indexescontentcrashes after measuring and loses the numbers — fall back toreasoning_content, or size the budget (200 was enough for the vision probe).MTP boundary missing for seq_id=… ; resyncing after a non-token stepappears in the log under draft resets. Self-recovering; not an outage signal.- Never
pkill -f llama-serveron Dankclaw — frank-zealot is also allama-server. The sweep key here is the payload name:pkill -f 'Qwen3.8-27B-Q8_0_ROCMFPX_AGENT'.
Operations
# deploy (planner selects this endpoint only via its own unit/env/serve trio)
./scripts/deploy.sh dankclaw --service frank-dragoon
# status / logs / cause of a crash loop
systemctl status frank-dragoon
journalctl -u frank-dragoon -n 200 --no-pager
# rebuild the pinned fork (only when deliberately moving the pin)
scripts/build-rocmfpx.sh
# re-verify the payload without re-downloading
scripts/download-frank-dragoon-kingjones.sh --verify-only
serve-frank-dragoon.sh refuses to start — before touching the port — unless the
fork binary, the weights, the MTP head and (unless FRANK_DRAGOON_MMPROJ="") the
projector all exist; scripts/deploy-remote.sh mirrors the same predicate so a
broken payload never stops the running unit. Caller environment overrides
frank-dragoon.env, and defaults use := so an explicitly empty value surfaces
as the error it reads as.
Rollback (as of retirement, 2026-10-03)
Primary rollback: the ALIGNED Q8 file itself is the previous shape's
payload and remains on disk at
/home/dank/models/kingjones-Qwen3.8-27B-ROCmFP4-STRIX-MTP/ — revert the
2026-10-03 swap commit (unit/env/serve trio) or repoint
FRANK_DRAGOON_MODEL_FILE/LLM_DRAGOON_MODEL_FILE, verify with
scripts/download-frank-dragoon-kingjones.sh --verify-only, redeploy.
git tag frank-dragoon-gufo-q4kxl-20261001 (gufo v0.1.1, Q4_K_XL +
DFlash2) is now a re-download rollback: the gufo payloads
/home/dank/models/Qwen3.8-27B-UD-Q4_K_XL/ (16.35 GiB) and
/home/dank/models/Qwen3.8-27B-UD-Q8_K_XL/ (incl. the DFlash2 drafter) were
removed from disk on 2026-10-03 with Frank's explicit approval to free space.
scripts/build-gufo.sh remains on disk; re-fetch per
frank-dragoon-gufo-qwen38-27b.
The one-day vLLM MiMo era's payloads (MiMo-V2.6 BF16 18 GiB,
Qwen3.5-9B MTP source 19 GiB, both DFlash draft dirs) were staged to
/home/dank/.AGENTTRASH/20261002-retired-llm-payloads/ on 2026-10-02 —
recoverable until the trash is purged, and never part of a rollback plan.
When it misbehaves
unknown tensor type/ ftype 115 refused — something moved off the ROCmFPX binary. Checkreadlink -f $(systemctl show frank-dragoon -p ExecStart)and the fork commit; this file cannot run on stock llama.cpp or gufo.- SIGSEGV in
ggml_compute_forward_set_rowsduring load — a fork build older than the36e9acdpin; rebuild withscripts/build-rocmfpx.sh. History: kingjones-q8agent-rocmfpx. - Slow decode with no log error — check whether the draft is engaged
(
/metrics,draft_n/draft_n_accepted; a zero draft count means the head did not load), and check GTT pressure withcat /sys/class/drm/card1/device/mem_info_gtt_used— a second resident copy of this model (an orphaned scratch server) drives the whole host into eviction and halves the rate silently. 500naming Jinja — achat_template_kwargsfield reached a server without--jinja.- HTTP 500 naming the template on the first request of a role — an
unmapped
reasoning_effort; fix the fold inmodels.yml, not the model.