mlx-bun 0.0.13 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (427) hide show
  1. package/README.md +71 -578
  2. package/bin/mlx-bun.mjs +1 -1
  3. package/docs/README.md +91 -0
  4. package/docs/{design → archive}/hlg-sampling.md +3 -3
  5. package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
  6. package/docs/{design → archive/investigations}/colibri-glm52-port.md +1 -1
  7. package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
  8. package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
  9. package/docs/{investigations → archive/investigations}/hlg-sampling-investigation.md +1 -1
  10. package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
  11. package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
  12. package/docs/archive/investigations/pareto-specialized-runtime-findings.md +92 -0
  13. package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
  14. package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
  15. package/docs/{planning → archive/planning}/chat-ui-vision.md +1 -1
  16. package/docs/{planning → archive/planning}/chunk-task-roadmap.md +1 -1
  17. package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +4 -4
  18. package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +1 -1
  19. package/docs/{planning → archive/planning}/release-notes-v0.0.9.md +1 -1
  20. package/docs/archive/planning/release-notes-v0.2.0.md +49 -0
  21. package/docs/{planning → archive/planning}/website-readme-pass-plan.md +1 -1
  22. package/docs/design/batching.md +569 -0
  23. package/docs/design/decode-speed-program.md +3178 -169
  24. package/docs/design/dreaming-nightly-pipeline.md +675 -282
  25. package/docs/design/generic-model-support.md +579 -334
  26. package/docs/design/kv-cache.md +680 -0
  27. package/docs/design/orpo-training.md +673 -1239
  28. package/docs/design/speculative-decoding.md +1627 -0
  29. package/docs/design/turboquant.md +2102 -0
  30. package/docs/design/unified-engine-frontier-plan.md +1831 -727
  31. package/docs/design/web-chat-redesign.md +666 -1083
  32. package/docs/planning/PRODUCT_ROADMAP.md +34 -1
  33. package/docs/planning/release-notes-v0.3.0.md +35 -0
  34. package/docs/planning/video-series.md +421 -0
  35. package/docs/reference/benchmarks.md +1162 -0
  36. package/docs/reference/cli.md +395 -149
  37. package/docs/reference/distribution.md +321 -181
  38. package/docs/reference/environment.md +348 -0
  39. package/docs/reference/glossary.md +39 -0
  40. package/docs/reference/library-api.md +580 -142
  41. package/docs/reference/memory.md +227 -64
  42. package/docs/reference/models.md +137 -6
  43. package/docs/reference/server-api.md +938 -422
  44. package/docs/reference/server-config.md +652 -320
  45. package/docs/reference/training.md +393 -254
  46. package/docs/reference/troubleshooting.md +166 -0
  47. package/package.json +10 -5
  48. package/src/admission-plan.ts +18 -0
  49. package/src/anthropic.ts +92 -3
  50. package/src/audio/decode.ts +2 -2
  51. package/src/audio/features.ts +2 -2
  52. package/src/backends/mlx/autoregressive.ts +108 -0
  53. package/src/backends/mlx/batch-group.ts +1646 -0
  54. package/src/backends/mlx/diffusion.ts +39 -0
  55. package/src/backends/mlx/draft-target.ts +47 -0
  56. package/src/backends/mlx/evaluation.ts +105 -0
  57. package/src/backends/mlx/fill-append.ts +45 -0
  58. package/src/backends/mlx/gateway-binding.ts +71 -0
  59. package/src/backends/mlx/graph.ts +38 -0
  60. package/src/backends/mlx/memory-client.ts +189 -0
  61. package/src/backends/mlx/memory-guard.ts +40 -0
  62. package/src/backends/mlx/methods.ts +90 -0
  63. package/src/backends/mlx/model-prompt.ts +164 -0
  64. package/src/backends/mlx/model-serving.ts +79 -0
  65. package/src/backends/mlx/prefill.ts +33 -0
  66. package/src/backends/mlx/request-policy.ts +20 -0
  67. package/src/backends/mlx/rollback.ts +51 -0
  68. package/src/backends/mlx/serial-executor.ts +273 -0
  69. package/src/backends/mlx/speculative.ts +114 -0
  70. package/src/backends/mlx/state-views.ts +26 -0
  71. package/src/backends/mlx/text-engine.ts +73 -0
  72. package/src/cli.ts +189 -61
  73. package/src/client.ts +66 -0
  74. package/src/config.ts +21 -4
  75. package/src/contracts/completion.ts +16 -0
  76. package/src/contracts/execution.ts +49 -0
  77. package/src/contracts/generation.ts +103 -0
  78. package/src/contracts/host.ts +7 -0
  79. package/src/contracts/jobs.ts +66 -0
  80. package/src/contracts/pi-provider.ts +30 -0
  81. package/src/contracts/pi.ts +259 -0
  82. package/src/contracts/resources.ts +18 -0
  83. package/src/contracts/scheduling.ts +27 -0
  84. package/src/contracts/tsconfig.json +14 -0
  85. package/src/diffusion/diffusion-generate.ts +218 -153
  86. package/src/embed.ts +1 -1
  87. package/src/engine/admission.ts +59 -0
  88. package/src/engine/cancellation.ts +38 -0
  89. package/src/engine/engine.ts +56 -0
  90. package/src/engine/execution-coordinator.ts +70 -0
  91. package/src/engine/execution-plan.ts +51 -0
  92. package/src/engine/resources.ts +42 -0
  93. package/src/engine/scheduler.ts +67 -0
  94. package/src/engine/session.ts +247 -0
  95. package/src/eval/README.md +44 -1
  96. package/src/eval/kl.ts +263 -23
  97. package/src/eval/reference-logits.ts +207 -0
  98. package/src/eval/runner.ts +10 -79
  99. package/src/eval/tasks/bfcl.ts +2 -1
  100. package/src/eval/tasks/gsm8k.ts +2 -1
  101. package/src/eval/tasks/hashhop.ts +2 -1
  102. package/src/eval/tasks/humaneval.ts +5 -4
  103. package/src/eval/tasks/ifeval.ts +2 -1
  104. package/src/eval/tasks/mmlu.ts +2 -1
  105. package/src/expert-io.ts +3 -1
  106. package/src/expert-offload.ts +3 -1
  107. package/src/fill/echo-index.ts +188 -0
  108. package/src/fill/fill-session.ts +452 -0
  109. package/src/fill/proposal.ts +68 -0
  110. package/src/fill/schema-rows.ts +506 -0
  111. package/src/fill/tool-boundary.ts +103 -0
  112. package/src/fit.ts +24 -43
  113. package/src/generate.ts +740 -337
  114. package/src/grammar.ts +14 -8
  115. package/src/harness-pi.ts +15 -34
  116. package/src/hub-rest.ts +4 -4
  117. package/src/index.ts +27 -0
  118. package/src/inference/denoising.ts +17 -0
  119. package/src/inference/graph.ts +33 -0
  120. package/src/inference/prefill.ts +39 -0
  121. package/src/inference/rollback.ts +7 -0
  122. package/src/jobs/db.ts +4 -0
  123. package/src/jobs/index.ts +2 -0
  124. package/src/jobs/job-entry.ts +15 -14
  125. package/src/jobs/runner.ts +98 -13
  126. package/src/jobs/task-client.ts +19 -0
  127. package/src/jobs/types.ts +2 -58
  128. package/src/kv-scheme.ts +199 -0
  129. package/src/kv-store.ts +459 -234
  130. package/src/lab/README.md +18 -0
  131. package/src/{assets → lab/curve}/curve-designer.html +2 -2
  132. package/src/{curve-sampler.ts → lab/curve/curve-sampler.ts} +2 -2
  133. package/src/{expert-trace.ts → lab/expert-trace/expert-trace.ts} +7 -5
  134. package/src/{model → lab/paged-kv}/paged-kv.ts +9 -6
  135. package/src/library.ts +40 -0
  136. package/src/lora.ts +18 -0
  137. package/src/media-fetch.ts +20 -4
  138. package/src/memory/article.ts +1 -1
  139. package/src/memory/chunk.ts +1 -1
  140. package/src/memory/model.ts +32 -170
  141. package/src/memory/prompts.ts +1 -1
  142. package/src/memory/rest.ts +1 -1
  143. package/src/memory/schedule.ts +1 -1
  144. package/src/memory/stages.ts +4 -1
  145. package/src/memory/vault.ts +3 -4
  146. package/src/mlx/array.ts +9 -10
  147. package/src/mlx/compile.ts +12 -2
  148. package/src/mlx/ffi.ts +66 -22
  149. package/src/mlx/materialize.ts +23 -0
  150. package/src/mlx/metal-kernel.ts +10 -11
  151. package/src/mlx/ops.ts +64 -19
  152. package/src/mlx/quantized-rows.ts +36 -0
  153. package/src/mlx/token-bitmask.ts +52 -0
  154. package/src/mlx/turboquant-kv-decode.ts +82 -0
  155. package/src/mlx/turboquant-kv-inverse.ts +122 -0
  156. package/src/mlx/turboquant-ops.ts +33 -3
  157. package/src/mlx/turboquant-tables.ts +2 -2
  158. package/src/model/batched-mask.ts +9 -3
  159. package/src/model/batched-quant.ts +2 -2
  160. package/src/model/batched-rotating-quant.ts +45 -99
  161. package/src/model/batched-rotating-state.ts +73 -0
  162. package/src/model/batched-rotating.ts +57 -106
  163. package/src/model/batched-row-storage.ts +127 -0
  164. package/src/model/compiled-decode.ts +4 -3
  165. package/src/model/diffusion-gemma.ts +8 -8
  166. package/src/model/factory.ts +87 -49
  167. package/src/model/fingerprint.ts +1 -1
  168. package/src/model/flash-attention.ts +3 -3
  169. package/src/model/gemma4-base.ts +187 -17
  170. package/src/model/gemma4.ts +6 -6
  171. package/src/model/generated/gemma4-12b.ts +52 -148
  172. package/src/model/generated/gemma4-26b.ts +34 -94
  173. package/src/model/generated/gemma4-e4b.ts +28 -76
  174. package/src/model/glm52-cache.ts +19 -9
  175. package/src/model/glm52-dsa.ts +13 -9
  176. package/src/model/glm52-memory.ts +28 -1
  177. package/src/model/implementation.ts +69 -0
  178. package/src/model/minicpm5.ts +7 -8
  179. package/src/model/profile.ts +443 -0
  180. package/src/model/qwen-append.ts +12 -0
  181. package/src/model/qwen-conv.ts +52 -0
  182. package/src/model/qwen3-delta.ts +98 -2
  183. package/src/model/qwen3-mrope.ts +252 -0
  184. package/src/model/qwen3_5-checkpoint.ts +164 -0
  185. package/src/model/qwen3_5.ts +336 -60
  186. package/src/model/support.ts +1 -1
  187. package/src/model/trellis-balanced-scatter.ts +51 -0
  188. package/src/model/trellis-linear.ts +672 -0
  189. package/src/model/trellis-shared-m.ts +151 -0
  190. package/src/model/trellis-shared-scatter.ts +144 -0
  191. package/src/model/trellis-splitk-prefill.ts +158 -0
  192. package/src/model/trellis-tiled-prefill.ts +136 -0
  193. package/src/model/trellis-vector-expand.ts +62 -0
  194. package/src/model/trellis-wide-prefill.ts +94 -0
  195. package/src/model/universal/dense.ts +1 -1
  196. package/src/model/universal/modules.ts +8 -1
  197. package/src/native/frame_extract.swift +140 -0
  198. package/src/native-pack.ts +15 -7
  199. package/src/pi-provider.ts +6 -64
  200. package/src/pi-web.ts +14 -320
  201. package/src/prompt-cache.ts +97 -54
  202. package/src/quantize/allocator.ts +1 -1
  203. package/src/quantize/atomic-output.ts +38 -0
  204. package/src/quantize/calibration.ts +2 -1
  205. package/src/quantize/config-writer.ts +16 -3
  206. package/src/quantize/index.ts +28 -1
  207. package/src/quantize/job.ts +11 -0
  208. package/src/quantize/quantizer.ts +265 -100
  209. package/src/quantize/rotate.ts +603 -0
  210. package/src/quantize/safetensors-writer.ts +79 -1
  211. package/src/quantize/sensitivity.ts +41 -59
  212. package/src/quantize/trellis.ts +586 -0
  213. package/src/quantize/weight-transform.ts +292 -0
  214. package/src/responses.ts +130 -3
  215. package/src/runtime-config.ts +81 -0
  216. package/src/sampler.ts +276 -4
  217. package/src/serve/admin-routes.ts +184 -0
  218. package/src/serve/aux-routes.ts +132 -0
  219. package/src/serve/batch-scheduler.ts +8 -1558
  220. package/src/serve/chat-request.ts +391 -0
  221. package/src/serve/chat-stage.ts +195 -0
  222. package/src/serve/checkpoint-identity.ts +64 -0
  223. package/src/serve/completion-executor.ts +354 -0
  224. package/src/serve/completion-sink.ts +157 -0
  225. package/src/serve/discovery-routes.ts +204 -0
  226. package/src/serve/generation-gateway.ts +211 -243
  227. package/src/serve/http.ts +159 -0
  228. package/src/serve/inference-request.ts +79 -0
  229. package/src/serve/isolate.ts +297 -105
  230. package/src/serve/kv-budget.ts +14 -0
  231. package/src/serve/lab-routes.ts +341 -0
  232. package/src/serve/lane-registry.ts +2 -1
  233. package/src/serve/model-admin-routes.ts +155 -0
  234. package/src/serve/model-binding.ts +43 -0
  235. package/src/serve/model-host.ts +512 -0
  236. package/src/serve/openai-wire.ts +103 -0
  237. package/src/serve/parent-application.ts +56 -0
  238. package/src/serve/pipeline.ts +33 -0
  239. package/src/serve/preparation.ts +33 -0
  240. package/src/serve/prompt-response-trace.ts +147 -0
  241. package/src/serve/request-plan.ts +162 -0
  242. package/src/serve/request-prep.ts +346 -0
  243. package/src/serve/response-lease.ts +24 -0
  244. package/src/serve/responses-client.ts +69 -0
  245. package/src/serve/session-completion-engine.ts +110 -0
  246. package/src/serve/session-search.ts +1 -1
  247. package/src/serve/static-routes.ts +101 -0
  248. package/src/serve/text-completion-stage.ts +104 -0
  249. package/src/serve/token-streams.ts +519 -0
  250. package/src/server.ts +523 -3551
  251. package/src/spec/assistant-source.ts +10 -44
  252. package/src/spec/deepspec-source.ts +6 -6
  253. package/src/spec/dflash-source.ts +9 -8
  254. package/src/spec/dspark/ab-stats.ts +3 -3
  255. package/src/spec/dspark/calibration.ts +2 -2
  256. package/src/spec/dspark/deepspec-module.ts +2 -2
  257. package/src/spec/dspark/generate-dflash.ts +2 -2
  258. package/src/spec/dspark/generate.ts +2 -2
  259. package/src/spec/dspark/loader.ts +1 -1
  260. package/src/spec/dspark/module-dflash.ts +5 -4
  261. package/src/spec/dspark/module.ts +3 -3
  262. package/src/spec/dspark/quantize-drafter.ts +1 -1
  263. package/src/spec/generate.ts +1 -1
  264. package/src/spec/glm52-mtp-source.ts +9 -1
  265. package/src/spec/ngram-source.ts +1 -1
  266. package/src/spec/prefix-state.ts +45 -0
  267. package/src/spec/qwen-mtp-source.ts +528 -0
  268. package/src/spec/serve-loop.ts +179 -213
  269. package/src/spec/source.ts +42 -10
  270. package/src/spec/two-model.ts +1 -1
  271. package/src/ssd-cache.ts +95 -24
  272. package/src/ssd-durability.ts +207 -0
  273. package/src/tool-call.ts +51 -14
  274. package/src/train/flash-cce.ts +14 -13
  275. package/src/train/forward.ts +38 -1
  276. package/src/train/loss.ts +3 -2
  277. package/src/train/prefix-shared.ts +5 -1
  278. package/src/train/segmented.ts +9 -6
  279. package/src/train/trainer.ts +9 -8
  280. package/src/vision/preprocess.ts +1 -1
  281. package/src/vision/prompt.ts +48 -2
  282. package/src/vision/qwen3vl-preprocess.ts +409 -0
  283. package/src/vision/qwen3vl-prompt.ts +196 -0
  284. package/src/vision/qwen3vl-tower.ts +555 -0
  285. package/src/vision/video-frames.ts +148 -0
  286. package/src/web/app.html +1 -1
  287. package/src/web/app.js +15 -6
  288. package/src/web/src/adapters-panel.ts +3 -3
  289. package/src/web/src/assistant.ts +2 -36
  290. package/src/web/src/chat.ts +16 -9
  291. package/src/web/src/composer.ts +4 -4
  292. package/src/web/src/hub.ts +1 -1
  293. package/src/web/src/markdown.ts +0 -0
  294. package/src/web/src/memory-panel.ts +1 -1
  295. package/src/web/src/model-picker.ts +1 -1
  296. package/src/web/src/palette.ts +1 -1
  297. package/src/web/src/protocol.ts +3 -39
  298. package/src/web/src/sessions.ts +1 -1
  299. package/src/web/src/ui-catalog.ts +4 -18
  300. package/src/web-assets.ts +47 -0
  301. package/src/weights.ts +134 -33
  302. package/docs/archive/mlx-bun-lab-report.html +0 -275
  303. package/docs/archive/wwdc-mlx-bun.html +0 -848
  304. package/docs/design/adapters-end-to-end.md +0 -205
  305. package/docs/design/batching-perf-path.md +0 -255
  306. package/docs/design/batching-v2-plan.md +0 -529
  307. package/docs/design/bucketing-stage.md +0 -197
  308. package/docs/design/compat-cli-surface-design.md +0 -230
  309. package/docs/design/docs-reorg-plan.md +0 -165
  310. package/docs/design/dspark-serving-program.md +0 -371
  311. package/docs/design/dspark-speculative-decoding.md +0 -268
  312. package/docs/design/grammar-spec-batching-integration.md +0 -301
  313. package/docs/design/memory-inference-path.md +0 -422
  314. package/docs/design/memory-synthesis.md +0 -287
  315. package/docs/design/memory-system.md +0 -237
  316. package/docs/design/mlx-lm-tool-parity-plan.md +0 -545
  317. package/docs/design/omlx-adoption-map.md +0 -98
  318. package/docs/design/orpo-dynamic-lambda.md +0 -220
  319. package/docs/design/orpo-future-enhancements.md +0 -340
  320. package/docs/design/paged-kv-cache.md +0 -214
  321. package/docs/design/parallel-slots.md +0 -567
  322. package/docs/design/parity-tier-dag.md +0 -161
  323. package/docs/design/repo-cleanup-plan.md +0 -189
  324. package/docs/design/runtime-isolation.md +0 -263
  325. package/docs/design/segmented-backward-training.md +0 -543
  326. package/docs/design/spec-decode-larger-targets.md +0 -229
  327. package/docs/design/ssd-kv-cold-tier.md +0 -288
  328. package/docs/design/structured-output.md +0 -484
  329. package/docs/design/tauri-desktop-app.md +0 -127
  330. package/docs/design/the-dreaming-master-plan.md +0 -445
  331. package/docs/design/turboquant-kv.md +0 -235
  332. package/docs/design/w4a16-compute-precision-spike.md +0 -232
  333. package/docs/design/web-chat-beat-matrix.md +0 -315
  334. package/docs/design/write-pipeline-entity.md +0 -468
  335. package/docs/investigations/curve-runs/bisector-route.json +0 -98
  336. package/docs/investigations/curve-runs/bisector-trace.json +0 -1393
  337. package/docs/investigations/curve-runs/curve-terrain.json +0 -1179
  338. package/docs/investigations/curve-runs/curve-terrain.svg +0 -42
  339. package/docs/investigations/hlg-ab.html +0 -34
  340. package/docs/investigations/hlg-explorer.html +0 -238
  341. package/docs/investigations/hlg-figs/cliff.svg +0 -1
  342. package/docs/investigations/hlg-figs/cross.svg +0 -1
  343. package/docs/investigations/hlg-figs/edges.svg +0 -1
  344. package/docs/investigations/hlg-figs/k20-grids.svg +0 -1
  345. package/docs/investigations/hlg-figs/k20-peaks.svg +0 -1
  346. package/docs/investigations/hlg-figs/lw-curve.svg +0 -1
  347. package/docs/investigations/hlg-figs/terrain.svg +0 -1
  348. package/docs/investigations/hlg-report.html +0 -262
  349. package/docs/investigations/hlg-runs/hlg-ab.json +0 -149
  350. package/docs/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
  351. package/docs/investigations/hlg-runs/hlg-blind.json +0 -107
  352. package/docs/investigations/hlg-runs/hlg-cliff.json +0 -197
  353. package/docs/investigations/hlg-runs/hlg-cross.json +0 -505
  354. package/docs/investigations/hlg-runs/hlg-edge.json +0 -388
  355. package/docs/investigations/hlg-runs/hlg-eval1.json +0 -25
  356. package/docs/investigations/hlg-runs/hlg-frontier.json +0 -86
  357. package/docs/investigations/hlg-runs/hlg-grid.json +0 -242
  358. package/docs/investigations/hlg-runs/hlg-grid2.json +0 -343
  359. package/docs/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
  360. package/docs/investigations/hlg-runs/hlg-map.json +0 -383
  361. package/docs/investigations/hlg-runs/run0-original.log +0 -159
  362. package/docs/investigations/hlg-runs/runA-recommended.log +0 -131
  363. package/docs/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
  364. package/docs/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
  365. package/docs/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
  366. package/docs/investigations/hlg-runs/runAD-ab-samples.log +0 -8
  367. package/docs/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
  368. package/docs/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
  369. package/docs/investigations/hlg-runs/runAG-eval-config2.log +0 -16
  370. package/docs/investigations/hlg-runs/runB-gain-variants.log +0 -192
  371. package/docs/investigations/hlg-runs/runC-pivots.log +0 -162
  372. package/docs/investigations/hlg-runs/runD-oetf.log +0 -132
  373. package/docs/investigations/hlg-runs/runE-eotf.log +0 -162
  374. package/docs/investigations/hlg-runs/runF-shaper-working.log +0 -86
  375. package/docs/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
  376. package/docs/investigations/hlg-runs/runH-wsweep.log +0 -176
  377. package/docs/investigations/hlg-runs/runI-asweep.log +0 -176
  378. package/docs/investigations/hlg-runs/runJ-knobmap.log +0 -49
  379. package/docs/investigations/hlg-runs/runK-frontier.log +0 -19
  380. package/docs/investigations/hlg-runs/runL-widemap.log +0 -65
  381. package/docs/investigations/hlg-runs/runM-frontier-emb.log +0 -15
  382. package/docs/investigations/hlg-runs/runN-verify.log +0 -116
  383. package/docs/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
  384. package/docs/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
  385. package/docs/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
  386. package/docs/investigations/hlg-runs/runR-blind-transcript.log +0 -79
  387. package/docs/investigations/hlg-runs/runS-cross-coherence.log +0 -33
  388. package/docs/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
  389. package/docs/investigations/hlg-runs/runU-cross-12b.log +0 -33
  390. package/docs/investigations/hlg-runs/runV-lw-e4b.log +0 -22
  391. package/docs/investigations/hlg-runs/runW-lw-12b.log +0 -22
  392. package/docs/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
  393. package/docs/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
  394. package/docs/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
  395. package/docs/planning/IDEAS.md +0 -69
  396. package/docs/reference/embedding.md +0 -197
  397. package/docs/reference/features-matrix.md +0 -100
  398. package/docs/reference/orpo-quickstart.md +0 -135
  399. package/src/flags.ts +0 -13
  400. /package/docs/{investigations → archive/investigations}/chunk-finetune-experiment.md +0 -0
  401. /package/docs/{investigations → archive/investigations}/colibri-oracle-pin.md +0 -0
  402. /package/docs/{investigations → archive/investigations}/curve-bisector-routing.md +0 -0
  403. /package/docs/{investigations → archive/investigations}/decode-roofline-lookagain.md +0 -0
  404. /package/docs/{investigations → archive/investigations}/dspark-handoff.md +0 -0
  405. /package/docs/{investigations → archive/investigations}/expert-offload-single-user-moe.md +0 -0
  406. /package/docs/{investigations → archive/investigations}/indexshare-performance-spike.md +0 -0
  407. /package/docs/{investigations → archive/investigations}/kernel-perf-review-2026-07.md +0 -0
  408. /package/docs/{investigations → archive/investigations}/lab-build-journal.md +0 -0
  409. /package/docs/{investigations → archive/investigations}/openwiki-evaluation.md +0 -0
  410. /package/docs/{investigations → archive/investigations}/orpo-base-uf-experiment-and-directions.md +0 -0
  411. /package/docs/{investigations → archive/investigations}/orpo-flash-cce-pin-leak.md +0 -0
  412. /package/docs/{investigations → archive/investigations}/orpo-uf-testing-handoff.md +0 -0
  413. /package/docs/{investigations → archive/investigations}/pi-builtin-investigation.md +0 -0
  414. /package/docs/{investigations → archive/investigations}/segmented-backward-handoff.md +0 -0
  415. /package/docs/{investigations → archive/investigations}/starter-model-port-handoff.md +0 -0
  416. /package/docs/{investigations → archive/investigations}/steel-flash-cce-handoff.md +0 -0
  417. /package/docs/{investigations → archive/investigations}/trainer-validation-experiment.md +0 -0
  418. /package/docs/{planning → archive/planning}/chat-ui-vision-memory-first.md +0 -0
  419. /package/docs/{planning → archive/planning}/journal.md +0 -0
  420. /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
  421. /package/docs/{planning → archive/planning}/release-notes-v0.0.10.md +0 -0
  422. /package/docs/{planning → archive/planning}/release-notes-v0.0.11.md +0 -0
  423. /package/docs/{planning → archive/planning}/release-notes-v0.0.12.md +0 -0
  424. /package/docs/{planning → archive/planning}/release-notes-v0.0.13.md +0 -0
  425. /package/docs/{planning → archive/planning}/web-ui-pass-plan.md +0 -0
  426. /package/{docs/investigations → src/serve/assets}/curve-terrain.html +0 -0
  427. /package/{docs/dag → src/serve/assets}/training-inference-map.html +0 -0
@@ -1,42 +0,0 @@
1
- <svg viewBox="0 0 980 560" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="t d" font-family="ui-sans-serif,system-ui,sans-serif">
2
- <title id="t">Curve terrain map</title>
3
- <desc id="d">First-pass terrain of custom log-prob curves. X is mid y at one percent, Y is shoulder y at nine percent, Z is rough diversity delta after junk penalty.</desc>
4
- <rect width="980" height="560" fill="#f7f9fc"/>
5
- <text x="38" y="42" font-size="22" font-weight="700" fill="#172033">Curve Terrain Map</text>
6
- <text x="38" y="65" font-size="12.5" fill="#667085">mlx-community/gemma-4-e4b-it-OptiQ-4bit · N=2 · seed=7300 · default diversity 0.803 · score = diversity delta minus junk penalty</text>
7
- <g transform="translate(250 50)"><path d="M130.0 340.0 L187.5 360.5 L245.0 381.0 L302.5 285.2 " fill="none" stroke="#cbd5e1" stroke-width="1"/><path d="M74.6 315.3 L132.1 340.0 L189.6 360.7 L247.1 327.2 L304.6 276.9 " fill="none" stroke="#cbd5e1" stroke-width="1"/><path d="M23.6 322.2 L81.1 342.7 L138.6 418.5 L196.1 364.9 L253.6 397.3 " fill="none" stroke="#cbd5e1" stroke-width="1"/><path d="M-37.1 235.0 L20.4 255.4 L77.9 300.3 L135.4 324.3 L192.9 343.7 " fill="none" stroke="#cbd5e1" stroke-width="1"/><path d="M-100.0 408.8 L-42.5 364.0 L15.0 348.4 L72.5 318.5 L130.0 339.0 " fill="none" stroke="#cbd5e1" stroke-width="1"/><path d="M130.0 340.0 L74.6 315.3 L23.6 322.2 L-37.1 235.0 L-100.0 408.8 " fill="none" stroke="#cbd5e1" stroke-width="1"/><path d="M187.5 360.5 L132.1 340.0 L81.1 342.7 L20.4 255.4 L-42.5 364.0 " fill="none" stroke="#cbd5e1" stroke-width="1"/><path d="M245.0 381.0 L189.6 360.7 L138.6 418.5 L77.9 300.3 L15.0 348.4 " fill="none" stroke="#cbd5e1" stroke-width="1"/><path d="M302.5 285.2 L247.1 327.2 L196.1 364.9 L135.4 324.3 L72.5 318.5 " fill="none" stroke="#cbd5e1" stroke-width="1"/><path d="M304.6 276.9 L253.6 397.3 L192.9 343.7 L130.0 339.0 " fill="none" stroke="#cbd5e1" stroke-width="1"/><circle cx="-37.1" cy="235.0" r="9.0" fill="rgb(8,145,178)" stroke="white" stroke-width="2">
8
- <title>mid=0.5, shoulder=28, diversity=0.999, score=0.196, junk=0.0%</title></circle><circle cx="20.4" cy="255.4" r="9.0" fill="rgb(8,145,178)" stroke="white" stroke-width="2">
9
- <title>mid=1, shoulder=28, diversity=0.999, score=0.196, junk=0.0%</title></circle><circle cx="304.6" cy="276.9" r="9.0" fill="rgb(8,145,178)" stroke="white" stroke-width="2">
10
- <title>mid=8, shoulder=10, diversity=1.000, score=0.197, junk=0.0%</title></circle><circle cx="302.5" cy="285.2" r="7.8" fill="rgb(17,131,195)" stroke="white" stroke-width="2">
11
- <title>mid=4, shoulder=6, diversity=0.922, score=0.119, junk=0.0%</title></circle><circle cx="77.9" cy="300.3" r="8.4" fill="rgb(12,138,187)" stroke="white" stroke-width="2">
12
- <title>mid=2, shoulder=28, diversity=0.960, score=0.157, junk=0.0%</title></circle><circle cx="74.6" cy="315.3" r="6.1" fill="rgb(29,111,220)" stroke="white" stroke-width="2">
13
- <title>mid=0.5, shoulder=10, diversity=0.806, score=0.003, junk=0.0%</title></circle><circle cx="72.5" cy="318.5" r="9.0" fill="rgb(8,145,178)" stroke="white" stroke-width="2">
14
- <title>mid=4, shoulder=50, diversity=1.000, score=0.197, junk=0.0%</title></circle><circle cx="23.6" cy="322.2" r="6.4" fill="rgb(27,115,216)" stroke="white" stroke-width="2">
15
- <title>mid=0.5, shoulder=16, diversity=0.825, score=0.022, junk=0.0%</title></circle><circle cx="135.4" cy="324.3" r="8.3" fill="rgb(13,137,188)" stroke="white" stroke-width="2">
16
- <title>mid=4, shoulder=28, diversity=0.955, score=0.152, junk=0.0%</title></circle><circle cx="247.1" cy="327.2" r="7.3" fill="rgb(20,125,203)" stroke="white" stroke-width="2">
17
- <title>mid=4, shoulder=10, diversity=0.886, score=0.083, junk=0.0%</title></circle><circle cx="130.0" cy="339.0" r="9.0" fill="rgb(8,145,178)" stroke="white" stroke-width="2">
18
- <title>mid=8, shoulder=50, diversity=1.000, score=0.197, junk=0.0%</title></circle><circle cx="130.0" cy="340.0" r="5.0" fill="rgb(37,99,235)" stroke="white" stroke-width="2">
19
- <title>mid=0.5, shoulder=6, diversity=0.735, score=-0.068, junk=0.0%</title></circle><circle cx="132.1" cy="340.0" r="6.0" fill="rgb(30,110,221)" stroke="white" stroke-width="2">
20
- <title>mid=1, shoulder=10, diversity=0.800, score=-0.003, junk=0.0%</title></circle><circle cx="81.1" cy="342.7" r="6.4" fill="rgb(27,115,216)" stroke="white" stroke-width="2">
21
- <title>mid=1, shoulder=16, diversity=0.825, score=0.022, junk=0.0%</title></circle><circle cx="192.9" cy="343.7" r="8.3" fill="rgb(13,137,187)" stroke="white" stroke-width="2">
22
- <title>mid=8, shoulder=28, diversity=0.956, score=0.153, junk=0.0%</title></circle><circle cx="15.0" cy="348.4" r="7.8" fill="rgb(17,131,195)" stroke="white" stroke-width="2">
23
- <title>mid=2, shoulder=50, diversity=0.919, score=0.116, junk=0.0%</title></circle><circle cx="187.5" cy="360.5" r="5.0" fill="rgb(37,99,235)" stroke="white" stroke-width="2">
24
- <title>mid=1, shoulder=6, diversity=0.735, score=-0.068, junk=0.0%</title></circle><circle cx="189.6" cy="360.7" r="6.0" fill="rgb(30,110,221)" stroke="white" stroke-width="2">
25
- <title>mid=2, shoulder=10, diversity=0.799, score=-0.004, junk=0.0%</title></circle><circle cx="-42.5" cy="364.0" r="6.9" fill="rgb(23,121,208)" stroke="white" stroke-width="2">
26
- <title>mid=1, shoulder=50, diversity=0.861, score=0.058, junk=0.0%</title></circle><circle cx="196.1" cy="364.9" r="6.8" fill="rgb(24,120,209)" stroke="white" stroke-width="2">
27
- <title>mid=4, shoulder=16, diversity=0.855, score=0.052, junk=0.0%</title></circle><circle cx="245.0" cy="381.0" r="5.0" fill="rgb(37,99,235)" stroke="white" stroke-width="2">
28
- <title>mid=2, shoulder=6, diversity=0.735, score=-0.068, junk=0.0%</title></circle><circle cx="253.6" cy="397.3" r="6.5" fill="rgb(26,116,213)" stroke="white" stroke-width="2">
29
- <title>mid=8, shoulder=16, diversity=0.836, score=0.033, junk=0.0%</title></circle><circle cx="-100.0" cy="408.8" r="5.3" fill="rgb(35,103,230)" stroke="white" stroke-width="2">
30
- <title>mid=0.5, shoulder=50, diversity=0.767, score=-0.047, junk=0.1%</title></circle><circle cx="138.6" cy="418.5" r="5.0" fill="rgb(37,99,235)" stroke="white" stroke-width="2">
31
- <title>mid=2, shoulder=16, diversity=0.736, score=-0.067, junk=0.0%</title></circle></g>
32
- <g transform="translate(38 420)">
33
- <text x="0" y="0" font-size="14" font-weight="700" fill="#172033">Highest first-pass cells</text><text x="0" y="24" font-size="12.5" fill="#344054">1. mid 8, shoulder 50 · diversity 1.000 · score 0.197 · junk 0.0%</text><text x="0" y="46" font-size="12.5" fill="#344054">2. mid 4, shoulder 50 · diversity 1.000 · score 0.197 · junk 0.0%</text><text x="0" y="68" font-size="12.5" fill="#344054">3. mid 8, shoulder 10 · diversity 1.000 · score 0.197 · junk 0.0%</text><text x="0" y="90" font-size="12.5" fill="#344054">4. mid 1, shoulder 28 · diversity 0.999 · score 0.196 · junk 0.0%</text><text x="0" y="112" font-size="12.5" fill="#344054">5. mid 0.5, shoulder 28 · diversity 0.999 · score 0.196 · junk 0.0%</text></g>
34
- <g transform="translate(742 420)">
35
- <rect x="0" y="-18" width="170" height="12" fill="url(#grad)"/>
36
- <defs><linearGradient id="grad"><stop offset="0" stop-color="#2563eb"/><stop offset="1" stop-color="#0891b2"/></linearGradient></defs>
37
- <text x="0" y="10" font-size="11.5" fill="#667085">low score</text>
38
- <text x="112" y="10" font-size="11.5" fill="#667085">high score</text>
39
- <text x="0" y="34" font-size="11.5" fill="#667085">red points would indicate junk penalty</text>
40
- </g>
41
- <text x="526" y="528" text-anchor="middle" font-size="12" fill="#667085">x: mid y@1% · y: shoulder y@9% · z: rough terrain score</text>
42
- </svg>
@@ -1,34 +0,0 @@
1
- <!doctype html><html lang="en"><head><meta charset="utf-8">
2
- <meta name="viewport" content="width=device-width,initial-scale=1"><title>HLG A/B samples</title><style>
3
- :root{--text:#1f2937;--text2:#475569;--text3:#94a3b8;--bg:#f7f9fc;--card:#fff;--bd:#e2e8f0;--grid:#f1f5f9}
4
- *{box-sizing:border-box}
5
- body{margin:0;background:var(--bg);color:var(--text);font:15px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",ui-sans-serif,system-ui,sans-serif;-webkit-font-smoothing:antialiased}
6
- .wrap{max-width:1240px;margin:0 auto;padding:34px 22px 100px}
7
- h1{font-size:25px;margin:0 0 3px;letter-spacing:-.02em}
8
- .sub{color:var(--text2);font-size:14.5px;max-width:780px;margin:0 0 8px}
9
- .legend{display:flex;flex-wrap:wrap;gap:14px;margin:14px 0 26px;font-size:13px}
10
- .legend .c{display:flex;gap:8px;align-items:baseline;background:var(--card);border:1px solid var(--bd);border-radius:10px;padding:8px 13px}
11
- .legend .dot{width:10px;height:10px;border-radius:3px;flex:none;position:relative;top:1px}
12
- .legend b{font-weight:700}.legend .d{color:var(--text3);font-size:12px}
13
- .card{background:var(--card);border:1px solid var(--bd);border-radius:14px;padding:18px 20px;margin:0 0 20px;box-shadow:0 1px 2px rgba(15,23,42,.04),0 10px 30px -24px rgba(15,23,42,.2)}
14
- .q{font-size:12px;text-transform:uppercase;letter-spacing:.06em;color:var(--text3);font-weight:700}
15
- .qt{font-size:16px;font-weight:600;margin:3px 0 16px}
16
- .cols{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
17
- @media(max-width:900px){.cols{grid-template-columns:1fr}}
18
- .col h3{font-size:13px;margin:0 0 9px;display:flex;align-items:center;gap:8px}
19
- .col h3 .dot{width:9px;height:9px;border-radius:3px}
20
- .col h3 .d{font-weight:400;color:var(--text3);font-size:11.5px}
21
- .samp{font-size:13.5px;color:#0f172a;background:var(--grid);border-radius:9px;padding:9px 11px;margin:0 0 8px;border-left:3px solid transparent}
22
- .samp .n{color:var(--text3);font-weight:700;font-size:11px;margin-right:6px}
23
- .note{font-size:13px;color:var(--text3);margin-top:28px;border-top:1px solid var(--bd);padding-top:14px}
24
- </style></head>
25
- <body><div class="wrap">
26
- <h1>HLG sampling — side-by-side samples</h1>
27
- <p class="sub">The same prompts, sampled three ways on <b>gemma-4-e4b-it-OptiQ-4bit</b> (3 samples each, fixed seeds). Only the
28
- sampling method changes. Read down a column to feel each sampler's character; read across to compare on one prompt.</p>
29
- <div class="legend"><div class="c"><span class="dot" style="background:#64748b"></span><div><b>Default recipe</b> &nbsp;<span class="d">the model's recommended sampler — T=1, top-p=0.95, top-k=64</span></div></div><div class="c"><span class="dot" style="background:#2563eb"></span><div><b>HLG base</b> &nbsp;<span class="d">A=0.35, s_m=0.7, target_gap=15, W=6</span></div></div><div class="c"><span class="dot" style="background:#0891b2"></span><div><b>HLG loose-A</b> &nbsp;<span class="d">A=0.01 (the diversity-leaning shoulder), rest as base</span></div></div></div>
30
- <div class="card"><div class="q">creative</div><div class="qt">Write the first sentence of a short story about a lighthouse keeper who discovers something strange in the fog.</div><div class="cols"><div class="col"><h3><span class="dot" style="background:#64748b"></span>Default recipe<span class="d">A</span></h3><div class="samp" style="border-left-color:#64748b"><span class="n">1</span>The fog, a thick, greasy blanket that clung to the granite tower like a shroud, always held secrets, but this morning, it delivered something far stranger than the usual drift of unseen seabirds.</div><div class="samp" style="border-left-color:#64748b"><span class="n">2</span>The thick, soupy fog that perpetually hugged the granite tower seemed to thicken further that night, muffling the roar of the ocean until it felt less like the sea and more like a vast, wet sigh, and then he saw it—a perfectly smooth, obsidian sphere bobbing just beyond the reach of his lantern beam.</div><div class="samp" style="border-left-color:#64748b"><span class="n">3</span>The fog, a thick, clammy shroud clinging to the granite tower, seemed to pulse with an unnatural life as Silas scanned the churning grey expanse.</div></div><div class="col"><h3><span class="dot" style="background:#2563eb"></span>HLG base<span class="d">B</span></h3><div class="samp" style="border-left-color:#2563eb"><span class="n">1</span>The fog, a thick, clammy blanket that swallowed the beam of the lamp, usually brought with it the familiar scent of salt and damp stone, but tonight, a faint, metallic tang drifted in, something utterly alien against the backdrop of the churning grey.</div><div class="samp" style="border-left-color:#2563eb"><span class="n">2</span>The fog, a thick, clammy blanket that swallowed the beam of the old tower, pressed against Silas’s windowpane, and it was in that suffocating grey that he first saw the impossible.</div><div class="samp" style="border-left-color:#2563eb"><span class="n">3</span>The fog, a thick, clammy shroud that swallowed the horizon whole, seemed to press against the glass of the lantern room, and it was in that oppressive whiteness that Silas first saw the impossible flicker.</div></div><div class="col"><h3><span class="dot" style="background:#0891b2"></span>HLG loose-A<span class="d">C</span></h3><div class="samp" style="border-left-color:#0891b2"><span class="n">1</span>The fog, a thick, milky blanket that clung to the granite cliffs like wet wool, always held secrets, but this evening, something decidedly out of place drifted through its milky shroud.</div><div class="samp" style="border-left-color:#0891b2"><span class="n">2</span>The relentless, clinging fog had been his only constant companion for three lonely weeks, until tonight, when a splash of unnatural emerald light pierced the milky grey swirling just beyond the tower's narrow beam.</div><div class="samp" style="border-left-color:#0891b2"><span class="n">3</span>The thick, soupy fog that clung to the coast had been a familiar, monotonous blanket for Elias for three years, but this morning, something broke through it.</div></div></div></div><div class="card"><div class="q">continuation</div><div class="qt">Complete this thought in a vivid, original way: 'The strangest thing about human memory is'</div><div class="cols"><div class="col"><h3><span class="dot" style="background:#64748b"></span>Default recipe<span class="d">A</span></h3><div class="samp" style="border-left-color:#64748b"><span class="n">1</span>'The strangest thing about human memory is **how it doesn't archive life; it remixes it.** It’s less a library and more a chaotic, brilliant tapestry where the scent of old rain from a childhood picnic might instantly trigger the bittersweet ache of a grief felt last week, seamlessly weaving the textures of two entirely different selves into a single, shimmering, unreliable present.'</div><div class="samp" style="border-left-color:#64748b"><span class="n">2</span>'The strangest thing about human memory is **how it doesn't catalog events, but rather *re-forges* them—a warm, unreliable tapestry woven from the brilliant threads of feeling, the frayed edges of suggestion, and the perfectly smooth, utterly fictional comfort of what we desperately wish had happened.**'</div><div class="samp" style="border-left-color:#64748b"><span class="n">3</span>'The strangest thing about human memory is **how it feels less like a recording and more like an act of tireless, beautiful, and often treacherous reconstruction.** It's not a dusty film reel; it's a restless alchemist's laboratory, where yesterday's sunlight is re-mixed with today's doubt, and the ghosts of forgotten moments shimmer into the present, always slightly rearranged, always colored by the urgent, vibrant necessity</div></div><div class="col"><h3><span class="dot" style="background:#2563eb"></span>HLG base<span class="d">B</span></h3><div class="samp" style="border-left-color:#2563eb"><span class="n">1</span>'The strangest thing about human memory is **how it doesn't archive; it *re-weaves*. It’s not a library where you pull a perfect volume from the shelf, but a loom where every recollection is re-threaded with the anxieties, the triumphs, and the sheer, messy passage of time, making the past less a fixed photograph and more a perpetually shifting, emotionally charged watercolor.**'</div><div class="samp" style="border-left-color:#2563eb"><span class="n">2</span>'The strangest thing about human memory is **how it doesn't archive; it *re-weaves*. It’s not a pristine library of moments, but a tapestry constantly being re-spun by the present, where the sharp edges of yesterday soften, the crucial details bleed into the background noise, and the emotional resonance of a forgotten Tuesday can suddenly bloom with the blinding, illogical clarity of a perfect, remembered sunset.**'</div><div class="samp" style="border-left-color:#2563eb"><span class="n">3</span>'The strangest thing about human memory is **how it doesn't archive events; it *re-weaves* them, a tapestry where the scent of rain from a childhood summer can suddenly bleed into the sharp, metallic tang of a present-day anxiety, making us believe we are recalling a perfect moment when, in reality, we are just listening to the echo of a feeling.**'</div></div><div class="col"><h3><span class="dot" style="background:#0891b2"></span>HLG loose-A<span class="d">C</span></h3><div class="samp" style="border-left-color:#0891b2"><span class="n">1</span>'The strangest thing about human memory is **how it acts like a kaleidoscope of forgotten dreams, capable of reassembling a perfect, polished vista of a past moment—a scent, the slant of light through a childhood window, the exact timbre of a forgotten argument—only to reveal, upon closer inspection, that the very foundation of that flawless image is made of shimmering, ill-fitting glass.**'</div><div class="samp" style="border-left-color:#0891b2"><span class="n">2</span>'The strangest thing about human memory is **how it doesn't catalog the past like a library, but rather re-authors it in the dusty, flickering spotlight of the present, leaving behind echoes of who we were, rather than the immutable blueprint of what actually occurred.**'</div><div class="samp" style="border-left-color:#0891b2"><span class="n">3</span>'The strangest thing about human memory is **how it acts less like a meticulously filed archive, and more like a perpetually haunted attic—a chaotic, dust-mote-filled space where forgotten sunlight sometimes illuminates a moment with such blinding, visceral clarity that you can still smell the rain on the cobblestones of a life you've long since left behind.**'</div></div></div></div><div class="card"><div class="q">factual</div><div class="qt">In one sentence, what causes the seasons on Earth?</div><div class="cols"><div class="col"><h3><span class="dot" style="background:#64748b"></span>Default recipe<span class="d">A</span></h3><div class="samp" style="border-left-color:#64748b"><span class="n">1</span>The seasons on Earth are caused by the tilt of the planet's axis as it revolves around the Sun.</div><div class="samp" style="border-left-color:#64748b"><span class="n">2</span>The Earth's tilt on its axis as it revolves around the Sun is what causes the seasons.</div><div class="samp" style="border-left-color:#64748b"><span class="n">3</span>The Earth's axial tilt of approximately 23.5 degrees as it orbits the sun causes the changing seasons.</div></div><div class="col"><h3><span class="dot" style="background:#2563eb"></span>HLG base<span class="d">B</span></h3><div class="samp" style="border-left-color:#2563eb"><span class="n">1</span>The seasons on Earth are caused by the tilt of the Earth's axis as it revolves around the Sun.</div><div class="samp" style="border-left-color:#2563eb"><span class="n">2</span>The seasons on Earth are caused by the tilt of the planet's axis as it revolves around the Sun.</div><div class="samp" style="border-left-color:#2563eb"><span class="n">3</span>The Earth's axial tilt, combined with its revolution around the Sun, causes the changing seasons.</div></div><div class="col"><h3><span class="dot" style="background:#0891b2"></span>HLG loose-A<span class="d">C</span></h3><div class="samp" style="border-left-color:#0891b2"><span class="n">1</span>The seasons on Earth are caused by the tilt of the planet's axis as it revolves around the Sun.</div><div class="samp" style="border-left-color:#0891b2"><span class="n">2</span>The Earth's tilt on its axis combined with its revolution around the Sun causes the changing seasons.</div><div class="samp" style="border-left-color:#0891b2"><span class="n">3</span>The Earth's axial tilt of approximately 23.5 degrees combined with its orbit around the sun is what causes the seasons.</div></div></div></div><div class="card"><div class="q">explain</div><div class="qt">Explain in two sentences why the sky is blue.</div><div class="cols"><div class="col"><h3><span class="dot" style="background:#64748b"></span>Default recipe<span class="d">A</span></h3><div class="samp" style="border-left-color:#64748b"><span class="n">1</span>The sky appears blue because of a phenomenon called Rayleigh scattering, where the Earth's atmosphere scatters shorter, blue-wavelength sunlight more effectively than longer, red wavelengths. This scattered blue light reaches our eyes from all directions, making the sky look blue.</div><div class="samp" style="border-left-color:#64748b"><span class="n">2</span>The sky appears blue because of a phenomenon called Rayleigh scattering. Sunlight, when entering the Earth's atmosphere, is scattered by nitrogen and oxygen molecules, with the shorter, blue wavelengths being scattered more effectively in all directions.</div><div class="samp" style="border-left-color:#64748b"><span class="n">3</span>The sky appears blue because of a phenomenon called Rayleigh scattering. This causes shorter, blue wavelengths of sunlight to be scattered more effectively by the molecules in the Earth's atmosphere than longer, red wavelengths.</div></div><div class="col"><h3><span class="dot" style="background:#2563eb"></span>HLG base<span class="d">B</span></h3><div class="samp" style="border-left-color:#2563eb"><span class="n">1</span>The sky appears blue because of a phenomenon called Rayleigh scattering. This process causes shorter, blue wavelengths of sunlight to be scattered more effectively by the molecules in the Earth's atmosphere than longer, redder wavelengths.</div><div class="samp" style="border-left-color:#2563eb"><span class="n">2</span>The sky appears blue because of a phenomenon called Rayleigh scattering. This occurs when sunlight enters the Earth's atmosphere and its shorter, blue-wavelength light is scattered more effectively by the tiny molecules of the atmosphere than the longer, redder wavelengths.</div><div class="samp" style="border-left-color:#2563eb"><span class="n">3</span>The sky appears blue because of a phenomenon called Rayleigh scattering. This process causes shorter, blue wavelengths of sunlight to be scattered more effectively by the molecules in the Earth's atmosphere than longer, red wavelengths.</div></div><div class="col"><h3><span class="dot" style="background:#0891b2"></span>HLG loose-A<span class="d">C</span></h3><div class="samp" style="border-left-color:#0891b2"><span class="n">1</span>The sky appears blue because of a phenomenon called Rayleigh scattering, where molecules of oxygen and nitrogen in the atmosphere scatter shorter, higher-energy blue wavelengths of sunlight more effectively than longer wavelengths. This scattering effect spreads the blue light across the entire sky, making it appear blue to our eyes.</div><div class="samp" style="border-left-color:#0891b2"><span class="n">2</span>The sky appears blue because of a phenomenon called Rayleigh scattering. This scattering of sunlight by the Earth's atmosphere preferentially scatters shorter, blue wavelengths of light across the sky in all directions.</div><div class="samp" style="border-left-color:#0891b2"><span class="n">3</span>The sky appears blue because of a phenomenon called Rayleigh scattering. This causes shorter, blue wavelengths of sunlight to be scattered more effectively by the molecules in the Earth's atmosphere than longer, red wavelengths.</div></div></div></div><div class="card"><div class="q">lateral</div><div class="qt">Give one unusual but genuinely plausible use for a paperclip, in a sentence.</div><div class="cols"><div class="col"><h3><span class="dot" style="background:#64748b"></span>Default recipe<span class="d">A</span></h3><div class="samp" style="border-left-color:#64748b"><span class="n">1</span>A tightly rolled paperclip can serve as a surprisingly effective, miniature shim to stabilize a slightly wobbly piece of delicate electronic equipment.</div><div class="samp" style="border-left-color:#64748b"><span class="n">2</span>A sturdy paperclip could be fashioned into a temporary, improvised fishing hook to snag small aquatic life during an emergency outing.</div><div class="samp" style="border-left-color:#64748b"><span class="n">3</span>A paperclip can be bent into a surprisingly effective, miniature fishing hook for retrieving small, lost items from narrow crevices.</div></div><div class="col"><h3><span class="dot" style="background:#2563eb"></span>HLG base<span class="d">B</span></h3><div class="samp" style="border-left-color:#2563eb"><span class="n">1</span>A paperclip could be bent into a makeshift, temporary hook to retrieve a dropped earring from a narrow drain.</div><div class="samp" style="border-left-color:#2563eb"><span class="n">2</span>A paperclip could be meticulously straightened and used as a temporary, fine-gauge shim to level a slightly wobbly antique picture frame.</div><div class="samp" style="border-left-color:#2563eb"><span class="n">3</span>A paperclip could be bent into a makeshift, temporary antenna to boost a weak radio signal during an outdoor emergency.</div></div><div class="col"><h3><span class="dot" style="background:#0891b2"></span>HLG loose-A<span class="d">C</span></h3><div class="samp" style="border-left-color:#0891b2"><span class="n">1</span>A paperclip could be bent into a miniature, temporary hook to retrieve a dropped earring from a tight spot behind a piece of furniture.</div><div class="samp" style="border-left-color:#0891b2"><span class="n">2</span>A paperclip, carefully bent, can serve as a makeshift, temporary shim to level a slightly uneven tripod leg on a camera in a pinch.</div><div class="samp" style="border-left-color:#0891b2"><span class="n">3</span>A paperclip can be bent into a surprisingly effective, albeit makeshift, reset pin for a jammed electronic device.</div></div></div></div><div class="card"><div class="q">voice</div><div class="qt">Describe the feeling of a city at 3am in one vivid sentence.</div><div class="cols"><div class="col"><h3><span class="dot" style="background:#64748b"></span>Default recipe<span class="d">A</span></h3><div class="samp" style="border-left-color:#64748b"><span class="n">1</span>The city at 3 am hums with a spectral energy, a mélange of distant sirens, the rhythmic sigh of cooling concrete, and the isolated echoes of late-night human solitude.</div><div class="samp" style="border-left-color:#64748b"><span class="n">2</span>The city at 3 am hums with a skeletal, phosphorescent energy, a vast, tired beast breathing slowly between the last echoes of the day's clamor and the relentless arrival of dawn.</div><div class="samp" style="border-left-color:#64748b"><span class="n">3</span>The city breathes a ragged, neon-streaked sigh of lonely industry, a vast, half-asleep beast illuminated by the spectral glow of forgotten streetlights.</div></div><div class="col"><h3><span class="dot" style="background:#2563eb"></span>HLG base<span class="d">B</span></h3><div class="samp" style="border-left-color:#2563eb"><span class="n">1</span>The city at 3 am is a vast, hushed beast, exhaling the metallic scent of cooling asphalt under the lonely, sodium-orange glow of forgotten streetlights.</div><div class="samp" style="border-left-color:#2563eb"><span class="n">2</span>The city at 3 am is a vast, humming beast, exhaling the cool, metallic scent of asphalt and the lonely, rhythmic sigh of distant sirens against a backdrop of deep, bruised indigo.</div><div class="samp" style="border-left-color:#2563eb"><span class="n">3</span>The city at 3 am is a vast, breathing beast, its neon veins pulsing with the ghosts of late-night revelers and the low, rhythmic hum of the sleeping concrete.</div></div><div class="col"><h3><span class="dot" style="background:#0891b2"></span>HLG loose-A<span class="d">C</span></h3><div class="samp" style="border-left-color:#0891b2"><span class="n">1</span>The city at 3 am hums with a solitary, neon-drenched exhaustion, a low thrum of secrets and forgotten sirens weaving through the skeletal geometry of sleeping giants.</div><div class="samp" style="border-left-color:#0891b2"><span class="n">2</span>The city at 3 am hums with a skeletal, phosphorescent energy, a vast, hushed beast whose only movements are the lonely sweep of headlights across slick asphalt and the distant, rhythmic sigh of the ventilation units.</div><div class="samp" style="border-left-color:#0891b2"><span class="n">3</span>The city breathes a humid, neon-tinged quiet, a skeletal monument to forgotten daytime revelry under a velvet-black sky.</div></div></div></div>
31
- <p class="note">Generated by <code>scripts/hlg-ab.ts</code> → <code>scripts/hlg-ab-html.ts</code>. Notice how <b>HLG base</b> tends to
32
- converge on a single strong continuation (lower diversity — the tight shoulder concentrates on the high-probability path), while
33
- <b>HLG loose-A</b> spreads out — the same behavior the diversity sweeps measured, here in plain text.</p>
34
- </div></body></html>
@@ -1,238 +0,0 @@
1
- <!doctype html><html lang="en"><head><meta charset="utf-8">
2
- <meta name="viewport" content="width=device-width,initial-scale=1">
3
- <title>HLG Sampling Explorer — real logits</title>
4
- <style>
5
- :root{--text:#1f2937;--text2:#475569;--text3:#94a3b8;--bg:#f7f9fc;--card:#fff;--bd:#e2e8f0;
6
- --accent:#2563eb;--accent2:#0891b2;--pos:#16a34a;--warn:#d97706;--danger:#dc2626;--grid:#eef2f7;--gray:#94a3b8;}
7
- *{box-sizing:border-box}
8
- html,body{height:100%;margin:0;overflow:hidden}
9
- body{background:var(--bg);color:var(--text);font:13px/1.4 -apple-system,BlinkMacSystemFont,"Segoe UI",ui-sans-serif,system-ui,sans-serif;-webkit-font-smoothing:antialiased}
10
- .app{height:100vh;display:grid;grid-template-columns:minmax(380px,42%) 1fr;gap:14px;padding:14px}
11
- .panel{background:var(--card);border:1px solid var(--bd);border-radius:12px;padding:12px 14px;box-shadow:0 1px 2px rgba(15,23,42,.04),0 10px 30px -24px rgba(15,23,42,.2);min-height:0;overflow:auto}
12
- .controls{display:flex;flex-direction:column}
13
- h1{font-size:15px;margin:0;letter-spacing:-.01em}
14
- .topbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:7px}
15
- .presets{display:flex;flex-wrap:wrap;gap:5px;margin-left:auto}
16
- .presets button{font:600 11px/1 inherit;padding:6px 9px;border:1px solid var(--bd);background:var(--card);border-radius:7px;cursor:pointer;color:var(--text2)}
17
- .presets button:hover{border-color:var(--accent);color:var(--accent)}
18
- .presets button.reset{color:var(--danger);border-color:#f3d6d6}
19
- .presets button.copy{background:var(--accent);color:#fff;border-color:var(--accent)}
20
- .distsel{display:flex;gap:5px;margin-bottom:8px;flex-wrap:wrap}
21
- .distsel button{font:600 11px/1 inherit;padding:6px 9px;border:1px solid var(--bd);background:var(--grid);border-radius:7px;cursor:pointer;color:var(--text2)}
22
- .distsel button.on{background:var(--accent);color:#fff;border-color:var(--accent)}
23
- .copyrow{display:flex;gap:6px;align-items:center;margin-bottom:9px}
24
- .copyrow input{flex:1;font:11px/1.3 ui-monospace,SFMono-Regular,Menlo,monospace;border:1px solid var(--bd);border-radius:7px;padding:6px 8px;background:var(--grid);color:#0f172a}
25
- .copyrow .ok{font-size:11px;font-weight:700;color:var(--pos);min-width:46px}
26
- .grid2{display:grid;grid-template-columns:1fr 1fr;gap:6px 16px;align-content:start}
27
- .gh{grid-column:1/-1;font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text3);margin:6px 0 0;border-top:1px solid var(--bd);padding-top:7px}
28
- .gh:first-child{border-top:none;padding-top:0;margin-top:0}
29
- .cell label{display:flex;justify-content:space-between;align-items:baseline;font-size:11.5px;font-weight:600;gap:6px}
30
- .cell label .v{font-weight:700;color:var(--accent);font-variant-numeric:tabular-nums;font-size:12px}
31
- .cell input[type=range]{width:100%;accent-color:var(--accent);height:16px;cursor:pointer;margin:1px 0 0}
32
- .figs{display:flex;flex-direction:column;gap:8px}
33
- .figs .panel{padding:8px 12px}
34
- .fh{font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--text2);font-weight:700;margin:0 0 2px}
35
- .fh small{font-weight:400;text-transform:none;letter-spacing:0;color:var(--text3)}
36
- svg{width:100%;height:auto;display:block}
37
- .legend{display:flex;gap:13px;flex-wrap:wrap;font-size:10.5px;color:var(--text2);margin-top:3px}
38
- .legend span{display:inline-flex;align-items:center;gap:5px}.legend i{width:14px;height:3px;border-radius:2px;display:inline-block}
39
- .readouts{display:grid;grid-template-columns:repeat(4,1fr);gap:7px;margin-top:6px}
40
- .ro{background:var(--grid);border-radius:7px;padding:5px 8px}
41
- .ro .k{font-size:9px;text-transform:uppercase;letter-spacing:.04em;color:var(--text3)}
42
- .ro .val{font-size:14px;font-weight:700;font-variant-numeric:tabular-nums}
43
- @media(max-width:820px){.app{grid-template-columns:1fr;height:auto;overflow:auto}html,body{overflow:auto}}
44
- </style></head>
45
- <body>
46
- <div class="app">
47
- <div class="panel controls">
48
- <div class="topbar"><h1>HLG Explorer · real logits</h1>
49
- <div class="presets">
50
- <button data-preset="base">Base</button><button data-preset="loose">Loose-A</button>
51
- <button data-preset="sharp">Sharp</button><button data-preset="base" class="reset">Reset</button>
52
- <button id="copyBtn" class="copy">Copy Values</button>
53
- </div>
54
- </div>
55
- <div class="distsel" id="distsel"></div>
56
- <div class="copyrow"><input id="cfgField" readonly spellcheck="false"><span class="ok" id="copyOk"></span></div>
57
- <div class="grid2" id="grid"></div>
58
- </div>
59
- <div class="figs">
60
- <div class="panel">
61
- <div class="fh">Transfer curve <small>· real tokens mapped on by their logits — watch them pile into the toe</small></div>
62
- <div id="curve"></div>
63
- <div class="legend"><span><i style="background:var(--accent)"></i>OETF</span><span><i style="background:var(--accent2)"></i>after γ</span><span><i style="background:var(--text3)"></i>temp (linear)</span><span><i style="background:var(--warn);height:8px;width:8px;border-radius:50%"></i>tokens</span></div>
64
- <div class="readouts" id="readouts"></div>
65
- </div>
66
- <div class="panel">
67
- <div class="fh">Distribution over the full 262k vocab <small>· x = rank (log) · y = probability (log)</small></div>
68
- <div id="dist"></div>
69
- <div class="legend"><span><i style="background:var(--gray)"></i>raw softmax</span><span><i style="background:var(--pos)"></i>default recipe (top-p·top-k)</span><span><i style="background:var(--accent)"></i>HLG</span><span><i style="background:var(--warn);height:9px;width:2px"></i>W reaches here</span></div>
70
- <div class="readouts" id="distro"></div>
71
- </div>
72
- </div>
73
- </div>
74
-
75
- <script src="hlg-figs/hlg-logits.js"></script>
76
- <script>
77
- const DISTS = (window.REAL_LOGITS||[]).map(d=>({...d, sorted:Float64Array.from(d.sorted)}));
78
- let di = DISTS.length? DISTS.findIndex(d=>d.tag==="creative") : -1; if(di<0) di=0;
79
-
80
- const DEF = { window:8, A:0.35, sM:0.7, targetGap:15, refGap:4, lw:1200, xM:0.55, yM:0.5, xFloor:0.2, yFloor:0.18, p:2.0, T:1.0, topP:0.95, topK:64 };
81
- const PRESETS = { base:{...DEF}, loose:{...DEF,A:0.01}, sharp:{...DEF,targetGap:40,sM:2.0,A:0.2} };
82
- const P = {...DEF};
83
-
84
- const GROUPS = [
85
- {h:"HLG — primary", items:[
86
- {k:"window",label:"W — window (nats)",min:1,max:40,step:0.5},
87
- {k:"A",label:"A — shoulder",min:0.01,max:5,step:0.01},
88
- {k:"sM",label:"s_m — mid slope",min:0.05,max:6,step:0.05},
89
- {k:"targetGap",label:"target_gap",min:4,max:50,step:1},
90
- {k:"lw",label:"L_W (γ)",min:0,max:6,step:0.02,log:true},
91
- {k:"refGap",label:"refGap",min:1,max:20,step:0.5},
92
- ]},
93
- {h:"HLG — geometry", items:[
94
- {k:"xM",label:"x_M",min:0.3,max:0.8,step:0.01},{k:"yM",label:"y_M",min:0.3,max:0.7,step:0.01},
95
- {k:"xFloor",label:"x_floor",min:0.05,max:0.45,step:0.01},{k:"yFloor",label:"y_floor",min:0.05,max:0.45,step:0.01},
96
- {k:"p",label:"p — mid power",min:1.2,max:4,step:0.05},
97
- ]},
98
- {h:"Default recipe (the standard sampler)", items:[
99
- {k:"T",label:"temperature",min:0.1,max:2,step:0.05},{k:"topP",label:"top-p",min:0.1,max:1,step:0.01},{k:"topK",label:"top-k",min:1,max:512,step:1},
100
- ]},
101
- ];
102
- const ALL = GROUPS.flatMap(g=>g.items);
103
- const lwToS=lw=>Math.log10(lw), sToLw=s=>Math.pow(10,s);
104
-
105
- function buildGrid(){
106
- const c=document.getElementById("grid"); c.innerHTML="";
107
- for(const g of GROUPS){ const h=document.createElement("div"); h.className="gh"; h.textContent=g.h; c.appendChild(h);
108
- for(const s of g.items){ const d=document.createElement("div"); d.className="cell";
109
- d.innerHTML=`<label>${s.label}<span class="v" id="v_${s.k}"></span></label><input type="range" id="s_${s.k}" min="${s.min}" max="${s.max}" step="${s.step}" value="${s.log?lwToS(P[s.k]):P[s.k]}">`;
110
- c.appendChild(d);
111
- d.querySelector("input").addEventListener("input",e=>{P[s.k]=s.log?sToLw(parseFloat(e.target.value)):parseFloat(e.target.value); render();});
112
- }
113
- }
114
- }
115
- function buildDistSel(){
116
- const c=document.getElementById("distsel"); c.innerHTML="";
117
- if(!DISTS.length){ c.innerHTML='<span style="color:var(--danger);font-size:11px">hlg-logits.js not loaded — run scripts/hlg-capture-logits.ts</span>'; return; }
118
- DISTS.forEach((d,i)=>{ const b=document.createElement("button"); b.textContent=`${d.tag} · ${d.entropyBits}b`; if(i===di)b.className="on";
119
- b.addEventListener("click",()=>{di=i; buildDistSel(); prep(); render();}); c.appendChild(b); });
120
- }
121
-
122
- // ---- shaper ----
123
- function geom(){
124
- const {xM,yM,xFloor,yFloor,p,sM,A,lw,window:W,targetGap,refGap}=P;
125
- const dxf=xM-xFloor, kc=(yM-sM*dxf-yFloor)/Math.pow(dxf,p), sFloor=sM+kc*p*Math.pow(dxf,p-1);
126
- const det=-Math.pow(xFloor,4), ec=(yFloor*2*xFloor-xFloor*xFloor*sFloor)/det, fc=(Math.pow(xFloor,3)*sFloor-yFloor*3*xFloor*xFloor)/det;
127
- const yPeak=yM+A*Math.log(1+(sM/A)*(1-xM)), gamma=1.2+0.42*Math.log10(Math.max(lw,1e-3)/1000);
128
- const oetfS=x=>{let y; if(x>=xM)y=yM+A*Math.log(Math.max(1+(sM/A)*(x-xM),1e-9)); else if(x>=xFloor)y=yM-sM*(xM-x)-kc*Math.pow(Math.max(xM-x,0),p); else y=ec*x*x*x+fc*x*x; return Math.max(y,0);};
129
- const shapeS=x=>Math.pow(Math.max(oetfS(x)/yPeak,1e-9),gamma);
130
- const xRef=Math.max(0,Math.min(1,1-refGap/W)), outScale=targetGap/Math.max(1e-6,1-shapeS(xRef));
131
- return {gamma,yPeak,outScale,xRef,oetfS,shapeS};
132
- }
133
-
134
- // ---- per-distribution prep ----
135
- let D=null;
136
- function logsumexp(arr,n){ let m=-1e30; for(let i=0;i<n;i++) if(arr[i]>m)m=arr[i]; let s=0; for(let i=0;i<n;i++) s+=Math.exp(arr[i]-m); return m+Math.log(s); }
137
- function prep(){
138
- if(!DISTS.length){ D=null; return; }
139
- const d=DISTS[di], s=d.sorted, V=s.length, lmax=s[0];
140
- const rawLse=logsumexp(s,V);
141
- // log-spaced sample ranks for rendering (+ dense head)
142
- const ranks=new Set(); for(let i=0;i<64;i++) ranks.add(i);
143
- const N=360, lV=Math.log10(V); for(let i=0;i<=N;i++) ranks.add(Math.min(V-1,Math.round(Math.pow(10,(i/N)*lV))-0+0));
144
- const sr=[...ranks].filter(r=>r<V).sort((a,b)=>a-b);
145
- D={s,V,lmax,rawLse,sr,tag:d.tag,ent:d.entropyBits};
146
- }
147
-
148
- // ---- distribution computations ----
149
- function probsAt(g){
150
- const {s,V,lmax,rawLse,sr}=D, {shapeS,outScale}=g, W=P.window;
151
- // raw
152
- const raw=sr.map(r=>Math.exp(s[r]-rawLse));
153
- // HLG: only tokens within W of top leave the toe; rest are the constant toe value
154
- let inWin=0; const thr=lmax-W; while(inWin<V && s[inWin]>thr) inWin++;
155
- const toeShaped=outScale*shapeS(0);
156
- const shapedOf=r=>{ if(r>=inWin) return toeShaped; const x=Math.max(0,Math.min(1,(s[r]-lmax)/W+1)); return outScale*shapeS(x); };
157
- let mx=toeShaped; for(let i=0;i<inWin;i++){ const v=shapedOf(i); if(v>mx)mx=v; }
158
- let Z=(V-inWin)*Math.exp(toeShaped-mx); for(let i=0;i<inWin;i++) Z+=Math.exp(shapedOf(i)-mx);
159
- const hlgLse=mx+Math.log(Z);
160
- const hlg=sr.map(r=>Math.exp(shapedOf(r)-hlgLse));
161
- // default recipe: temp → full softmax → keep top-p ∩ top-k → renormalize
162
- const T=P.T; const scaled=new Float64Array(V); for(let i=0;i<V;i++) scaled[i]=s[i]/T;
163
- const sLse=T===1?(rawLse):logsumexp(scaled,V);
164
- let cum=0, mset=V; for(let i=0;i<V;i++){ cum+=Math.exp(scaled[i]-sLse); if(cum>=P.topP){ mset=i+1; break; } }
165
- const keep=Math.max(1,Math.min(Math.round(P.topK),mset));
166
- let dZ=logsumexp(scaled.subarray(0,keep),keep);
167
- const def=sr.map(r=>r<keep?Math.exp(scaled[r]-dZ):0);
168
- return {raw,hlg,def,inWin,keep,hlgTop1:Math.exp(shapedOf(0)-hlgLse)};
169
- }
170
-
171
- // ---- curve panel ----
172
- const CW=560,CH=210,ML=42,MR=14,MT=15,MB=30;
173
- const cx=x=>ML+x*(CW-ML-MR), cy=(y,ym)=>MT+(1-y/ym)*(CH-MT-MB);
174
- const poly=(fn,ym,n=140)=>{let d="";for(let i=0;i<=n;i++){const x=i/n;d+=(i?"L":"M")+cx(x).toFixed(1)+" "+cy(fn(x),ym).toFixed(1)+" ";}return d;};
175
- function drawCurve(g){
176
- const {oetfS,yPeak,shapeS}=g, oetfN=x=>Math.max(0,oetfS(x)/yPeak);
177
- let ym=1; for(let i=0;i<=140;i++){const x=i/140; ym=Math.max(ym,oetfN(x),shapeS(x));} ym=Math.min(ym,8);
178
- let s=`<svg viewBox="0 0 ${CW} ${CH}" font-family="inherit">`;
179
- s+=`<rect x="${cx(0)}" y="${MT}" width="${cx(P.xFloor)-cx(0)}" height="${CH-MT-MB}" fill="#fde2e2" opacity=".5"/><rect x="${cx(P.xFloor)}" y="${MT}" width="${cx(P.xM)-cx(P.xFloor)}" height="${CH-MT-MB}" fill="#fff3d6" opacity=".5"/><rect x="${cx(P.xM)}" y="${MT}" width="${cx(1)-cx(P.xM)}" height="${CH-MT-MB}" fill="#dcfce7" opacity=".5"/>`;
180
- s+=`<text x="${(cx(0)+cx(P.xFloor))/2}" y="${MT+11}" text-anchor="middle" font-size="9" fill="#b91c1c">toe</text><text x="${(cx(P.xFloor)+cx(P.xM))/2}" y="${MT+11}" text-anchor="middle" font-size="9" fill="#92400e">mid</text><text x="${(cx(P.xM)+cx(1))/2}" y="${MT+11}" text-anchor="middle" font-size="9" fill="#166534">shoulder</text>`;
181
- for(let f=0;f<=1.0001;f+=0.25){const yv=f*ym; s+=`<line x1="${ML}" y1="${cy(yv,ym)}" x2="${CW-MR}" y2="${cy(yv,ym)}" stroke="var(--grid)"/>`;}
182
- s+=`<line x1="${cx(0)}" y1="${cy(0,ym)}" x2="${cx(1)}" y2="${cy(1,ym)}" stroke="var(--text3)" stroke-width="1.3" stroke-dasharray="5 4"/>`;
183
- for(const xv of [P.xFloor,P.xM]) s+=`<line x1="${cx(xv)}" y1="${MT}" x2="${cx(xv)}" y2="${CH-MB}" stroke="var(--text3)" stroke-dasharray="2 3" opacity=".6"/>`;
184
- s+=`<path d="${poly(oetfN,ym)}" fill="none" stroke="var(--accent)" stroke-width="2.2"/><path d="${poly(shapeS,ym)}" fill="none" stroke="var(--accent2)" stroke-width="2.2"/>`;
185
- // real tokens: top 80 mapped on by logit
186
- if(D){ const n=Math.min(80,D.V); for(let r=0;r<n;r++){ const x=Math.max(0,Math.min(1,(D.s[r]-D.lmax)/P.window+1)); s+=`<circle cx="${cx(x)}" cy="${cy(shapeS(x),ym)}" r="${r===0?3.4:2.4}" fill="var(--warn)" stroke="#fff" stroke-width="0.8" opacity="${r===0?1:0.7}"/>`; } }
187
- s+=`<text x="${(ML+CW-MR)/2}" y="${CH-3}" text-anchor="middle" font-size="9.5" fill="var(--text2)">signal x (1 = top token · 0 = ≥W nats below)</text>`;
188
- if(g.gamma<0) s+=`<text x="${(ML+CW-MR)/2}" y="${MT+28}" text-anchor="middle" font-size="11" font-weight="700" fill="var(--danger)">γ&lt;0 — ranking inverts (incoherent)</text>`;
189
- s+=`</svg>`; document.getElementById("curve").innerHTML=s;
190
- }
191
-
192
- // ---- distribution panel (log rank × log prob) ----
193
- const DW=560,DH=210,DL=44,DR=12,DT=12,DB=30, PLO=-7;
194
- function dx(r){ return DL+(Math.log10(r+1)/Math.log10(D.V))*(DW-DL-DR); }
195
- function dy(p){ const lp=p>0?Math.log10(p):PLO; return DT+(1-(Math.max(lp,PLO)-PLO)/(0-PLO))*(DH-DT-DB); }
196
- function linePath(arr){ let d="",started=false; for(let i=0;i<D.sr.length;i++){ const r=D.sr[i],p=arr[i]; if(p<=0){started=false;continue;} d+=(started?"L":"M")+dx(r).toFixed(1)+" "+dy(p).toFixed(1)+" "; started=true; } return d; }
197
- function drawDist(pr){
198
- if(!D){ document.getElementById("dist").innerHTML='<div style="padding:30px;text-align:center;color:var(--text3)">no real logits loaded</div>'; document.getElementById("distro").innerHTML=""; return; }
199
- let s=`<svg viewBox="0 0 ${DW} ${DH}" font-family="inherit">`;
200
- for(let e=0;e>=PLO;e--){ const yy=dy(Math.pow(10,e)); s+=`<line x1="${DL}" y1="${yy}" x2="${DW-DR}" y2="${yy}" stroke="var(--grid)"/><text x="${DL-5}" y="${yy+3}" text-anchor="end" font-size="8" fill="var(--text3)">1e${e}</text>`; }
201
- for(let e=0;Math.pow(10,e)<D.V;e++){ const xx=dx(Math.pow(10,e)); s+=`<line x1="${xx}" y1="${DT}" x2="${xx}" y2="${DH-DB}" stroke="var(--grid)"/><text x="${xx}" y="${DH-DB+12}" text-anchor="middle" font-size="8" fill="var(--text3)">${e===0?"1":"1e"+e}</text>`; }
202
- s+=`<text x="${(DL+DW-DR)/2}" y="${DH-2}" text-anchor="middle" font-size="9" fill="var(--text2)">token rank (sorted by logit) →</text>`;
203
- // W reach marker
204
- let inWin=pr.inWin; s+=`<line x1="${dx(inWin)}" y1="${DT}" x2="${dx(inWin)}" y2="${DH-DB}" stroke="var(--warn)" stroke-width="1.6" stroke-dasharray="3 2"/>`;
205
- s+=`<line x1="${dx(pr.keep)}" y1="${DT}" x2="${dx(pr.keep)}" y2="${DH-DB}" stroke="var(--pos)" stroke-width="1.2" stroke-dasharray="2 3" opacity=".7"/>`;
206
- s+=`<path d="${linePath(pr.raw)}" fill="none" stroke="var(--gray)" stroke-width="2"/>`;
207
- s+=`<path d="${linePath(pr.def)}" fill="none" stroke="var(--pos)" stroke-width="2"/>`;
208
- s+=`<path d="${linePath(pr.hlg)}" fill="none" stroke="var(--accent)" stroke-width="2"/>`;
209
- s+=`</svg>`; document.getElementById("dist").innerHTML=s;
210
- }
211
-
212
- function cfgJSON(){ return JSON.stringify({window:P.window,A:P.A,sM:P.sM,targetGap:P.targetGap,refGap:P.refGap,lw:Math.round(P.lw),xM:P.xM,yM:P.yM,xFloor:P.xFloor,yFloor:P.yFloor,p:P.p}); }
213
- function render(){
214
- for(const sl of ALL){ const el=document.getElementById("v_"+sl.k); if(!el)continue;
215
- el.textContent = sl.k==="lw"?Math.round(P.lw).toLocaleString():(Number.isInteger(P[sl.k])?P[sl.k]:P[sl.k].toFixed(2)); }
216
- const g=geom(); drawCurve(g);
217
- const ro=[["γ",g.gamma.toFixed(2)],["out_scale",g.outScale.toFixed(1)],["tokens in W",D?probsAt(g).inWin:"—"],["x_ref",g.xRef.toFixed(2)]];
218
- let pr=null; if(D){ pr=probsAt(g); drawDist(pr);
219
- const dr=[["HLG top-1",(pr.hlg[0]*100).toFixed(1)+"%"],["raw top-1",(pr.raw[0]*100).toFixed(1)+"%"],["default keeps",pr.keep],["W reaches rank",pr.inWin]];
220
- document.getElementById("distro").innerHTML=dr.map(([k,v])=>`<div class="ro"><div class="k">${k}</div><div class="val">${v}</div></div>`).join("");
221
- }
222
- // curve readouts (recompute inWin cheaply)
223
- const ro2=[["γ",g.gamma.toFixed(2)],["out_scale",g.outScale.toFixed(1)],["tokens in W",pr?pr.inWin:"—"],["dist",D?`${D.tag} (${D.ent}b)`:"—"]];
224
- document.getElementById("readouts").innerHTML=ro2.map(([k,v])=>`<div class="ro"><div class="k">${k}</div><div class="val" style="font-size:${String(v).length>8?11:14}px">${v}</div></div>`).join("");
225
- document.getElementById("cfgField").value=cfgJSON();
226
- }
227
- function applyPreset(n){ Object.assign(P,PRESETS[n]); for(const sl of ALL){ const inp=document.getElementById("s_"+sl.k); if(inp) inp.value=sl.log?lwToS(P[sl.k]):P[sl.k]; } render(); }
228
- function copyValues(){ const txt=cfgJSON(), ok=document.getElementById("copyOk"); const done=()=>{ok.textContent="Copied!";setTimeout(()=>ok.textContent="",1600);};
229
- if(navigator.clipboard&&navigator.clipboard.writeText) navigator.clipboard.writeText(txt).then(done,()=>{fb(txt);done();}); else {fb(txt);done();} }
230
- function fb(t){ const f=document.getElementById("cfgField"); f.focus(); f.select(); try{document.execCommand("copy");}catch(e){} }
231
-
232
- buildGrid(); buildDistSel(); prep();
233
- document.querySelectorAll(".presets button[data-preset]").forEach(b=>b.addEventListener("click",()=>applyPreset(b.dataset.preset)));
234
- document.getElementById("copyBtn").addEventListener("click",copyValues);
235
- document.getElementById("cfgField").addEventListener("click",e=>e.target.select());
236
- render();
237
- </script>
238
- </body></html>
@@ -1 +0,0 @@
1
- <svg viewBox="0 0 920 450" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="t d" font-family="ui-sans-serif,system-ui,sans-serif"><title id="t">HLG cliff resolution — two shapes</title><desc id="d">Fine junk% gradient through the target_gap cliff (a graded ramp, position shifts by vocab) and the W lower edge at high A (a sharp model-invariant edge near 7.5), three models.</desc><text x="460" y="30" text-anchor="middle" font-size="16.5" font-weight="700" fill="var(--text-primary,#1f2937)">Fine cliff resolution — the coarse grid jumped over two different shapes</text><text x="460" y="49" text-anchor="middle" font-size="11.5" fill="var(--text-secondary,#6b7280)">unit steps · mean canary junk% (K=5 seeds) · the transition the 8/12 and 5/10 jumps hid</text><text x="244" y="42" text-anchor="middle" font-size="14" font-weight="700" fill="var(--text-primary,#1f2937)">target_gap cliff — a graded ramp</text><text x="244" y="58" text-anchor="middle" font-size="10.5" fill="var(--text-secondary,#6b7280)">base (A=0.35, s_m=0.7, W=6) · position shifts by vocab</text><line x1="44" y1="380" x2="444" y2="380" stroke="var(--border,#e5e7eb)" stroke-opacity="0.6"/><text x="36" y="384" text-anchor="end" font-size="10" fill="var(--text-tertiary,#9ca3af)">0%</text><line x1="44" y1="291.17647058823525" x2="444" y2="291.17647058823525" stroke="var(--border,#e5e7eb)" stroke-opacity="0.6"/><text x="36" y="295.17647058823525" text-anchor="end" font-size="10" fill="var(--text-tertiary,#9ca3af)">10%</text><line x1="44" y1="202.35294117647058" x2="444" y2="202.35294117647058" stroke="var(--border,#e5e7eb)" stroke-opacity="0.6"/><text x="36" y="206.35294117647058" text-anchor="end" font-size="10" fill="var(--text-tertiary,#9ca3af)">20%</text><line x1="44" y1="113.52941176470588" x2="444" y2="113.52941176470588" stroke="var(--border,#e5e7eb)" stroke-opacity="0.6"/><text x="36" y="117.52941176470588" text-anchor="end" font-size="10" fill="var(--text-tertiary,#9ca3af)">30%</text><line x1="44" y1="371.11764705882354" x2="444" y2="371.11764705882354" stroke="var(--positive,#16a34a)" stroke-width="1.2" stroke-dasharray="5 3" stroke-opacity="0.8"/><text x="444" y="367.11764705882354" text-anchor="end" font-size="9.5" fill="var(--positive,#16a34a)">coherent &lt;1%</text><line x1="44" y1="380" x2="44" y2="384" stroke="var(--text-tertiary,#9ca3af)"/><text x="44" y="397" text-anchor="middle" font-size="10" fill="var(--text-secondary,#6b7280)">7</text><line x1="110.66666666666666" y1="380" x2="110.66666666666666" y2="384" stroke="var(--text-tertiary,#9ca3af)"/><text x="110.66666666666666" y="397" text-anchor="middle" font-size="10" fill="var(--text-secondary,#6b7280)">8</text><line x1="177.33333333333331" y1="380" x2="177.33333333333331" y2="384" stroke="var(--text-tertiary,#9ca3af)"/><text x="177.33333333333331" y="397" text-anchor="middle" font-size="10" fill="var(--text-secondary,#6b7280)">9</text><line x1="244" y1="380" x2="244" y2="384" stroke="var(--text-tertiary,#9ca3af)"/><text x="244" y="397" text-anchor="middle" font-size="10" fill="var(--text-secondary,#6b7280)">10</text><line x1="310.66666666666663" y1="380" x2="310.66666666666663" y2="384" stroke="var(--text-tertiary,#9ca3af)"/><text x="310.66666666666663" y="397" text-anchor="middle" font-size="10" fill="var(--text-secondary,#6b7280)">11</text><line x1="377.33333333333337" y1="380" x2="377.33333333333337" y2="384" stroke="var(--text-tertiary,#9ca3af)"/><text x="377.33333333333337" y="397" text-anchor="middle" font-size="10" fill="var(--text-secondary,#6b7280)">12</text><line x1="444" y1="380" x2="444" y2="384" stroke="var(--text-tertiary,#9ca3af)"/><text x="444" y="397" text-anchor="middle" font-size="10" fill="var(--text-secondary,#6b7280)">13</text><text x="244" y="416" text-anchor="middle" font-size="11" fill="var(--text-secondary,#6b7280)">target_gap →</text><path d="M44.0 131.3 L110.7 104.6 L177.3 229.0 L244.0 371.1 L310.7 371.1 L377.3 380.0 L444.0 380.0" fill="none" stroke="#2563eb" stroke-width="2.5" stroke-opacity="0.9"/><circle cx="44" cy="131.29411764705884" r="3" fill="#2563eb"/><circle cx="110.66666666666666" cy="104.64705882352942" r="3" fill="#2563eb"/><circle cx="177.33333333333331" cy="229" r="3" fill="#2563eb"/><circle cx="244" cy="371.11764705882354" r="3" fill="#2563eb"/><circle cx="310.66666666666663" cy="371.11764705882354" r="3" fill="#2563eb"/><circle cx="377.33333333333337" cy="380" r="3" fill="#2563eb"/><circle cx="444" cy="380" r="3" fill="#2563eb"/><path d="M44.0 166.8 L110.7 229.0 L177.3 344.5 L244.0 371.1 L310.7 380.0 L377.3 380.0 L444.0 380.0" fill="none" stroke="#d97706" stroke-width="2.5" stroke-opacity="0.9"/><circle cx="44" cy="166.8235294117647" r="3" fill="#d97706"/><circle cx="110.66666666666666" cy="229" r="3" fill="#d97706"/><circle cx="177.33333333333331" cy="344.4705882352941" r="3" fill="#d97706"/><circle cx="244" cy="371.11764705882354" r="3" fill="#d97706"/><circle cx="310.66666666666663" cy="380" r="3" fill="#d97706"/><circle cx="377.33333333333337" cy="380" r="3" fill="#d97706"/><circle cx="444" cy="380" r="3" fill="#d97706"/><path d="M44.0 300.1 L110.7 371.1 L177.3 371.1 L244.0 362.2 L310.7 380.0 L377.3 380.0 L444.0 380.0" fill="none" stroke="#0891b2" stroke-width="2.5" stroke-opacity="0.9"/><circle cx="44" cy="300.05882352941177" r="3" fill="#0891b2"/><circle cx="110.66666666666666" cy="371.11764705882354" r="3" fill="#0891b2"/><circle cx="177.33333333333331" cy="371.11764705882354" r="3" fill="#0891b2"/><circle cx="244" cy="362.2352941176471" r="3" fill="#0891b2"/><circle cx="310.66666666666663" cy="380" r="3" fill="#0891b2"/><circle cx="377.33333333333337" cy="380" r="3" fill="#0891b2"/><circle cx="444" cy="380" r="3" fill="#0891b2"/><text x="704" y="42" text-anchor="middle" font-size="14" font-weight="700" fill="var(--text-primary,#1f2937)">W edge @ A=100 — a sharp cliff</text><text x="704" y="58" text-anchor="middle" font-size="10.5" fill="var(--text-secondary,#6b7280)">channel closes abruptly 7→8 in all three</text><line x1="504" y1="380" x2="904" y2="380" stroke="var(--border,#e5e7eb)" stroke-opacity="0.6"/><text x="496" y="384" text-anchor="end" font-size="10" fill="var(--text-tertiary,#9ca3af)">0%</text><line x1="504" y1="291.17647058823525" x2="904" y2="291.17647058823525" stroke="var(--border,#e5e7eb)" stroke-opacity="0.6"/><text x="496" y="295.17647058823525" text-anchor="end" font-size="10" fill="var(--text-tertiary,#9ca3af)">10%</text><line x1="504" y1="202.35294117647058" x2="904" y2="202.35294117647058" stroke="var(--border,#e5e7eb)" stroke-opacity="0.6"/><text x="496" y="206.35294117647058" text-anchor="end" font-size="10" fill="var(--text-tertiary,#9ca3af)">20%</text><line x1="504" y1="113.52941176470588" x2="904" y2="113.52941176470588" stroke="var(--border,#e5e7eb)" stroke-opacity="0.6"/><text x="496" y="117.52941176470588" text-anchor="end" font-size="10" fill="var(--text-tertiary,#9ca3af)">30%</text><line x1="504" y1="371.11764705882354" x2="904" y2="371.11764705882354" stroke="var(--positive,#16a34a)" stroke-width="1.2" stroke-dasharray="5 3" stroke-opacity="0.8"/><text x="904" y="367.11764705882354" text-anchor="end" font-size="9.5" fill="var(--positive,#16a34a)">coherent &lt;1%</text><line x1="504" y1="380" x2="504" y2="384" stroke="var(--text-tertiary,#9ca3af)"/><text x="504" y="397" text-anchor="middle" font-size="10" fill="var(--text-secondary,#6b7280)">3</text><line x1="561.1428571428571" y1="380" x2="561.1428571428571" y2="384" stroke="var(--text-tertiary,#9ca3af)"/><text x="561.1428571428571" y="397" text-anchor="middle" font-size="10" fill="var(--text-secondary,#6b7280)">4</text><line x1="618.2857142857142" y1="380" x2="618.2857142857142" y2="384" stroke="var(--text-tertiary,#9ca3af)"/><text x="618.2857142857142" y="397" text-anchor="middle" font-size="10" fill="var(--text-secondary,#6b7280)">5</text><line x1="675.4285714285714" y1="380" x2="675.4285714285714" y2="384" stroke="var(--text-tertiary,#9ca3af)"/><text x="675.4285714285714" y="397" text-anchor="middle" font-size="10" fill="var(--text-secondary,#6b7280)">6</text><line x1="732.5714285714286" y1="380" x2="732.5714285714286" y2="384" stroke="var(--text-tertiary,#9ca3af)"/><text x="732.5714285714286" y="397" text-anchor="middle" font-size="10" fill="var(--text-secondary,#6b7280)">7</text><line x1="789.7142857142858" y1="380" x2="789.7142857142858" y2="384" stroke="var(--text-tertiary,#9ca3af)"/><text x="789.7142857142858" y="397" text-anchor="middle" font-size="10" fill="var(--text-secondary,#6b7280)">8</text><line x1="846.8571428571429" y1="380" x2="846.8571428571429" y2="384" stroke="var(--text-tertiary,#9ca3af)"/><text x="846.8571428571429" y="397" text-anchor="middle" font-size="10" fill="var(--text-secondary,#6b7280)">9</text><line x1="904" y1="380" x2="904" y2="384" stroke="var(--text-tertiary,#9ca3af)"/><text x="904" y="397" text-anchor="middle" font-size="10" fill="var(--text-secondary,#6b7280)">10</text><text x="704" y="416" text-anchor="middle" font-size="11" fill="var(--text-secondary,#6b7280)">window (W) →</text><path d="M504.0 166.8 L561.1 157.9 L618.3 202.4 L675.4 131.3 L732.6 237.9 L789.7 380.0 L846.9 380.0 L904.0 380.0" fill="none" stroke="#2563eb" stroke-width="2.5" stroke-opacity="0.9"/><circle cx="504" cy="166.8235294117647" r="3" fill="#2563eb"/><circle cx="561.1428571428571" cy="157.94117647058823" r="3" fill="#2563eb"/><circle cx="618.2857142857142" cy="202.35294117647058" r="3" fill="#2563eb"/><circle cx="675.4285714285714" cy="131.29411764705884" r="3" fill="#2563eb"/><circle cx="732.5714285714286" cy="237.88235294117646" r="3" fill="#2563eb"/><circle cx="789.7142857142858" cy="380" r="3" fill="#2563eb"/><circle cx="846.8571428571429" cy="380" r="3" fill="#2563eb"/><circle cx="904" cy="380" r="3" fill="#2563eb"/><path d="M504.0 149.1 L561.1 149.1 L618.3 166.8 L675.4 220.1 L732.6 264.5 L789.7 380.0 L846.9 380.0 L904.0 380.0" fill="none" stroke="#d97706" stroke-width="2.5" stroke-opacity="0.9"/><circle cx="504" cy="149.05882352941177" r="3" fill="#d97706"/><circle cx="561.1428571428571" cy="149.05882352941177" r="3" fill="#d97706"/><circle cx="618.2857142857142" cy="166.8235294117647" r="3" fill="#d97706"/><circle cx="675.4285714285714" cy="220.11764705882354" r="3" fill="#d97706"/><circle cx="732.5714285714286" cy="264.52941176470586" r="3" fill="#d97706"/><circle cx="789.7142857142858" cy="380" r="3" fill="#d97706"/><circle cx="846.8571428571429" cy="380" r="3" fill="#d97706"/><circle cx="904" cy="380" r="3" fill="#d97706"/><path d="M504.0 282.3 L561.1 282.3 L618.3 300.1 L675.4 344.5 L732.6 362.2 L789.7 380.0 L846.9 380.0 L904.0 380.0" fill="none" stroke="#0891b2" stroke-width="2.5" stroke-opacity="0.9"/><circle cx="504" cy="282.29411764705884" r="3" fill="#0891b2"/><circle cx="561.1428571428571" cy="282.29411764705884" r="3" fill="#0891b2"/><circle cx="618.2857142857142" cy="300.05882352941177" r="3" fill="#0891b2"/><circle cx="675.4285714285714" cy="344.4705882352941" r="3" fill="#0891b2"/><circle cx="732.5714285714286" cy="362.2352941176471" r="3" fill="#0891b2"/><circle cx="789.7142857142858" cy="380" r="3" fill="#0891b2"/><circle cx="846.8571428571429" cy="380" r="3" fill="#0891b2"/><circle cx="904" cy="380" r="3" fill="#0891b2"/><line x1="310" y1="436" x2="330" y2="436" stroke="#2563eb" stroke-width="2.5"/><circle cx="320" cy="436" r="3" fill="#2563eb"/><text x="336" y="440" font-size="11" fill="var(--text-secondary,#6b7280)">e4b</text><line x1="410" y1="436" x2="430" y2="436" stroke="#d97706" stroke-width="2.5"/><circle cx="420" cy="436" r="3" fill="#d97706"/><text x="436" y="440" font-size="11" fill="var(--text-secondary,#6b7280)">12B</text><line x1="510" y1="436" x2="530" y2="436" stroke="#0891b2" stroke-width="2.5"/><circle cx="520" cy="436" r="3" fill="#0891b2"/><text x="536" y="440" font-size="11" fill="var(--text-secondary,#6b7280)">CPM5</text></svg>
@@ -1 +0,0 @@
1
- <svg viewBox="0 0 960 658" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="t d" font-family="ui-sans-serif,system-ui,sans-serif"><title id="t">HLG coherence geometry across three models</title><desc id="d">Cross-pair coherence grids for e4b, 12B and CPM5. The sharpness cluster (s_m×tg, A×tg) replicates across all three; the window axis (s_m×W, A×W) tracks vocab size — the two Gemmas agree, CPM5 diverges.</desc><text x="480" y="26" text-anchor="middle" font-size="17" font-weight="700" fill="var(--text-primary,#1f2937)">Does the geometry generalize? Cross-pair coherence across 3 models</text><text x="480" y="46" text-anchor="middle" font-size="12" fill="var(--text-secondary,#6b7280)">green = coherent · red ✗ = canary broke · each grid is 4×4 over the break-spanning ranges</text><text x="288" y="78" text-anchor="middle" font-size="13" font-weight="700" fill="var(--text-primary,#1f2937)">e4b</text><text x="288" y="93" text-anchor="middle" font-size="9.5" fill="var(--text-tertiary,#9ca3af)">Gemma · 262k</text><text x="518" y="78" text-anchor="middle" font-size="13" font-weight="700" fill="var(--text-primary,#1f2937)">12B</text><text x="518" y="93" text-anchor="middle" font-size="9.5" fill="var(--text-tertiary,#9ca3af)">Gemma · 262k</text><text x="748" y="78" text-anchor="middle" font-size="13" font-weight="700" fill="var(--text-primary,#1f2937)">CPM5</text><text x="748" y="93" text-anchor="middle" font-size="9.5" fill="var(--text-tertiary,#9ca3af)">Llama · ~73k</text><rect x="14" y="108" width="932" height="244" rx="8" fill="var(--positive,#16a34a)" fill-opacity="0.05" stroke="var(--positive,#16a34a)" stroke-opacity="0.35"/><text x="26" y="124" font-size="12" font-weight="700" fill="var(--positive,#16a34a)">Replicates across all 3 — the sharpness cluster</text><text x="150" y="180" text-anchor="end" font-size="12.5" font-weight="600" fill="var(--text-primary,#1f2937)">s_m × target_gap</text><rect x="262" y="146" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="281" y="146" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="300" y="146" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="319" y="146" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="262" y="165" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="270.75" y="177.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="281" y="165" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="300" y="165" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="319" y="165" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="262" y="184" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="270.75" y="196.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="281" y="184" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="289.75" y="196.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="300" y="184" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="319" y="184" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="262" y="203" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="270.75" y="215.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="281" y="203" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="289.75" y="215.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="300" y="203" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="319" y="203" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><text x="256" y="184" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)" transform="rotate(-90 256 184)">s_m →</text><text x="300" y="233" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)">tg →</text><rect x="492" y="146" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="511" y="146" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="530" y="146" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="549" y="146" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="492" y="165" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="500.75" y="177.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="511" y="165" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="530" y="165" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="549" y="165" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="492" y="184" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="500.75" y="196.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="511" y="184" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="519.75" y="196.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="530" y="184" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="549" y="184" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="492" y="203" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="500.75" y="215.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="511" y="203" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="519.75" y="215.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="530" y="203" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="549" y="203" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><text x="486" y="184" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)" transform="rotate(-90 486 184)">s_m →</text><text x="530" y="233" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)">tg →</text><rect x="722" y="146" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="741" y="146" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="760" y="146" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="779" y="146" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="722" y="165" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="741" y="165" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="760" y="165" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="779" y="165" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="722" y="184" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="730.75" y="196.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="741" y="184" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="749.75" y="196.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="760" y="184" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="779" y="184" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="722" y="203" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="730.75" y="215.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="741" y="203" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="749.75" y="215.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="760" y="203" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="779" y="203" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><text x="716" y="184" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)" transform="rotate(-90 716 184)">s_m →</text><text x="760" y="233" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)">tg →</text><text x="150" y="298" text-anchor="end" font-size="12.5" font-weight="600" fill="var(--text-primary,#1f2937)">A × target_gap</text><rect x="262" y="264" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="270.75" y="276.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="281" y="264" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="300" y="264" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="319" y="264" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="262" y="283" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="270.75" y="295.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="281" y="283" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="289.75" y="295.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="300" y="283" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="319" y="283" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="262" y="302" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="270.75" y="314.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="281" y="302" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="300" y="302" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="319" y="302" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="262" y="321" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="270.75" y="333.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="281" y="321" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="289.75" y="333.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="300" y="321" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="319" y="321" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><text x="256" y="302" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)" transform="rotate(-90 256 302)">A →</text><text x="300" y="351" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)">tg →</text><rect x="492" y="264" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="500.75" y="276.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="511" y="264" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="530" y="264" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="549" y="264" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="492" y="283" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="500.75" y="295.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="511" y="283" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="530" y="283" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="549" y="283" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="492" y="302" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="500.75" y="314.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="511" y="302" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="530" y="302" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="549" y="302" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="492" y="321" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="500.75" y="333.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="511" y="321" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="519.75" y="333.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="530" y="321" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="549" y="321" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><text x="486" y="302" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)" transform="rotate(-90 486 302)">A →</text><text x="530" y="351" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)">tg →</text><rect x="722" y="264" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="730.75" y="276.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="741" y="264" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="760" y="264" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="779" y="264" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="722" y="283" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="730.75" y="295.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="741" y="283" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="760" y="283" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="779" y="283" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="722" y="302" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="730.75" y="314.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="741" y="302" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="760" y="302" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="779" y="302" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="722" y="321" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="730.75" y="333.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="741" y="321" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="749.75" y="333.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="760" y="321" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="779" y="321" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><text x="716" y="302" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)" transform="rotate(-90 716 302)">A →</text><text x="760" y="351" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)">tg →</text><rect x="14" y="366" width="932" height="244" rx="8" fill="var(--accent,#2563eb)" fill-opacity="0.05" stroke="var(--accent,#2563eb)" stroke-opacity="0.35"/><text x="26" y="382" font-size="12" font-weight="700" fill="var(--accent,#2563eb)">Vocab-dependent — the window axis (Gemmas agree, CPM5 diverges)</text><text x="150" y="438" text-anchor="end" font-size="12.5" font-weight="600" fill="var(--text-primary,#1f2937)">s_m × W</text><rect x="262" y="404" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="270.75" y="416.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="281" y="404" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="300" y="404" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="319" y="404" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="262" y="423" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="270.75" y="435.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="281" y="423" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="300" y="423" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="319" y="423" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="262" y="442" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="270.75" y="454.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="281" y="442" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="289.75" y="454.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="300" y="442" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="319" y="442" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="262" y="461" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="270.75" y="473.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="281" y="461" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="289.75" y="473.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="300" y="461" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="319" y="461" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><text x="256" y="442" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)" transform="rotate(-90 256 442)">s_m →</text><text x="300" y="491" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)">W →</text><rect x="492" y="404" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="500.75" y="416.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="511" y="404" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="530" y="404" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="549" y="404" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="492" y="423" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="500.75" y="435.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="511" y="423" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="530" y="423" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="549" y="423" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="492" y="442" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="500.75" y="454.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="511" y="442" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="519.75" y="454.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="530" y="442" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="549" y="442" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="492" y="461" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="500.75" y="473.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="511" y="461" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="519.75" y="473.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="530" y="461" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="549" y="461" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><text x="486" y="442" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)" transform="rotate(-90 486 442)">s_m →</text><text x="530" y="491" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)">W →</text><rect x="722" y="404" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="741" y="404" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="760" y="404" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="779" y="404" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="722" y="423" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="741" y="423" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="760" y="423" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="779" y="423" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="722" y="442" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="741" y="442" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="760" y="442" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="779" y="442" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="722" y="461" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="741" y="461" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="760" y="461" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="779" y="461" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><text x="716" y="442" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)" transform="rotate(-90 716 442)">s_m →</text><text x="760" y="491" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)">W →</text><text x="150" y="556" text-anchor="end" font-size="12.5" font-weight="600" fill="var(--text-primary,#1f2937)">A × W</text><rect x="262" y="522" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="270.75" y="534.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="281" y="522" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="300" y="522" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="319" y="522" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="262" y="541" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="270.75" y="553.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="281" y="541" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="300" y="541" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="319" y="541" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="262" y="560" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="270.75" y="572.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="281" y="560" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="300" y="560" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="319" y="560" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="262" y="579" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="270.75" y="591.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="281" y="579" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="289.75" y="591.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="300" y="579" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="319" y="579" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><text x="256" y="560" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)" transform="rotate(-90 256 560)">A →</text><text x="300" y="609" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)">W →</text><rect x="492" y="522" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="500.75" y="534.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="511" y="522" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="530" y="522" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="549" y="522" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="492" y="541" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="500.75" y="553.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="511" y="541" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="530" y="541" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="549" y="541" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="492" y="560" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="500.75" y="572.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="511" y="560" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="519.75" y="572.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="530" y="560" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="549" y="560" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="492" y="579" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="500.75" y="591.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="511" y="579" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="519.75" y="591.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="530" y="579" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="549" y="579" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="557.75" y="591.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><text x="486" y="560" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)" transform="rotate(-90 486 560)">A →</text><text x="530" y="609" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)">W →</text><rect x="722" y="522" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="741" y="522" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="760" y="522" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="779" y="522" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="722" y="541" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="741" y="541" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="760" y="541" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="779" y="541" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="722" y="560" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="730.75" y="572.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="741" y="560" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="760" y="560" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="779" y="560" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="787.75" y="572.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="722" y="579" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="730.75" y="591.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="741" y="579" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="749.75" y="591.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><rect x="760" y="579" width="17.5" height="17.5" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><rect x="779" y="579" width="17.5" height="17.5" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="787.75" y="591.25" text-anchor="middle" font-size="10" fill="#b91c1c">✗</text><text x="716" y="560" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)" transform="rotate(-90 716 560)">A →</text><text x="760" y="609" text-anchor="middle" font-size="9" fill="var(--text-tertiary,#9ca3af)">W →</text><g transform="translate(26,644)"><rect x="0" y="-11" width="14" height="14" rx="2" fill="var(--positive,#16a34a)" fill-opacity="0.22" stroke="var(--positive,#16a34a)" stroke-opacity="0.4"/><text x="20" y="0" font-size="11" fill="var(--text-secondary,#6b7280)">coherent</text><rect x="100" y="-11" width="14" height="14" rx="2" fill="#ef4444" fill-opacity="0.34" stroke="#ef4444" stroke-opacity="0.4"/><text x="120" y="0" font-size="11" fill="var(--text-secondary,#6b7280)">canary broke</text><text x="240" y="0" font-size="11" font-style="italic" fill="var(--text-tertiary,#9ca3af)">Same red pattern across columns = the curve, not the model.</text></g></svg>