opencode-cache-engine 0.4.4 → 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
@@ -32,7 +32,7 @@ The plugin currently has four cache-policy families:
32
32
  unchanged. GPT-6 and future 5.6+/6+/7+ versions resolve through the same
33
33
  documented boundary.
34
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** — narrow, content-preserving `<env>` relocation and diagnostics.
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 MiMo-V2.6 and the GLM-5.3-and-later family, 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
@@ -286,19 +286,33 @@ whether a header was already present or added, and provider-identity changes
286
286
  (`glm_provider_changed`). They do not record the header value.
287
287
 
288
288
 
289
- ## MiMo-V2.6 (Flash / Pro)
289
+ ## MiMo V2.6 and later
290
290
 
291
291
  ### Policy: prefix stability + OpenRouter session affinity
292
292
 
293
- MiMo-V2.6 is Xiaomi's current model family. The plugin targets exactly two
294
- 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:
295
306
 
296
307
  * `xiaomi/mimo-v2.6-flash` / `mimo-v2.6-flash`
297
308
  * `xiaomi/mimo-v2.6-pro` / `mimo-v2.6-pro`
309
+ * `xiaomi/mimo-v2.6-pro-ultraspeed` / `mimo-v2.6-pro-ultraspeed`
298
310
 
299
311
  Detection also tolerates `provider/model` shapes where `api.id` contains those
300
- slugs. It deliberately does **not** match `mimo-v2.5`, `mimo-v2.5-pro`,
301
- `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.
302
316
 
303
317
  ### Implicit context caching
304
318
 
@@ -313,9 +327,9 @@ Implicit caching is the default assumption.
313
327
 
314
328
  ### Environment-block stabilization
315
329
 
316
- MiMo uses the same narrow, content-preserving transformation as GLM-5.3: the
317
- identifiable volatile `<env>` block is relocated to the **tail** of the single
318
- 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
319
333
  keeps the large reusable prefix stable when only the environment/date changes.
320
334
 
321
335
  The transformation is applied only when:
@@ -349,12 +363,13 @@ Explicit telemetry events:
349
363
 
350
364
  ### OpenRouter session affinity
351
365
 
352
- For MiMo-V2.6 requests whose actual OpenCode provider identity is `openrouter`,
353
- CacheEngine adds its existing deterministic, session-scoped `x-session-id`
354
- request header. If a case-insensitive `x-session-id` already exists in model or
355
- plugin headers, CacheEngine preserves it and does not replace it. Eligibility
356
- uses both the MiMo-V2.6 family and the actual provider identity; a matching model
357
- 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.
358
373
 
359
374
  For Xiaomi's direct endpoint and every other non-OpenRouter provider, CacheEngine
360
375
  does not add its OpenRouter-specific `x-session-id`. Direct provider endpoints
@@ -435,7 +450,7 @@ and are reported diagnostically; the message content is left untouched.
435
450
  | DeepSeek | `deepseek` (V4-and-later family + passive fallback) | No | No | None | provider `cache.read` / `cache.write` |
436
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 |
437
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) |
438
- | MiMo-V2.6 | Flash / Pro only | Yes, narrowly (`<env>` tail) | No: implicit caching only | `x-session-id` on OpenRouter only | `cached_tokens / prompt_tokens` |
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` |
439
454
 
440
455
  `x-session-id` is an HTTP affinity header, not a provider cache key or
441
456
  cache-control field. Non-OpenRouter endpoints do not receive CacheEngine's
@@ -947,14 +962,15 @@ neutral
947
962
  The model detector recognizes:
948
963
 
949
964
  * DeepSeek model/provider identifiers
950
- * GPT-5.6 variants
951
- * GLM-5.3 variants
952
- * 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`, ...)
953
968
 
954
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.
955
970
 
956
- MiMo detection targets exactly Flash and Pro: it excludes `mimo-v2.5`,
957
- `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`.
958
974
 
959
975
  Unknown models use the neutral policy.
960
976
 
@@ -1053,7 +1069,7 @@ returns the runtime-facing descriptor the hooks consume: the legacy policy
1053
1069
  string plus explicit capability flags.
1054
1070
 
1055
1071
  Only registry entries marked `legacy` enable runtime behavior; documented but
1056
- 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
1057
1073
  models resolve to a neutral runtime. A newer or unknown model therefore never
1058
1074
  inherits a current model's mutation unless the registry explicitly registers it.
1059
1075
  The GPT family is a documented exception in the sense that its boundary is
@@ -1288,7 +1304,7 @@ release, use:
1288
1304
  ```json
1289
1305
  {
1290
1306
  "plugin": [
1291
- "opencode-cache-engine@0.4.1"
1307
+ "opencode-cache-engine@0.4.5"
1292
1308
  ]
1293
1309
  }
1294
1310
  ```
@@ -1391,14 +1407,14 @@ xiaomi/mimo-v2.6-flash
1391
1407
  xiaomi/mimo-v2.6-pro
1392
1408
  ```
1393
1409
 
1394
- `mimo-v2.5`, `mimo-v2.5-pro`, and `mimo-v2.6-pro-ultraspeed` are intentionally
1395
- 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.
1396
1412
 
1397
1413
  ---
1398
1414
 
1399
1415
  ## OpenRouter affinity header is not added
1400
1416
 
1401
- CacheEngine adds its `x-session-id` only for a detected MiMo-V2.6 or GLM-5.3-and-later
1417
+ CacheEngine adds its `x-session-id` only for a detected MiMo V2.6-and-later or GLM-5.3-and-later
1402
1418
  request when the actual OpenCode `providerID` is exactly `openrouter`. A direct
1403
1419
  provider route or missing provider identity is bypassed. If a case-insensitive
1404
1420
  `x-session-id` is already present in model or plugin headers, it is preserved
@@ -1429,10 +1445,10 @@ A telemetry failure is intentionally swallowed so it does not break model execut
1429
1445
  The current implementation is intentionally conservative:
1430
1446
 
1431
1447
  ```text
1432
- DeepSeek -> preserve and measure
1433
- GPT-5.6 -> documented cache key/options; user/harness controls the 272K pricing boundary
1434
- GLM-5.3 -> preserve-content <env> relocation + OpenRouter affinity header
1435
- 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)
1436
1452
  ```
1437
1453
 
1438
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
 
@@ -292,8 +292,8 @@ made here); **hold** = do not inherit without first-party evidence.
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
@@ -405,3 +404,27 @@ a newer model inherits an older policy. They must not be resolved by guessing.
405
404
  - Evidence caveat: because no later GLM generation is documented, the
406
405
  "GLM-5.3 and later" boundary is a CacheEngine inference about a passive
407
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.4",
3
+ "version": "0.4.5",
4
4
  "private": false,
5
5
  "description": "Provider-aware prompt-cache optimization and telemetry for OpenCode",
6
6
  "keywords": [
@@ -121,6 +121,30 @@ export function isGlm53OrLater(slug) {
121
121
  return false
122
122
  }
123
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
+
124
148
  // Candidate ids for exact/alias lookup. Includes the raw apiID/modelID, the
125
149
  // lower-cased forms, and a single stripped transport/vendor prefix
126
150
  // (e.g. "openai/gpt-5.6-luna" -> "gpt-5.6-luna", "xiaomi/mimo-v2.6-flash" ->
@@ -409,14 +433,42 @@ export const POLICY_REGISTRY = [
409
433
  id: "xiaomi.mimo-v2.6-pro-ultraspeed",
410
434
  creator: "xiaomi",
411
435
  family: "mimo-v2.6",
412
- kind: "exact",
436
+ kind: "family",
437
+ pattern: /mimo-v2\.6-pro-ultraspeed/i,
413
438
  exactIds: ["mimo-v2.6-pro-ultraspeed"],
414
439
  baseline: "xiaomi.implicit-cache",
415
440
  overlays: [],
416
- legacy: false,
417
- runtime: rt("neutral"),
418
- policyStatus: "documented-series-member-without-registered-overlay",
419
- 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.",
420
472
  inventoryRef: "§4 Xiaomi MiMo",
421
473
  },
422
474
  {
@@ -56,6 +56,7 @@ import {
56
56
  isDeepseekV4OrLater,
57
57
  isGlm53OrLater,
58
58
  isGpt56OrLater,
59
+ isMimoAfterV26,
59
60
  resolveLegacyFamily,
60
61
  resolvePolicy,
61
62
  resolveRuntimePolicy,
@@ -325,11 +326,13 @@ test("MiMo V2.6 Flash/Pro match MiMo policy (openrouter + direct)", () => {
325
326
  )
326
327
  })
327
328
 
328
- 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)", () => {
329
330
  assert.equal(detectPolicy(M("openrouter", "xiaomi/mimo-v2.5")), POLICY_NEUTRAL)
330
331
  assert.equal(detectPolicy(M("openrouter", "xiaomi/mimo-v2.5-pro")), POLICY_NEUTRAL)
331
332
  assert.equal(detectPolicy(M("xiaomi", "mimo-v2.5")), POLICY_NEUTRAL)
332
- 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).
333
336
  assert.equal(detectPolicy(M("xiaomi", "mimo-v2.6-flashx")), POLICY_NEUTRAL)
334
337
  })
335
338
 
@@ -1448,7 +1451,7 @@ test("resolvePolicy: MiMo V2.6 Flash/Pro carry the overlay; Pro UltraSpeed is an
1448
1451
  assert.equal(ultraspeed.matchType, "exact")
1449
1452
  assert.deepEqual(overlayIds(ultraspeed), [])
1450
1453
  const uEntry = POLICY_REGISTRY.find((e) => e.id === "xiaomi.mimo-v2.6-pro-ultraspeed")
1451
- assert.equal(uEntry.policyStatus, "documented-series-member-without-registered-overlay")
1454
+ assert.equal(uEntry.policyStatus, "documented-series-member-baseline-only")
1452
1455
 
1453
1456
  const v25 = resolvePolicy(M("xiaomi", "mimo-v2.5"))
1454
1457
  assert.equal(v25.family, "neutral")
@@ -1656,7 +1659,10 @@ async function runPolicyMigrationProbe() {
1656
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 } },
1657
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 } },
1658
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 } },
1659
- { 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 } },
1660
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 } },
1661
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 } },
1662
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 } },
@@ -2010,3 +2016,102 @@ test("v0.4.4: GLM OpenRouter affinity is transport-gated for later GLM too", asy
2010
2016
  assert.equal(or.existingHeadersPreserved, true)
2011
2017
  assert.equal(direct.existingHeadersPreserved, true)
2012
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
+ })