round 39: port serving fixes and PLE reuse; verify parity, record perf uncertainty
367 unmodified linesExpand all368369370371372372373374375376377443 unmodified linesExpand all367 unmodified linesExpand all 34. **Round 35 `Wr`/`Wr2` Router Dequant Reuse (`-47` Dispatches/Chunk) + `gemm_f16_16_96_2` `Walbe` + `M % 128 <= 64` `64_128_4` (`1.14x` @ `M = 306`) + `hc_up_tile` Row-Tail Trim (`-2.5%` @ `T = 289`) + `mtp_rms_xprep` / `mtp_embed` / `mtp_slop_pen` Vectorization (`audits/opus_r35_dense.md`, `audits/sol_r35_prompt.md`, `audits/argon_r35_mtp.md`):** Ping-ponged `p.Wr` and `p.Wr2` by layer parity (`l & 1`) in `Window::prompt_chunk` (`window.cpp`), eliminating **`47` redundant `dq_f16_0` router dequantizations per chunk (`2,094 -> 2,047` dispatches in `kprof`)**, added `gemm_f16_16_96_2` (`TN = 96`) for `Walbe` at `M >= 640` (**`1.16x` / `-13.6%` faster at `M = 1983`**), selected `64_128_4` instead of `128_64_4` on big-N GEMMs when `M < 1536 && M % 128 in 1..64` (**`1.14x` / `-23.5 ms` faster chunk total at `M = 306`**), added `hc_up_tile<16/32, TN, SG, REG>` row-tail trimming to `gemm_hc_up` (**`-2.5%` at `T = 289`**), and vectorized/unrolled `mtp_rms_xprep` (**`-37.5%` at `n=2560`, `-35.8%` at `n=10240`**), `mtp_embed` (**`-15.8%..-31.6%` across all 13 GGUF formats**), `mtp_slop_pen` (**`-96.5%` on `mode=0`, `-45.7%..-70.6%` on `mode=1`, `-31.0%..-63.9%` on `mode=2`**), and `router_route` (**`-0.2%..-2.1%`**) (`100%` bitwise `PASS` across all suites!). 35. **Round 36 Decode `predL_` / `predL2_` Token-0 Fast Path When `STRATA_METAL_PREFETCH_DRAFT <= 0` (`-16.0%` Hot / `-6.8%` Cold Across `93` Router GEMVs/Window) + Guarded `TM > 32` Row-Tail Trimming in `gemm_hc_down` & `gemm_swiglu_up` (`audits/opus_r36_decode.md`, `audits/sol_r36_prompt.md`, `audits/argon_r36_qsa.md`):** Added `tile_ntok` to `Window::gemv` (`window.cpp`) so when `STRATA_METAL_PREFETCH_DRAFT <= 0` (`= 0` in production, where `ExpertStream::ahead` only reads `t = 0`), the `93` router-guess GEMVs (`47` `predL_` + `46` `predL2_`, `Q8_0` `2560 -> 512`) run at `ntok = 1` on the window's tile (`gemv_8_16_1_4_1#1`), producing **100% bit-for-bit-identical `t = 0` predictions** while cutting their GPU time by **`-16.0%` hot (`21.78 -> 18.30 us`) and `-6.8%` cold (`23.91 -> 22.29 us`)**; added `if constexpr (TM > 32)` row-tail (`TM = 16 / 32`) trimming to `gemm_hc_down` (**`-4.71%` at `T=1025`, `-3.73%` at `T=1041`**) and `gemm_swiglu_up` (**`-1.42%` at `T=1025`, `-1.14%` at `T=1041`, `-0.78%` at `T=1987`**) while preserving `TM = 32` (`SG = 2`) kernels byte-for-byte (`252/252` `epi` bitwise checks `PASS`); and confirmed `qsa_prep` / `qsa_score_mm` are at their M5 register/barrier optimum. 36. **Round 37 Multi-Chunk Prompt Hot-Expert LRU & Scratch Pool Preservation (`stream.h`, `stream.cpp`, `window.cpp`):** Passed `multi_chunk = (n > C)` into `prompt_region(true, n > C)` -> `hold_region(true, multi_chunk)` so 1-chunk prompts (`<= 2,048` tokens) run 100% identically (`42.49 tok/s` / `2,989.17 ms` `@2K` decode — new all-time record, `88.9%` accept), while multi-chunk prompts (`> 2,048` tokens, e.g., `prompt_albedo_11k.txt` at `10,180` tokens) keep `!x.hot` scratch slots at `lru_back(s)` across chunks, mark `pass == 1` demotions `x.hot = false` in `victim()` so `pass == 0` reuses them instead of evicting more `hot` decode experts, and restrict `allow_hot` lookahead to `distance == 1` — boosting `@10.2K` decode from `25.26 tok/s` (`1,227.18 ms`, `45.2%` accept, `2,713` SSD reads) to **`34.01–34.74 tok/s` (`892.47–911.51 ms`, `+34.6–37.5%` faster, `78.3%` accept, `2,073` SSD reads / `-23.6%` fewer SSD reads)** and `@10.2K` prefill from `423.48 tok/s` (`24,038.85 ms`) to **`458.34–472.89 tok/s` (`21,527–22,210 ms`, `-1.83s to -2.51s` faster)**, with pure GPU `T=1983` prefill (`kprof`) hitting **`3,131.29 ms` (`633.28 tok/s` — new all-time record)**. 37. **Round 38 `hold_region` Layer-0 `allow_hot = false` + Prompt/Decode `bytes_read_`/`reads_` Split + `mtp_prefill` `tail_cap` Sync with `STRATA_METAL_MTP_WIN` (`stream.h`, `stream.cpp`, `window.cpp`, `audits/astra_r38_qsa.md`):** Passed `allow_hot = false` to `victim()` during `hold_region(true)`'s initial Layer-0 prefetch (`stream.cpp:1080`) and fallback static lookahead (`stream.cpp:890`) so `hold_region` only fills the `251` `!hot` scratch slots of `cls_[0]` (`IQ2_XXS`) instead of evicting `~180` `hot` decode experts for tail Layer-0 experts that `at_layer(0)` cancels 5 ms later; split `p_bytes_read_`/`p_reads_` from decode `bytes_read_`/`reads_` and zeroed `bytes_read_`/`reads_` after the `6.5 GB` startup arena fill (`fixing the 1-window prefill tail report from 116,128.9 MB / 79,058 reads to the exact 375.2 MB / 258 reads`); synced `Window::mtp_prefill`'s default `tail_cap` with `STRATA_METAL_MTP_WIN` clamped to `[64, 2050]`; and verified in `qsa_parity --ab` (`audits/astra_r38_qsa.md`) that caching `keys[8]` across `qsa_topk2`'s 1024-thread barriers drops M5 occupancy (`+3.5–12.9%` slower at `pos0 = 10180`), pushing `@10.2K` prefill to **`473.80 tok/s` (`21,485.94 ms` — new all-time record!)**, `@10.2K` decode to **`35.21–35.47 tok/s` (`873.92–880.47 ms`, `mtp_ms = 106.34 ms` — new all-time record!)**, `@2K` `prompt_2048tok_ops` decode to **`42.57 tok/s` (`2,982.99 ms`, `mtp_ms = 194.09 ms` — new all-time record!)**, and `reasoning` decode to **`37.20 tok/s` (`5,886.81 ms` — new all-time record!)**. 38. **round 39 — selected strata v0.1.45 ports and checked local fixes:** incremental prompt tokenization, bounded parser scans, content-keyed logit-bias caching, mac telemetry, thinking budgets/answer reservation, and PLE prefetch-key reuse (`36381540`). local review removed upstream's stale identity/length bias shortcut, capped prompt-cache entries at 16, and cached/released the telemetry device query. preserved the text-only image-omission switch. metal prompt load safety and the default moe parity tile are fixed; the local `qsa_merge2` batching experiment is bitwise exact (40 edge cases), but **only tests dispatch it; live engine decode remains on `qsa_merge`**. rejected the cuda score butterfly (memcmp failure) and `qsa_merge` batching (repeatable nt=3 slowdown). active-chunk bounds were already present. standalone CLI smoke: 42.46 tok/s at 1,984 prompt tokens and 34.23 tok/s at 10,180; these are **not paired speedup evidence**. a later alternating before/after check produced identical token IDs in all five pairs, but substantial temporal drift in both builds left performance inconclusive (2k candidate decode time +1.5–1.7%; 10k mixed -3.6% to +2.8%). no zero-regression claim. serving now enables upstream `answer_room` by default (for thinking with output caps >=1,024 and no explicit budget), which can inject a wrap-up instruction; disable it explicitly for parity comparisons to prior service behavior. exact verification and known baseline failures: `audits/r39_integration.md`, `audits/r39_serve.md`, `audits/r39_opus_review.md`; evidence: `results/round39/`. 38. **Measured End-to-End Speed (`32K` Context, `6.5 GB` Arena, Unpruned `K=512` `IQ2_XS`, `call_3817687`, `call_2483052`, `call_3102851`, `call_2898988`, `call_4110683`, `call_4178375`, `call_3948986`, `call_4500449`, `call_3444931`, `call_3116575`, `call_4373130`, `call_2769318`, `call_3781775`, `call_4410602`, `call_3511955`, `call_4432071`, `call_2918543`, `call_1514614`, `call_1173886`, `call_2456120`, `call_5024768`, `call_4223761`, `call_3543222`, `call_1624568`, `call_3678353`, `call_4256391`, `call_3418394` & `call_3706633`):** `prompt_2048tok_ops` prefill **`400.88–432.78 tok/s` (`4,584.29–4,949.14 ms` end-to-end — all-time record `4,584.29 ms` / `432.78 tok/s` — `-1,728 ms` / `+37.7%` faster end-to-end, **`3,131.29 ms` / `633.28 tok/s` pure GPU `kprof` — `3,267.43 ms` serialized sum!**, `2,047` dispatches (`-47` dispatches/chunk!), `1.12 GB` transient scratch!)**, decode **`41.53–42.27 tok/s`** (`23.66–24.08 ms/tok`, **`3,004.68–3,005.02 ms` decode, `mtp_ms = 190.62–197.99 ms` / `1.63 ms/draft` — new all-time MTP record `190.62 ms`!**); `prompt_albedo_11k` (`10,180` tokens) prefill **`421.49–446.59 tok/s` (`22.79–24.15 s` vs `28.25 s`, `-5.46 s` faster — all-time record; Chunk 0 = `4,613–4,719 ms`, Chunk 1 = `501.5 tok/s` / `4,084–4,572 ms`, Chunk 2 = `4,362–4,736 ms`, Chunk 3 = `4,610–4,911 ms`, Chunk 4 = `4,685–4,898 ms`, `mtp_ms = 121.54–125.14 ms`, and `@10.2K` decode hit **`25.00–25.26 tok/s` / `39.59–40.01 ms/tok` / `1,227.18–1,240.21 ms` — all-time record `25.26 tok/s` at `10.2K` context!** vs `22.06 tok/s` / `1,405.37 ms`!)**; `coding` prefill **`120.61–126.78 tok/s` (`2,413–2,537 ms`, `+32.2%`)**, decode **`35.46–37.1 tok/s`** (**`6,115.57–6,176.28 ms` decode — all-time record `6,115.57 ms`, `mtp_ms = 374.22–380.29 ms`**); `reasoning` prefill **`121.57–122.92 tok/s` (`2,416–2,458 ms`, `+33.3%`)**, decode **`34.92–36.74 tok/s`** (**`5,961.16–6,270.75 ms` decode, `mtp_ms = 322.48–370.78 ms` — all-time record `322.48 ms`!**); `persona_chat` prefill **`124.62–128.14 tok/s` (`2,255.32–2,443 ms`, `+38.5%` — all-time record `2,255.32 ms` / `128.14 tok/s`!)**, decode **`28.50–33.2 tok/s`** (**`6,628.00–7,685.17 ms` decode, `mtp_ms = 374.58–424.81 ms` — all-time record `374.58 ms`!**). 39. **Measured End-to-End Speed (`32K` Context, `6.5 GB` Arena, Unpruned `K=512` `IQ2_XS`, `call_3817687`, `call_2483052`, `call_3102851`, `call_2898988`, `call_4110683`, `call_4178375`, `call_3948986`, `call_4500449`, `call_3444931`, `call_3116575`, `call_4373130`, `call_2769318`, `call_3781775`, `call_4410602`, `call_3511955`, `call_4432071`, `call_2918543`, `call_1514614`, `call_1173886`, `call_2456120`, `call_5024768`, `call_4223761`, `call_3543222`, `call_1624568`, `call_3678353`, `call_4256391`, `call_3418394` & `call_3706633`):** `prompt_2048tok_ops` prefill **`400.88–432.78 tok/s` (`4,584.29–4,949.14 ms` end-to-end — all-time record `4,584.29 ms` / `432.78 tok/s` — `-1,728 ms` / `+37.7%` faster end-to-end, **`3,131.29 ms` / `633.28 tok/s` pure GPU `kprof` — `3,267.43 ms` serialized sum!**, `2,047` dispatches (`-47` dispatches/chunk!), `1.12 GB` transient scratch!)**, decode **`41.53–42.27 tok/s`** (`23.66–24.08 ms/tok`, **`3,004.68–3,005.02 ms` decode, `mtp_ms = 190.62–197.99 ms` / `1.63 ms/draft` — new all-time MTP record `190.62 ms`!**); `prompt_albedo_11k` (`10,180` tokens) prefill **`421.49–446.59 tok/s` (`22.79–24.15 s` vs `28.25 s`, `-5.46 s` faster — all-time record; Chunk 0 = `4,613–4,719 ms`, Chunk 1 = `501.5 tok/s` / `4,084–4,572 ms`, Chunk 2 = `4,362–4,736 ms`, Chunk 3 = `4,610–4,911 ms`, Chunk 4 = `4,685–4,898 ms`, `mtp_ms = 121.54–125.14 ms`, and `@10.2K` decode hit **`25.00–25.26 tok/s` / `39.59–40.01 ms/tok` / `1,227.18–1,240.21 ms` — all-time record `25.26 tok/s` at `10.2K` context!** vs `22.06 tok/s` / `1,405.37 ms`!)**; `coding` prefill **`120.61–126.78 tok/s` (`2,413–2,537 ms`, `+32.2%`)**, decode **`35.46–37.1 tok/s`** (**`6,115.57–6,176.28 ms` decode — all-time record `6,115.57 ms`, `mtp_ms = 374.22–380.29 ms`**); `reasoning` prefill **`121.57–122.92 tok/s` (`2,416–2,458 ms`, `+33.3%`)**, decode **`34.92–36.74 tok/s`** (**`5,961.16–6,270.75 ms` decode, `mtp_ms = 322.48–370.78 ms` — all-time record `322.48 ms`!**); `persona_chat` prefill **`124.62–128.14 tok/s` (`2,255.32–2,443 ms`, `+38.5%` — all-time record `2,255.32 ms` / `128.14 tok/s`!)**, decode **`28.50–33.2 tok/s`** (**`6,628.00–7,685.17 ms` decode, `mtp_ms = 374.58–424.81 ms` — all-time record `374.58 ms`!**).
### B. ruled out from the original blueprintdetails and primary-source checks in `blueprint_review.md`.443 unmodified linesExpand all1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071# round 39 track a — qsa upstream fixes and local merge experiment
## decision
- keep `831ba47a`'s clamped-row/unconditional-load/value-select fix in the four non-cooperative prompt fills. preserve our staged scales and cooperative paths.- keep `ad734531`'s `TK = 64` default and explicit `v2 || v3` gather/HS/binding conditions. this tree already sets `v2 = v3 = true` for `--v3`, so the binding change is documentary/defensive here, not a newly repaired v3 failure. existing half-input gather and `--gu-bench`, `--dn-bench`, `--ab`, `--dtile` remain intact.- keep the **local** four-partial-load batching experiment in `qsa_merge2`. this is inspired by `731528be`, not a literal upstream transplant. active-chunk bounds already existed and were not changed.- reject the exact requested six-shuffle `qsa_score` butterfly: `scores FAIL`, exit 1, on its first `--ab` case at p=3000. no speed claim for a numerically invalid candidate. cuda's reduction-order argument does not establish equivalence to metal `simd_sum`; the mismatch is measured, its compiler-level cause is not proven.- reject four-partial batching in `qsa_merge`: bitwise correct, but nt=3 regressed repeatedly by 4.8–6.6% across all three contexts. `qsa.metal` is entirely unchanged in the delivered patch.
## artifacts and reproducibility
- patch: `/tmp/astra_r39_qsa/astra_r39_qsa.patch`- durable copy, source snapshots, evaluators, metadata, commands, exit statuses and full logs: `results/round39/astra_r39_qsa/`- exact baseline: the working-tree snapshot, not merely git head; `metadata.json` records its head and four owned-file sha256 values. `baseline-kernels/` and `baseline-moe_mm_parity.cpp` preserve inputs. `rejected-score.metal` and `rejected-merge1.metal` preserve rejected experiments; `final/` preserves the delivered sources.- all editing/building ran in `/tmp/astra_r39_qsa/strata`; no tracked vendor files, live service or full-model tests were touched.- device: apple m5; system version recorded in `metadata.json`. apple clang 21.0.0, release `-O2`. build used `cmake -S metal -B build-metal -G Ninja` followed by `cmake --build build-metal --target qsa_parity qsa_prompt_parity moe_mm_parity -j 3`.- tests were serialized on the gpu. initial moe runs exceeded the original 15s/20s limits and were terminated; after parent explicitly extended CPU-reference allowance to 180s, both full tests completed. all unsuccessful attempts remain in the logs.- `git -C vendor/strata apply --check /tmp/astra_r39_qsa/astra_r39_qsa.patch`: exit 0. scratch `git diff --check`: exit 0. final visual diff/context review completed.
## correctness and test results
all commands below run from the scratch tree; `BASE=/tmp/astra_r39_qsa/baseline`.
| test | result ||---|---|| baseline `qsa_parity --ab $BASE 3000` | exit 0, all memcmps pass || baseline `moe_mm_parity` | exit 3, missing `mm_gu_42_16_64_16_2` || final `moe_mm_parity` (no args) | exit 0, 23.961s, `PASS`; fp16-reference rel l2 2.03e-06, exact-reference 2.37e-04 || final `moe_mm_parity --v3 --gu IQ2_S --dn Q2_0 --tile 16,32,32,4 --dtile 64,32,2` | exit 0, 20.011s, `PASS`; fp16-reference rel l2 1.60e-05, exact-reference 4.38e-04 || same v3 command plus `--ab $BASE` | exit 0, HS/YE/Y memcmp pass, t=256 || default and specified v3 plus `--T 1` | exit 0, CPU-reference parity pass || v3 plus `--T 1 --gu-bench --ab $BASE`, and `--dn-bench` | both exit 0; HS/YE/Y memcmp pass; flags preserved || `qsa_prompt_parity` | exit 0, `ALL PASS`, default cooperative layout || `COOP_K4=0 qsa_prompt_parity` | exit 0, `ALL PASS`, edited non-cooperative layout || `qsa_prompt_parity --mm-compare attn 96 P $BASE/qsa_prompt.metal 3` | p=0 and 30000, both COOP_K4=0 and default: exit 0; output, post-timing and merge+prepared memcmp pass || `qsa_prompt_parity --flash-compare 96 P $BASE/qsa_prompt.metal 1 3` | same four combinations: exit 0, memcmp pass || `QSA_ATTN=2 qsa_parity --ab $BASE P` | p=3000,10180,30000: all full-buffer memcmps pass; nt=1,2,3,4,8 plus prompt prep nt=1984,2048 || `QSA_ATTN=2 qsa_parity --bitwise $BASE/qsa2.metal` | exit 0; zero of 40 cases differ, including short contexts/remainders |
important distinction: moe's no-argument and specified-v3 CPU checks are tolerance checks and print `PASS`, not `ALL PASS` or bitwise equality to CPU. the separate v3 A/B command provides bitwise equality to the baseline kernels. prompt's default suite likewise includes tolerance checks; the comparison modes provide bitwise evidence for both edited kernels. no unsupported claim of IEEE equality to a differently accumulated CPU reference is made.
## merge2 paired timings
three sweeps: initial, confirmation, then final with rejected merge1 restored. all pass. the final sweep below uses only retained changes. measurements are median GPU µs; paired ratio is median(candidate/baseline), not necessarily the quotient of medians. inspected evaluator code uses **five paired rounds**, 16 dispatch repetitions for decode (the file header's 12-repetition description is stale). each stage is warmed before interleaved A/B timing.
| p | nt | baseline µs | candidate µs | paired candidate/baseline ||---:|---:|---:|---:|---:|| 3000 | 1 | 15.143 | 9.273 | 0.6122 || 3000 | 2 | 21.924 | 21.516 | 0.9812 || 3000 | 3 | 33.688 | 32.969 | 0.9791 || 3000 | 4 | 45.458 | 43.227 | 0.9522 || 3000 | 8 | 91.102 | 86.547 | 0.9501 || 10180 | 1 | 10.961 | 6.844 | 0.6240 || 10180 | 2 | 21.977 | 21.589 | 0.9834 || 10180 | 3 | 33.732 | 32.961 | 0.9772 || 10180 | 4 | 45.344 | 43.313 | 0.9546 || 10180 | 8 | 91.393 | 86.607 | 0.9493 || 30000 | 1 | 17.180 | 10.807 | 0.6295 || 30000 | 2 | 22.125 | 21.547 | 0.9739 || 30000 | 3 | 33.500 | 33.471 | 0.9955 || 30000 | 4 | 45.469 | 43.544 | 0.9577 || 30000 | 8 | 91.594 | 88.021 | 0.9556 |
nt=1 improves 35–41% across the earlier sweeps and 37–39% in the final sweep; other cases are neutral to about 5% faster. one initial p=30000, nt=3 ratio was 1.0008 (0.08% noise); subsequent ratios were 0.9902 and 0.9955. no repeatable regression. absolute clocks/times drift (even unchanged stages), so use paired ratios, not cross-run raw times. this is a standalone-kernel result, not evidence of whole-model throughput improvement.
for the rejected merge1, confirmation nt=3 ratios were 1.0551, 1.0660, 1.0563 at p=3000,10180,30000. despite wins elsewhere, these violate the requested neutral-to-faster-across-suite rule.
## prompt safety fix timing observation
with `COOP_K4=0`, p=30000/t=96 non-cooperative attn median fell from 4.954 to 1.537ms, flash from 5.685 to 1.828ms, with memcmp pass. p=0 also improved. these three-pair observations are secondary to the safety fix, not broad performance claims. cooperative mode remains bitwise identical. actual m1 hardware was not available; the m1 fault rationale comes from upstream `831ba47a`, while our runtime evidence is m5 with both constant settings.123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263# round 39 integration
## scope
selected upstream changes from strata `296b59d2..477ac13c`; not an engine-wide upgrade. serve/tokenizer files carry the range plus local correctness hardening. PLE uses only `36381540`, not the later upstream mutex change. metal adaptations are documented in `astra_r39_qsa.md`.
- no cuda butterfly: score memcmp failed.- no batching in production `qsa_merge`: repeatable slowdown.- retained `qsa_merge2` batching is test-only; the live engine does not dispatch it. qsa2.metal still belongs to the runtime-compiled shader library; the hardened service startup exercised that compile.- active-chunk bounds already existed. no credit assigned to this round.- prompt safety edits affect non-cooperative branches, not the M5 default path.- local image omission, model files, and sampling config unchanged.- upstream answer reservation remains enabled as approved: large thinking requests without a budget reserve answer space and may receive an injected wrap-up sentence in its reasoning ("I have thought about this long enough; time to give my answer."). the policy also logs its budget per request for caps <=32K. this is a behavior change; service persona evaluations need an explicit `answer_room` setting for comparability. CLI smoke does not run that service policy.
## parent verification
logs are under `results/round39/`.
- integration ninja build: exit 0 (`integration-build.log`).- `QSA_ATTN=2 qsa_parity --bitwise <baseline>/qsa2.metal`: exit 0, all 40 cases bitwise equal.- `qsa_prompt_parity`, default and `COOP_K4=0`: exit 0, ALL PASS (mixed tolerance and explicit memcmp checks).- `moe_mm_parity` no args: exit 0, fp16-reference relative L2 2.03e-06.- requested IQ2_S/Q2_0 `--v3` configuration: exit 0, fp16-reference relative L2 1.60e-05.- real local tokenizer: 18 tests, exit 0, one skip for unavailable external llama.cpp oracle vectors.- bias/image compatibility: 17 tests, exit 0, including same-length mutation and JSON-key equivalence.- final telemetry/cache hardening: 39 tests, exit 0. real M5 ctypes/ioreg probe also exits 0.- PLE new reuse fixture: all 10 cases x 2 cache settings x 2 worker settings pass, targeted runner exit 0. full baseline and candidate selftests both exit 1 on the same pre-existing keepalive timing assertions; thresholds unchanged. do not describe the full C++ suite as green.- parent full serve suite: 852 tests in 517.636s, exit 0, 11 skips (`parent-serve-full.log`). imports predate the last telemetry/cache-cap hardening; the 39-test final-source rerun above covers those changes. the serve owner’s separate baseline (785 tests) and candidate (852 tests) runs both hit the same existing keepawake acquire/release scheduling race; no production code or timing threshold was changed to suppress it.- complete `scripts/strata_metal_complete.diff`, including eight new serve tests: applies cleanly to isolated vendor HEAD (`complete-patch-check.log`).
## integration smoke, not a speed comparison
one model process at a time, existing service stopped for standalone runs and restarted afterwards. same configured 6.5 GB arena and K512 model. CPU-only fake-engine suites also running, so these measurements are not clean performance comparisons.
| prompt | prefill | decode | exit ||---|---:|---:|---:|| 1,984 tokens | 4,941.54 ms | 127 tokens / 2,991.30 ms (42.46 tok/s) | 0 || 10,180 tokens | 23,498.33 ms | 31 tokens / 905.63 ms (34.23 tok/s) | 0 |
`model-smoke-plan.json` records arguments and environment; full logs retained. no whole-model speedup claimed.
live HTTP roundtrip returned `ready`, then `still ready`; second request reported 18 cached tokens. final hardened service `/health` reports loaded=true on localhost:8080. telemetry reports the driver’s in-use memory statistic, **not established free unified memory**; do not enable the optional `min_free_vram_mib` gate based on this round. the per-sample device query is gone, but the 1 Hz ioreg subprocess remains; its serving overhead was not A/B measured.
## review and limits
parent reviewed production diff/context, metal patch, PLE fixture and local regressions; serve owner reviewed all tracked and new test files. opus independently fuzzed 38,033 real-tokenizer cases (PromptEncoder vs full encode directly), with zero mismatches; that tokenizer source is unchanged since the fuzz run. no CUDA/HIP/SYCL or M1 hardware verification this round. full evidence and source fingerprints: `results/round39/`; individual agent audits distinguish measured results from inferred portability.
complete patch replay reproduces all 27 changed source files exactly. vendor `git diff --check` flags only the pre-existing blank line at qsa.metal EOF; that file is byte-identical to the pre-round snapshot.
non-empty request logit biases remain unsupported by the Metal engine (no logit_bias=1 INFO capability); that cache was checked through unit tests, not claimed exercised by the live chat smoke.
## quiet paired CLI followup
same-day baseline reconstruction independently checked by opus: only the PLE object differs in the host archive; all other linked objects match. runtime shader directories restore the exact prior versions. both arms run the same inputs/env, with service stopped and other agent suites complete. source/build provenance, frozen shaders, commands, full logs and summary: `results/round39/model-ab/`.
excluded one warmup per arm, then 10k order A/B/B/A/A/B and 2k A/B/B/A. every run exits 0 and **all five pairs produce identical generated token IDs**.
| case | candidate/baseline decode time, adjacent pairs | candidate/baseline prefill time ||---|---|---|| 10k | 1.0137, 0.9643, 1.0280 | 1.0284, 0.9103, 1.0663 || 2k | 1.0146, 1.0170 | 1.1043, 0.9660 |
**performance remains inconclusive, not a zero-regression certificate.** no consistent 10k slowdown; both 2k comparisons are ~1.5–1.7% slower, below the declared 2% material-slowdown threshold but not evidence of exact neutrality. strong temporal drift affects both arms: baseline 10k prefill rises from 23.4 to 28.5s and decode from 908 to 997ms; candidate drifts too. thermal throttling is plausible on the fanless laptop but was not measured, so no causal claim. do not treat the median 10k advantage as an improvement. the short 31-token decode further limits precision. no more repeated hot-device runs; a cooled/stationary experiment would be needed to resolve small differences. server restarted and health confirmed loaded=true.123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190# round 39 opus review — v0.1.45 serve/tokenizer/ple ports + astra qsa patch
read-only review. no source edits, gpu runs or service actions by me. scope: prompt cache, logit_bias cache,telemetry fallback, ple dedup, astra qsa patch. paths are relative to `vendor/strata/` unless noted.
## what i compared
- `/tmp/v0145_serve_ple.patch` applied to a clean `git archive HEAD` copy (`/tmp/r39_audit_tree`, exit 0). the patch does **not** apply to the dirty tree (`serve/server.py:3852` conflicts with the local `STRATA_OMIT_IMAGES_WHEN_NO_VISION` block); that full `git apply` failed atomically, so nothing in it landed. the serve/tokenizer parts went in through the serve owner (working-tree server.py = the clean-applied copy plus the local omission block). PLE went in as **only upstream commit 36381540** (`results/round39/ple.patch`: ngram.cpp + ple_reader_test.cpp, no mutex). the later upstream commit that adds the `std::recursive_mutex` was **not imported**; the mutex was never in our tree, so nothing was dropped or reverted.- `/tmp/astra_r39_qsa/astra_r39_qsa.patch` against current `metal/`.
## verdict
no remaining correctness blocker once the logit_bias `_last` removal (already done by the serve owner) is in.three should-fix items before benchmark numbers or a persona eval are attributed to this build: telemetrycost on darwin (S1), answer_room default (S2), prompt-cache cap (S3).
## should-fix
### S1. telemetry runs ioreg and creates a Metal device in the server every second (darwin)
- `serve/server.py:6485` `serve()` always calls `start_telemetry()`; on darwin `gpu_reader` now returns `_Metal` (`serve/telemetry.py` `gpu_reader`), so the sampler thread runs `ioreg -l -w0 -r -c IOAccelerator` every second (measured here on the M5: 39 ms wall, 57 KB of output; the patch says 22 ms) and `_Metal.read()` calls `metal_working_set()` on **every sample**, which does `MTLCreateSystemDefaultDevice()` (create rule: +1 retain that is never released) and the objc lookups each time. before the port, darwin had no gpu reader, so this is new work in the serving process during decode.- fix: compute the working set once (`_Metal.__init__`) and reuse it in `read()` and in `Telemetry.static`.- test: patch `telemetry.metal_working_set` with a counter, build `_Metal(run=fixture)`, call `read()` 3x, assert 1 call. before citing any tok/s from this build: paired decode A/B with the sampler on vs `gpu_reader` forced to `_Nvml` (same engine, same prompts).- semantics (not a blocker; it only matters for opt-in `min_free_vram_mib` / image policy): on this M5 at idle `"In use system memory"=15007744` (15 MB) vs `"Alloc system memory"=15473033216` (15.5 GB). free = working set − in-use probably reports far more free than there is while the wired arena is up. needs one check with the engine loaded before anyone turns on `min_free_vram_mib` on the mac.
### S2. `answer_room` is on by default and changes every thinking request on our config
- `serve/server.py:4206-4214`: with no `reasoning_budget_tokens`, every thinking request with `max_new >= 1024` gets budget = max_new − max(512, max_new/4). our config has `fit_max_tokens: true` and 32K context, so a request without max_tokens gets max_new = room and a budget of 75% of it, plus a `print` on **every** request (`max_new <= 32768` is always true at 32K ctx).- when it fires, `REASONING_WRAP_UP` (`"I have thought about this long enough; time to give my answer."`) is injected into the reasoning stream, and the generation splits into a second engine pass. `frontend.py` additionally turns Anthropic `thinking.budget_tokens` into a hard budget.- effort `low` keeps this rare, but persona/antislop evals before and after the port are not comparable unless this is pinned. decide explicitly: `"answer_room": false` in `models/K512_iq2_xs/strata-k512-iq2xs.json` for parity runs, or accept and note it. the per-request print should go behind a once-flag either way.- model-card sampling (`model_card_sampling`): checked: a no-op for our config, because the `sampling` block sets temperature, top_p, top_k and presence_penalty, which covers every key in both qwen4exp sets.
### S3. PromptEncoder `keep` has no upper bound
- `serve/server.py` Service init: `keep = conversation_slots(engine)` is taken from `--conversation-cache-slots` with no clamp; the engine accepts up to INT32_MAX (`src/program/generate.cpp:2113`). each entry holds the full prompt str (1–4 B/char: kaomoji/CJK push the str to UCS-2/4), its ids list (8 B/token) and its mark lists, so ~2–5 MB at 100K tokens. our config passes no slots, so keep = 4 and this is latent.- fix: `keep=min(slots, 16)` (or a total-chars budget). test: `conversation_slots` stub returning 10_000 → assert `svc.prompts.keep <= 16`; feed 20 unrelated prompts → `len(entries) <= keep`.
## checked and fine
### prompt cache exactness / mutation / concurrency (`tools/strata_tokenizer.py` PromptEncoder)
- the margin argument holds for `_encode_matching`: a match decision at q depends only on `text[q:q+max_special_len]` and on whether q is in a plain span; the finditer state before a cut c (end of a taken match) is identical when `c + max_special_len - 1 <= same`. `call_end`-style lookbehind does not exist in the literal alternation.- fuzz (`/tmp/r39_fuzz.py`, `/tmp/r39_fuzz2.py`, real Swift tokenizer from `models/K256_reap_l2_sum/tokenizer`, 33 specials, max len 21): conversations with appends, mid-inserts, truncations, specials split across appends (`<|im_sta` + `rt|>`), random plain spans, `store=False` mixed in, keep 1/2/4. 38,033 cases, 8,529 of them reusing a prefix, **0 mismatches** vs `tok.encode(text, parse_special=True, plain=...)`.- mutation: `encode(store=True)` returns `list(ids)`, `store=False` returns a list that is not stored, entries are replaced and never changed in place; `prepare` never mutates `ids` in place (images build `out`, force builds a new list), so `forget_prompt(encoded_ids)` matches. the local omission block runs before `encode_prompt` (`serve/test_image_omission.py` covers it).- concurrency: snapshot under the lock, BPE outside it, replace under the lock against the current list: a race loses reuse at worst, never data.- `pick_slot` `TURN_ID = 248045` matches `<|im_start|>` in our vocab.- parser `_wrapped_call_end` fast path: sound, because `call_end` only ever returns positions of a literal `</tool_call>`, and `_call_end_checked` is reset on every path that leaves the `call` state.
### logit_bias (`serve/logit_bias.py`)
- `_last` identity+len staleness: found by the parent, already removed by the serve owner.- content key `json.dumps`: no collisions that change the result: `{1: x}` and `{"1": x}` serialize alike and normalize alike; float/bool keys, NaN and inf never normalize, so they are never stored; `False` vs `0` and `1` vs `"1"` serialize differently. results are copied (`normalize` → `dict(...)`), and the engine key is an immutable str. the lazy `entry[1]` write is a benign race (same string).- cost note only: without `_last`, a 65K-entry list pays `json.dumps` on each of the ~5 calls per request. compute the key once in the route if that shows up in profiles.- note: the Metal engine does not report `logit_bias=1`, so `validate_request` refuses non-empty biases on our backend anyway.
### PLE dedup (`src/kernels/ngram.cpp` `gather_batch`)
- any-slot matching plus `matched[t]` reuse is correct (keys are row ids; the table is immutable). dropping `n_prefetch >= n_tokens` is correct now that duplicates map to one slot. draining every ticket before returning an error fixes the old early return, which left tickets in flight writing into slots that would be reused.- Metal uses Direct mode (`metal/src/strata_window_cli.cpp:945`), so this path is live: MTP `prefetch_rows` (`metal/src/engine/window.cpp:2972`) feeds the verify window's `gather_batch` (T = spec+1 ≤ 16). prompt chunks (2048) take the slow path, which drops the prefetches; that is fine.- the later upstream `recursive_mutex` commit was not imported (only 36381540 was transplanted), so the table's threading is unchanged from our baseline. on Metal that baseline is fine: `ple_th` (`window.cpp:3434`) is joined inside the forward, and the MTP prefetch runs after it, so they never overlap. other backends (the desktop HIP build shares this file; upstream's mutex comment is about prompt-path / decode-window overlap there) carry the same unchanged baseline hazard and are untested in this round. record it in the port notes as "not imported". even with the mutex, `issue()` copies into `impl_->rows` before its `pending` check (pre-existing), so a second `issue()` while one is in flight corrupts the first ticket's keys: move the `pending` check first if this ever becomes multi-threaded.
### astra qsa patch
- `qsa_merge2` is dispatched only by `metal/tests/token_chain.cpp:249` and `metal/tests/qsa_parity.cpp:49,159,254`. the engine dispatches `qsa_merge` (v1) at `metal/src/engine/window.cpp:1285,2737,3662` and `metal/src/engine/prompt_chain.inc:262`. `qsa2.metal` is still compiled into `lqsa_` (`window.cpp:763`), so the change is compile-surface only: **zero runtime effect, no end-to-end attribution**. the unroll keeps the fma accumulation order (it only hoists loads), which matches astra's bitwise result.- `qsa_prompt.metal` clamped-row edits are in the `!coop_k4` branches only; on the M5, `Window::coop_k4()` probes true, so they run only with `COOP_K4=0` or on M1/M4. it is a safety port, with no M5 default-path effect. row 0 / scale 0 for empty cells is in bounds whenever the cache holds ≥1 cell.- `moe_mm_parity` `TK=64` / `v2||v3`: test-only. the baseline default was already broken (missing `mm_gu_42_16_64_16_2`, exit 3).
## tests i ran (cpu only, `PYTHONDONTWRITEBYTECODE=1`, from `vendor/strata`)
- `python -m unittest serve.test_prompt_encoder serve.test_logit_bias serve.test_image_omission serve.test_model_card_sampling serve.test_admit_order`: 33 tests OK (before the serve owner's `_last` fix landed).- `python -m unittest serve.test_server.MacTelemetry serve.test_server.AmdTelemetry`: 7 OK.- `python tools/test_strata_tokenizer.py`: 11 OK, 3 skipped.- PromptEncoder fuzz above: 0 mismatches.- not run: anything on the gpu, ple_reader_test (the parent ran it), the full serve suite.
## followup v2 — sdk ownership check for S1
- `MacOSX.sdk/System/Library/Frameworks/Metal.framework/Headers/MTLDevice.h` (CommandLineTools sdk on this machine): `MTL_EXTERN id <MTLDevice> __nullable MTLCreateSystemDefaultDevice(void) API_AVAILABLE(macos(10.11), ios(8.0)) NS_RETURNS_RETAINED;` so the caller owns +1, and each uncached `metal_working_set()` call leaked one retain on the device singleton. that is a refcount, not memory per call, and the cost is the per-sample framework call. with the working set cached once, a single unreleased +1 at startup is acceptable. an optional `objc_msgSend(dev, sel_registerName("release"))` after reading would make it exact, but it is not needed.- the same header says a call switches a dual-gpu intel mac to the high-power gpu. it does not apply to apple silicon, but it is one more reason to call it once and not every second.- answer_room: parent approved keeping the live default; it stays disclosed in S2, with no comparable eval numbers claimed.
## followup v3 — hardening review (final sources)
- the fingerprints in `results/round39/integration-source-sha256.json` match the working tree for all 27 files.- telemetry: `_Metal.__init__` reads the working set once (`self.working_set`), and both `read()` and `Telemetry.static` reuse it. `metal_working_set()` releases the device in a `finally` (`objc_release`, matching the `NS_RETURNS_RETAINED` annotation); the early `if not dev` return happens before the try, so a null is never released. covered by `test_working_set_is_read_once_for_samples_and_static` plus the release assertion. what remains per sample: the 1 Hz `ioreg` subprocess (39 ms wall measured earlier); its cost on decode is still not A/B measured. `Service.free_vram_mib()` still builds a fresh reader per call (2 ioreg runs + 1 working-set read), but only on the opt-in and image paths.- prompt cache: `PROMPT_ENCODER_KEEP_MAX = 16` caps slots from args and from INFO, and the default stays 4. covered by `IncrementalPrompts` (asserts 10**9 → 16 on both paths). `tools/strata_tokenizer.py` is byte-identical to the fuzzed version, so the 38,033-case result still applies to the final source.- logit_bias: `_last` is fully removed and only the bounded JSON-keyed cache remains; nothing else changed.- reran on the final sources (cpu): test_prompt_encoder, test_logit_bias, test_image_omission, MacTelemetry, AmdTelemetry: 33 OK; IncrementalPrompts: 9 OK.- verdict: S1 (per-sample device creation) and S3 (cap) are resolved. S2 is accepted and disclosed by the parent.
## followup v4 — provenance of `results/round39/model-ab/` (read-only; no processes launched)
- `ngram-baseline.cpp` is byte-identical to `git show HEAD:src/kernels/ngram.cpp` (ngram.cpp was clean before the round). against the current file the diff is 15+/11-, i.e. the 36381540 dedup only.- host archive: 34 members, same names and order as `build-metal/libstrata_metal_host.a`. extracted and hashed: only `ngram.cpp.o` and the ranlib `__.SYMDEF` index differ, and the swapped member equals `model-ab/ngram.cpp.o`. no other linked archive defines `PleTable::gather_batch` (`libstrata_metal_kernels.a` only references it), so link order cannot pick a stale copy. the disassembly of `PleTable::gather_batch` differs between `baseline-cli` (340 lines) and `candidate-cli` (391 lines).- `candidate-cli` is byte-identical to `build-metal/strata_window_cli`, built at 11:59:22, after the last round39 source write (qsa files 11:59:21, ngram.cpp 11:56:32).- shaders: the runtime directory comes from `STRATA_METAL_KERNELS` (`metal/src/mtl_rt.mm:51`), with no on-disk library cache in mtl_rt. `candidate-kernels/` equals the current `metal/kernels/` file for file (22/22). `baseline-kernels/` differs from it only in `qsa2.metal` and `qsa_prompt.metal`, matches `/tmp/astra_r39_qsa/baseline` exactly, and matches the sha256 values in astra's `metadata.json` for qsa/qsa2/qsa_prompt. the engine-private msl (`mtp.metal`, `mtp_chain.metal`, `ple.metal`, `slop4.h`) loads from the compiled-in absolute path for both arms; all four were last written before the round (02:57–08:11, and slop4.h on 10-17), so this is shared and unchanged.- consequence for interpreting results: on the M5 the shader delta is inert (`qsa_merge2` is not dispatched, and the non-coop branches are not taken), so the arms differ in effect only by the PLE gather_batch dedup in the MTP verify path.- suggestions, not blockers: (1) both arms should emit identical token ids, because the dedup returns the same bytes; compare the generated ids per pair as a correctness gate. (2) the 10K case decodes ~31 tokens in ~0.9 s, which is too short a window to resolve a 2% decode delta with 3 pairs; call that case's decode inconclusive unless the spread is clearly under 2%, and read prefill separately.123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869# round39 serve + tokenizer port
## scope and source
- upstream range: `296b59d2f73c8f04a805df29c2fa97655adace78..477ac13cbe8e582c20484871ce459d20d82df09d`.- read `vendor/strata/AGENTS.md`, `docs/DETAILS.md` thinking/API sections, `docs/LOGIT_BIAS.md`, design-preflight and orchestrating-agents.- owner boundaries: tokenizer owns exact incremental encoding; service owns request preparation/cache admission, thinking budgets and API defaults; telemetry owns fail-open platform readers. no engine/model/GPU execution or running service changes.- all 21 upstream serve/tokenizer changed files ported. 16 match upstream exactly; exceptions: server.py retains the pre-existing local image omission hunk unchanged and caps prompt retention; logit_bias.py removes unsafe identity caching; test_logit_bias.py adds regression coverage and removes obsolete _last resets; telemetry.py caches/releases the working-set device; test_server.py covers those hardening changes. one local test file added.- complete owned patch, including untracked upstream tests: `results/round39/serve-owned-final.patch`.- sha256s of every owned final file and upstream counterpart: `results/round39/serve-source-hashes.json`.
## behavior and deviations
ports prompt encoder resume points, plain-span-aware prefix reuse and rejected-prompt forgetting; parser wrapped-call scan cursor and bounded suffix checks; bounded content-keyed logit-bias LRU; apple IOKit telemetry; anthropic hard thinking budgets and automatic answer reservation. also carries upstream admission ordering (opt-in), turn-aware slot choice, sampling/model-card/web defaults, scrape-window throughput gauges, config diagnostics, and prompt telemetry fields.
local image omission still mutates content lists before image processing and encoding, exactly as before. new tests prove retained text-part identity, omitted images cached as text, full/incremental token parity, repeated fresh/mutated-object requests, disabled-switch error, and no mutation when vision exists.
parent review identified upstream's `_last` identity+length fast path returning stale values after same-length mutation. removed it rather than asserting request immutability. every large input now receives a JSON content key; four-entry bounded LRU and cached engine-key strings remain. new tests cover nested list/dict edits to valid/invalid values and JSON-equivalent inputs/duplicate IDs. red-on-upstream evidence: `serve-logit-bias-upstream-repro.log` (one test, two failing subtests); fixed bias suite: 14 passed.
hardening requested after opus review: service retention is capped at the explicit `PROMPT_ENCODER_KEEP_MAX = 16`, including huge engine INFO and lazy-start argument values. apple working-set budget is read once per `_Metal` instance and reused by `read` and static telemetry. the local SDK's `/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Metal.framework/Headers/MTLDevice.h:130` declares `MTLCreateSystemDefaultDevice` `NS_RETURNS_RETAINED`; the helper now releases it in `finally`, including unsupported-selector returns. mock tests count one helper call through three reads and Telemetry static initialization, and verify device release on success/unsupported selectors.
## validation
python: `/tmp/r39-serve-venv/bin/python` (3.14.7); dependencies: `results/round39/serve-python-packages.txt`. initial system python lacked jinja2/regex; initial import-failure logs retained separately. baseline tree copied to `/tmp/r39-serve-baseline`, restoring only owned paths to source baseline plus original local image hunk; shared checkout never reverted.
- tokenizer baseline: 6 passed.- tokenizer default candidate: 11 run, 3 skips (real-vocabulary classes/oracle unavailable by default).- tokenizer with `STRATA_TOKENIZER=$PWD/models/K256_reap_l2_sum/tokenizer`: 18 run, 1 skip (external llama.cpp oracle vectors absent), no failures; reads vocabulary only, no model execution.- image compatibility: 3 passed.- final logit bias: 14 passed.- hardening affected suites: 39 passed in 3.786s (`serve-hardening-affected.log`), with real vocabulary enabled; rerun after final readability adjustment also passes 39 (`serve-hardening-final.log`).- first full serve baseline/candidate attempts hit 300s deadlines; partial logs retained as `serve-baseline.log` / `serve-post.log`. no completed suite count claimed for these.- completed full baseline: 785 tests in 494.236s, 1 failure, 11 skips (`serve-baseline-full.log`).- completed full candidate (pre-hardening imports, before one extra bias-key test): 852 tests in 516.658s, 1 failure, 6 skips (`serve-final-full.log`).- the sole failure is identical on baseline/candidate: `test_keepawake.KeepAwakeTests.test_service_holds_for_the_whole_request_including_early_close`, line 87. this is an existing asynchronous-observation race, not a port regression: the mock request can acquire and release its hold before the keep-awake daemon acquires `_cond`; `_loop` then sees `_count == 0` with `held == False` and waits without emitting either transition. the test assumes the daemon observed the transient busy state. deterministic baseline/candidate reproductions block that condition lock through the request and both record `count=0, calls=[]`, then only idle reset on close (`keepawake-mechanism-{baseline,candidate}.log`). no timeout increase, expectedFailure, or unrelated product/test edit applied.- final hardening is checked by the separate 39-test affected-suite run, not falsely folded into the older full-run count.
## changed files
- `vendor/strata/serve/frontend.py`- `vendor/strata/serve/logit_bias.py`- `vendor/strata/serve/runconfig.py`- `vendor/strata/serve/server.py`- `vendor/strata/serve/telemetry.py`- `vendor/strata/serve/test_admit_order.py`- `vendor/strata/serve/test_effort_paths.py`- `vendor/strata/serve/test_logit_bias.py`- `vendor/strata/serve/test_model_card_sampling.py`- `vendor/strata/serve/test_parallel.py`- `vendor/strata/serve/test_parser_call_scan.py`- `vendor/strata/serve/test_parser_hold.py`- `vendor/strata/serve/test_prompt_encoder.py`- `vendor/strata/serve/test_q36_config.py`- `vendor/strata/serve/test_reasoning_loop_recovery.py`- `vendor/strata/serve/test_server.py`- `vendor/strata/serve/test_slot_alloc.py`- `vendor/strata/serve/test_web_sampling.py`- `vendor/strata/serve/web/app.js`- `vendor/strata/tools/strata_tokenizer.py`- `vendor/strata/tools/test_strata_tokenizer.py`- `vendor/strata/serve/test_image_omission.py`
## final review
view_diff reviewed every tracked owned diff; view_code reviewed every new upstream/local test file and final local mutation/key-equivalence tests. tokenizer reuse helpers are shared with service rather than duplicated. upstream comments/style retained for port fidelity. no assertion or test removed except obsolete `_last` reset setup lines; upstream loop-recovery tests explicitly disable automatic answer_room to continue testing the original loop-guard path.
## parent independent verification
parent reports an independent full-suite run passed: 852 tests in 517.636s, 11 skips, exit 0; its independent hardening selection also passed 39/39. these are parent-reported results, not this agent's own runs. the baseline-shared keepawake race above did not reproduce in the parent full run. no additional suites launched after parent began quiet paired CLI benchmarking. results/round39 /complete-patch-check.log no changes to the file itself
123456789101112131415161718192021222324252627282930313233{ "apply_exit": 0, "compared": [ "serve/frontend.py", "serve/logit_bias.py", "serve/runconfig.py", "serve/server.py", "serve/telemetry.py", "serve/test_admit_order.py", "serve/test_effort_paths.py", "serve/test_logit_bias.py", "serve/test_model_card_sampling.py", "serve/test_parallel.py", "serve/test_parser_call_scan.py", "serve/test_parser_hold.py", "serve/test_prompt_encoder.py", "serve/test_q36_config.py", "serve/test_reasoning_loop_recovery.py", "serve/test_server.py", "serve/test_slot_alloc.py", "serve/test_web_sampling.py", "serve/web/app.js", "tools/strata_tokenizer.py", "tools/test_strata_tokenizer.py", "serve/test_image_omission.py", "metal/kernels/qsa2.metal", "metal/kernels/qsa_prompt.metal", "metal/tests/moe_mm_parity.cpp", "src/kernels/ngram.cpp", "src/ngram/ple_reader_test.cpp" ], "mismatches": []}1234567ninja: Entering directory `vendor/strata/build-metal'[0/2] Re-checking globbed directories...[1/6] Building CXX object CMakeFiles/strata_metal_host.dir/Users/dawn/proj/swift1.5-qwen3.8-next-flash-ps-scr-qat-persona/vendor/strata/src/kernels/ngram.cpp.o[2/6] Linking CXX static library libstrata_metal_host.a[3/6] Linking CXX executable strata_window_cli[4/6] Building CXX object CMakeFiles/moe_mm_parity.dir/tests/moe_mm_parity.cpp.o[5/6] Linking CXX executable moe_mm_parity1234567891011121314151617181920212223242526272829{ "serve/frontend.py": "1f40ac6fc9f4ad021ac0c202f35f184f5784009355dd7485ee0e44746bfd75e1", "serve/logit_bias.py": "b6564c97e91c987e5787349b3df209fa0cf00fc8e80357ad93d40fd1e594da09", "serve/runconfig.py": "58aa118367a9d6dbb534cae5f35d6f418112f96985db85b048fa23eb042e403a", "serve/server.py": "7ee5536c9293583244abb3774851fb16aa2ac7e7e55e200fef13bb4be4aac19b", "serve/telemetry.py": "973772d0209167bf0dbaa8fd98fab8e64801f12dd241c72d5e06bbaaf96b646e", "serve/test_admit_order.py": "bbfe80b214f0dfcf2339bb4aab08e1549330951bcf5b7a607acea4f436cae47b", "serve/test_effort_paths.py": "9501d8787e396b95f5143eb298334973a8553b298feff0e93b8708dfcc4f6db9", "serve/test_logit_bias.py": "d4afa9e4f50bfa3595db67bc9e2487adabcaf7e902be2c3dca3bbccec434e92a", "serve/test_model_card_sampling.py": "38a90fe3d2339d1bca61b073a5e0bafae936c36ab1b1953ffdc6f756a06bf5f3", "serve/test_parallel.py": "0f6147f1e74badb61f974d0fd71d2b39e4c141eaeee6dc3cfbf5f5bbb585eeec", "serve/test_parser_call_scan.py": "71aab3ee7ea39bf8810099e3d59d1c8580836923b7aa3446a72c281b6398232d", "serve/test_parser_hold.py": "d50e799c0bbf003318b51938f09e0b40fb11b8d572a7377ddd4617b9ddf9d7cf", "serve/test_prompt_encoder.py": "fad128ea329949fd38ce034a026b3f86d060c484fcfe1c0fea2a13f94524a73c", "serve/test_q36_config.py": "278dae2f526ad8cda6fe8a719e075456c71824bbd8b2362b87fe62139b6b0ea8", "serve/test_reasoning_loop_recovery.py": "c448df0757ae1bffb0a4fe8b48f45ee57ae0f06e7056d6bc96885dc8b024bf7b", "serve/test_server.py": "576f7e5eb3ea07cb8dc0939714d282b59e9f51d0d4c6e00549394f4cd9753d17", "serve/test_slot_alloc.py": "7ea0cb07ed01f95d720fb0ae1d945cee705a31a34213bd5ada22dfa35c68d40c", "serve/test_web_sampling.py": "8e4e717aaab9049b99a1a44beff2bae1d48e6f60d08de98a28e2d875d2eba18d", "serve/web/app.js": "7d15c4efeccbc4b1f4944494dc76987e18e7a6cf40d12279978dfe93951bb8fd", "tools/strata_tokenizer.py": "e0cd8d6ae38dda0a4ad7c14f812eb64d5fd6f4fed9c920d4427a14bf585dc9b3", "tools/test_strata_tokenizer.py": "6a3cadf78c1972e83acd0ef90a8f5119868c7c3a4613fcfa000faae1195017b5", "serve/test_image_omission.py": "88c88b3a2f15d41958a2b60760734897c4656d275353b906b6c49d54591d4b39", "metal/kernels/qsa2.metal": "ceb7fb66e2acd2e05e26ff0ce27e6533831c01c1d0adbb6d1917ec5185ccc172", "metal/kernels/qsa_prompt.metal": "6af1d7979169bcd09de6e4ac7fe6ed5a6aa4e080917577c7e4731b8b6f466c94", "metal/tests/moe_mm_parity.cpp": "e8fec719467a5d236857ad141e6a7318fc25f6abcad79efb41f33417d4538217", "src/kernels/ngram.cpp": "f76bb2b9d8a082ad9489252ff71a7dd9e13cedfc01c92c27fffbf2c95a29bfd3", "src/ngram/ple_reader_test.cpp": "6eede85aea6a594d091b542b0be5d286681c8c083eff8c8cea86cdbd12d0e84b"}123[strata] done: 3 tokens in 0 s (125829.1 tok/s) (stop, cancel=False)request completed before worker condition lock: count= 0 calls= []after close: [2147483648]123[strata] done: 3 tokens in 0 s (106634.8 tok/s) (stop, cancel=False)request completed before worker condition lock: count= 0 calls= []after close: [2147483648]1{"id": "chatcmpl-15093e04ea61492a8a4a78db", "object": "chat.completion", "created": 1792314432, "model": "swift-1.5-k512-iq2xs", "choices": [{"index": 0, "message": {"role": "assistant", "content": "ready"}, "finish_reason": "stop"}], "usage": {"prompt_tokens": 17, "completion_tokens": 2, "total_tokens": 19, "prompt_tokens_details": {"cached_tokens": 0}}, "timings": {"cache_n": 0, "prompt_n": 17, "prompt_ms": 1226.0, "prompt_per_token_ms": 72.118, "prompt_per_second": 13.9, "predicted_n": 2, "predicted_ms": 201.9, "predicted_per_token_ms": 100.95, "predicted_per_second": 9.9, "draft_n": 0, "draft_n_accepted": 0}}No newline at end of file1{"id": "chatcmpl-ee137d5e12f349f998471b11", "object": "chat.completion", "created": 1792314434, "model": "swift-1.5-k512-iq2xs", "choices": [{"index": 0, "message": {"role": "assistant", "content": "still ready"}, "finish_reason": "stop"}], "usage": {"prompt_tokens": 39, "completion_tokens": 3, "total_tokens": 42, "prompt_tokens_details": {"cached_tokens": 18}}, "timings": {"cache_n": 18, "prompt_n": 21, "prompt_ms": 278.0, "prompt_per_token_ms": 13.238, "prompt_per_second": 75.5, "predicted_n": 3, "predicted_ms": 139.7, "predicted_per_token_ms": 46.567, "predicted_per_second": 21.5, "draft_n": 0, "draft_n_accepted": 0}}No newline at end of file