@cortexkit/opencode-magic-context 0.36.1 → 0.38.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 (176) hide show
  1. package/README.md +2 -0
  2. package/dist/config/index.d.ts.map +1 -1
  3. package/dist/config/project-security.d.ts +2 -1
  4. package/dist/config/project-security.d.ts.map +1 -1
  5. package/dist/config/schema/magic-context.d.ts +10 -0
  6. package/dist/config/schema/magic-context.d.ts.map +1 -1
  7. package/dist/{conflict-warning-hook-mt0ttc4x.js → conflict-warning-hook-an4fxhwf.js} +3 -3
  8. package/dist/{derive-budgets-88mxk2w1.js → derive-budgets-da4yg3tz.js} +3 -2
  9. package/dist/features/magic-context/context-authority.d.ts.map +1 -1
  10. package/dist/features/magic-context/dreamer/classify-prompt.d.ts +5 -1
  11. package/dist/features/magic-context/dreamer/classify-prompt.d.ts.map +1 -1
  12. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
  13. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
  14. package/dist/features/magic-context/dreamer/manifest-parser.d.ts +8 -0
  15. package/dist/features/magic-context/dreamer/manifest-parser.d.ts.map +1 -1
  16. package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts +7 -1
  17. package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts.map +1 -1
  18. package/dist/features/magic-context/dreamer/map-memories.d.ts +18 -0
  19. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  20. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts +5 -0
  21. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts.map +1 -1
  22. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  23. package/dist/features/magic-context/dreamer/verify-prompt.d.ts +5 -1
  24. package/dist/features/magic-context/dreamer/verify-prompt.d.ts.map +1 -1
  25. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  26. package/dist/features/magic-context/fail-closed-block.d.ts +6 -1
  27. package/dist/features/magic-context/fail-closed-block.d.ts.map +1 -1
  28. package/dist/features/magic-context/memory/embedding-openai.d.ts +3 -1
  29. package/dist/features/magic-context/memory/embedding-openai.d.ts.map +1 -1
  30. package/dist/features/magic-context/memory/project-identity.d.ts +6 -0
  31. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  32. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  33. package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
  34. package/dist/features/magic-context/reclaim-protection.d.ts +13 -0
  35. package/dist/features/magic-context/reclaim-protection.d.ts.map +1 -0
  36. package/dist/features/magic-context/smart-notes/runner.d.ts.map +1 -1
  37. package/dist/features/magic-context/smart-notes/wake-plane.d.ts +21 -0
  38. package/dist/features/magic-context/smart-notes/wake-plane.d.ts.map +1 -0
  39. package/dist/features/magic-context/storage-db.d.ts +19 -3
  40. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  41. package/dist/features/magic-context/storage-meta-persisted.d.ts +23 -0
  42. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  43. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  44. package/dist/features/magic-context/storage-meta-shared.d.ts.map +1 -1
  45. package/dist/features/magic-context/storage-primers.d.ts +11 -0
  46. package/dist/features/magic-context/storage-primers.d.ts.map +1 -1
  47. package/dist/features/magic-context/storage-schema-helpers.d.ts.map +1 -1
  48. package/dist/features/magic-context/storage-tags.d.ts +13 -5
  49. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  50. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts +7 -0
  51. package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
  52. package/dist/features/magic-context/window-report-ledger.d.ts +70 -0
  53. package/dist/features/magic-context/window-report-ledger.d.ts.map +1 -0
  54. package/dist/hooks/auto-update-checker/checker.d.ts +8 -1
  55. package/dist/hooks/auto-update-checker/checker.d.ts.map +1 -1
  56. package/dist/hooks/auto-update-checker/index.d.ts.map +1 -1
  57. package/dist/hooks/magic-context/channel2-cycle.d.ts +16 -0
  58. package/dist/hooks/magic-context/channel2-cycle.d.ts.map +1 -0
  59. package/dist/hooks/magic-context/channel2-delivery.d.ts +3 -9
  60. package/dist/hooks/magic-context/channel2-delivery.d.ts.map +1 -1
  61. package/dist/hooks/magic-context/command-handler.d.ts +2 -0
  62. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  63. package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts +33 -103
  64. package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts.map +1 -1
  65. package/dist/hooks/magic-context/emergency-drop.d.ts.map +1 -1
  66. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  67. package/dist/hooks/magic-context/event-resolvers.d.ts +4 -0
  68. package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
  69. package/dist/hooks/magic-context/execute-status.d.ts +3 -1
  70. package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
  71. package/dist/hooks/magic-context/fold-execution-gate.d.ts +2 -0
  72. package/dist/hooks/magic-context/fold-execution-gate.d.ts.map +1 -0
  73. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  74. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  75. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  76. package/dist/hooks/magic-context/live-session-state.d.ts +3 -0
  77. package/dist/hooks/magic-context/live-session-state.d.ts.map +1 -1
  78. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  79. package/dist/hooks/magic-context/lkg-slot.d.ts +20 -0
  80. package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
  81. package/dist/hooks/magic-context/module-state-sync.d.ts +8 -0
  82. package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
  83. package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
  84. package/dist/hooks/magic-context/module-wire.d.ts +6 -1
  85. package/dist/hooks/magic-context/module-wire.d.ts.map +1 -1
  86. package/dist/hooks/magic-context/rust-mode-transform.d.ts +21 -2
  87. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  88. package/dist/hooks/magic-context/strip-content.d.ts +27 -0
  89. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  90. package/dist/hooks/magic-context/supersession-reclaim.d.ts.map +1 -1
  91. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  92. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts +78 -0
  93. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -0
  94. package/dist/hooks/magic-context/tool-reclaim.d.ts.map +1 -1
  95. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +14 -3
  96. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  97. package/dist/hooks/magic-context/transform.d.ts +10 -0
  98. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  99. package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
  100. package/dist/{index-nsx2n9eg.js → index-4cz5nfxf.js} +3 -3
  101. package/dist/{index-f1tnb3vm.js → index-8pqfcghm.js} +21 -9
  102. package/dist/index-9zhhvr4w.js +733 -0
  103. package/dist/{index-zp6x6s6a.js → index-cae89eas.js} +25 -6
  104. package/dist/index-cgyfn1s2.js +53 -0
  105. package/dist/{index-3zqcdwqr.js → index-crke4z5j.js} +7 -4
  106. package/dist/{index-1skzp4dc.js → index-mmvhrqqb.js} +1991 -274
  107. package/dist/{index-tsgs7td8.js → index-pck9vadr.js} +1 -1
  108. package/dist/{index-3tnkymva.js → index-sw8gnq34.js} +1 -1
  109. package/dist/index.d.ts.map +1 -1
  110. package/dist/index.js +1714 -988
  111. package/dist/plugin/hooks/create-session-hooks.d.ts +3 -0
  112. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  113. package/dist/plugin/messages-transform.d.ts.map +1 -1
  114. package/dist/plugin/rpc-handlers.d.ts +2 -0
  115. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  116. package/dist/{recomp-orchestrator-a0g9b52q.js → recomp-orchestrator-jsde4ygw.js} +7 -6
  117. package/dist/{safe-notification-target-c11fdda2.js → safe-notification-target-b693f9x3.js} +2 -2
  118. package/dist/{send-session-notification-bgtf4853.js → send-session-notification-dxske5zm.js} +3 -3
  119. package/dist/shared/conflict-detector.d.ts +63 -0
  120. package/dist/shared/conflict-detector.d.ts.map +1 -1
  121. package/dist/shared/harness-provider-map.d.ts +8 -0
  122. package/dist/shared/harness-provider-map.d.ts.map +1 -1
  123. package/dist/shared/logger.d.ts +8 -0
  124. package/dist/shared/logger.d.ts.map +1 -1
  125. package/dist/shared/models-dev-cache.d.ts +7 -0
  126. package/dist/shared/models-dev-cache.d.ts.map +1 -1
  127. package/dist/shared/prompt-surface-runtime.d.ts.map +1 -1
  128. package/dist/shared/prompt-surface.d.ts +2 -0
  129. package/dist/shared/prompt-surface.d.ts.map +1 -1
  130. package/dist/shared/rpc-client.d.ts.map +1 -1
  131. package/dist/shared/rpc-server.d.ts.map +1 -1
  132. package/dist/shared/rpc-types.d.ts +29 -0
  133. package/dist/shared/rpc-types.d.ts.map +1 -1
  134. package/dist/shared/rpc-utils.d.ts +28 -9
  135. package/dist/shared/rpc-utils.d.ts.map +1 -1
  136. package/dist/shared/tail-hygiene-status.d.ts +15 -0
  137. package/dist/shared/tail-hygiene-status.d.ts.map +1 -0
  138. package/dist/shared/window-geometry.d.ts +90 -0
  139. package/dist/shared/window-geometry.d.ts.map +1 -0
  140. package/dist/{storage-meta-session-df9tstzr.js → storage-meta-session-mk4gsnke.js} +4 -3
  141. package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
  142. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  143. package/dist/tui/data/context-db.d.ts.map +1 -1
  144. package/dist/tui-compiled/data/context-db.d.ts.map +1 -1
  145. package/package.json +3 -1
  146. package/src/config/index.ts +2 -0
  147. package/src/config/latch-permanence-guard.test.ts +218 -0
  148. package/src/config/project-security.ts +10 -1
  149. package/src/config/schema/magic-context.ts +12 -2
  150. package/src/shared/__fixtures__/window-overlay.v1.json +337 -0
  151. package/src/shared/conflict-detector.test.ts +176 -1
  152. package/src/shared/conflict-detector.ts +126 -3
  153. package/src/shared/harness-provider-map.test.ts +20 -0
  154. package/src/shared/harness-provider-map.ts +19 -0
  155. package/src/shared/logger.test.ts +119 -0
  156. package/src/shared/logger.ts +33 -15
  157. package/src/shared/models-dev-cache.test.ts +42 -0
  158. package/src/shared/models-dev-cache.ts +62 -9
  159. package/src/shared/prompt-surface-runtime.ts +5 -3
  160. package/src/shared/prompt-surface.test.ts +38 -0
  161. package/src/shared/prompt-surface.ts +15 -2
  162. package/src/shared/rpc-client.ts +4 -2
  163. package/src/shared/rpc-server.ts +1 -0
  164. package/src/shared/rpc-types.ts +30 -0
  165. package/src/shared/rpc-utils.test.ts +162 -13
  166. package/src/shared/rpc-utils.ts +224 -31
  167. package/src/shared/tail-hygiene-status.ts +57 -0
  168. package/src/shared/window-geometry.test.ts +342 -0
  169. package/src/shared/window-geometry.ts +626 -0
  170. package/src/tui/data/context-db.ts +5 -0
  171. package/src/tui/index.tsx +33 -1
  172. package/src/tui/slots/sidebar-content.tsx +17 -5
  173. package/src/tui-compiled/data/context-db.ts +5 -0
  174. package/src/tui-compiled/index.tsx +359 -273
  175. package/src/tui-compiled/slots/sidebar-content.tsx +316 -287
  176. package/dist/index-wgvxkqpx.js +0 -342
@@ -0,0 +1,342 @@
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, resolveOutputReserve } 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("output_reserve forms override a pre-carved input and overlay output facts", () => {
244
+ const data = overlay("openai-codex", "gpt-5.6-sol", {
245
+ "output.enforced": fact({ kind: "stated", value: 68_000 }),
246
+ });
247
+ const cases = [
248
+ 16_384,
249
+ { default: 16_384 },
250
+ { default: 32_000, "openai-codex/gpt-5.6-sol": 16_384 },
251
+ ] as const;
252
+
253
+ for (const reserveConfig of cases) {
254
+ const result = deriveWindowGeometry(
255
+ "openai-codex",
256
+ "gpt-5.6-sol",
257
+ { context: 400_000, input: 272_000, output: 128_000 },
258
+ {
259
+ overlay: resolveWindowOverlayFacts("openai-codex", "gpt-5.6-sol", data),
260
+ outputReserveOverride: resolveOutputReserve(
261
+ "openai-codex",
262
+ "gpt-5.6-sol",
263
+ reserveConfig,
264
+ ),
265
+ },
266
+ );
267
+ expect(result?.usableSoft).toBe(272_000 - 16_384);
268
+ expect(result?.derivation).toMatchObject({
269
+ window: 272_000,
270
+ reserve: 16_384,
271
+ reserveSource: "output_config",
272
+ });
273
+ }
274
+ });
275
+
276
+ test("provider hook wins over overlay, while overlay beats catalog", () => {
277
+ const data = overlay("provider", "model", {
278
+ "window.enforced": fact({ kind: "stated", value: 300_000 }),
279
+ "output.enforced": fact({ kind: "stated", value: 20_000 }),
280
+ });
281
+ const overlayOnly = deriveWindowGeometry(
282
+ "provider",
283
+ "model",
284
+ { context: 200_000, output: 10_000 },
285
+ { overlay: resolveWindowOverlayFacts("provider", "model", data) },
286
+ );
287
+ const hooked = deriveWindowGeometry(
288
+ "provider",
289
+ "model",
290
+ { context: 200_000, output: 10_000 },
291
+ {
292
+ overlay: resolveWindowOverlayFacts("provider", "model", data),
293
+ providerLimit: { context: 400_000, output: 30_000 },
294
+ },
295
+ );
296
+ expect(overlayOnly?.derivation.window).toBe(300_000);
297
+ expect(hooked?.derivation.window).toBe(400_000);
298
+ expect(hooked?.derivation.reserve).toBe(30_000);
299
+ });
300
+
301
+ test("clamps an inversion and logs it", () => {
302
+ const logs: string[] = [];
303
+ const result = deriveWindowGeometry(
304
+ "provider",
305
+ "model",
306
+ { context: 200_000, input: 190_000, output: 10_000 },
307
+ {
308
+ providerLimit: { context: 192_000, input: 190_000, output: 10_000 },
309
+ log: (message) => logs.push(message),
310
+ },
311
+ );
312
+ expect(result?.usableHard).toBe(result?.usableSoft);
313
+ expect(logs).toHaveLength(1);
314
+ expect(logs[0]).toContain("clamped");
315
+ });
316
+
317
+ test("keeps no-overlay usableSoft byte-identical to legacy resolveLimit", () => {
318
+ const corpus = [
319
+ ["openai", "real", { context: 200_000, output: 32_000 }],
320
+ ["openai", "zero", { context: 200_000, output: 0 }],
321
+ ["xai", "placeholder", { context: 500_000, output: 500_000 }],
322
+ ["google", "separate", { context: 1_000_000, output: 65_536 }],
323
+ ["anthropic", "input", { context: 1_000_000, input: 900_000, output: 128_000 }],
324
+ ] as const;
325
+ for (const [provider, model, limit] of corpus) {
326
+ const result = deriveWindowGeometry(provider, model, limit);
327
+ expect(result?.usableSoft).toBe(resolveLimit(limit, provider, model));
328
+ }
329
+ });
330
+
331
+ test("display percentage uses the same usableSoft scheduler base", () => {
332
+ const result = deriveWindowGeometry("openai", "model", {
333
+ context: 204_000,
334
+ output: 30_600,
335
+ }) as NonNullable<ReturnType<typeof deriveWindowGeometry>>;
336
+ const input = 105_900;
337
+ const schedulerPercentage = (input / result.usableSoft) * 100;
338
+ expect(formatWindowDerivationLine(input, result)).toContain(
339
+ `(${schedulerPercentage.toFixed(1)}%)`,
340
+ );
341
+ });
342
+ });