@cortexkit/opencode-magic-context 0.36.0 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/dist/config/index.d.ts.map +1 -1
  2. package/dist/config/project-security.d.ts +2 -1
  3. package/dist/config/project-security.d.ts.map +1 -1
  4. package/dist/config/schema/magic-context.d.ts +10 -0
  5. package/dist/config/schema/magic-context.d.ts.map +1 -1
  6. package/dist/{conflict-warning-hook-dw9fs934.js → conflict-warning-hook-an4fxhwf.js} +4 -4
  7. package/dist/{derive-budgets-88mxk2w1.js → derive-budgets-0f8xpyw2.js} +3 -2
  8. package/dist/features/magic-context/context-authority.d.ts +12 -0
  9. package/dist/features/magic-context/context-authority.d.ts.map +1 -1
  10. package/dist/features/magic-context/dreamer/classify.d.ts +2 -0
  11. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
  12. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts +2 -0
  13. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
  14. package/dist/features/magic-context/dreamer/lease.d.ts +10 -3
  15. package/dist/features/magic-context/dreamer/lease.d.ts.map +1 -1
  16. package/dist/features/magic-context/dreamer/map-memories.d.ts +2 -0
  17. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  18. package/dist/features/magic-context/dreamer/module-apply.d.ts +5 -0
  19. package/dist/features/magic-context/dreamer/module-apply.d.ts.map +1 -1
  20. package/dist/features/magic-context/dreamer/promote-primers.d.ts +2 -0
  21. package/dist/features/magic-context/dreamer/promote-primers.d.ts.map +1 -1
  22. package/dist/features/magic-context/dreamer/refresh-primers.d.ts +2 -0
  23. package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
  24. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  25. package/dist/features/magic-context/dreamer/task-scheduler.d.ts +5 -2
  26. package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
  27. package/dist/features/magic-context/dreamer/verify.d.ts +2 -0
  28. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  29. package/dist/features/magic-context/memory/embedding-openai.d.ts +3 -1
  30. package/dist/features/magic-context/memory/embedding-openai.d.ts.map +1 -1
  31. package/dist/features/magic-context/memory/project-identity.d.ts +6 -0
  32. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  33. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  34. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  35. package/dist/features/magic-context/mural/compress-cues.d.ts +2 -0
  36. package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
  37. package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
  38. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  39. package/dist/features/magic-context/schema-fence-probe.d.ts +1 -0
  40. package/dist/features/magic-context/schema-fence-probe.d.ts.map +1 -1
  41. package/dist/features/magic-context/smart-notes/condition-compiler.d.ts +1 -0
  42. package/dist/features/magic-context/smart-notes/condition-compiler.d.ts.map +1 -1
  43. package/dist/features/magic-context/smart-notes/runner.d.ts.map +1 -1
  44. package/dist/features/magic-context/smart-notes/wake-plane.d.ts +21 -0
  45. package/dist/features/magic-context/smart-notes/wake-plane.d.ts.map +1 -0
  46. package/dist/features/magic-context/storage-clone.d.ts +6 -0
  47. package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
  48. package/dist/features/magic-context/storage-db.d.ts +14 -3
  49. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  50. package/dist/features/magic-context/storage-identity-merge.d.ts.map +1 -1
  51. package/dist/features/magic-context/storage-meta-persisted.d.ts +22 -0
  52. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  53. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  54. package/dist/features/magic-context/storage-meta-shared.d.ts.map +1 -1
  55. package/dist/features/magic-context/storage-primers.d.ts +11 -0
  56. package/dist/features/magic-context/storage-primers.d.ts.map +1 -1
  57. package/dist/features/magic-context/storage-schema-helpers.d.ts.map +1 -1
  58. package/dist/features/magic-context/storage-tags.d.ts +2 -0
  59. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  60. package/dist/features/magic-context/storage.d.ts +1 -1
  61. package/dist/features/magic-context/storage.d.ts.map +1 -1
  62. package/dist/features/magic-context/user-memory/review-user-memories.d.ts +2 -0
  63. package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
  64. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts +7 -0
  65. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
  66. package/dist/features/magic-context/window-report-ledger.d.ts +70 -0
  67. package/dist/features/magic-context/window-report-ledger.d.ts.map +1 -0
  68. package/dist/hooks/magic-context/child-session-spawn.d.ts +1 -0
  69. package/dist/hooks/magic-context/child-session-spawn.d.ts.map +1 -1
  70. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  71. package/dist/hooks/magic-context/compaction-off-transition.d.ts.map +1 -1
  72. package/dist/hooks/magic-context/compartment-render-epoch.d.ts +5 -3
  73. package/dist/hooks/magic-context/compartment-render-epoch.d.ts.map +1 -1
  74. package/dist/hooks/magic-context/embed-session-state.d.ts +1 -1
  75. package/dist/hooks/magic-context/embed-session-state.d.ts.map +1 -1
  76. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  77. package/dist/hooks/magic-context/event-resolvers.d.ts +4 -0
  78. package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
  79. package/dist/hooks/magic-context/execute-status.d.ts +2 -1
  80. package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
  81. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  82. package/dist/hooks/magic-context/inject-compartments.d.ts +8 -0
  83. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  84. package/dist/hooks/magic-context/lkg-replay.d.ts +5 -2
  85. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  86. package/dist/hooks/magic-context/lkg-slot.d.ts +20 -0
  87. package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
  88. package/dist/hooks/magic-context/module-state-sync.d.ts +9 -0
  89. package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
  90. package/dist/hooks/magic-context/module-transport.d.ts +20 -3
  91. package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
  92. package/dist/hooks/magic-context/module-wire.d.ts +6 -1
  93. package/dist/hooks/magic-context/module-wire.d.ts.map +1 -1
  94. package/dist/hooks/magic-context/read-session-formatting.d.ts +1 -0
  95. package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
  96. package/dist/hooks/magic-context/rust-mode-transform.d.ts +20 -0
  97. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  98. package/dist/hooks/magic-context/strip-content.d.ts +31 -1
  99. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  100. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  101. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +12 -3
  102. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  103. package/dist/hooks/magic-context/transform.d.ts +10 -0
  104. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  105. package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
  106. package/dist/{index-3nfgbsp4.js → index-0ze9p983.js} +897 -114
  107. package/dist/{index-nsx2n9eg.js → index-4cz5nfxf.js} +3 -3
  108. package/dist/{index-0c9dmw9m.js → index-8mtsfhyg.js} +33 -3
  109. package/dist/{index-f1tnb3vm.js → index-8pqfcghm.js} +21 -9
  110. package/dist/{index-37rt2bka.js → index-cae89eas.js} +26 -7
  111. package/dist/index-cgyfn1s2.js +53 -0
  112. package/dist/{index-z8v31d85.js → index-crke4z5j.js} +144 -14
  113. package/dist/{index-tsgs7td8.js → index-pck9vadr.js} +1 -1
  114. package/dist/index-q0t189ay.js +741 -0
  115. package/dist/{index-3tnkymva.js → index-sw8gnq34.js} +1 -1
  116. package/dist/index.d.ts.map +1 -1
  117. package/dist/index.js +1952 -795
  118. package/dist/plugin/hooks/create-session-hooks.d.ts +3 -0
  119. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  120. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  121. package/dist/plugin/rust-tool-backends.d.ts +4 -0
  122. package/dist/plugin/rust-tool-backends.d.ts.map +1 -1
  123. package/dist/{recomp-orchestrator-7wbbvf87.js → recomp-orchestrator-c3ff16k7.js} +8 -7
  124. package/dist/{safe-notification-target-c11fdda2.js → safe-notification-target-b693f9x3.js} +2 -2
  125. package/dist/{send-session-notification-bgtf4853.js → send-session-notification-dxske5zm.js} +3 -3
  126. package/dist/shared/conflict-detector.d.ts +63 -0
  127. package/dist/shared/conflict-detector.d.ts.map +1 -1
  128. package/dist/shared/conflict-fixer.d.ts.map +1 -1
  129. package/dist/shared/harness-provider-map.d.ts +8 -0
  130. package/dist/shared/harness-provider-map.d.ts.map +1 -1
  131. package/dist/shared/jsonc-edit.d.ts +18 -0
  132. package/dist/shared/jsonc-edit.d.ts.map +1 -0
  133. package/dist/shared/jsonc-parser.d.ts +11 -1
  134. package/dist/shared/jsonc-parser.d.ts.map +1 -1
  135. package/dist/shared/logger.d.ts +8 -0
  136. package/dist/shared/logger.d.ts.map +1 -1
  137. package/dist/shared/models-dev-cache.d.ts +5 -0
  138. package/dist/shared/models-dev-cache.d.ts.map +1 -1
  139. package/dist/shared/prompt-surface-runtime.d.ts.map +1 -1
  140. package/dist/shared/prompt-surface.d.ts +7 -3
  141. package/dist/shared/prompt-surface.d.ts.map +1 -1
  142. package/dist/shared/rpc-client.d.ts.map +1 -1
  143. package/dist/shared/rpc-types.d.ts +14 -0
  144. package/dist/shared/rpc-types.d.ts.map +1 -1
  145. package/dist/shared/rpc-utils.d.ts +32 -6
  146. package/dist/shared/rpc-utils.d.ts.map +1 -1
  147. package/dist/shared/tui-preferences.d.ts +9 -0
  148. package/dist/shared/tui-preferences.d.ts.map +1 -1
  149. package/dist/shared/window-geometry.d.ts +89 -0
  150. package/dist/shared/window-geometry.d.ts.map +1 -0
  151. package/dist/{storage-meta-session-kh5egr11.js → storage-meta-session-mk4gsnke.js} +4 -3
  152. package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
  153. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  154. package/dist/tui/data/context-db.d.ts.map +1 -1
  155. package/dist/tui-compiled/data/context-db.d.ts.map +1 -1
  156. package/package.json +2 -1
  157. package/src/config/index.test.ts +23 -0
  158. package/src/config/index.ts +43 -9
  159. package/src/config/latch-permanence-guard.test.ts +218 -0
  160. package/src/config/project-security.ts +10 -1
  161. package/src/config/schema/magic-context.test.ts +2 -1
  162. package/src/config/schema/magic-context.ts +13 -3
  163. package/src/shared/__fixtures__/window-overlay.v1.json +337 -0
  164. package/src/shared/conflict-detector.test.ts +176 -1
  165. package/src/shared/conflict-detector.ts +126 -3
  166. package/src/shared/conflict-fixer.test.ts +174 -0
  167. package/src/shared/conflict-fixer.ts +66 -70
  168. package/src/shared/harness-provider-map.test.ts +20 -0
  169. package/src/shared/harness-provider-map.ts +19 -0
  170. package/src/shared/jsonc-edit.ts +295 -0
  171. package/src/shared/jsonc-parser.test.ts +33 -0
  172. package/src/shared/jsonc-parser.ts +54 -2
  173. package/src/shared/logger.test.ts +119 -0
  174. package/src/shared/logger.ts +33 -15
  175. package/src/shared/models-dev-cache.test.ts +17 -0
  176. package/src/shared/models-dev-cache.ts +58 -6
  177. package/src/shared/prompt-surface-runtime.ts +5 -3
  178. package/src/shared/prompt-surface.test.ts +91 -2
  179. package/src/shared/prompt-surface.ts +35 -11
  180. package/src/shared/rpc-client.ts +4 -2
  181. package/src/shared/rpc-types.ts +14 -0
  182. package/src/shared/rpc-utils.test.ts +173 -13
  183. package/src/shared/rpc-utils.ts +202 -18
  184. package/src/shared/tui-preferences.test.ts +52 -2
  185. package/src/shared/tui-preferences.ts +42 -17
  186. package/src/shared/window-geometry.test.ts +309 -0
  187. package/src/shared/window-geometry.ts +629 -0
  188. package/src/tui/data/context-db.ts +5 -0
  189. package/src/tui/index.tsx +22 -0
  190. package/src/tui-compiled/data/context-db.ts +5 -0
  191. package/src/tui-compiled/index.tsx +319 -255
  192. package/dist/index-wgvxkqpx.js +0 -342
@@ -250,6 +250,28 @@ export function queueTuiPreferenceUpdate(
250
250
 
251
251
  const WATCH_DEBOUNCE_MS = 150;
252
252
 
253
+ type WatchReadFile = (file: string) => Promise<string>;
254
+ type WatchDirectory = (
255
+ directory: string,
256
+ listener: (event: string, filename: string | null) => void,
257
+ ) => { close(): void };
258
+
259
+ let watchReadFile: WatchReadFile = (file) => readFile(file, "utf8");
260
+ let watchDirectory: WatchDirectory = (directory, listener) => watch(directory, listener);
261
+
262
+ export function __setTuiPreferencesWatchTestHooks(hooks: {
263
+ readFile?: WatchReadFile;
264
+ watch?: WatchDirectory;
265
+ }): void {
266
+ watchReadFile = hooks.readFile ?? ((file) => readFile(file, "utf8"));
267
+ watchDirectory = hooks.watch ?? ((directory, listener) => watch(directory, listener));
268
+ }
269
+
270
+ export function __resetTuiPreferencesWatchTestHooks(): void {
271
+ watchReadFile = (file) => readFile(file, "utf8");
272
+ watchDirectory = (directory, listener) => watch(directory, listener);
273
+ }
274
+
253
275
  // Watches the DIRECTORY, not the file: editors and our own atomic writes replace
254
276
  // the file via rename, which kills file-level watchers.
255
277
  //
@@ -266,16 +288,22 @@ export function watchTuiPreferences(onChange: () => void): () => void {
266
288
  const name = basename(file);
267
289
  let timer: ReturnType<typeof setTimeout> | null = null;
268
290
  let lastSeen: string | null = null;
269
- // Seed asynchronously; a real change before the seed resolves still wins
270
- // because the debounce re-reads fresh and compares against `lastSeen` (null
271
- // → does not match → fires).
272
- void readFile(file, "utf8")
273
- .then((text) => {
274
- if (lastSeen === null) lastSeen = text;
275
- })
276
- .catch(() => {});
277
291
  try {
278
- const watcher = watch(dirname(file), (_event, filename) => {
292
+ lastSeen = readFileSync(file, "utf8");
293
+ } catch {
294
+ // A missing or temporarily unreadable baseline is retried after registration.
295
+ }
296
+ const reconcile = (): void => {
297
+ void watchReadFile(file)
298
+ .catch(() => null)
299
+ .then((text) => {
300
+ if (text === null || text === lastSeen) return;
301
+ lastSeen = text;
302
+ onChange();
303
+ });
304
+ };
305
+ try {
306
+ const watcher = watchDirectory(dirname(file), (_event, filename) => {
279
307
  const isOurs =
280
308
  filename === name ||
281
309
  (filename?.startsWith(`${name}.`) && filename.endsWith(".tmp"));
@@ -283,16 +311,13 @@ export function watchTuiPreferences(onChange: () => void): () => void {
283
311
  if (timer) clearTimeout(timer);
284
312
  timer = setTimeout(() => {
285
313
  timer = null;
286
- void readFile(file, "utf8")
287
- .catch(() => null)
288
- .then((text) => {
289
- if (text === null) return;
290
- if (text === lastSeen) return;
291
- lastSeen = text;
292
- onChange();
293
- });
314
+ reconcile();
294
315
  }, WATCH_DEBOUNCE_MS);
295
316
  });
317
+ // Reconcile after registration: a change between the baseline read and
318
+ // watcher installation is observed here, while later changes schedule
319
+ // the same reconciliation path through the watcher callback above.
320
+ reconcile();
296
321
  return () => {
297
322
  if (timer) clearTimeout(timer);
298
323
  watcher.close();
@@ -0,0 +1,309 @@
1
+ import { afterEach, describe, expect, test } from "bun:test";
2
+ import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { resolveLimit } from "./models-dev-cache";
6
+ import {
7
+ deriveWindowGeometry,
8
+ formatWindowDerivationLine,
9
+ parseWindowOverlay,
10
+ placeholderFilteredOutput,
11
+ readWindowOverlayFile,
12
+ resolveWindowOverlayFacts,
13
+ scalarizeFact,
14
+ type WindowOverlay,
15
+ type WindowOverlayFact,
16
+ } from "./window-geometry";
17
+
18
+ const fixture = JSON.parse(
19
+ readFileSync(new URL("./__fixtures__/window-overlay.v1.json", import.meta.url), "utf8"),
20
+ ) as unknown;
21
+ const parsedFixture = parseWindowOverlay(fixture).overlay as WindowOverlay;
22
+ const tempDirs: string[] = [];
23
+
24
+ function fact(
25
+ value: WindowOverlayFact["value"],
26
+ overrides: Partial<WindowOverlayFact> = {},
27
+ ): WindowOverlayFact {
28
+ return {
29
+ value,
30
+ grade: "measured",
31
+ units: "provider",
32
+ boundary: "Observed",
33
+ source_ref: "test",
34
+ observed_at: "2026-08-13T00:00:00Z",
35
+ ...overrides,
36
+ };
37
+ }
38
+
39
+ function overlay(
40
+ provider: string,
41
+ model: string,
42
+ facts: Record<string, WindowOverlayFact>,
43
+ ): WindowOverlay {
44
+ return {
45
+ schema: "fusiform-window-overlay/v1",
46
+ generated_at: "2026-08-13T00:00:00Z",
47
+ minted_provider_ids: [],
48
+ cells: [{ provider_id: provider, model_id: model, facts }],
49
+ };
50
+ }
51
+
52
+ afterEach(() => {
53
+ for (const path of tempDirs.splice(0)) rmSync(path, { recursive: true, force: true });
54
+ });
55
+
56
+ describe("Fusiform overlay v1", () => {
57
+ test("scalarizes every tagged union conservatively", () => {
58
+ expect(scalarizeFact({ kind: "stated", value: 272_000 })).toBe(272_000);
59
+ expect(scalarizeFact({ kind: "bracket", at_least: 340_000, below: 372_001 })).toBe(340_000);
60
+ expect(scalarizeFact({ kind: "bracket", below: 372_001 })).toBeUndefined();
61
+ expect(scalarizeFact({ kind: "unknown", why: "never_measured" })).toBeUndefined();
62
+ });
63
+
64
+ test("preserves a half-open bracket and derives exactly from at_least", () => {
65
+ const halfOpen = parseWindowOverlay({
66
+ schema: "fusiform-window-overlay/v1",
67
+ generated_at: "2026-08-13T00:00:00Z",
68
+ minted_provider_ids: [],
69
+ cells: [
70
+ {
71
+ provider_id: "openai-chatgpt-oauth",
72
+ model_id: "gpt-5.6-sol",
73
+ facts: {
74
+ "window.advertised": fact({ kind: "stated", value: 272_000 }),
75
+ "window.enforced": fact({ kind: "bracket", at_least: 340_000 }),
76
+ },
77
+ },
78
+ ],
79
+ }).overlay;
80
+ const parsedValue = halfOpen?.cells[0]?.facts["window.enforced"]?.value;
81
+ expect(parsedValue).toEqual({ kind: "bracket", at_least: 340_000 });
82
+ expect(parsedValue && "below" in parsedValue).toBe(false);
83
+ const halfOpenResult = deriveWindowGeometry(
84
+ "openai-chatgpt-oauth",
85
+ "gpt-5.6-sol",
86
+ { context: 272_000, output: 128_000 },
87
+ {
88
+ overlay: resolveWindowOverlayFacts("openai-chatgpt-oauth", "gpt-5.6-sol", halfOpen),
89
+ },
90
+ );
91
+ const statedResult = deriveWindowGeometry(
92
+ "openai-chatgpt-oauth",
93
+ "gpt-5.6-sol",
94
+ { context: 272_000, output: 128_000 },
95
+ {
96
+ overlay: resolveWindowOverlayFacts(
97
+ "openai-chatgpt-oauth",
98
+ "gpt-5.6-sol",
99
+ overlay("openai-chatgpt-oauth", "gpt-5.6-sol", {
100
+ "window.enforced": fact({ kind: "stated", value: 340_000 }),
101
+ }),
102
+ ),
103
+ },
104
+ );
105
+ expect(halfOpenResult).toEqual(statedResult);
106
+ });
107
+
108
+ test("specific cells override wildcard facts per fact", () => {
109
+ const data: WindowOverlay = {
110
+ schema: "fusiform-window-overlay/v1",
111
+ generated_at: "2026-08-13T00:00:00Z",
112
+ minted_provider_ids: [],
113
+ cells: [
114
+ {
115
+ provider_id: "ollama-cloud",
116
+ model_id: "*",
117
+ facts: {
118
+ "output.enforced": fact({ kind: "stated", value: 65_536 }),
119
+ geometry: fact({ kind: "stated", value: "shared_upfront" }),
120
+ },
121
+ },
122
+ {
123
+ provider_id: "ollama-cloud",
124
+ model_id: "deepseek-v4",
125
+ facts: {
126
+ "output.enforced": fact({ kind: "stated", value: 32_000 }),
127
+ },
128
+ },
129
+ ],
130
+ };
131
+ const facts = resolveWindowOverlayFacts("ollama-cloud", "deepseek-v4", data)?.facts;
132
+ expect(scalarizeFact(facts?.["output.enforced"]?.value as never)).toBe(32_000);
133
+ expect(facts?.geometry?.value).toEqual({ kind: "stated", value: "shared_upfront" });
134
+ });
135
+
136
+ test("refuses an unrecognized schema before considering familiar cells", () => {
137
+ const v2 = {
138
+ ...(fixture as Record<string, unknown>),
139
+ schema: "fusiform-window-overlay/v2",
140
+ };
141
+ const parsed = parseWindowOverlay(v2);
142
+ expect(parsed.overlay).toBeUndefined();
143
+ expect(parsed.refusal).toContain("unrecognized schema");
144
+ });
145
+
146
+ test("skips bad cells once and keeps valid cells", () => {
147
+ const badCell = {
148
+ provider_id: "bad",
149
+ model_id: "model",
150
+ facts: { "window.enforced": { value: { kind: "stated", value: 1_000_000 } } },
151
+ };
152
+ const parsed = parseWindowOverlay({
153
+ ...(fixture as Record<string, unknown>),
154
+ cells: [badCell, ...(fixture as { cells: unknown[] }).cells],
155
+ });
156
+ expect(parsed.badCells).toBe(1);
157
+ expect(parsed.overlay?.cells.length).toBe(parsedFixture.cells.length);
158
+ });
159
+
160
+ test("a missing file is silent and a bad file logs one summary", () => {
161
+ const dir = mkdtempSync(join(tmpdir(), "window-overlay-test-"));
162
+ tempDirs.push(dir);
163
+ const logs: string[] = [];
164
+ expect(
165
+ readWindowOverlayFile(join(dir, "missing.json"), (message) => logs.push(message)),
166
+ ).toBeUndefined();
167
+ expect(logs).toEqual([]);
168
+ const path = join(dir, "bad.json");
169
+ writeFileSync(path, JSON.stringify({ ...(fixture as object), schema: "v2" }));
170
+ expect(readWindowOverlayFile(path, (message) => logs.push(message))).toBeUndefined();
171
+ expect(logs).toHaveLength(1);
172
+ });
173
+ });
174
+
175
+ describe("window geometry", () => {
176
+ test("filters placeholders independently in both directions", () => {
177
+ expect(placeholderFilteredOutput(0, 1_000_000)).toBeUndefined();
178
+ expect(placeholderFilteredOutput(1_000_000, 1_000_000)).toBeUndefined();
179
+ expect(placeholderFilteredOutput(1_000_001, 1_000_000)).toBeUndefined();
180
+ expect(placeholderFilteredOutput(65_536, 1_000_000)).toBe(65_536);
181
+ expect(
182
+ deriveWindowGeometry("xai", "mixed", {
183
+ context: 500_000,
184
+ input: 300_000,
185
+ output: 500_000,
186
+ })?.usableSoft,
187
+ ).toBe(300_000);
188
+ });
189
+
190
+ test("fixture table yields the 65% execution bases from the spec", () => {
191
+ const cases = [
192
+ ["openai-chatgpt-oauth", "gpt-5.6", 272_000, 128_000, 200_200],
193
+ ["anthropic", "claude-opus-5", 1_000_000, 128_000, 629_200],
194
+ // Producer batch downgraded google's geometry to considered-unknown
195
+ // (Google's docs contradict the separate-quota reading), so the
196
+ // derivation demotes to shared_upfront and reserves OpenCode's
197
+ // actual request cap B = min(65_536, 32_000):
198
+ // floor(0.65 * (1_048_576 - 32_000)) — not the no-reserve 681_574.
199
+ ["google", "gemini-3.5-flash", 1_048_576, 65_536, 660_774],
200
+ ["xai", "grok-4.6", 500_000, 500_000, 304_200],
201
+ ["ollama-cloud", "deepseek-v4-flash", 1_048_576, 384_000, 660_774],
202
+ ["moonshotai", "kimi-k3", 1_048_576, 1_048_576, 660_774],
203
+ ] as const;
204
+ for (const [provider, model, context, output, expectedExecute] of cases) {
205
+ const result = deriveWindowGeometry(
206
+ provider,
207
+ model,
208
+ { context, output },
209
+ {
210
+ overlay: resolveWindowOverlayFacts(provider, model, parsedFixture),
211
+ },
212
+ );
213
+ expect(Math.floor((result?.usableSoft ?? 0) * 0.65)).toBe(expectedExecute);
214
+ }
215
+ });
216
+
217
+ test("grok derives from geometry, window, and default output without an enforced output", () => {
218
+ const facts = resolveWindowOverlayFacts("xai", "grok-4.6", parsedFixture);
219
+ expect(facts?.facts["output.enforced"]).toBeUndefined();
220
+ const result = deriveWindowGeometry(
221
+ "xai",
222
+ "grok-4.6",
223
+ { context: 500_000, output: 500_000 },
224
+ { overlay: facts },
225
+ );
226
+ expect(result?.geometry).toBe("shared_truncating");
227
+ expect(result?.usableSoft).toBe(468_000);
228
+ });
229
+
230
+ test("kimi reserves its default output instead of placeholder advertised output", () => {
231
+ const result = deriveWindowGeometry(
232
+ "moonshotai",
233
+ "kimi-k3",
234
+ { context: 1_048_576, output: 1_048_576 },
235
+ {
236
+ overlay: resolveWindowOverlayFacts("moonshotai", "kimi-k3", parsedFixture),
237
+ },
238
+ );
239
+ expect(result?.derivation.reserve).toBe(32_000);
240
+ expect(result?.usableSoft).toBe(1_016_576);
241
+ });
242
+
243
+ test("provider hook wins over overlay, while overlay beats catalog", () => {
244
+ const data = overlay("provider", "model", {
245
+ "window.enforced": fact({ kind: "stated", value: 300_000 }),
246
+ "output.enforced": fact({ kind: "stated", value: 20_000 }),
247
+ });
248
+ const overlayOnly = deriveWindowGeometry(
249
+ "provider",
250
+ "model",
251
+ { context: 200_000, output: 10_000 },
252
+ { overlay: resolveWindowOverlayFacts("provider", "model", data) },
253
+ );
254
+ const hooked = deriveWindowGeometry(
255
+ "provider",
256
+ "model",
257
+ { context: 200_000, output: 10_000 },
258
+ {
259
+ overlay: resolveWindowOverlayFacts("provider", "model", data),
260
+ providerLimit: { context: 400_000, output: 30_000 },
261
+ },
262
+ );
263
+ expect(overlayOnly?.derivation.window).toBe(300_000);
264
+ expect(hooked?.derivation.window).toBe(400_000);
265
+ expect(hooked?.derivation.reserve).toBe(30_000);
266
+ });
267
+
268
+ test("clamps an inversion and logs it", () => {
269
+ const logs: string[] = [];
270
+ const result = deriveWindowGeometry(
271
+ "provider",
272
+ "model",
273
+ { context: 200_000, input: 190_000, output: 10_000 },
274
+ {
275
+ providerLimit: { context: 192_000, input: 190_000, output: 10_000 },
276
+ log: (message) => logs.push(message),
277
+ },
278
+ );
279
+ expect(result?.usableHard).toBe(result?.usableSoft);
280
+ expect(logs).toHaveLength(1);
281
+ expect(logs[0]).toContain("clamped");
282
+ });
283
+
284
+ test("keeps no-overlay usableSoft byte-identical to legacy resolveLimit", () => {
285
+ const corpus = [
286
+ ["openai", "real", { context: 200_000, output: 32_000 }],
287
+ ["openai", "zero", { context: 200_000, output: 0 }],
288
+ ["xai", "placeholder", { context: 500_000, output: 500_000 }],
289
+ ["google", "separate", { context: 1_000_000, output: 65_536 }],
290
+ ["anthropic", "input", { context: 1_000_000, input: 900_000, output: 128_000 }],
291
+ ] as const;
292
+ for (const [provider, model, limit] of corpus) {
293
+ const result = deriveWindowGeometry(provider, model, limit);
294
+ expect(result?.usableSoft).toBe(resolveLimit(limit, provider, model));
295
+ }
296
+ });
297
+
298
+ test("display percentage uses the same usableSoft scheduler base", () => {
299
+ const result = deriveWindowGeometry("openai", "model", {
300
+ context: 204_000,
301
+ output: 30_600,
302
+ }) as NonNullable<ReturnType<typeof deriveWindowGeometry>>;
303
+ const input = 105_900;
304
+ const schedulerPercentage = (input / result.usableSoft) * 100;
305
+ expect(formatWindowDerivationLine(input, result)).toContain(
306
+ `(${schedulerPercentage.toFixed(1)}%)`,
307
+ );
308
+ });
309
+ });