mlx-bun 0.0.7 → 0.0.9

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 (138) hide show
  1. package/README.md +112 -20
  2. package/docs/design/batching-v2-plan.md +515 -0
  3. package/docs/design/bucketing-stage.md +196 -0
  4. package/docs/design/compat-cli-surface-design.md +11 -11
  5. package/docs/design/diffusion-gemma-port.md +602 -0
  6. package/docs/design/docs-reorg-plan.md +1 -1
  7. package/docs/design/dreaming-nightly-pipeline.md +291 -0
  8. package/docs/design/dspark-speculative-decoding.md +106 -0
  9. package/docs/design/generic-model-support.md +381 -0
  10. package/docs/design/memory-inference-path.md +422 -0
  11. package/docs/design/memory-synthesis.md +287 -0
  12. package/docs/design/minicpm5-decode-megakernel.md +484 -0
  13. package/docs/design/mlx-lm-tool-parity-plan.md +535 -0
  14. package/docs/design/orpo-dynamic-lambda.md +41 -0
  15. package/docs/design/orpo-training.md +35 -5
  16. package/docs/design/parallel-slots.md +12 -1
  17. package/docs/design/parity-tier-dag.md +13 -5
  18. package/docs/design/spec-decode-larger-targets.md +229 -0
  19. package/docs/design/tauri-desktop-app.md +2 -2
  20. package/docs/design/the-dreaming-handoff.md +141 -0
  21. package/docs/design/the-dreaming-master-plan.md +446 -0
  22. package/docs/design/write-pipeline-entity.md +468 -0
  23. package/docs/investigations/curve-bisector-routing.md +1 -1
  24. package/docs/investigations/decode-roofline-lookagain.md +262 -0
  25. package/docs/investigations/dspark-handoff.md +58 -0
  26. package/docs/investigations/kernel-perf-review-2026-07.md +92 -0
  27. package/docs/planning/PRODUCT_ROADMAP.md +2 -2
  28. package/docs/planning/curve-sampler-research-plan.md +331 -0
  29. package/docs/planning/memory-docs-and-dag-plan.md +185 -0
  30. package/docs/planning/pi-integration-review.md +178 -0
  31. package/docs/planning/release-notes-v0.0.9.md +122 -0
  32. package/docs/planning/web-ui-pass-plan.md +213 -0
  33. package/docs/planning/website-readme-pass-plan.md +224 -0
  34. package/docs/reference/cli.md +255 -0
  35. package/docs/reference/embedding.md +7 -2
  36. package/docs/reference/library-api.md +22 -3
  37. package/docs/reference/memory.md +5 -5
  38. package/docs/reference/models.md +137 -0
  39. package/docs/reference/orpo-quickstart.md +6 -0
  40. package/docs/reference/server-api.md +187 -9
  41. package/docs/reference/server-config.md +40 -9
  42. package/docs/reference/training.md +25 -11
  43. package/package.json +1 -1
  44. package/src/anthropic.ts +22 -0
  45. package/src/assets/curve-designer.html +1 -1
  46. package/src/chat-template.ts +25 -7
  47. package/src/cli.ts +1029 -86
  48. package/src/config.ts +54 -3
  49. package/src/diffusion/diffusion-generate.ts +436 -0
  50. package/src/download.ts +99 -8
  51. package/src/embed.ts +77 -0
  52. package/src/eval/perplexity.ts +164 -0
  53. package/src/eval/runner.ts +19 -7
  54. package/src/eval/tasks/bfcl.ts +1 -1
  55. package/src/generate.ts +196 -19
  56. package/src/harness-pi.ts +43 -17
  57. package/src/index.ts +2 -0
  58. package/src/lora.ts +2 -2
  59. package/src/memory/article.ts +558 -0
  60. package/src/memory/chunk-validation.ts +150 -0
  61. package/src/memory/chunk.ts +305 -12
  62. package/src/memory/cluster.ts +344 -17
  63. package/src/memory/coverage.ts +134 -0
  64. package/src/memory/crosslink.ts +0 -0
  65. package/src/memory/db.ts +184 -45
  66. package/src/memory/entity.ts +203 -0
  67. package/src/memory/gate.ts +187 -0
  68. package/src/memory/history.ts +152 -0
  69. package/src/memory/ingest.ts +324 -11
  70. package/src/memory/model.ts +321 -0
  71. package/src/memory/normalize.ts +671 -0
  72. package/src/memory/parse.ts +22 -0
  73. package/src/memory/pipeline.ts +242 -30
  74. package/src/memory/prompts.ts +42 -0
  75. package/src/memory/query.ts +334 -0
  76. package/src/memory/reconcile.ts +734 -0
  77. package/src/memory/redirect.ts +108 -0
  78. package/src/memory/reindex.ts +325 -0
  79. package/src/memory/resolve.ts +307 -0
  80. package/src/memory/route.ts +272 -0
  81. package/src/memory/schedule.ts +6 -4
  82. package/src/memory/stages.ts +774 -0
  83. package/src/memory/synthesize.ts +1629 -20
  84. package/src/memory/tools.ts +446 -96
  85. package/src/memory/vault.ts +462 -35
  86. package/src/memory/wikify.ts +1057 -16
  87. package/src/mlx/ffi.ts +11 -0
  88. package/src/mlx/ops.ts +113 -0
  89. package/src/model/compiled-decode.ts +43 -8
  90. package/src/model/diffusion-gemma.ts +1026 -0
  91. package/src/model/factory.ts +35 -8
  92. package/src/model/flash-attention.ts +4 -2
  93. package/src/model/fused-decode-kernel.ts +14 -7
  94. package/src/model/fused-mlp-kernel.ts +169 -0
  95. package/src/model/fused-swiglu-kernel.ts +240 -0
  96. package/src/model/gemma4-base.ts +62 -6
  97. package/src/model/gemma4.ts +33 -2
  98. package/src/model/minicpm5.ts +106 -8
  99. package/src/model/qwen3.ts +276 -0
  100. package/src/model/steel-linear-kernel.ts +96 -0
  101. package/src/model/support.ts +45 -7
  102. package/src/model/universal/archs.ts +332 -0
  103. package/src/model/universal/dense.ts +576 -0
  104. package/src/model/universal/modules.ts +163 -0
  105. package/src/model/universal/rope.ts +366 -0
  106. package/src/pi-provider.ts +1 -1
  107. package/src/pi-terminal.ts +29 -8
  108. package/src/pi-web.ts +19 -2
  109. package/src/quantize/config-writer.ts +1 -1
  110. package/src/registry.ts +215 -7
  111. package/src/responses.ts +23 -0
  112. package/src/sampler.ts +220 -9
  113. package/src/serve/batch-scheduler.ts +272 -80
  114. package/src/serve/generation-gateway.ts +90 -18
  115. package/src/server.ts +643 -50
  116. package/src/spec/drafter.ts +81 -49
  117. package/src/spec/dspark/data-dflash.ts +156 -0
  118. package/src/spec/dspark/data.ts +201 -0
  119. package/src/spec/dspark/generate-dflash.ts +193 -0
  120. package/src/spec/dspark/generate.ts +290 -0
  121. package/src/spec/dspark/loss.ts +213 -0
  122. package/src/spec/dspark/module-dflash.ts +361 -0
  123. package/src/spec/dspark/module.ts +540 -0
  124. package/src/spec/dspark/sample.ts +112 -0
  125. package/src/spec/generate.ts +40 -19
  126. package/src/status-page.html +1 -1
  127. package/src/tokenizer.ts +7 -0
  128. package/src/train/diffusion-lora.ts +216 -0
  129. package/src/train/flash-cce.ts +70 -15
  130. package/src/train/fuse.ts +243 -0
  131. package/src/train/index.ts +3 -0
  132. package/src/train/job.ts +8 -0
  133. package/src/train/loss.ts +289 -30
  134. package/src/train/prefix-shared.ts +33 -5
  135. package/src/train/segmented.ts +67 -11
  136. package/src/train/trainer.ts +92 -28
  137. package/src/vision/diffusion-vision.ts +620 -0
  138. package/src/web/skills/memory/SKILL.md +40 -17
@@ -0,0 +1,331 @@
1
+ # Curve sampler — preregistered research plan (distinctness track)
2
+
3
+ *2026-07-01. Status: PREREGISTERED — hypotheses and analysis fixed BEFORE the
4
+ fresh runs. Mandate (Josh): "I am not ready to give up on the curve sampler.
5
+ I think there ARE outputs that cannot be reached by just p, k and temp — temp
6
+ means you cannot control different areas of prob." The old experiments are not
7
+ trusted as-is (audit in §6); this plan replaces them. The distinctness track is
8
+ being PURSUED, not folded into the assessment's "honest negative" framing
9
+ (reports/curve-designer-paper-assessment-2026-07-01.md) — the assessment's
10
+ venue advice (workshop/demo tier unless the empirical section lands) is noted,
11
+ not contested.*
12
+
13
+ Object under study: `src/curve-sampler.ts` — the v2 monotone-cubic (PCHIP)
14
+ log-prob transfer curve, `p_out ∝ exp(curve(log p_in))`, replacing
15
+ temperature+top-p/top-k when active.
16
+
17
+ ---
18
+
19
+ ## 1. The theorem (in hand — pure math, section-ready)
20
+
21
+ **Setup.** Base next-token logprobs ℓ ∈ ℝ^V, base probs p = softmax(ℓ). Call a
22
+ sampler a **single-slope truncation sampler** if its output is
23
+
24
+ q_i ∝ exp(ℓ_i / T) for i ∈ S, q_i = 0 otherwise,
25
+
26
+ for some temperature T > 0 and survivor set S. This family contains, exactly:
27
+
28
+ | method | survivor set S | S is a rank prefix? | slope on S |
29
+ |---|---|---|---|
30
+ | temperature | V | yes (trivially) | 1/T |
31
+ | top-k | k highest | yes | 1/T |
32
+ | top-p | smallest prefix with mass ≥ p | yes | 1/T |
33
+ | min-p | {i : p_i ≥ α·p_max} | yes | 1/T |
34
+ | top-nσ | {i : ℓ_i ≥ ℓ_max − n·σ(ℓ)} | yes | 1/T |
35
+ | ε / η (desmoothing) | absolute / entropy-scaled floor | yes | 1/T |
36
+ | typical | surprisal closest to H | **not necessarily** | 1/T |
37
+ | mirostat | feedback-chosen k per step | yes (per step) | 1/T |
38
+
39
+ Every published truncation sampler differs only in HOW it picks S — on the
40
+ survivors, all of them apply ONE global slope.
41
+
42
+ **Gap-ratio invariant.** For any a, b, c ∈ S with distinct ℓ values:
43
+
44
+ R(q) := (ln q_a − ln q_b) / (ln q_b − ln q_c)
45
+ = (ℓ_a − ℓ_b) / (ℓ_b − ℓ_c) = R(p).
46
+
47
+ Proof: ln q_i = ℓ_i/T − ln Z_S; the normalizer cancels in differences, T
48
+ cancels in the ratio. So **no choice of T and no choice of survivor set can
49
+ change the log-gap ratios of surviving tokens** — one scalar cannot set
50
+ different sharpness in different probability regions.
51
+
52
+ **The curve breaks it.** A monotone map w with slope s₁ on one log-prob region
53
+ and s₂ ≠ s₁ on another gives R(q) = (s₁/s₂)·R(p) for tokens straddling the
54
+ regions — order preserved (monotonicity), ratios changed. Hence a curve
55
+ distribution with mismatched gap ratios is unreachable EXACTLY by any member of
56
+ the family above; the witness (§2) shows the inexact gap is also structurally
57
+ large where it matters. Truncating the mismatched region instead costs its
58
+ whole mass in TV — so TV_min ≳ min(ratio-mismatch cost, lifted-band mass / 2).
59
+
60
+ **Honest boundary (both directions).** The curve is a FIXED pointwise map of
61
+ the token's own value: it cannot express distribution-ADAPTIVE head selection
62
+ (min-p's α·p_max, top-nσ's σ(ℓ), typical's H, mirostat's feedback) nor
63
+ non-monotone re-ranking (XTC). The two families intersect exactly on
64
+ {temperature + absolute-threshold gates}; **neither contains the other**. The
65
+ claim being pursued is "the curve reaches per-step distributions the standard
66
+ family cannot", not "the curve subsumes it". (The fork-routing impossibility —
67
+ fork-ness is a trajectory property invisible to any local warp — stands as the
68
+ other half of the characterization; see curve-bisector-routing.md, strengthened
69
+ per §6 F5.)
70
+
71
+ ## 2. The witness (in hand — measured 2026-07-01)
72
+
73
+ `scripts/experiments/curve-distinctness.ts` (this session; MiniCPM5-1B-OptiQ-
74
+ 4bit, M1 Max 32 GB). 20 real next-token distributions (5 prompts × {start,
75
+ max-entropy "fork", min-entropy, after-comma}); per position, a witness curve
76
+ that (i) keeps the top-2 gap EXACTLY as sharp as T=0.7 and (ii) lifts the
77
+ p∈[0.001, 0.02] band's total mass to 2× its T=0.7 value (or the largest
78
+ feasible factor on flat distributions). Fit = exhaustive (T ∈ [0.05, 3] step
79
+ 0.001-refined, survivor-prefix m ∈ {1..300, 325..2000, V}) minimizing total
80
+ variation — since every (p, k, min-p, top-nσ, ε) survivor set is a rank
81
+ prefix, the m-sweep covers ALL of them jointly, any application order.
82
+
83
+ | pos | kind | H (nats) | band mass ref→witness | TV_min | (T*, k*) |
84
+ |---|---|---|---|---|---|
85
+ | creative start | start | 1.67 | 0.011→0.022 (×2.0) | 0.0105 | (0.73, 1773) |
86
+ | creative fork | max-H | 4.94 | 0.270→0.512 (×1.9) | **0.187** | (1.73, 168) |
87
+ | creative comma | after-comma | 4.12 | 0.068→0.136 (×2.0) | 0.0630 | (0.77, 402) |
88
+ | advice start | start | 1.10 | 0.010→0.021 (×2.0) | 0.0075 | (0.74, 798) |
89
+ | advice fork | max-H | 3.99 | 0.204→0.408 (×2.0) | **0.167** | (0.88, 265) |
90
+ | advice comma | after-comma | 1.15 | 0.002→0.004 (×2.0) | 0.0020 | (0.70, 1773) |
91
+ | factual start | start | 1.16 | 0.015→0.030 (×2.0) | 0.0096 | (0.77, 94) |
92
+ | factual fork | max-H | 3.43 | 0.072→0.143 (×2.0) | 0.0593 | (0.76, 243) |
93
+ | factual comma | after-comma | 1.92 | 0.028→0.056 (×2.0) | 0.0265 | (0.74, 101) |
94
+ | continuation start | start | 1.01 | 0.009→0.017 (×2.0) | 0.0067 | (0.74, 1323) |
95
+ | continuation fork | max-H | 5.19 | 0.369→0.568 (×1.5) | **0.119** | (1.23, 235) |
96
+ | continuation comma | after-comma | 2.13 | 0.032→0.064 (×2.0) | 0.0165 | (0.78, 500) |
97
+ | brainstorm start | start | 2.16 | 0.014→0.029 (×2.0) | 0.0142 | (0.72, 1723) |
98
+ | brainstorm fork | max-H | 5.76 | 0.434→0.585 (×1.35) | **0.114** | (1.20, 264) |
99
+ | brainstorm comma | after-comma | 1.73 | 0.016→0.033 (×2.0) | 0.0177 | (0.73, 1148) |
100
+
101
+ (5 min-entropy positions skipped: band empty — near-deterministic steps have
102
+ nothing to lift; the theorem is about positions where sampling matters.)
103
+
104
+ - **Irreducible TV: min 0.0020, median 0.0177, mean 0.0547, max 0.187.**
105
+ - **Fitter control: refitting plain T=0.7 gives max TV 0.008** (mostly
106
+ ≤0.002) — the gaps are real, 10–20× above fitter slack at forks.
107
+ - **The gap concentrates exactly at forks** (high-entropy positions): TV
108
+ 0.11–0.19 — no (T, p, k, min-p, top-nσ) combination gets within 11–19% total
109
+ variation of the witness there. Best fits either keep T≈0.7-sharp heads and
110
+ miss the band, or go hot (T*=1.2–1.7) to buy band mass and give up the top-2
111
+ gap. Full-support pure temperature is worse still (TV 0.17–0.28 at forks).
112
+ - The witness is realizable by the shipped designer: the PCHIP spline through
113
+ the printed knots reproduces the analytic piecewise-linear witness to mean
114
+ TV 0.0083; the curve JSON is printed by the script for pasting into
115
+ `/curves`.
116
+ - **Text-level (directional, N=30/arm, 3 prompts, not preregistered):** under
117
+ a fixed global witness curve vs its best global match (T=0.77, k=750),
118
+ per-step TV along generated trajectories averaged 0.024–0.061 (max 0.24),
119
+ but distinct-1/2/3 and junk were indistinguishable at this N. Honest read:
120
+ **per-step distinctness is proven; whether it produces measurably different
121
+ TEXT distributions is exactly H2 below, and is open.**
122
+
123
+ Reproduce: `bun scripts/experiments/curve-distinctness.ts` (flags:
124
+ `--model`, `--positions-per-prompt`, `--gen-n`, `--gen-tokens`, `--skip-text`).
125
+
126
+ ## 3. Hypotheses (fixed before the fresh runs)
127
+
128
+ - **H1 — per-step distinctness. PROVEN** (§1 theorem + §2 witness). The curve
129
+ family reaches next-token distributions with TV ≥ 0.05 (median-fork ≥ 0.1)
130
+ from the entire single-slope truncation family, at matched top-2 sharpness.
131
+ Remaining H1 work is replication breadth only: same probe on e4b + 12B
132
+ (262k vocab) and 20 → 100 positions. *Null outcome possible:* larger-vocab
133
+ models could shrink the band-lift headroom; report whatever comes out.
134
+ - **H2 — text-level distributional distinctness at matched coherence.** There
135
+ exists a curve (the §2 global witness is the preregistered candidate) such
136
+ that the distribution of its generations differs from EVERY tuned
137
+ single-slope baseline's at equal coherence: MAUVE(curve, baseline) <
138
+ MAUVE(baseline-seed-A, baseline-seed-B) − δ, with δ set by the bootstrap CI.
139
+ *Null outcome is live:* per-step TV of 0.02–0.06 per token may wash out in
140
+ 60-token texts (the directional N=30 probe saw no distinct-n separation).
141
+ A null here = "per-step distinctness does not surface in text statistics at
142
+ this scale" — publishable as the boundary of claim 1, and the method paper
143
+ stays closed.
144
+ - **H3 — a task/regime where curve-reachable points lie OUTSIDE the
145
+ (T,p,k)+min-p+top-nσ Pareto front** (quality × diversity at matched
146
+ coherence). Candidate regimes (fixed now): (a) constrained-form generation
147
+ where the head must stay sharp while mid-band alternatives carry the
148
+ variety (structured lists, fixed-opening continuations); (b) fork-dense
149
+ creative prompts (the §2 fork TV is largest there); (c) repeated-sampling
150
+ best-of-N settings where band mass controls candidate coverage. *Null
151
+ outcome is live* and would land exactly on the assessment's analysis-paper
152
+ framing.
153
+
154
+ ## 4. Preregistered protocol (the referee-grade run)
155
+
156
+ **Models:** MiniCPM5-1B (73k vocab), gemma-4-e4b (262k), gemma-4-12B (262k) —
157
+ all cached OptiQ-4bit builds; the vocab split is a known moderator (hlg
158
+ investigation §15).
159
+
160
+ **Arms (per model, per prompt):**
161
+ 1. `default` — the model's own generation_config recipe (temperature/top-p/top-k).
162
+ 2. `best-Tpk` — (T, p, k) tuned on a held-out prompt set for the target
163
+ coherence level (grid: T ∈ {0.5..1.5 step 0.1} × p ∈ {0.85, 0.9, 0.95, 1} ×
164
+ k ∈ {0, 40, 64, 100, 200}).
165
+ 3. `min-p` — α ∈ {0.02, 0.05, 0.1, 0.2} × T ∈ {0.7..1.5}.
166
+ 4. `top-nσ` — n ∈ {1, 1.5, 2, 3} × T ∈ {0.7..1.5}.
167
+ 5. `mirostat` — τ ∈ {3, 4, 5} (implement or mark N/A if not landed; absence
168
+ documented, not silently dropped).
169
+ 6. `curve-witness` — the §2 global witness curve (knots frozen in the script
170
+ output, checked into the plan by hash once the run starts).
171
+ 7. `curve-tuned` — ONE curve hand-tuned in the designer per model BEFORE
172
+ scoring (tuning prompts disjoint from eval prompts), then frozen.
173
+
174
+ **Prompts:** 30 prompts, 10 per pole {creative/open, advice/constrained,
175
+ factual} — fixed list checked in before the run; disjoint 10-prompt tuning set.
176
+
177
+ **N and power.** N = 100 continuations per (arm × prompt-pole × model) cell,
178
+ 64 tokens each. Basis: the old N=10 runs put the sd of a cell's self-BLEU
179
+ run-mean at ≈0.06 (runO swing 0.083 between two seed bands), i.e. a minimum
180
+ detectable effect ≈ 0.17 at N=10 — bigger than every effect ever claimed. At
181
+ N=100 the run-mean sd scales to ≈0.019, MDE ≈ 0.053 at α=.05/power .8; for
182
+ Δ≈0.05 effects run the planned replication (below) and pool. MAUVE gets
183
+ bootstrap CIs (1000 resamples); LLM-judge cells get binomial CIs.
184
+
185
+ **Seed discipline.** Explicit integer seeds only — no wall-clock seeding
186
+ anywhere (the batch same-ms collision class). Disjoint bands per arm:
187
+ arm i uses seeds `10000·(i+1) + {0..N−1}`. The WHOLE grid is run TWICE with
188
+ band offset +5000 (built-in fresh-seed replication — the discipline that
189
+ caught both premature verdicts in hlg §14). No cross-arm seed pairing (arms
190
+ are different distributions; pairing buys nothing and invites accidental
191
+ correlation stories).
192
+
193
+ **Metrics (all fixed now):**
194
+ - **Coherence gate (per sample, gates everything else):** (a) non-Latin
195
+ letter ratio < 1% AND (b) mean per-token logprob under the model's OWN
196
+ default recipe ≥ (pole-median of the default arm − 1.5 nats) AND (c) no
197
+ 4-gram repeated ≥ 3× within the sample. (b)/(c) close the F4 hole — Latin
198
+ word-salad and repetition-degeneration currently pass the gate.
199
+ - **Diversity:** coherence-GATED distinct-1/2/3 (computed only over gate
200
+ survivors, reported with survivor rate) + self-BLEU (leave-one-out, so it
201
+ has per-sample values and a real variance estimate).
202
+ - **Distributional:** MAUVE between arm outputs and (i) the default arm and
203
+ (ii) each other, per pole; embedding model = a real sentence encoder (not
204
+ the LM's own hidden states — a known weak proxy).
205
+ - **Quality:** LLM-judge per the dreaming eval methodology (cloud judge;
206
+ hand-curated gold anchors drafted before scoring; surface-variant dedup;
207
+ judge the artifacts, blind to arm, position-flipped pairs). Judge prompt
208
+ frozen in the harness before the run.
209
+ - **Per-step (mechanism):** mean TV along trajectories between the curve arm
210
+ and its best-fit single-slope arm (already implemented in the witness
211
+ script) — connects H2 outcomes back to H1 magnitude.
212
+
213
+ **Pareto construction (H3):** per pole × model, plot (coherence-gated
214
+ diversity, judge quality) for every arm-cell; H3 is supported iff a curve
215
+ cell sits outside the convex hull of ALL single-slope cells with
216
+ non-overlapping bootstrap CIs, in ≥2 of 3 models.
217
+
218
+ **Commands (harnesses to extend from the existing probe):**
219
+ ```bash
220
+ # H1 replication breadth (exists today):
221
+ bun scripts/experiments/curve-distinctness.ts --model gemma-4-e4b-it-OptiQ-4bit --skip-text
222
+ bun scripts/experiments/curve-distinctness.ts --model gemma-4-12B-it-OptiQ-4bit --skip-text
223
+ # H2/H3 (to build: curve-frontier.ts = hlg-frontier.ts skeleton + arms above,
224
+ # N=100, gate (a)+(b)+(c), leave-one-out self-BLEU, MAUVE export):
225
+ bun scripts/experiments/curve-frontier.ts --model <m> --n 100 --seed-band 10000
226
+ bun scripts/experiments/curve-frontier.ts --model <m> --n 100 --seed-band 15000 # replication
227
+ # LLM-judge pass: reuse the dreaming judge protocol (docs/design/* memory-synthesis eval).
228
+ ```
229
+ Machine note: label every result with host/chip/RAM (two laptops in rotation —
230
+ M1 Max 32 GB / M4 Pro 24 GB; neither canonical). Nothing here is a perf claim,
231
+ but the labeling rule stands.
232
+
233
+ **Decision rules (fixed now).**
234
+ - H2 supported → the paper gains an empirical section 4; method-adjacent
235
+ framing becomes defensible at workshop+.
236
+ - H2 null, H3 null → ship the assessment's analysis paper (theorem + witness +
237
+ falsification methodology + tool); the distinctness result stays as the
238
+ per-step section. No re-running with new metrics until a NEW preregistered
239
+ amendment is written.
240
+ - Any post-hoc metric additions are labeled exploratory, never headline.
241
+
242
+ ## 5. Paper skeleton this feeds
243
+
244
+ 1. The curve designer (tool, live demo). 2. Expressivity: the gap-ratio
245
+ invariant + the two-sided boundary (§1) + fork-routing locality impossibility.
246
+ 3. The witness — per-step unreachability, quantitative (§2). 4. Text-level
247
+ results (H2/H3, whatever they are). 5. Sampler-evaluation hygiene (fresh-seed
248
+ repeats catching both false negative and false dominance; coherence-gated
249
+ diversity; the audit below as methods material).
250
+
251
+ ## 6. Why the old data is not trusted — audit of the prior experiments
252
+
253
+ Committed artifacts checked: `docs/investigations/curve-runs/*.json`,
254
+ `docs/investigations/hlg-runs/*`, harness sources. Severity: **INVALIDATES** /
255
+ **WEAKENS** / cosmetic.
256
+
257
+ - **F1 — INVALIDATES (the old distinctness claim).** The curve-temp family
258
+ (`scripts/experiments/curve-temp-match.ts:53-69`, `curve-temp-seedsearch.ts:23-47`,
259
+ `curve-temp-grid.ts:26-41`, `curve-temp-weights.ts:28-52`) tests whether pure
260
+ temperature EXACTLY reproduces a specific 64–90-token curve-generated string
261
+ across ~924 samples. (a) No control arm: a temperature-generated string would
262
+ also never be reproduced at other seeds — P(specific sequence) =
263
+ e^(−Σ per-token surprisal) ≈ 0 for ANY stochastic sampler, so "0 exact
264
+ matches" is the guaranteed outcome and distinguishes nothing. (b) With
265
+ top_p=0/top_k=0 the support is FULL — every string is reachable by
266
+ temperature with p>0, so "temperature won't go there" is a category error at
267
+ the string level; the meaningful object is the per-step distribution (now
268
+ measured properly in §2). (c) The headline "0 crossed the fork" is
269
+ conditioned on first reproducing the 84-char prefix exactly
270
+ (`curve-temp-grid.ts:11,31`; `curve-temp-seedsearch.ts:28-30`) — essentially
271
+ only the curve's own seed ever reached the fork, so the fork test had
272
+ effective N≈0. Consequence: `curve-bisector-routing.md` §1's "the curve still
273
+ reaches outputs temperature can't" (repeated in its §3 conclusion) is
274
+ unsupported by those runs. The claim happens to be TRUE per §1–2 here, but
275
+ for the per-step reason, not the exact-string one.
276
+ - **F2 — INVALIDATES (transfer of the "wash" verdict to the v2 curve).** The
277
+ only terrain map of the v2 designer family, `scripts/experiments/curve-terrain.ts:18`
278
+ (`--n` default 2, max 5), ran at **N=2 samples/cell, 48 tokens, 2 prompts**
279
+ (committed artifact `curve-runs/curve-terrain.json`: n=2) — self-BLEU at N=2
280
+ is meaningless. Every N=10 frontier number (hlg-frontier/runK-runO) measured
281
+ the **v1 HLGShaper** — a different sampler (adaptive windowed-anchor, i.e.
282
+ distribution-dependent, OUTSIDE the fixed-curve family). **The v2 drawn-curve
283
+ family has never been competitively evaluated at any usable N.** The
284
+ assessment's "method paper closed by own data" inherits this gap.
285
+ - **F3 — WEAKENS (every diversity comparison at N=10).** From the
286
+ investigation's own runO: a cell's self-BLEU run-mean moved 0.083 between
287
+ seed bands → sd(run-mean) ≈ 0.06 → minimum detectable effect ≈ 0.17 at N=10
288
+ with one run/cell. Every delta ever claimed (0.05–0.11) is below MDE. The doc
289
+ ultimately landed there honestly ("wash at this N"), but intermediate
290
+ verdicts (§12 "conclusive", §13 "definitive", §14 "DOMINANCE") each
291
+ overran the resolution; ~200+ samples/cell is the floor for Δ≈0.05 (§4 N).
292
+ - **F4 — WEAKENS (coherence gates).** All automated verdicts gate coherence on
293
+ non-Latin-script ratio alone (`hlg-map.ts:51-56`, `hlg-frontier.ts:55-59`,
294
+ `curve-terrain.ts:94-98`): Latin-script incoherence ("the planet' adorable
295
+ axis", "—aving purpose", repetition loops) passes as 0% junk, so
296
+ diversity-vs-coherence frontiers can be bought with undetected degeneration.
297
+ The doc's "read the text" discipline patched this manually; the §4 gate
298
+ (logprob + repetition + script) mechanizes it.
299
+ - **F5 — WEAKENS (the fork-routing "falsification").** `bisector-route.ts:16`
300
+ — 20 seeds × 1 prompt/pole; the FORK/REMERGE hazard ratios rest on 3–16
301
+ fork-departure events per policy (`curve-runs/bisector-route.json` cohN);
302
+ binomial SE on the rates is ±0.1–0.2, so "router 0.79 ≈ identity 0.77" is an
303
+ equivalence claim an underpowered test cannot establish (it could not
304
+ distinguish a 1.5–2× real ratio). The point estimates being identical is
305
+ suggestive, and the locality argument is sound a priori — but the doc's
306
+ headline "Falsified" and the assessment's "falsified with a proper control"
307
+ overstate; the doc's own caveats (5 prompts/pole, more seeds, user-drawn 5th
308
+ policy) are the fix and move into this protocol.
309
+ - **F6 — cosmetic (seeding).** No wall-clock/same-ms seeding in any audited
310
+ harness — all fixed explicit seeds (curve-temp 100+i / 0..299 / 200+i;
311
+ curve-terrain 7300; hlg-map 1234+i, canary 7+i; hlg-frontier 1000+i;
312
+ hlg-grid 2000+i; bisector-route 1..20) and `/generate` derives per-sample
313
+ seeds as base+i (`src/server.ts:1680`). The batch same-ms collision bug does
314
+ not taint these. Arms share seed bases (paired design) with only runO as a
315
+ fresh-seed repeat — §4 makes replication structural instead.
316
+ - **F7 — cosmetic.** `bisector-trace.ts` computes rank-2 labels via
317
+ `forwardHidden+logitsFromHidden` while the greedy reference comes from
318
+ `generate()` — the two are known to diverge on near-ties
319
+ (`src/eval/runner.ts:109-113`), and near-ties are forks; the committed
320
+ artifact shows tfMismatch 0/1/0, so no material impact, but the assert
321
+ should stay.
322
+
323
+ ## 7. Doc map
324
+
325
+ - This plan: `docs/planning/curve-sampler-research-plan.md` (preregistration —
326
+ amend by appending, never by silent edit).
327
+ - Witness probe: `scripts/experiments/curve-distinctness.ts`.
328
+ - Assessment: `reports/curve-designer-paper-assessment-2026-07-01.md`.
329
+ - Prior investigations (superseded on the points in §6):
330
+ `docs/investigations/hlg-sampling-investigation.md`,
331
+ `docs/investigations/curve-bisector-routing.md`.
@@ -0,0 +1,185 @@
1
+ # Memory docs organization + DAG-view refresh — review & plan
2
+
3
+ Status: **proposal**, 2026-07-01. Read-only review; nothing here has been
4
+ executed. Two mandates: (A) get the Dreaming doc set into an organized state,
5
+ (B) assess and plan the refresh of the parity-tier DAG view. Josh's live,
6
+ uncommitted edits (`dreaming-nightly-pipeline.md` + the two SUPERSEDED banners)
7
+ are treated as the direction of record and untouched.
8
+
9
+ ---
10
+
11
+ ## A. The Dreaming doc set
12
+
13
+ ### A.1 Inventory — role and verdict per doc
14
+
15
+ | Doc | Role | State (verified 2026-07-01) | Verdict |
16
+ |---|---|---|---|
17
+ | `docs/design/dreaming-nightly-pipeline.md` (new, uncommitted) | **CANONICAL system design** — pipeline, fixed principles, decisions-overridden table, work plan | Current; self-declares supersession over master-plan / memory-synthesis / handoff | **Keep as the hub.** It's already the entry point by construction. |
18
+ | `docs/design/the-dreaming-master-plan.md` | Execution spec (P0–P10 task DAG, port-source map, schemas) | Bannered PARTIALLY SUPERSEDED (Josh's edit). Carries no as-built state — a reader can't tell P0–P9 are DONE | Keep, banner is right. **Add a one-line as-built note** ("built through P9; live state in STATUS.md") so the task list reads as history+reference, not TODO. |
19
+ | `docs/design/the-dreaming-handoff.md` | Session log / live handoff (2026-06-28) | **Stale as a handoff:** cursor 720 (now 900/2096 paused), "everything is uncommitted" (merged 2026-07-01), "wire through persistent server" (in-process gateway landed instead), batch default (now 1). Lessons §1–8 remain valuable | **Demote to historical.** Banner: "Session log 2026-06-28 — live state is STATUS.md § THE DREAMING; the numbered LEARNED/CORRECTED list remains load-bearing." Stop maintaining two live handoffs. |
20
+ | `docs/design/memory-synthesis.md` | M1 design, 1st iteration (embeddings, section-route) | Bannered SUPERSEDED (Josh's edit) | Keep for history. No further action. |
21
+ | `docs/design/bucketing-stage.md` | Classify-stage design (2026-06-26) | **No banner.** Core content (embeddings as candidate-narrower) is dead under "no embeddings anywhere"; the binary-question ladder survives inside the nightly BUCKET stage | **Needs a SUPERSEDED banner** (same shape as memory-synthesis's): dead = embedding narrower + silhouette; survives = capacity-by-decomposition, one-binary-question-at-a-time. |
22
+ | `docs/design/write-pipeline-entity.md` | Entity-keyed routing design (2026-06-26); itself "supersedes bucket-centric routing" | **No banner.** Half-dead: pure entity ROUTE (no bucket layer) is replaced by BUCKET→RESOLVE; the personal-notability checklist is dead. Survives: articles-are-THINGS, name/alias/category lookup, no-embeddings routing | **Needs a PARTIALLY SUPERSEDED banner** mapping survives/dead — otherwise its own "supersedes bucketing" claim inverts the actual chain for a newcomer. |
23
+ | `docs/design/memory-system.md` | M0 substrate design (vault, read tools, CLI, scheduling, consent) | **Status header is FALSE**: "synthesize is currently a safe no-op stub", "stage modules throw if called" — the pipeline is built and has produced 677+ articles. Directly contradicts `docs/reference/memory.md`. The four-adapter table + "Next implementation steps" describe the abandoned M1 sketch | **Fix the header + scope it down.** Retitle scope to "M0 substrate: vault + read path (landed)"; delete or banner the "Synthesis pipeline design (M1/M2)" and "Next implementation steps" sections, pointing at dreaming-nightly-pipeline. The substrate half (storage layout, tools, skill, scheduling, consent) is still the best writeup of the read side — keep it. |
24
+ | `docs/design/memory-inference-path.md` | Inference-path rework: design + measured verification | Accurate, self-bannered (BUILT + VERIFIED; batching measured a loss). It's really an investigation record | Fine as-is. Optional (low priority): move to `docs/investigations/` where measured-experiment records live. |
25
+ | `docs/reference/memory.md` | User-facing reference | Mostly current (synthesize description matches as-built stages; status truth fixed 2026-07-01). **But** the "Synthesis roadmap" section still tells the old four-named-LoRA / HF-adapter-pack story (memory-bucket/memory-synthesis/memory-editor LoRAs "distributed from Hugging Face") — not the plan of record (`memory-<stage>` convention, only `memory-chunk` exists, base+policy otherwise) | **Rewrite the roadmap section** to the as-built stage list + the `memory-<stage>` adapter convention; update stage names again when BUCKET/RESOLVE land. |
26
+ | `STATUS.md` § THE DREAMING | Live state | Current and correct (batch default 1, third-person fix merged, import paused at cursor 900/2096, inference-path landed) | Keep as the ONLY live-state location. |
27
+
28
+ ### A.2 Contradictions / staleness found (the concrete list)
29
+
30
+ 1. **memory-system.md vs reference/memory.md** — "synthesize is a no-op stub"
31
+ vs "runs the full local synthesis DAG". Two tracked docs, opposite claims.
32
+ Worst offender; fix first.
33
+ 2. **Stage-name drift across four vocabularies:**
34
+ - memory-system: `ingest→chunk→cluster→synthesize→wikify→changelog`
35
+ - memory-synthesis: `CHUNK→FILTER→CLASSIFY→SYNTHESIZE→NORMALIZE→WIKIFY`
36
+ - as-built (`stages.ts`, handoff, reference): `segment→extract→route→create/patch→reconcile→link→wikify`
37
+ - canonical target (nightly pipeline): `SEGMENT→BUCKET→RESOLVE→SYNTHESIZE→gates→RECONCILE→LINK→NORMALIZE→EDITORIAL`
38
+ Rule going forward: **reference/memory.md speaks as-built; dreaming-nightly-pipeline speaks target**; every other doc is history and says so.
39
+ 3. **Unbannered middle links of the supersession chain**: the chain is
40
+ memory-synthesis → bucketing-stage → write-pipeline-entity → master-plan →
41
+ nightly-pipeline, and only the first and fourth links carry banners.
42
+ bucketing-stage still presents embeddings as production machinery;
43
+ write-pipeline-entity still presents the notability checklist.
44
+ 4. **Two live handoffs** (the-dreaming-handoff.md and STATUS.md § Dreaming)
45
+ with diverged facts (cursor 720 vs 900; uncommitted vs merged).
46
+ 5. **Four-adapter product story duplicated** (memory-system.md AND
47
+ reference/memory.md) vs the actual `memory-<stage>`-iff-exists convention.
48
+ 6. **CLAUDE.md doc map out of sync**: `dreaming-nightly-pipeline.md`,
49
+ `generic-model-support.md`, `mlx-lm-tool-parity-plan.md`,
50
+ `batching-v2-plan.md` are on disk but absent from the doc-map lists.
51
+
52
+ ### A.3 Proposed end-state
53
+
54
+ No renames, no folder moves, no merges mid-flight (the import is paused
55
+ mid-run and the nightly doc is uncommitted). Organization = **banners +
56
+ one scope-fix + one hub table + reading order**, all cheap and link-stable:
57
+
58
+ 1. **Canonical entry point: `dreaming-nightly-pipeline.md`.** Add a short
59
+ "Doc family" table at its top covering ALL of: master-plan (task refs),
60
+ handoff (history), memory-synthesis / bucketing-stage /
61
+ write-pipeline-entity (history), memory-system (M0 substrate),
62
+ memory-inference-path (inference seam), reference/memory.md (user-facing),
63
+ STATUS.md (live state). Today it names only three of these.
64
+ 2. **Banner the two unbannered history docs** (bucketing-stage,
65
+ write-pipeline-entity) with survives/dead maps as in A.1.
66
+ 3. **Fix memory-system.md's header + amputate its M1 sketch** (A.1 row).
67
+ 4. **Demote the-dreaming-handoff.md to a dated session log** pointing at
68
+ STATUS.md; add the as-built one-liner to the master plan.
69
+ 5. **Rewrite reference/memory.md's roadmap section** to as-built.
70
+ 6. **Sync the CLAUDE.md doc map** (A.2 item 6).
71
+
72
+ **Newcomer reading order** (to be stated in the nightly doc's family table):
73
+ 1. `docs/reference/memory.md` — what it is, how to use it
74
+ 2. `docs/design/dreaming-nightly-pipeline.md` — the canonical design +
75
+ decisions-overridden table
76
+ 3. `STATUS.md` § THE DREAMING — where it stands, what's next
77
+ 4. `docs/design/the-dreaming-master-plan.md` — per-task file/port/schema
78
+ references (respect the banner)
79
+ 5. History, only for archaeology: memory-synthesis → bucketing-stage →
80
+ write-pipeline-entity → the-dreaming-handoff → memory-inference-path
81
+
82
+ ---
83
+
84
+ ## B. The DAG view (docs/dag/training-inference-map.html + parity-tier-dag.md)
85
+
86
+ ### B.1 What exists today
87
+
88
+ - **parity-tier-dag.md** — the framework doc. **Already refreshed 2026-07-01**:
89
+ it carries the corrected lever table (perf-kernel = L3/opt-in, off in bare
90
+ `--l2`), the f1bf5cc post-mortem, and the two-axes rule. Not stale.
91
+ - **training-inference-map.html** — a hand-authored cytoscape control-flow map,
92
+ **MiniCPM5-1B only**, two tabs (inference ~150 nodes: generate loop → forward
93
+ → attention → sdpa dispatch → tiled/unfused kernels → KV bf16/quant →
94
+ sampler; training ~90 nodes: step loop → segmented/prefix → SFT/DPO/ORPO loss
95
+ heads incl. flash-CCE → AdamW → metrics). Every node carries a hardcoded
96
+ `file:line`. Branch edges carry the exact flag/predicate
97
+ (`perfKernelEnabled()`, `fusedSdpaSupported`, `MLX_BUN_TRAIN_ATTN`, …).
98
+ - **Gap vs its own billing:** PLAN.md and parity-tier-dag.md call it
99
+ "tier-tagged" — it is **not**. Nodes are colored by *subsystem*; no node
100
+ carries an L1/L2/L3 tag. The tier story exists only in prose.
101
+
102
+ ### B.2 Staleness after 2026-07-01
103
+
104
+ | Area | What changed | Map impact |
105
+ |---|---|---|
106
+ | L2 tier contract (commit `381382c`) | `TIERS.l2.perf → false`; bare `--l2` = stock unfused L=1 decode; perf kernel is L3/`--l3` | The `perfKernelEnabled()` branch (n92→n95) still exists, so the *structure* is right — but nothing in the map encodes tier presets, so the map can't show that `--l2` and `--l3` now take different sdpa routes. This is exactly the "for each config, how is it actually running" question the map is supposed to answer. |
107
+ | Sampling processors (2026-07-01) | L1-faithful min_p / XTC / presence+frequency penalties / logit_bias landed end-to-end | Sampler subtree (n177–n194) shows only curve/HLG/topP/topK/temp — the new mlx-lm-parity processor chain is absent. |
108
+ | Training `sft_scope` (d32fe32) | ORPO chosen-NLL default `full` (prompt+response token-mean CE), `response` = legacy | ORPO loss subtree (t46/t55) has no sft_scope branch. |
109
+ | Tier-0 generic models (9bd9f1b) | `UniversalDenseModel`, 11 archs, factory ladder dedicated→generated→generic→reject | **Absent entirely.** The map is titled MiniCPM5-1B; no model-dispatch view exists at all (no gemma4 generated specializations, no Qwen3/3.5, no DiffusionGemma denoising route, no batching lane either). |
110
+ | Line numbers | ~3 weeks of commits incl. today's uncommitted gemma4-base.ts / cli.ts edits | Every `file:line` is drift-suspect; they were the map's credibility feature. |
111
+
112
+ ### B.3 Refresh plan — three deliverables, ordered by value/effort
113
+
114
+ **B3.1 Minimal manual patch to un-stale the current HTML (~0.5 day).**
115
+ Keep it hand-authored, make it honest:
116
+ 1. Header banner: "hand-authored snapshot 2026-06-21, MiniCPM5-1B; line
117
+ numbers approximate; tier semantics in parity-tier-dag.md".
118
+ 2. **Add real tier tags** — a `tier` field per node + border color. Even
119
+ tagging just the dispatch nodes delivers the promised feature: `n87
120
+ ops.sdpa` (bf16) = L1 · `n83/n98` quantizedSdpa/tiled = L2 · `n92/n95`
121
+ perf-kernel/fusedDecodeSdpa = **L3 opt-in, off in bare `--l2` (381382c)**
122
+ · `n22/n27/n28` compiled-decode = tier-preserving (bit-exact) ·
123
+ flash-CCE/ORPO/segmented/prefix training nodes = L3.
124
+ 3. Sampler: insert one node before the temp/topP chain — "logits processors
125
+ (mlx-lm L1): repetition/presence/frequency · logit_bias · min_p · XTC".
126
+ 4. Training: add the `sft_scope full|response` branch at the ORPO chosen-NLL
127
+ node.
128
+ 5. Add a tiny third tab "model dispatch" (~10 nodes): the `factory.ts`
129
+ ladder — DiffusionGemma → MiniCPM5 → Qwen3.5 → Qwen3 → gemma4
130
+ generated/monolith → **UniversalDense (Tier-0, 11 archs, L1-gated)** →
131
+ reject.
132
+
133
+ **B3.2 Runtime route explainer (recommended first "derive from code" step,
134
+ ~1 day).** Josh's ask is literally "for each model and config, how it is
135
+ actually running" — the cheapest ground-truth answer is not static analysis
136
+ but a CLI verb, e.g. `mlx-bun route <model> [--l1|--l2|--l3] [--kv-quant …]`,
137
+ that:
138
+ - runs `applyDecodeRoute()` (cli.ts:723 — the TIERS preset table is already a
139
+ machine-readable matrix), loads **config only** (no weights),
140
+ - evaluates the actual exported predicates (`perfKernelEnabled`,
141
+ `fusedDecodeKernelSupported`, `fusedSwiglu/GeluEnabled+Supported`,
142
+ `NO_FUSED_SDPA`, `CompiledDecode.for` eligibility, kv-quant resolution,
143
+ factory ladder selection),
144
+ - prints the resolved route as a tree/JSON: which model class, which sdpa
145
+ path, which kernels, which tier each hop sits in, and **which flag would
146
+ change each hop**.
147
+ Correct by construction (it calls the same functions the server calls), zero
148
+ drift, and it answers per-model × per-config today. The HTML map becomes the
149
+ anatomy poster; this verb is the live X-ray.
150
+
151
+ **B3.3 Derived DAG + CI parity gate (the two open PLAN boxes, ~2–4 days).**
152
+ What "derive the DAG from code" concretely means here:
153
+ - **Roots are curated, extraction is mechanical.** A bun generator script
154
+ (ts-morph / TS compiler API) walks from a small fixed root list —
155
+ `generate()`, `createModel()`, the trainer step, `sampleStep`, each model's
156
+ `quantizedSdpa`/attention dispatch — and records: every branch on a
157
+ `process.env.MLX_BUN_*` read or an exported `*Enabled()`/`*Supported()`
158
+ call, plus call edges between the roots' subgraphs. Nodes get
159
+ `{id, label, file, line}` extracted from the AST (line numbers can never
160
+ drift again). Output: `docs/dag/dag.json`, one graph per model class
161
+ (the factory ladder gives the model dimension).
162
+ - **Tier tags live in a checked-in sidecar** (`docs/dag/tiers.json`:
163
+ `node → {tier, oracleTest}`) merged into the JSON at generation time. The
164
+ generator fails if a tagged node vanished (renames get caught).
165
+ - **CI gate**: a workflow step asserts every **L1-tagged** node names an
166
+ `oracleTest` file that exists and passes (`bun test <file>`); an L1 node
167
+ without a passing bit-exact test fails CI or must be re-tagged L3. This is
168
+ PLAN's "the oracle is the gate becomes a check" box — and it composes with
169
+ STATUS finding #4 (no CI at all): land the `tsc + bun test` gate first,
170
+ hang the L1-tag check off it.
171
+ - **Rendering**: keep the existing cytoscape HTML shell; replace the
172
+ hardcoded `INFER`/`TRAIN` consts with the generated JSON (inlined by the
173
+ generator so the file stays a self-contained artifact).
174
+ - **Deliberate non-goal**: fully deriving the fine-grained *op-level* nodes
175
+ (the tiled-sdpa online-softmax internals, AdamW math). That's 1–2 weeks of
176
+ static-analysis plumbing for content that changes rarely. Two-level design
177
+ instead: derived flag/route/dispatch graph (auto, CI-checked) + the
178
+ hand-authored op subgraphs kept as leaf expansions, refreshed manually.
179
+
180
+ **Sequencing:** B3.1 now (un-stale the artifact) → B3.2 (the per-model/config
181
+ truth Josh asked for) → B3.3 (kills the hand-authored map and closes the two
182
+ PLAN checkboxes). The fourth PLAN box (rationalize the flag surface) falls out
183
+ of B3.2+B3.3: once every flag maps to a route edge in the JSON, the
184
+ always-on / knob / parity⇄opt classification in parity-tier-dag.md §"Why this
185
+ matters" can be generated instead of argued.