opencode-cache-engine 0.4.3 → 0.4.5

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.
package/README.md CHANGED
@@ -31,8 +31,8 @@ The plugin currently has four cache-policy families:
31
31
  * **GPT-5.6 and later** — documented cache-key/options metadata, with prompt text
32
32
  unchanged. GPT-6 and future 5.6+/6+/7+ versions resolve through the same
33
33
  documented boundary.
34
- * **GLM-5.3** — narrow, content-preserving `<env>` relocation and diagnostics.
35
- * **MiMo-V2.6** — narrow, content-preserving `<env>` relocation and diagnostics.
34
+ * **GLM-5.3 and later** — GLM implicit-cache baseline and diagnostics; GLM-5.3 additionally uses a narrow, content-preserving `<env>` relocation overlay.
35
+ * **MiMo V2.6 and later** — MiMo implicit-cache baseline and diagnostics; MiMo V2.6 Flash/Pro additionally use a narrow, content-preserving `<env>` relocation overlay.
36
36
 
37
37
  Family classification is not hard-coded in the runtime. A pure policy registry
38
38
  and resolver in `src/cache-policy-core.mjs` returns a structured result
@@ -42,7 +42,7 @@ the single runtime source of policy classification. The first-party research
42
42
  behind each registry entry is recorded in
43
43
  [docs/cache-policy-inventory.md](docs/cache-policy-inventory.md).
44
44
 
45
- For both MiMo-V2.6 and GLM-5.3, CacheEngine adds its deterministic
45
+ For the MiMo V2.6-and-later family and the GLM-5.3-and-later family, CacheEngine adds its deterministic
46
46
  `x-session-id` request header only when OpenCode identifies the actual provider
47
47
  as `openrouter`. It does not add that OpenRouter-specific header for
48
48
  non-OpenRouter providers; direct provider endpoints retain their provider-native
@@ -205,6 +205,12 @@ GLM-5.3 and MiMo-V2.6 use the only prompt-text transformation in the current
205
205
  plugin: a narrow, content-preserving relocation of the identifiable `<env>`
206
206
  block for the eligible model family.
207
207
 
208
+ Since v0.4.4 the GLM **family baseline** and the GLM-5.3 **overlay** are
209
+ separate. A resolved GLM-5.3-and-later model inherits the implicit-cache baseline
210
+ and the non-mutating GLM diagnostics/transport, but the `<env>` relocation below
211
+ is a GLM-5.3-specific overlay and is **not** inherited by a newer GLM merely
212
+ because its version number is higher.
213
+
208
214
  The plugin identifies OpenCode's volatile `<env>` section and moves it to the **tail of the system prompt**.
209
215
 
210
216
  Conceptually:
@@ -280,19 +286,33 @@ whether a header was already present or added, and provider-identity changes
280
286
  (`glm_provider_changed`). They do not record the header value.
281
287
 
282
288
 
283
- ## MiMo-V2.6 (Flash / Pro)
289
+ ## MiMo V2.6 and later
284
290
 
285
291
  ### Policy: prefix stability + OpenRouter session affinity
286
292
 
287
- MiMo-V2.6 is Xiaomi's current model family. The plugin targets exactly two
288
- identifiers:
293
+ MiMo-V2.6 is Xiaomi's current model family. Since v0.4.5 the plugin separates
294
+ three concerns:
295
+
296
+ * **Family baseline** — the implicit-cache baseline plus cached-token telemetry,
297
+ provider-change/prefix diagnostics, and OpenRouter session affinity. This
298
+ applies to the documented V2.6 Flash and Pro identifiers, the
299
+ `mimo-v2.6-pro-ultraspeed` mode id, and any future MiMo generation after V2.6.
300
+ * **Validated overlay** — the `<env>` relocation described below, registered only
301
+ for MiMo V2.6 Flash/Pro.
302
+ * **Transport affinity** — OpenRouter `x-session-id`, gated on the actual
303
+ `openrouter` provider identity.
304
+
305
+ The documented V2.6 identifiers are:
289
306
 
290
307
  * `xiaomi/mimo-v2.6-flash` / `mimo-v2.6-flash`
291
308
  * `xiaomi/mimo-v2.6-pro` / `mimo-v2.6-pro`
309
+ * `xiaomi/mimo-v2.6-pro-ultraspeed` / `mimo-v2.6-pro-ultraspeed`
292
310
 
293
311
  Detection also tolerates `provider/model` shapes where `api.id` contains those
294
- slugs. It deliberately does **not** match `mimo-v2.5`, `mimo-v2.5-pro`,
295
- `mimo-v2.6-pro-ultraspeed`, or unrelated MiMo models.
312
+ slugs. Future generations after V2.6 (for example `mimo-v2.7-*`) resolve to the
313
+ family baseline so a new model remains usable even when its exact id is unknown.
314
+ `mimo-v2.5`, `mimo-v2.5-pro`, `mimo-v2`, and undocumented V2.6 variants such as
315
+ `mimo-v2.6-flashx` remain neutral.
296
316
 
297
317
  ### Implicit context caching
298
318
 
@@ -307,9 +327,9 @@ Implicit caching is the default assumption.
307
327
 
308
328
  ### Environment-block stabilization
309
329
 
310
- MiMo uses the same narrow, content-preserving transformation as GLM-5.3: the
311
- identifiable volatile `<env>` block is relocated to the **tail** of the single
312
- system string. Contents are preserved byte-for-byte; only position changes. This
330
+ MiMo V2.6 Flash/Pro use the same narrow, content-preserving transformation as
331
+ GLM-5.3: the identifiable volatile `<env>` block is relocated to the **tail** of
332
+ the single system string. Contents are preserved byte-for-byte; only position changes. This
313
333
  keeps the large reusable prefix stable when only the environment/date changes.
314
334
 
315
335
  The transformation is applied only when:
@@ -343,12 +363,13 @@ Explicit telemetry events:
343
363
 
344
364
  ### OpenRouter session affinity
345
365
 
346
- For MiMo-V2.6 requests whose actual OpenCode provider identity is `openrouter`,
347
- CacheEngine adds its existing deterministic, session-scoped `x-session-id`
348
- request header. If a case-insensitive `x-session-id` already exists in model or
349
- plugin headers, CacheEngine preserves it and does not replace it. Eligibility
350
- uses both the MiMo-V2.6 family and the actual provider identity; a matching model
351
- slug on another endpoint is not enough.
366
+ For MiMo V2.6-and-later requests whose actual OpenCode provider identity is
367
+ `openrouter`, CacheEngine adds its existing deterministic, session-scoped
368
+ `x-session-id` request header. If a case-insensitive `x-session-id` already
369
+ exists in model or plugin headers, CacheEngine preserves it and does not replace
370
+ it. Eligibility uses both the MiMo V2.6-and-later family and the actual provider
371
+ identity; a matching model slug on another endpoint is not enough. This is
372
+ transport affinity, separate from the V2.6 Flash/Pro `<env>` overlay.
352
373
 
353
374
  For Xiaomi's direct endpoint and every other non-OpenRouter provider, CacheEngine
354
375
  does not add its OpenRouter-specific `x-session-id`. Direct provider endpoints
@@ -428,8 +449,8 @@ and are reported diagnostically; the message content is left untouched.
428
449
  | ------------- | --------- | ------------------- | ----------------------- | -------------------------- | -------------------- |
429
450
  | DeepSeek | `deepseek` (V4-and-later family + passive fallback) | No | No | None | provider `cache.read` / `cache.write` |
430
451
  | GPT-5.6 and later | version boundary `gpt-<major>[.<minor>] ≥ 5.6` on OpenAI-ish endpoints (includes GPT-6) | No | Yes: `prompt_cache_key` + options | None | provider cache tokens |
431
- | GLM-5.3 | `glm-5.3*` | Yes, narrowly (`<env>` tail) | No provider cache key | `x-session-id` on OpenRouter only | provider cache tokens (GLM ratio) |
432
- | MiMo-V2.6 | Flash / Pro only | Yes, narrowly (`<env>` tail) | No: implicit caching only | `x-session-id` on OpenRouter only | `cached_tokens / prompt_tokens` |
452
+ | GLM-5.3 and later | `glm-5.3+` | Yes, narrowly (`<env>` tail) on GLM-5.3 only | No provider cache key | `x-session-id` on OpenRouter only | provider cache tokens (GLM ratio) |
453
+ | MiMo V2.6 and later | `mimo-v2.6+` (family) | Yes, narrowly (`<env>` tail) on V2.6 Flash/Pro only | No: implicit caching only | `x-session-id` on OpenRouter only | `cached_tokens / prompt_tokens` |
433
454
 
434
455
  `x-session-id` is an HTTP affinity header, not a provider cache key or
435
456
  cache-control field. Non-OpenRouter endpoints do not receive CacheEngine's
@@ -941,14 +962,15 @@ neutral
941
962
  The model detector recognizes:
942
963
 
943
964
  * DeepSeek model/provider identifiers
944
- * GPT-5.6 variants
945
- * GLM-5.3 variants
946
- * MiMo-V2.6 Flash and Pro (`xiaomi/mimo-v2.6-flash`, `mimo-v2.6-pro`, ...)
965
+ * GPT-5.6-and-later variants
966
+ * GLM-5.3-and-later variants
967
+ * MiMo V2.6-and-later family (`mimo-v2.6-flash`, `mimo-v2.6-pro`, `mimo-v2.6-pro-ultraspeed`, ...)
947
968
 
948
969
  The GPT-5.6-and-later family has an additional OpenAI/Azure-context check, so a string containing a qualifying GPT version (for example `gpt-5.6` or `gpt-6`) does not automatically cause GPT-specific fields to be sent to an unrelated endpoint.
949
970
 
950
- MiMo detection targets exactly Flash and Pro: it excludes `mimo-v2.5`,
951
- `mimo-v2.5-pro`, and `mimo-v2.6-pro-ultraspeed`.
971
+ MiMo detection keeps the documented V2.6 ids and covers future generations after
972
+ V2.6; it excludes `mimo-v2.5`, `mimo-v2.5-pro`, `mimo-v2`, and undocumented V2.6
973
+ variants such as `mimo-v2.6-flashx`.
952
974
 
953
975
  Unknown models use the neutral policy.
954
976
 
@@ -1047,7 +1069,7 @@ returns the runtime-facing descriptor the hooks consume: the legacy policy
1047
1069
  string plus explicit capability flags.
1048
1070
 
1049
1071
  Only registry entries marked `legacy` enable runtime behavior; documented but
1050
- non-legacy entries (for example `mimo-v2.6-pro-ultraspeed`) and all unknown
1072
+ non-legacy aliases (for example `gpt-daybreak-blue-latest`) and all unknown
1051
1073
  models resolve to a neutral runtime. A newer or unknown model therefore never
1052
1074
  inherits a current model's mutation unless the registry explicitly registers it.
1053
1075
  The GPT family is a documented exception in the sense that its boundary is
@@ -1282,7 +1304,7 @@ release, use:
1282
1304
  ```json
1283
1305
  {
1284
1306
  "plugin": [
1285
- "opencode-cache-engine@0.4.1"
1307
+ "opencode-cache-engine@0.4.5"
1286
1308
  ]
1287
1309
  }
1288
1310
  ```
@@ -1385,14 +1407,14 @@ xiaomi/mimo-v2.6-flash
1385
1407
  xiaomi/mimo-v2.6-pro
1386
1408
  ```
1387
1409
 
1388
- `mimo-v2.5`, `mimo-v2.5-pro`, and `mimo-v2.6-pro-ultraspeed` are intentionally
1389
- not matched.
1410
+ `mimo-v2.5`, `mimo-v2.5-pro`, `mimo-v2`, and undocumented V2.6 variants such as
1411
+ `mimo-v2.6-flashx` are intentionally not matched.
1390
1412
 
1391
1413
  ---
1392
1414
 
1393
1415
  ## OpenRouter affinity header is not added
1394
1416
 
1395
- CacheEngine adds its `x-session-id` only for a detected MiMo-V2.6 or GLM-5.3
1417
+ CacheEngine adds its `x-session-id` only for a detected MiMo V2.6-and-later or GLM-5.3-and-later
1396
1418
  request when the actual OpenCode `providerID` is exactly `openrouter`. A direct
1397
1419
  provider route or missing provider identity is bypassed. If a case-insensitive
1398
1420
  `x-session-id` is already present in model or plugin headers, it is preserved
@@ -1423,10 +1445,10 @@ A telemetry failure is intentionally swallowed so it does not break model execut
1423
1445
  The current implementation is intentionally conservative:
1424
1446
 
1425
1447
  ```text
1426
- DeepSeek -> preserve and measure
1427
- GPT-5.6 -> documented cache key/options; user/harness controls the 272K pricing boundary
1428
- GLM-5.3 -> preserve-content <env> relocation + OpenRouter affinity header
1429
- MiMo-V2.6 -> preserve-content <env> relocation + OpenRouter affinity header
1448
+ DeepSeek -> preserve and measure
1449
+ GPT-5.6+ -> documented cache key/options; user/harness controls the 272K pricing boundary
1450
+ GLM-5.3+ -> family baseline; GLM-5.3 only: preserve-content <env> relocation + OpenRouter affinity header
1451
+ MiMo V2.6+ -> family baseline; V2.6 Flash/Pro only: preserve-content <env> relocation (+ OpenRouter affinity header)
1430
1452
  ```
1431
1453
 
1432
1454
  That separation is the core design of the project.
@@ -75,10 +75,10 @@ Detection consequences worth stating explicitly:
75
75
  matched → neutral. **[O]**
76
76
  - `deepseek-v5` (or any future `*deepseek*` id) matches the passive DeepSeek
77
77
  branch because the regex is a bare substring test. **[O]**
78
- - `mimo-v2.6-pro-ultraspeed` is **not** matched: the `(?![\w-])` lookahead fails
79
- on the following `-`. Test `MiMo V2.5 and Pro-UltraSpeed do NOT match MiMo policy`
80
- confirms this. **[O]**
81
- - `mimo-v2.5*` and `glm-5.2`/`glm-4.x` are neutral. **[O]**
78
+ - `mimo-v2.6-pro-ultraspeed` is matched by its own explicit entry since v0.4.5
79
+ (MiMo family baseline, no `<env>` overlay). **[O]**
80
+ - Undocumented V2.6 variants such as `mimo-v2.6-flashx` remain neutral, and
81
+ `mimo-v2.5*` and `glm-5.2`/`glm-4.x` are neutral. **[O]**
82
82
 
83
83
  ---
84
84
 
@@ -288,12 +288,12 @@ made here); **hold** = do not inherit without first-party evidence.
288
288
  | DeepSeek | future-looking V4+ identifiers: `deepseek-v4.1`, `deepseek-v4`, `deepseek-v5` | Not documented as request ids (`deepseek-v4.1`/`deepseek-v4` invalid or version-string only) | Passive via the V4-and-later family predicate or the safe creator fallback (v0.4.3); no mutation | keep passive; treat as unknown-friendly | none | Medium (detection) / Low (future ids) | DeepSeek *Models & Pricing*; *Chat Completions API* | 2026-09-27 |
289
289
  | DeepSeek | pre-V4 negative controls: `deepseek-chat`, `deepseek-reasoner` | Retired names (retired 2026-07-24); no separate V4+ cache policy claimed | Passive | hold | n/a | High | DeepSeek *Change Log*; *news260424* | 2026-09-26 |
290
290
  | Z.AI | GLM 5.3: `glm-5.3`, `glm-5.3-flash`, `glm-5.3-flashx` | Implicit automatic caching; `cached_tokens`; stable-prompt-first guidance; no documented min/TTL/key | GLM policy: `<env>` relocation; OpenRouter `x-session-id` | keep (env relocation is an exact overlay, not a Z.AI control) | env relocation is the overlay; keep scoped to GLM-5.3 | Medium | Z.AI *Context Caching*; *Chat Completion*; *Pricing* | 2026-09-26 |
291
- | Z.AI | current later GLM generations (documented): none newer than 5.3; newest below is `glm-5.2`/`glm-5.1`/`glm-5`/`glm-4.7` | Same implicit mechanism documented service-wide; cached-input price per model | neutral (only `glm-5.3` matched) | **hold** — no doc says 5.3 overlay extends upward; none newer documented | n/a | High (no later gens documented) | Z.AI *New Released*; *Pricing* | 2026-09-26 |
291
+ | Z.AI | current later GLM generations (documented): none newer than 5.3; newest below is `glm-5.2`/`glm-5.1`/`glm-5`/`glm-4.7` | Same implicit mechanism documented service-wide; cached-input price per model | GLM-5.3 family baseline via the 5.3-and-later boundary; **no** `<env>` overlay (v0.4.4) | **baseline only** — overlay stays 5.3-explicit | none documented | High (no later gens documented) | Z.AI *New Released*; *Pricing* | 2026-09-27 |
292
292
  | Z.AI | 5.2 and earlier negative controls: `glm-5.2`, `glm-5.1`, `glm-5`, `glm-4.7`, `glm-4.6`, `glm-4.5`, `glm-4-32b-*` | Cacheable (except `glm-4-32b-0414-128k`), different cached-input pricing; no cache-semantics difference documented | neutral | hold | n/a | High | Z.AI *Pricing*; *Chat Completion* (enum) | 2026-09-26 |
293
293
  | Xiaomi | MiMo V2.6 Flash: `mimo-v2.6-flash` (OR `xiaomi/mimo-v2.6-flash`) | Provider-managed implicit caching; `cached_tokens`; no documented min/TTL/key/prefix rules | MiMo policy: `<env>` relocation; provider-change telemetry; OpenRouter `x-session-id` | keep scoped as exact-model overlay | env relocation unsupported by docs → treat as overlay | Medium | MiMo *Models*; *Pricing*; *openai-api* | 2026-09-26 |
294
294
  | Xiaomi | MiMo V2.6 Pro: `mimo-v2.6-pro` (OR `xiaomi/mimo-v2.6-pro`) | Same documented per-model implicit caching; per-model pricing | MiMo policy (same as Flash) | keep | none documented | Medium | MiMo *Models*; *Pricing* | 2026-09-26 |
295
- | Xiaomi | MiMo V2.6 Pro UltraSpeed: `mimo-v2.6-pro-ultraspeed` (OR `xiaomi/mimo-v2.6-pro-ultraspeed`) | Documented as a Pro **mode**, same V2.6 series; "Context Caching" listed; no documented mechanism difference from Pro | **Not matched** → neutral (`(?![\w-])` blocks it) | **extend OR document as exception** — docs treat it as the same V2.6 series, but no doc proves identical cache controls | explicit decision needed; current behavior is a de-facto exact-model exception | Medium | MiMo *news/latest/v2-6*; *Models*; *Pricing* | 2026-09-26 |
296
- | Xiaomi | later MiMo generations: none documented beyond V2.6; V2.5 deprecates 2026-10-21 | Not documented | neutral | hold (no docs) | n/a | High (no later gens documented) | MiMo *Models* | 2026-09-26 |
295
+ | Xiaomi | MiMo V2.6 Pro UltraSpeed: `mimo-v2.6-pro-ultraspeed` (OR `xiaomi/mimo-v2.6-pro-ultraspeed`) | Documented as a Pro **mode**, same V2.6 series; "Context Caching" listed; no documented mechanism difference from Pro | MiMo family baseline only (cached-token telemetry, provider-change/prefix diagnostics, OpenRouter affinity); **no** `<env>` overlay (v0.4.5) | family baseline; overlay stays Flash/Pro-explicit | none — baseline only | Medium | MiMo *news/latest/v2-6*; *Models*; *Pricing* | 2026-09-27 |
296
+ | Xiaomi | later MiMo generations: none documented beyond V2.6; V2.5 deprecates 2026-10-21 | Not documented; no inheritance rule | Passive family baseline for any future >V2.6 id (v0.4.5); no `<env>` overlay | keep passive, baseline only | none | High (no later gens documented) | MiMo *Models*; *updates/model* | 2026-09-27 |
297
297
  | Xiaomi | V2.5 negative control: `mimo-v2.5`, `mimo-v2.5-pro` | Documented as deprecated 2026-10-21; cache capability listed; no V2.6 policy inheritance claimed | neutral | hold | n/a | High | MiMo *Models*; *news/latest/v2-6* | 2026-09-26 |
298
298
 
299
299
  ---
@@ -323,9 +323,8 @@ a newer model inherits an older policy. They must not be resolved by guessing.
323
323
  undocumented.
324
324
  9. **Xiaomi V2.6 Pro UltraSpeed cache mechanism.** Documented as the same V2.6
325
325
  series and a Pro mode, but no first-party statement proves identical cache
326
- controls to Pro/Flash. This is the one place where CacheEngine's current
327
- non-match (`mimo-v2.6-pro-ultraspeed` → neutral) is a real scope decision
328
- rather than a documented fact.
326
+ controls to Pro/Flash. v0.4.5 resolves this as a CacheEngine scope decision:
327
+ UltraSpeed gets the family **baseline only** (no `<env>` overlay).
329
328
  10. **MiMo on OpenRouter.** OpenRouter's Prompt Caching page documents no
330
329
  MiMo-specific cache section; only generic sticky-routing behavior applies.
331
330
  11. **OpenAI Chat Completions usage-field naming** (`prompt_tokens_details` vs
@@ -384,3 +383,48 @@ a newer model inherits an older policy. They must not be resolved by guessing.
384
383
  - Evidence caveat: first-party pages conflict on whether `deepseek-v4-pro` still
385
384
  routes as a distinct model in late 2026; this does not affect the passive
386
385
  policy, which carries no mutation either way.
386
+
387
+ ### Follow-up: v0.4.4 GLM-5.3-and-later baseline vs GLM-5.3 overlay
388
+
389
+ - Z.AI docs were re-verified on **2026-09-27**. GLM-5.3 is the newest documented
390
+ text generation (no `glm-5.4`/`glm-6`); GLM-5.3 is explicitly "the same base
391
+ model as GLM-5.2" with post-training differences. Caching is implicit with no
392
+ `cache_control`/`prompt_cache_key`/breakpoint/TTL field; `cached_tokens` is the
393
+ reported field. Z.AI publishes **no** generational-inheritance rule.
394
+ - The `<env>` relocation has **no first-party basis** — it is a CacheEngine
395
+ implementation overlay. v0.4.4 therefore separates the concepts:
396
+ - **Family baseline** (`zai.glm-5.3-plus`, predicate `glm >= 5.3`): implicit
397
+ caching plus the non-mutating GLM diagnostics/transport (thinking-integrity
398
+ telemetry, GLM cache ratio, provider-change telemetry, OpenRouter
399
+ `x-session-id`). No prompt rewrite.
400
+ - **GLM-5.3 overlay**: the `<env>` relocation stays registered only on the
401
+ GLM-5.3 family entry, so a later GLM does **not** inherit it.
402
+ - GLM-5.2 and earlier remain neutral. No new GLM cache-control field is added,
403
+ and GLM-5.3 behavior is unchanged.
404
+ - Evidence caveat: because no later GLM generation is documented, the
405
+ "GLM-5.3 and later" boundary is a CacheEngine inference about a passive
406
+ baseline, not a Z.AI contract; it is safe because it introduces no mutation.
407
+
408
+ ### Follow-up: v0.4.5 MiMo V2.6+ baseline vs the validated MiMo overlay
409
+
410
+ - Xiaomi MiMo docs were re-verified on **2026-09-27**. The V2.6 series is Pro +
411
+ Flash, with UltraSpeed documented as a Pro **mode** exposed as
412
+ `mimo-v2.6-pro-ultraspeed`. No generation newer than V2.6 is documented, and
413
+ no generational-inheritance rule is published. Caching is provider-managed
414
+ implicit with no cache-control field in any compat schema; usage fields are
415
+ per-protocol `cached_tokens`/`cache_read_input_tokens`. V2.5 deprecates
416
+ 2026-10-21.
417
+ - The `<env>` relocation has **no first-party basis** — it is a CacheEngine
418
+ overlay. v0.4.5 therefore separates:
419
+ - **Family baseline** (documented V2.6 Flash/Pro, the UltraSpeed mode entry,
420
+ and any future >V2.6 id via `isMimoAfterV26`): cached-token telemetry,
421
+ provider-change/prefix diagnostics, OpenRouter `x-session-id`. No prompt
422
+ rewrite.
423
+ - **Validated overlay**: the `<env>` relocation stays registered only on the
424
+ V2.6 Flash/Pro entry.
425
+ - UltraSpeed moves from neutral to the family baseline (no overlay). V2.5 and
426
+ earlier stay neutral; undocumented V2.6 variants such as `mimo-v2.6-flashx`
427
+ also stay neutral (narrow detection preserved).
428
+ - No MiMo cache-control field is invented. Evidence caveat: since no >V2.6
429
+ generation is documented, future coverage is a CacheEngine inference about a
430
+ passive baseline (safe: no mutation), not a Xiaomi contract.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-cache-engine",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "private": false,
5
5
  "description": "Provider-aware prompt-cache optimization and telemetry for OpenCode",
6
6
  "keywords": [
@@ -102,6 +102,49 @@ export function isDeepseekV4OrLater(slug) {
102
102
  return false
103
103
  }
104
104
 
105
+ // GLM-5.3-and-later family baseline (docs/cache-policy-inventory.md §3; Z.AI
106
+ // docs re-verified 2026-09-27). Z.AI publishes no generational-inheritance rule
107
+ // and no explicit cache control, so this is a CacheEngine inference about a
108
+ // passive/implicit baseline; it is safe because it grants no mutation. The
109
+ // GLM-5.3 `<env>` relocation is a separate, explicit overlay and is NOT granted
110
+ // by this predicate. GLM-5.2 and earlier stay outside this family.
111
+ export function isGlm53OrLater(slug) {
112
+ const text = String(slug ?? "").toLowerCase()
113
+ const re = /glm-(\d{1,3})(?:\.(\d))?(?![\d.])/g
114
+ let m
115
+ while ((m = re.exec(text)) !== null) {
116
+ const major = Number(m[1])
117
+ const minor = m[2] === undefined ? 0 : Number(m[2])
118
+ if (major > 5) return true
119
+ if (major === 5 && minor >= 3) return true
120
+ }
121
+ return false
122
+ }
123
+
124
+ // MiMo generations strictly newer than V2.6 (docs/cache-policy-inventory.md §4;
125
+ // Xiaomi docs re-verified 2026-09-27). The documented V2.6 ids (Flash/Pro and
126
+ // the Pro UltraSpeed mode) are matched by their explicit entries; this predicate
127
+ // covers a future V2.7+/V3+ generation that CacheEngine has never seen, granting
128
+ // only the passive baseline (telemetry + transport) and never the `<env>`
129
+ // relocation overlay, so it is safe by construction. V2.5 and earlier stay
130
+ // neutral.
131
+ //
132
+ // It intentionally does NOT match the existing V2.6 literal, so undocumented
133
+ // V2.6 variants (for example `mimo-v2.6-flashx`) stay neutral per the narrow
134
+ // MiMo detection rule.
135
+ export function isMimoAfterV26(slug) {
136
+ const text = String(slug ?? "").toLowerCase()
137
+ const re = /mimo-v(\d+)(?:\.(\d+))?(?![\d.])/g
138
+ let m
139
+ while ((m = re.exec(text)) !== null) {
140
+ const major = Number(m[1])
141
+ const minor = m[2] === undefined ? 0 : Number(m[2])
142
+ if (major > 2) return true
143
+ if (major === 2 && minor > 6) return true
144
+ }
145
+ return false
146
+ }
147
+
105
148
  // Candidate ids for exact/alias lookup. Includes the raw apiID/modelID, the
106
149
  // lower-cased forms, and a single stripped transport/vendor prefix
107
150
  // (e.g. "openai/gpt-5.6-luna" -> "gpt-5.6-luna", "xiaomi/mimo-v2.6-flash" ->
@@ -344,6 +387,29 @@ export const POLICY_REGISTRY = [
344
387
  }),
345
388
  inventoryRef: "§3 Z.AI GLM",
346
389
  },
390
+ {
391
+ // v0.4.4: "GLM-5.3 and later" family baseline. A future 5.3+ model inherits
392
+ // the implicit-cache baseline and its non-mutating diagnostics/transport,
393
+ // but NOT the GLM-5.3-specific `<env>` relocation overlay (`overlays: []`
394
+ // and no `envRelocation` capability). GLM-5.2 and earlier stay neutral.
395
+ id: "zai.glm-5.3-plus",
396
+ creator: "z.ai",
397
+ family: "glm-5.3",
398
+ kind: "family",
399
+ predicate: isGlm53OrLater,
400
+ baseline: "zai.implicit-cache",
401
+ overlays: [],
402
+ legacy: true,
403
+ runtime: rt("glm53", {
404
+ thinkingIntegrity: true,
405
+ cacheRatio: "glm",
406
+ providerChange: "glm",
407
+ openRouterAffinity: true,
408
+ }),
409
+ boundary: "GLM-5.3 and later",
410
+ note: "Z.AI publishes no generational-inheritance rule and no explicit cache control. The baseline is implicit caching; the `<env>` relocation is a GLM-5.3-only CacheEngine overlay and is intentionally not inherited. No cache-control field is invented.",
411
+ inventoryRef: "§3 Z.AI GLM",
412
+ },
347
413
  {
348
414
  id: "xiaomi.mimo-v2.6",
349
415
  creator: "xiaomi",
@@ -367,14 +433,42 @@ export const POLICY_REGISTRY = [
367
433
  id: "xiaomi.mimo-v2.6-pro-ultraspeed",
368
434
  creator: "xiaomi",
369
435
  family: "mimo-v2.6",
370
- kind: "exact",
436
+ kind: "family",
437
+ pattern: /mimo-v2\.6-pro-ultraspeed/i,
371
438
  exactIds: ["mimo-v2.6-pro-ultraspeed"],
372
439
  baseline: "xiaomi.implicit-cache",
373
440
  overlays: [],
374
- legacy: false,
375
- runtime: rt("neutral"),
376
- policyStatus: "documented-series-member-without-registered-overlay",
377
- note: "Documented as a Pro mode in the same V2.6 series, but the inventory does not establish identical cache controls and CacheEngine registers no overlay for it.",
441
+ legacy: true,
442
+ runtime: rt("mimo26", {
443
+ cacheRatio: "mimo",
444
+ providerChange: "mimo",
445
+ prefixDiagnostics: true,
446
+ openRouterAffinity: true,
447
+ }),
448
+ policyStatus: "documented-series-member-baseline-only",
449
+ note: "v0.4.5: documented as a Pro mode in the same V2.6 series. It gets the MiMo family baseline (cached-token telemetry, provider-change/prefix diagnostics, OpenRouter affinity) but NOT the validated `<env>` relocation overlay.",
450
+ inventoryRef: "§4 Xiaomi MiMo",
451
+ },
452
+ {
453
+ // v0.4.5: "MiMo V2.6 and later" family baseline. A future 2.6+ model gets
454
+ // the passive baseline and its non-mutating diagnostics/transport, but never
455
+ // the `<env>` overlay, which stays explicit to the validated Flash/Pro entry.
456
+ id: "xiaomi.mimo-v2.6-plus",
457
+ creator: "xiaomi",
458
+ family: "mimo-v2.6",
459
+ kind: "family",
460
+ predicate: isMimoAfterV26,
461
+ baseline: "xiaomi.implicit-cache",
462
+ overlays: [],
463
+ legacy: true,
464
+ runtime: rt("mimo26", {
465
+ cacheRatio: "mimo",
466
+ providerChange: "mimo",
467
+ prefixDiagnostics: true,
468
+ openRouterAffinity: true,
469
+ }),
470
+ boundary: "MiMo V2.6 and later",
471
+ note: "Xiaomi documents implicit caching with no cache-control field and no generational-inheritance rule; the `<env>` relocation is a CacheEngine overlay with no first-party basis and is not inherited.",
378
472
  inventoryRef: "§4 Xiaomi MiMo",
379
473
  },
380
474
  {
@@ -54,7 +54,9 @@ import {
54
54
  OVERLAYS,
55
55
  POLICY_REGISTRY,
56
56
  isDeepseekV4OrLater,
57
+ isGlm53OrLater,
57
58
  isGpt56OrLater,
59
+ isMimoAfterV26,
58
60
  resolveLegacyFamily,
59
61
  resolvePolicy,
60
62
  resolveRuntimePolicy,
@@ -324,11 +326,13 @@ test("MiMo V2.6 Flash/Pro match MiMo policy (openrouter + direct)", () => {
324
326
  )
325
327
  })
326
328
 
327
- test("MiMo V2.5 and Pro-UltraSpeed do NOT match MiMo policy", () => {
329
+ test("MiMo V2.5 stays neutral; V2.6 Pro UltraSpeed now resolves (v0.4.5)", () => {
328
330
  assert.equal(detectPolicy(M("openrouter", "xiaomi/mimo-v2.5")), POLICY_NEUTRAL)
329
331
  assert.equal(detectPolicy(M("openrouter", "xiaomi/mimo-v2.5-pro")), POLICY_NEUTRAL)
330
332
  assert.equal(detectPolicy(M("xiaomi", "mimo-v2.5")), POLICY_NEUTRAL)
331
- assert.equal(detectPolicy(M("xiaomi", "mimo-v2.6-pro-ultraspeed")), POLICY_NEUTRAL)
333
+ // v0.4.5: UltraSpeed is a documented V2.6 series member (baseline only).
334
+ assert.equal(detectPolicy(M("xiaomi", "mimo-v2.6-pro-ultraspeed")), POLICY_MIMO26)
335
+ // Undocumented V2.6 variants remain neutral (narrow detection preserved).
332
336
  assert.equal(detectPolicy(M("xiaomi", "mimo-v2.6-flashx")), POLICY_NEUTRAL)
333
337
  })
334
338
 
@@ -1447,7 +1451,7 @@ test("resolvePolicy: MiMo V2.6 Flash/Pro carry the overlay; Pro UltraSpeed is an
1447
1451
  assert.equal(ultraspeed.matchType, "exact")
1448
1452
  assert.deepEqual(overlayIds(ultraspeed), [])
1449
1453
  const uEntry = POLICY_REGISTRY.find((e) => e.id === "xiaomi.mimo-v2.6-pro-ultraspeed")
1450
- assert.equal(uEntry.policyStatus, "documented-series-member-without-registered-overlay")
1454
+ assert.equal(uEntry.policyStatus, "documented-series-member-baseline-only")
1451
1455
 
1452
1456
  const v25 = resolvePolicy(M("xiaomi", "mimo-v2.5"))
1453
1457
  assert.equal(v25.family, "neutral")
@@ -1650,10 +1654,15 @@ async function runPolicyMigrationProbe() {
1650
1654
  { name: "deepseek-gateway", model: { providerID: "acme-gateway", id: "my-deepseek-mirror", api: { id: "my-deepseek-mirror" } }, expect: { policy: "deepseek", env: false, gpt: false, header: false } },
1651
1655
  { name: "glm-5.3-direct", model: { providerID: "zai", id: "glm-5.3", api: { id: "glm-5.3" } }, expect: { policy: "glm53", env: true, gpt: false, header: false } },
1652
1656
  { name: "glm-5.3-openrouter", model: { providerID: "openrouter", id: "z-ai/glm-5.3-flash", api: { id: "z-ai/glm-5.3-flash" } }, expect: { policy: "glm53", env: true, gpt: false, header: true } },
1657
+ { name: "glm-5.4-direct", model: { providerID: "zai", id: "glm-5.4", api: { id: "glm-5.4" } }, expect: { policy: "glm53", env: false, gpt: false, header: false } },
1658
+ { name: "glm-5.4-openrouter", model: { providerID: "openrouter", id: "z-ai/glm-5.4", api: { id: "z-ai/glm-5.4" } }, expect: { policy: "glm53", env: false, gpt: false, header: true } },
1653
1659
  { name: "glm-5.2", model: { providerID: "zai", id: "glm-5.2", api: { id: "glm-5.2" } }, expect: { policy: "neutral", env: false, gpt: false, header: false } },
1654
1660
  { name: "mimo-v2.6-flash-direct", model: { providerID: "xiaomi", id: "mimo-v2.6-flash", api: { id: "mimo-v2.6-flash" } }, expect: { policy: "mimo26", env: true, gpt: false, header: false } },
1655
1661
  { name: "mimo-v2.6-pro-openrouter", model: { providerID: "openrouter", id: "xiaomi/mimo-v2.6-pro", api: { id: "xiaomi/mimo-v2.6-pro" } }, expect: { policy: "mimo26", env: true, gpt: false, header: true } },
1656
- { name: "mimo-v2.6-pro-ultraspeed", model: { providerID: "xiaomi", id: "mimo-v2.6-pro-ultraspeed", api: { id: "mimo-v2.6-pro-ultraspeed" } }, expect: { policy: "neutral", env: false, gpt: false, header: false } },
1662
+ { name: "mimo-v2.6-pro-ultraspeed", model: { providerID: "xiaomi", id: "mimo-v2.6-pro-ultraspeed", api: { id: "mimo-v2.6-pro-ultraspeed" } }, expect: { policy: "mimo26", env: false, gpt: false, header: false } },
1663
+ { name: "mimo-v2.7-future", model: { providerID: "xiaomi", id: "mimo-v2.7-flash", api: { id: "mimo-v2.7-flash" } }, expect: { policy: "mimo26", env: false, gpt: false, header: false } },
1664
+ { name: "mimo-v2.7-openrouter", model: { providerID: "openrouter", id: "xiaomi/mimo-v2.7-flash", api: { id: "xiaomi/mimo-v2.7-flash" } }, expect: { policy: "mimo26", env: false, gpt: false, header: true } },
1665
+ { name: "mimo-v2.6-pro-ultraspeed-openrouter", model: { providerID: "openrouter", id: "xiaomi/mimo-v2.6-pro-ultraspeed", api: { id: "xiaomi/mimo-v2.6-pro-ultraspeed" } }, expect: { policy: "mimo26", env: false, gpt: false, header: true } },
1657
1666
  { name: "mimo-v2.5", model: { providerID: "xiaomi", id: "mimo-v2.5", api: { id: "mimo-v2.5" } }, expect: { policy: "neutral", env: false, gpt: false, header: false } },
1658
1667
  { name: "unknown-provider", model: { providerID: "mystery-provider", id: "xiaomi/mimo-v2.6-flash", api: { id: "xiaomi/mimo-v2.6-flash" } }, expect: { policy: "mimo26", env: true, gpt: false, header: false } },
1659
1668
  { name: "unknown-openrouter", model: { providerID: "openrouter", id: "acme/mystery-9", api: { id: "acme/mystery-9" } }, expect: { policy: "neutral", env: false, gpt: false, header: false } },
@@ -1915,3 +1924,194 @@ test("v0.4.3: DeepSeek never receives OpenRouter affinity or GPT/GLM/MiMo fields
1915
1924
  assert.equal(r.existingHeadersPreserved, true, `${name}: headers preserved`)
1916
1925
  }
1917
1926
  })
1927
+
1928
+ // ===========================================================================
1929
+ // v0.4.4 GLM-5.3-and-later family baseline vs the GLM-5.3-specific overlay
1930
+ //
1931
+ // Source: Z.AI docs re-verified 2026-09-27 (docs/cache-policy-inventory.md §3).
1932
+ // Z.AI documents implicit caching (no cache control) and publishes no
1933
+ // generational-inheritance rule; the `<env>` relocation is a CacheEngine overlay
1934
+ // with no first-party basis. GLM-5.2 and earlier stay neutral.
1935
+ // ===========================================================================
1936
+
1937
+ test("v0.4.4: isGlm53OrLater matches GLM-5.3+ version tokens only", () => {
1938
+ const inFamily = ["glm-5.3", "glm-5.3-flash", "glm-5.3-flashx", "glm-5.4", "glm-5.9", "glm-6", "z-ai/glm-5.3-flash"]
1939
+ for (const id of inFamily) assert.equal(isGlm53OrLater(id), true, `${id} is 5.3+`)
1940
+ const outOfFamily = ["glm-5.2", "glm-5.1", "glm-5", "glm-4.7", "glm-4.6", "glm-4.5", "glm-4.5-air", "glm-4-32b-0414-128k", ""]
1941
+ for (const id of outOfFamily) assert.equal(isGlm53OrLater(id), false, `${id} is pre-5.3`)
1942
+ })
1943
+
1944
+ test("v0.4.4: GLM-5.3 keeps its overlay; a later GLM gets the baseline only", () => {
1945
+ const g53 = resolvePolicy(M("zai", "glm-5.3"))
1946
+ assert.equal(g53.family, "glm-5.3")
1947
+ assert.equal(baseId(g53), "zai.implicit-cache")
1948
+ assert.deepEqual(overlayIds(g53), ["glm53.env-relocation"])
1949
+
1950
+ const g54 = resolvePolicy(M("zai", "glm-5.4"))
1951
+ assert.equal(g54.creator, "z.ai")
1952
+ assert.equal(g54.family, "glm-5.3")
1953
+ assert.equal(baseId(g54), "zai.implicit-cache") // same family baseline
1954
+ assert.deepEqual(overlayIds(g54), []) // overlay is NOT inherited
1955
+
1956
+ // Runtime capability separation: baseline diagnostics/transport yes, prompt rewrite no.
1957
+ const c53 = resolveRuntimePolicy(M("zai", "glm-5.3"))
1958
+ const c54 = resolveRuntimePolicy(M("zai", "glm-5.4"))
1959
+ assert.equal(c54.policy, "glm53")
1960
+ assert.equal(c54.envRelocation, null)
1961
+ assert.equal(c54.thinkingIntegrity, true)
1962
+ assert.equal(c54.cacheRatio, "glm")
1963
+ assert.equal(c54.providerChange, "glm")
1964
+ assert.equal(c54.openRouterAffinity, true)
1965
+ assert.equal(c53.envRelocation, "glm")
1966
+
1967
+ // Boundary metadata is traceable and the overlay is registered separately.
1968
+ const plus = POLICY_REGISTRY.find((e) => e.id === "zai.glm-5.3-plus")
1969
+ assert.equal(plus.boundary, "GLM-5.3 and later")
1970
+ assert.deepEqual(plus.overlays, [])
1971
+ assert.ok(plus.inventoryRef)
1972
+ })
1973
+
1974
+ test("v0.4.4: GLM-5.2 and earlier stay neutral", () => {
1975
+ for (const id of ["glm-5.2", "glm-5.1", "glm-5", "glm-4.7", "glm-4.6", "glm-4.5"]) {
1976
+ const r = resolvePolicy(M("zai", id))
1977
+ assert.equal(r.family, "neutral", `${id} neutral`)
1978
+ assert.deepEqual(overlayIds(r), [])
1979
+ assert.equal(resolveRuntimePolicy(M("zai", id)).policy, "neutral")
1980
+ }
1981
+ })
1982
+
1983
+ test("v0.4.4: legacy detectPolicy follows the GLM-5.3-and-later boundary", () => {
1984
+ assert.equal(detectPolicy(M("zai", "glm-5.3-flash")), POLICY_GLM53)
1985
+ assert.equal(detectPolicy(M("zai", "glm-5.4")), POLICY_GLM53)
1986
+ assert.equal(detectPolicy(M("zai", "glm-5.2")), POLICY_NEUTRAL)
1987
+ })
1988
+
1989
+ test("v0.4.4: <env> absent leaves system content unchanged", () => {
1990
+ const plain = "Stable instructions only.\nNo environment block here."
1991
+ const r = relocateVolatileEnvBlock(plain)
1992
+ assert.equal(r.changed, false)
1993
+ assert.equal(r.text, plain)
1994
+ })
1995
+
1996
+ test("v0.4.4: later GLM inherits the baseline but never the <env> rewrite (runtime)", async () => {
1997
+ const { results } = await policyMigrationResults()
1998
+ const g53 = results.find((r) => r.name === "glm-5.3-direct")
1999
+ const g54 = results.find((r) => r.name === "glm-5.4-direct")
2000
+ assert.ok(g53 && g54)
2001
+ // Identical system text with a valid <env> block present in both cases.
2002
+ assert.equal(g53.systemRelocated, true) // 5.3 overlay fires
2003
+ assert.equal(g54.systemRelocated, false) // later GLM does NOT inherit it
2004
+ assert.equal(g54.runtimePolicy, "glm53") // but the family baseline applies
2005
+ assert.equal(g54.gptOptionInjected, false)
2006
+ assert.equal(g54.affinityHeaderAttached, false)
2007
+ })
2008
+
2009
+ test("v0.4.4: GLM OpenRouter affinity is transport-gated for later GLM too", async () => {
2010
+ const { results } = await policyMigrationResults()
2011
+ const or = results.find((r) => r.name === "glm-5.4-openrouter")
2012
+ const direct = results.find((r) => r.name === "glm-5.4-direct")
2013
+ assert.equal(or.affinityHeaderAttached, true)
2014
+ assert.equal(or.systemRelocated, false)
2015
+ assert.equal(direct.affinityHeaderAttached, false)
2016
+ assert.equal(or.existingHeadersPreserved, true)
2017
+ assert.equal(direct.existingHeadersPreserved, true)
2018
+ })
2019
+
2020
+ // ===========================================================================
2021
+ // v0.4.5 MiMo V2.6+ family baseline vs the validated MiMo overlay
2022
+ //
2023
+ // Source: Xiaomi MiMo docs re-verified 2026-09-27
2024
+ // (docs/cache-policy-inventory.md §4). Caching is provider-managed/implicit with
2025
+ // no cache-control field; the `<env>` relocation is a CacheEngine overlay with
2026
+ // no first-party basis; V2.5 deprecates 2026-10-21. No V2.7+/inheritance rule is
2027
+ // documented, so future coverage is a safe passive baseline only.
2028
+ // ===========================================================================
2029
+
2030
+ test("v0.4.5: isMimoAfterV26 matches generations strictly after V2.6", () => {
2031
+ const inFamily = ["mimo-v2.7-flash", "mimo-v2.7", "mimo-v2.8-pro", "mimo-v3", "mimo-v3.1-flash", "xiaomi/mimo-v2.7-flash"]
2032
+ for (const id of inFamily) assert.equal(isMimoAfterV26(id), true, `${id} is after V2.6`)
2033
+ const outOfFamily = ["mimo-v2.6-flash", "mimo-v2.6-pro", "mimo-v2.6-pro-ultraspeed", "mimo-v2.6-flashx", "mimo-v2.5", "mimo-v2.5-pro", "mimo-v2-flash", ""]
2034
+ for (const id of outOfFamily) assert.equal(isMimoAfterV26(id), false, `${id} is not after V2.6`)
2035
+ })
2036
+
2037
+ test("v0.4.5: Flash/Pro keep the overlay; UltraSpeed and later get the baseline only", () => {
2038
+ const flash = resolvePolicy(M("xiaomi", "mimo-v2.6-flash"))
2039
+ assert.equal(flash.family, "mimo-v2.6")
2040
+ assert.equal(baseId(flash), "xiaomi.implicit-cache")
2041
+ assert.deepEqual(overlayIds(flash), ["mimo26.env-relocation"])
2042
+ assert.deepEqual(overlayIds(resolvePolicy(M("xiaomi", "mimo-v2.6-pro"))), ["mimo26.env-relocation"])
2043
+
2044
+ for (const id of ["mimo-v2.6-pro-ultraspeed", "mimo-v2.7-flash"]) {
2045
+ const r = resolvePolicy(M("xiaomi", id))
2046
+ assert.equal(r.family, "mimo-v2.6", `${id}: family`)
2047
+ assert.equal(baseId(r), "xiaomi.implicit-cache", `${id}: same baseline`)
2048
+ assert.deepEqual(overlayIds(r), [], `${id}: no overlay`)
2049
+ const c = resolveRuntimePolicy(M("xiaomi", id))
2050
+ assert.equal(c.policy, "mimo26", `${id}: policy`)
2051
+ assert.equal(c.envRelocation, null, `${id}: no prompt rewrite`)
2052
+ assert.equal(c.cacheRatio, "mimo", `${id}: cached-token ratio`)
2053
+ assert.equal(c.providerChange, "mimo", `${id}: provider diagnostics`)
2054
+ assert.equal(c.openRouterAffinity, true, `${id}: affinity capability`)
2055
+ assert.equal(c.gptCacheMetadata, false, `${id}: no leak`)
2056
+ }
2057
+
2058
+ // Same baseline object family for the overlay and non-overlay members.
2059
+ assert.equal(baseId(resolvePolicy(M("xiaomi", "mimo-v2.7-flash"))), baseId(flash))
2060
+ })
2061
+
2062
+ test("v0.4.5: MiMo V2.5 and earlier stay neutral", () => {
2063
+ for (const id of ["mimo-v2.5", "mimo-v2.5-pro", "mimo-v2-flash", "mimo-v2"]) {
2064
+ const r = resolvePolicy(M("xiaomi", id))
2065
+ assert.equal(r.family, "neutral", `${id}: neutral`)
2066
+ assert.deepEqual(overlayIds(r), [], `${id}: no overlay`)
2067
+ assert.equal(resolveRuntimePolicy(M("xiaomi", id)).policy, "neutral", `${id}: neutral runtime`)
2068
+ }
2069
+ })
2070
+
2071
+ test("v0.4.5: legacy detectPolicy follows the MiMo V2.6+ boundary", () => {
2072
+ assert.equal(detectPolicy(M("xiaomi", "mimo-v2.6-flash")), POLICY_MIMO26)
2073
+ assert.equal(detectPolicy(M("xiaomi", "mimo-v2.6-pro-ultraspeed")), POLICY_MIMO26)
2074
+ assert.equal(detectPolicy(M("xiaomi", "mimo-v2.7-flash")), POLICY_MIMO26)
2075
+ assert.equal(detectPolicy(M("xiaomi", "mimo-v2.5")), POLICY_NEUTRAL)
2076
+ assert.equal(detectPolicy(M("xiaomi", "mimo-v2.6-flashx")), POLICY_NEUTRAL)
2077
+ })
2078
+
2079
+ test("v0.4.5: <env> absent is a no-op for MiMo transforms", () => {
2080
+ const plain = "Stable MiMo instructions.\nNo environment block."
2081
+ const r = relocateVolatileEnvBlock(plain)
2082
+ assert.equal(r.changed, false)
2083
+ assert.equal(r.text, plain)
2084
+ })
2085
+
2086
+ test("v0.4.5: later MiMo inherits the baseline but never the <env> overlay (runtime)", async () => {
2087
+ const { results } = await policyMigrationResults()
2088
+ const flash = results.find((r) => r.name === "mimo-v2.6-flash-direct")
2089
+ const ultra = results.find((r) => r.name === "mimo-v2.6-pro-ultraspeed")
2090
+ const future = results.find((r) => r.name === "mimo-v2.7-future")
2091
+ assert.ok(flash && ultra && future)
2092
+ // Identical system text with a valid <env> block present in every case.
2093
+ assert.equal(flash.systemRelocated, true) // validated Flash overlay fires
2094
+ assert.equal(ultra.systemRelocated, false) // UltraSpeed: baseline only
2095
+ assert.equal(future.systemRelocated, false) // future model: baseline only
2096
+ assert.equal(ultra.runtimePolicy, "mimo26")
2097
+ assert.equal(future.runtimePolicy, "mimo26")
2098
+ })
2099
+
2100
+ test("v0.4.5: MiMo OpenRouter affinity stays transport-gated", async () => {
2101
+ const { results } = await policyMigrationResults()
2102
+ const orFuture = results.find((r) => r.name === "mimo-v2.7-openrouter")
2103
+ const orUltra = results.find((r) => r.name === "mimo-v2.6-pro-ultraspeed-openrouter")
2104
+ const direct = results.find((r) => r.name === "mimo-v2.7-future")
2105
+ assert.equal(orFuture.affinityHeaderAttached, true)
2106
+ assert.equal(orUltra.affinityHeaderAttached, true)
2107
+ assert.equal(direct.affinityHeaderAttached, false)
2108
+ assert.equal(orFuture.systemRelocated, false) // affinity is transport, not the overlay
2109
+ })
2110
+
2111
+ test("v0.4.5: MiMo baseline invents no cache fields and keeps cached-token telemetry", () => {
2112
+ const c = resolveRuntimePolicy(M("xiaomi", "mimo-v2.7-flash"))
2113
+ assert.equal(c.gptCacheMetadata, false)
2114
+ assert.equal(c.envRelocation, null)
2115
+ assert.equal(c.cacheRatio, "mimo") // cachedTokens / promptTokens
2116
+ assert.equal(mimoHitRate(75, 100), 75)
2117
+ })