@warmdrift/kgauto-compiler 2.0.0-alpha.31 → 2.0.0-alpha.33

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.
@@ -328,7 +328,8 @@ var STARTER_CHAINS_GROUNDED = {
328
328
  { id: "claude-sonnet-4-6", grounding: "judgment", reason: "Reasoning + cost balance \u2014 engineer pick" },
329
329
  { id: "claude-opus-4-7", grounding: "judgment", reason: 'Same-provider walk-UP on 429 (rare exception to "always cheaper")' },
330
330
  { id: "gemini-2.5-pro", grounding: "judgment", reason: "Cross-provider anchor" },
331
- { id: "deepseek-v4-pro", grounding: "judgment", reason: "Tier 3 cost floor \u2014 no brain evidence yet" }
331
+ { id: "deepseek-v4-pro", grounding: "judgment", reason: "Tier 3 cost floor \u2014 no brain evidence yet" },
332
+ { id: "gpt-5.4", grounding: "judgment", reason: "alpha.33: third-provider tail (archetypePerf=7) \u2014 closes openai-in-default-fallback-chains" }
332
333
  ],
333
334
  // Quality + cost match.
334
335
  generate: [
@@ -359,7 +360,8 @@ var STARTER_CHAINS_GROUNDED = {
359
360
  { id: "claude-sonnet-4-6", grounding: "judgment", reason: "Quality anchor \u2014 engineer pick" },
360
361
  { id: "claude-haiku-4-5", grounding: "judgment", reason: "Same-provider step-down" },
361
362
  { id: "gemini-2.5-pro", grounding: "judgment", reason: "Cross-provider anchor" },
362
- { id: "gemini-2.5-flash", grounding: "judgment", reason: "Cost floor \u2014 forgiving archetype tolerates Flash" }
363
+ { id: "gemini-2.5-flash", grounding: "judgment", reason: "Cost floor \u2014 forgiving archetype tolerates Flash" },
364
+ { id: "gpt-5.4-mini", grounding: "judgment", reason: "alpha.33: third-provider tail (archetypePerf=7) \u2014 closes openai-in-default-fallback-chains" }
363
365
  ],
364
366
  // Parallel-tool throughput champion — Flash leads on the L-040 cliff
365
367
  // (capability-fact: Flash 15-75 parallel calls/step vs DeepSeek 7-8).
@@ -367,21 +369,24 @@ var STARTER_CHAINS_GROUNDED = {
367
369
  { id: "gemini-2.5-flash", grounding: "capability-fact", reason: "L-040 parallel-tool throughput champion (15-75 calls/step)" },
368
370
  { id: "gemini-2.5-pro", grounding: "capability-fact", reason: "Cross-provider tier 1 with strong parallel-tool support" },
369
371
  { id: "claude-sonnet-4-6", grounding: "judgment", reason: "Quality safety net for blocked-Flash case" },
370
- { id: "claude-haiku-4-5", grounding: "judgment", reason: "Reduced tool budget \u2014 cliff at 16 fires" }
372
+ { id: "claude-haiku-4-5", grounding: "judgment", reason: "Reduced tool budget \u2014 cliff at 16 fires" },
373
+ { id: "gpt-5.4-mini", grounding: "judgment", reason: "alpha.33: third-provider tail \u2014 OpenAI parallel-tool capable archetype" }
371
374
  ],
372
375
  // Cost-sensitive + tolerant. DeepSeek brain-evidence tier 1.
373
376
  summarize: [
374
377
  { id: "gemini-2.5-flash", grounding: "judgment", reason: "Cost-sensitive primary \u2014 engineer pick" },
375
378
  { id: "deepseek-v4-flash", grounding: "measured", reason: "Brain-validated tier 1 for cost-sensitive summarize workloads", n: 169 },
376
379
  { id: "claude-haiku-4-5", grounding: "judgment", reason: "Quality safety net" },
377
- { id: "gemini-2.5-flash-lite", grounding: "judgment", reason: "Emergency floor \u2014 onboarded s22, no brain evidence yet" }
380
+ { id: "gemini-2.5-flash-lite", grounding: "judgment", reason: "Emergency floor \u2014 onboarded s22, no brain evidence yet" },
381
+ { id: "gpt-5.4-nano", grounding: "judgment", reason: "alpha.33: third-provider tail (archetypePerf=6) \u2014 cheapest OpenAI, matches summarize cost-band" }
378
382
  ],
379
383
  // Brain-validated DeepSeek tier 1 (169 rows, 0% empty rate).
380
384
  classify: [
381
385
  { id: "gemini-2.5-flash", grounding: "judgment", reason: "Cost-sensitive primary \u2014 engineer pick" },
382
386
  { id: "deepseek-v4-flash", grounding: "measured", reason: "Brain-validated tier 1 (169 rows, 0% empty rate)", n: 169 },
383
387
  { id: "claude-haiku-4-5", grounding: "judgment", reason: "Quality safety net" },
384
- { id: "gemini-2.5-flash-lite", grounding: "judgment", reason: "Cache-discount 10\xD7 floor for repeat-prompt workloads" }
388
+ { id: "gemini-2.5-flash-lite", grounding: "judgment", reason: "Cache-discount 10\xD7 floor for repeat-prompt workloads" },
389
+ { id: "gpt-5.4-nano", grounding: "judgment", reason: "alpha.33: third-provider tail (archetypePerf=6) \u2014 cheapest OpenAI for classify" }
385
390
  ]
386
391
  };
387
392
  var STARTER_CHAINS = (() => {
@@ -436,7 +441,7 @@ function resolveStarterForMode(archetype, toolOrchestration, allChains) {
436
441
  return allChains[archetype];
437
442
  }
438
443
  function getDefaultFallbackChain(opts) {
439
- const { archetype, primary, maxDepth = 3, policy, reachability, toolOrchestration } = opts;
444
+ const { archetype, primary, maxDepth = 4, policy, reachability, toolOrchestration } = opts;
440
445
  if (maxDepth < 1) {
441
446
  throw new Error(
442
447
  `getDefaultFallbackChain: maxDepth must be >= 1, got ${maxDepth}`
@@ -1,6 +1,6 @@
1
- import { G as GlassboxEvent } from '../types-BjrIFPGe.mjs';
2
- export { A as AdvisoryFiredData, C as CompileDoneData, a as CompileStartData, E as ExecuteAttemptData, b as ExecuteSuccessData, F as FallbackWalkedData, c as GLASSBOX_STREAM_TTL_MS, d as GlassboxEventKind, e as GlassboxPubSub } from '../types-BjrIFPGe.mjs';
3
- import '../ir-De2AQtlr.mjs';
1
+ import { G as GlassboxEvent } from '../types-2QzI0Ep1.mjs';
2
+ export { A as AdvisoryFiredData, C as CompileDoneData, a as CompileStartData, E as ExecuteAttemptData, b as ExecuteSuccessData, F as FallbackWalkedData, c as GLASSBOX_STREAM_TTL_MS, d as GlassboxEventKind, e as GlassboxPubSub } from '../types-2QzI0Ep1.mjs';
3
+ import '../ir-DubC20e3.mjs';
4
4
  import '../dialect.mjs';
5
5
 
6
6
  /**
@@ -1,6 +1,6 @@
1
- import { G as GlassboxEvent } from '../types-D_JAhCv4.js';
2
- export { A as AdvisoryFiredData, C as CompileDoneData, a as CompileStartData, E as ExecuteAttemptData, b as ExecuteSuccessData, F as FallbackWalkedData, c as GLASSBOX_STREAM_TTL_MS, d as GlassboxEventKind, e as GlassboxPubSub } from '../types-D_JAhCv4.js';
3
- import '../ir-BIAT9gJk.js';
1
+ import { G as GlassboxEvent } from '../types-DYcO82xh.js';
2
+ export { A as AdvisoryFiredData, C as CompileDoneData, a as CompileStartData, E as ExecuteAttemptData, b as ExecuteSuccessData, F as FallbackWalkedData, c as GLASSBOX_STREAM_TTL_MS, d as GlassboxEventKind, e as GlassboxPubSub } from '../types-DYcO82xh.js';
3
+ import '../ir-GnYPkpGo.js';
4
4
  import '../dialect.js';
5
5
 
6
6
  /**
@@ -1,5 +1,5 @@
1
- import { G as GlassboxEvent } from '../types-BjrIFPGe.mjs';
2
- import { h as Adapter, u as SectionKind } from '../ir-De2AQtlr.mjs';
1
+ import { G as GlassboxEvent } from '../types-2QzI0Ep1.mjs';
2
+ import { i as Adapter, v as SectionKind } from '../ir-DubC20e3.mjs';
3
3
  import '../dialect.mjs';
4
4
 
5
5
  /**
@@ -148,6 +148,99 @@ interface TraceDetail extends TraceSummary {
148
148
  health: TraceHealth;
149
149
  }
150
150
 
151
+ /**
152
+ * proxy(req) — Glass-Box replay query handler.
153
+ *
154
+ * GET /api/glassbox/proxy?traceId=<id> → single compile_outcomes row for trace
155
+ * GET /api/glassbox/proxy?limit=<N> → N most-recent compile_outcomes rows
156
+ * GET /api/glassbox/proxy → defaults to limit=20
157
+ *
158
+ * Brain reads go through PostgREST on Supabase. We always filter by
159
+ * `app_id=eq.<appId>` even though the scoped JWT's RLS policy already
160
+ * enforces tenant isolation — the explicit filter trims the network payload
161
+ * and makes the query intent obvious to anyone reading logs.
162
+ *
163
+ * Scrub: the optional `scrub` hook runs on each row before responding so
164
+ * sensitive payloads (rendered prompts, tool calls) can be redacted at the
165
+ * proxy boundary. Default is identity (no-op).
166
+ */
167
+
168
+ /**
169
+ * Typed boundary transformer: compile_outcomes row (snake_case, Postgres
170
+ * native) → TraceSummary (camelCase, TypeScript native + extension wire
171
+ * contract). Single canonical mapping site — every DB-shape ↔ wire-shape
172
+ * crossing routes through here so renderer-expected fields can't silently
173
+ * go missing. See `feedback_typed_boundary_transformers.md` for the rule.
174
+ */
175
+ declare function rowToSummary(row: Record<string, unknown>): TraceSummary;
176
+ /**
177
+ * Typed boundary transformer (L-118): compile_outcomes row → TraceDetail.
178
+ * Single canonical mapping site for the detail-view wire contract. Pre-018
179
+ * brain rows return NULL for the new columns; this transformer applies
180
+ * type-safe defaults (0 for token columns, undefined for optional strings)
181
+ * so the renderer never crashes on missing fields.
182
+ *
183
+ * alpha.28 extends the field set per the renderer design contract — every
184
+ * extended field has a default. The `counterfactuals` + `projectedDailyCost`
185
+ * fields are populated by the proxy AFTER this transformer runs (they need
186
+ * profile lookup / brain query / async I/O).
187
+ */
188
+ declare function rowToDetail(row: Record<string, unknown>): TraceDetail;
189
+
190
+ /**
191
+ * computeCounterfactuals — for a served trace, compute up to 2 cheaper
192
+ * alternatives that ALSO meet the archetype quality floor.
193
+ *
194
+ * Pure function. Called at detail-view time by the proxy's `rowToDetail`
195
+ * path. The cost-equivalent answer to "what could this have run on without
196
+ * tanking quality?" lets the Glass-Box render `💰 Cheaper alternatives` so a
197
+ * founder sees the actual cost of the routing choice rather than just the
198
+ * served cost.
199
+ *
200
+ * Mechanism (per design contract Phase 0 spec):
201
+ * 1. Walk the archetype's full default fallback chain.
202
+ * 2. For each model in the chain (excluding the served model):
203
+ * - Skip if archetypePerf[archetype] < ARCHETYPE_FLOOR_DEFAULT (6).
204
+ * Matches the cliff-advisor work — never recommend a swap that
205
+ * violates the quality floor. (Composition with Builder C is
206
+ * intentional.)
207
+ * - Skip if profile missing.
208
+ * - Compute estimated cost at the OBSERVED token counts:
209
+ * non_cached_in = tokensIn - cacheReadInputTokens
210
+ * cost = (non_cached_in / 1e6) * profile.costInputPer1m
211
+ * + (cacheable_in / 1e6) * profile.costInputPer1m
212
+ * * profile.lowering.cache.discount
213
+ * + (tokensOut / 1e6) * profile.costOutputPer1m
214
+ * - Only include if estimatedCostUsd ≤ 0.9 × servedCostUsd
215
+ * (≥10% cheaper — below that's noise of token-count estimation).
216
+ * 3. Sort cheapest first.
217
+ * 4. Cap to top 2.
218
+ *
219
+ * Edge cases:
220
+ * - tokensIn === 0 → return [] (can't meaningfully estimate).
221
+ * - servedCostUsd === 0 → return [] (no baseline to beat).
222
+ * - Zero matching alternatives → return [] (renderer hides the card).
223
+ * - Served model isn't in the chain (e.g. forceModel'd off-chain) → use
224
+ * the chain for the archetype anyway.
225
+ */
226
+
227
+ /** Only surface swaps that save at least 10% vs. served. */
228
+ declare const COUNTERFACTUAL_MIN_SAVINGS_RATIO = 0.1;
229
+ /** Cap on alternatives surfaced per trace. */
230
+ declare const COUNTERFACTUAL_MAX_RESULTS = 2;
231
+ interface ComputeCounterfactualsArgs {
232
+ servedModel: string;
233
+ servedCostUsd: number;
234
+ archetype: string;
235
+ tokensIn: number;
236
+ tokensOut: number;
237
+ /** Defaults to 0 when caller doesn't know. */
238
+ cacheReadInputTokens?: number;
239
+ /** Reserved for future per-mode chain selection. */
240
+ toolOrchestration?: 'parallel' | 'sequential' | 'either';
241
+ }
242
+ declare function computeCounterfactuals(args: ComputeCounterfactualsArgs): TraceCounterfactual[];
243
+
151
244
  /**
152
245
  * Public entry point for `@warmdrift/kgauto-compiler/glassbox-routes`.
153
246
  *
@@ -239,4 +332,4 @@ interface GlassboxRoutes {
239
332
  }
240
333
  declare function createGlassboxRoutes(config: GlassboxRoutesConfig): GlassboxRoutes;
241
334
 
242
- export { type GlassboxRoutes, type GlassboxRoutesConfig, type TraceDetail, type TraceSummary, createGlassboxRoutes };
335
+ export { type AdvisoryRecord, COUNTERFACTUAL_MAX_RESULTS, COUNTERFACTUAL_MIN_SAVINGS_RATIO, type ComputeCounterfactualsArgs, type GlassboxRoutes, type GlassboxRoutesConfig, type TraceCounterfactual, type TraceDetail, type TraceHealth, type TraceSectionRewrite, type TraceSummary, computeCounterfactuals, createGlassboxRoutes, rowToDetail, rowToSummary };
@@ -1,5 +1,5 @@
1
- import { G as GlassboxEvent } from '../types-D_JAhCv4.js';
2
- import { h as Adapter, u as SectionKind } from '../ir-BIAT9gJk.js';
1
+ import { G as GlassboxEvent } from '../types-DYcO82xh.js';
2
+ import { i as Adapter, v as SectionKind } from '../ir-GnYPkpGo.js';
3
3
  import '../dialect.js';
4
4
 
5
5
  /**
@@ -148,6 +148,99 @@ interface TraceDetail extends TraceSummary {
148
148
  health: TraceHealth;
149
149
  }
150
150
 
151
+ /**
152
+ * proxy(req) — Glass-Box replay query handler.
153
+ *
154
+ * GET /api/glassbox/proxy?traceId=<id> → single compile_outcomes row for trace
155
+ * GET /api/glassbox/proxy?limit=<N> → N most-recent compile_outcomes rows
156
+ * GET /api/glassbox/proxy → defaults to limit=20
157
+ *
158
+ * Brain reads go through PostgREST on Supabase. We always filter by
159
+ * `app_id=eq.<appId>` even though the scoped JWT's RLS policy already
160
+ * enforces tenant isolation — the explicit filter trims the network payload
161
+ * and makes the query intent obvious to anyone reading logs.
162
+ *
163
+ * Scrub: the optional `scrub` hook runs on each row before responding so
164
+ * sensitive payloads (rendered prompts, tool calls) can be redacted at the
165
+ * proxy boundary. Default is identity (no-op).
166
+ */
167
+
168
+ /**
169
+ * Typed boundary transformer: compile_outcomes row (snake_case, Postgres
170
+ * native) → TraceSummary (camelCase, TypeScript native + extension wire
171
+ * contract). Single canonical mapping site — every DB-shape ↔ wire-shape
172
+ * crossing routes through here so renderer-expected fields can't silently
173
+ * go missing. See `feedback_typed_boundary_transformers.md` for the rule.
174
+ */
175
+ declare function rowToSummary(row: Record<string, unknown>): TraceSummary;
176
+ /**
177
+ * Typed boundary transformer (L-118): compile_outcomes row → TraceDetail.
178
+ * Single canonical mapping site for the detail-view wire contract. Pre-018
179
+ * brain rows return NULL for the new columns; this transformer applies
180
+ * type-safe defaults (0 for token columns, undefined for optional strings)
181
+ * so the renderer never crashes on missing fields.
182
+ *
183
+ * alpha.28 extends the field set per the renderer design contract — every
184
+ * extended field has a default. The `counterfactuals` + `projectedDailyCost`
185
+ * fields are populated by the proxy AFTER this transformer runs (they need
186
+ * profile lookup / brain query / async I/O).
187
+ */
188
+ declare function rowToDetail(row: Record<string, unknown>): TraceDetail;
189
+
190
+ /**
191
+ * computeCounterfactuals — for a served trace, compute up to 2 cheaper
192
+ * alternatives that ALSO meet the archetype quality floor.
193
+ *
194
+ * Pure function. Called at detail-view time by the proxy's `rowToDetail`
195
+ * path. The cost-equivalent answer to "what could this have run on without
196
+ * tanking quality?" lets the Glass-Box render `💰 Cheaper alternatives` so a
197
+ * founder sees the actual cost of the routing choice rather than just the
198
+ * served cost.
199
+ *
200
+ * Mechanism (per design contract Phase 0 spec):
201
+ * 1. Walk the archetype's full default fallback chain.
202
+ * 2. For each model in the chain (excluding the served model):
203
+ * - Skip if archetypePerf[archetype] < ARCHETYPE_FLOOR_DEFAULT (6).
204
+ * Matches the cliff-advisor work — never recommend a swap that
205
+ * violates the quality floor. (Composition with Builder C is
206
+ * intentional.)
207
+ * - Skip if profile missing.
208
+ * - Compute estimated cost at the OBSERVED token counts:
209
+ * non_cached_in = tokensIn - cacheReadInputTokens
210
+ * cost = (non_cached_in / 1e6) * profile.costInputPer1m
211
+ * + (cacheable_in / 1e6) * profile.costInputPer1m
212
+ * * profile.lowering.cache.discount
213
+ * + (tokensOut / 1e6) * profile.costOutputPer1m
214
+ * - Only include if estimatedCostUsd ≤ 0.9 × servedCostUsd
215
+ * (≥10% cheaper — below that's noise of token-count estimation).
216
+ * 3. Sort cheapest first.
217
+ * 4. Cap to top 2.
218
+ *
219
+ * Edge cases:
220
+ * - tokensIn === 0 → return [] (can't meaningfully estimate).
221
+ * - servedCostUsd === 0 → return [] (no baseline to beat).
222
+ * - Zero matching alternatives → return [] (renderer hides the card).
223
+ * - Served model isn't in the chain (e.g. forceModel'd off-chain) → use
224
+ * the chain for the archetype anyway.
225
+ */
226
+
227
+ /** Only surface swaps that save at least 10% vs. served. */
228
+ declare const COUNTERFACTUAL_MIN_SAVINGS_RATIO = 0.1;
229
+ /** Cap on alternatives surfaced per trace. */
230
+ declare const COUNTERFACTUAL_MAX_RESULTS = 2;
231
+ interface ComputeCounterfactualsArgs {
232
+ servedModel: string;
233
+ servedCostUsd: number;
234
+ archetype: string;
235
+ tokensIn: number;
236
+ tokensOut: number;
237
+ /** Defaults to 0 when caller doesn't know. */
238
+ cacheReadInputTokens?: number;
239
+ /** Reserved for future per-mode chain selection. */
240
+ toolOrchestration?: 'parallel' | 'sequential' | 'either';
241
+ }
242
+ declare function computeCounterfactuals(args: ComputeCounterfactualsArgs): TraceCounterfactual[];
243
+
151
244
  /**
152
245
  * Public entry point for `@warmdrift/kgauto-compiler/glassbox-routes`.
153
246
  *
@@ -239,4 +332,4 @@ interface GlassboxRoutes {
239
332
  }
240
333
  declare function createGlassboxRoutes(config: GlassboxRoutesConfig): GlassboxRoutes;
241
334
 
242
- export { type GlassboxRoutes, type GlassboxRoutesConfig, type TraceDetail, type TraceSummary, createGlassboxRoutes };
335
+ export { type AdvisoryRecord, COUNTERFACTUAL_MAX_RESULTS, COUNTERFACTUAL_MIN_SAVINGS_RATIO, type ComputeCounterfactualsArgs, type GlassboxRoutes, type GlassboxRoutesConfig, type TraceCounterfactual, type TraceDetail, type TraceHealth, type TraceSectionRewrite, type TraceSummary, computeCounterfactuals, createGlassboxRoutes, rowToDetail, rowToSummary };
@@ -20,7 +20,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/glassbox-routes/index.ts
21
21
  var glassbox_routes_exports = {};
22
22
  __export(glassbox_routes_exports, {
23
- createGlassboxRoutes: () => createGlassboxRoutes
23
+ COUNTERFACTUAL_MAX_RESULTS: () => COUNTERFACTUAL_MAX_RESULTS,
24
+ COUNTERFACTUAL_MIN_SAVINGS_RATIO: () => COUNTERFACTUAL_MIN_SAVINGS_RATIO,
25
+ computeCounterfactuals: () => computeCounterfactuals,
26
+ createGlassboxRoutes: () => createGlassboxRoutes,
27
+ rowToDetail: () => rowToDetail,
28
+ rowToSummary: () => rowToSummary
24
29
  });
25
30
  module.exports = __toCommonJS(glassbox_routes_exports);
26
31
 
@@ -1409,7 +1414,8 @@ var STARTER_CHAINS_GROUNDED = {
1409
1414
  { id: "claude-sonnet-4-6", grounding: "judgment", reason: "Reasoning + cost balance \u2014 engineer pick" },
1410
1415
  { id: "claude-opus-4-7", grounding: "judgment", reason: 'Same-provider walk-UP on 429 (rare exception to "always cheaper")' },
1411
1416
  { id: "gemini-2.5-pro", grounding: "judgment", reason: "Cross-provider anchor" },
1412
- { id: "deepseek-v4-pro", grounding: "judgment", reason: "Tier 3 cost floor \u2014 no brain evidence yet" }
1417
+ { id: "deepseek-v4-pro", grounding: "judgment", reason: "Tier 3 cost floor \u2014 no brain evidence yet" },
1418
+ { id: "gpt-5.4", grounding: "judgment", reason: "alpha.33: third-provider tail (archetypePerf=7) \u2014 closes openai-in-default-fallback-chains" }
1413
1419
  ],
1414
1420
  // Quality + cost match.
1415
1421
  generate: [
@@ -1440,7 +1446,8 @@ var STARTER_CHAINS_GROUNDED = {
1440
1446
  { id: "claude-sonnet-4-6", grounding: "judgment", reason: "Quality anchor \u2014 engineer pick" },
1441
1447
  { id: "claude-haiku-4-5", grounding: "judgment", reason: "Same-provider step-down" },
1442
1448
  { id: "gemini-2.5-pro", grounding: "judgment", reason: "Cross-provider anchor" },
1443
- { id: "gemini-2.5-flash", grounding: "judgment", reason: "Cost floor \u2014 forgiving archetype tolerates Flash" }
1449
+ { id: "gemini-2.5-flash", grounding: "judgment", reason: "Cost floor \u2014 forgiving archetype tolerates Flash" },
1450
+ { id: "gpt-5.4-mini", grounding: "judgment", reason: "alpha.33: third-provider tail (archetypePerf=7) \u2014 closes openai-in-default-fallback-chains" }
1444
1451
  ],
1445
1452
  // Parallel-tool throughput champion — Flash leads on the L-040 cliff
1446
1453
  // (capability-fact: Flash 15-75 parallel calls/step vs DeepSeek 7-8).
@@ -1448,21 +1455,24 @@ var STARTER_CHAINS_GROUNDED = {
1448
1455
  { id: "gemini-2.5-flash", grounding: "capability-fact", reason: "L-040 parallel-tool throughput champion (15-75 calls/step)" },
1449
1456
  { id: "gemini-2.5-pro", grounding: "capability-fact", reason: "Cross-provider tier 1 with strong parallel-tool support" },
1450
1457
  { id: "claude-sonnet-4-6", grounding: "judgment", reason: "Quality safety net for blocked-Flash case" },
1451
- { id: "claude-haiku-4-5", grounding: "judgment", reason: "Reduced tool budget \u2014 cliff at 16 fires" }
1458
+ { id: "claude-haiku-4-5", grounding: "judgment", reason: "Reduced tool budget \u2014 cliff at 16 fires" },
1459
+ { id: "gpt-5.4-mini", grounding: "judgment", reason: "alpha.33: third-provider tail \u2014 OpenAI parallel-tool capable archetype" }
1452
1460
  ],
1453
1461
  // Cost-sensitive + tolerant. DeepSeek brain-evidence tier 1.
1454
1462
  summarize: [
1455
1463
  { id: "gemini-2.5-flash", grounding: "judgment", reason: "Cost-sensitive primary \u2014 engineer pick" },
1456
1464
  { id: "deepseek-v4-flash", grounding: "measured", reason: "Brain-validated tier 1 for cost-sensitive summarize workloads", n: 169 },
1457
1465
  { id: "claude-haiku-4-5", grounding: "judgment", reason: "Quality safety net" },
1458
- { id: "gemini-2.5-flash-lite", grounding: "judgment", reason: "Emergency floor \u2014 onboarded s22, no brain evidence yet" }
1466
+ { id: "gemini-2.5-flash-lite", grounding: "judgment", reason: "Emergency floor \u2014 onboarded s22, no brain evidence yet" },
1467
+ { id: "gpt-5.4-nano", grounding: "judgment", reason: "alpha.33: third-provider tail (archetypePerf=6) \u2014 cheapest OpenAI, matches summarize cost-band" }
1459
1468
  ],
1460
1469
  // Brain-validated DeepSeek tier 1 (169 rows, 0% empty rate).
1461
1470
  classify: [
1462
1471
  { id: "gemini-2.5-flash", grounding: "judgment", reason: "Cost-sensitive primary \u2014 engineer pick" },
1463
1472
  { id: "deepseek-v4-flash", grounding: "measured", reason: "Brain-validated tier 1 (169 rows, 0% empty rate)", n: 169 },
1464
1473
  { id: "claude-haiku-4-5", grounding: "judgment", reason: "Quality safety net" },
1465
- { id: "gemini-2.5-flash-lite", grounding: "judgment", reason: "Cache-discount 10\xD7 floor for repeat-prompt workloads" }
1474
+ { id: "gemini-2.5-flash-lite", grounding: "judgment", reason: "Cache-discount 10\xD7 floor for repeat-prompt workloads" },
1475
+ { id: "gpt-5.4-nano", grounding: "judgment", reason: "alpha.33: third-provider tail (archetypePerf=6) \u2014 cheapest OpenAI for classify" }
1466
1476
  ]
1467
1477
  };
1468
1478
  var STARTER_CHAINS = (() => {
@@ -1517,7 +1527,7 @@ function resolveStarterForMode(archetype, toolOrchestration, allChains) {
1517
1527
  return allChains[archetype];
1518
1528
  }
1519
1529
  function getDefaultFallbackChain(opts) {
1520
- const { archetype, primary, maxDepth = 3, policy, reachability, toolOrchestration } = opts;
1530
+ const { archetype, primary, maxDepth = 4, policy, reachability, toolOrchestration } = opts;
1521
1531
  if (maxDepth < 1) {
1522
1532
  throw new Error(
1523
1533
  `getDefaultFallbackChain: maxDepth must be >= 1, got ${maxDepth}`
@@ -2454,5 +2464,10 @@ function createGlassboxRoutes(config) {
2454
2464
  }
2455
2465
  // Annotate the CommonJS export names for ESM import in node:
2456
2466
  0 && (module.exports = {
2457
- createGlassboxRoutes
2467
+ COUNTERFACTUAL_MAX_RESULTS,
2468
+ COUNTERFACTUAL_MIN_SAVINGS_RATIO,
2469
+ computeCounterfactuals,
2470
+ createGlassboxRoutes,
2471
+ rowToDetail,
2472
+ rowToSummary
2458
2473
  });
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ARCHETYPE_FLOOR_DEFAULT,
3
3
  getDefaultFallbackChain
4
- } from "../chunk-WXCFWUCN.mjs";
4
+ } from "../chunk-XJZRDGHF.mjs";
5
5
  import {
6
6
  tryGetProfile
7
7
  } from "../chunk-JQGRWJZO.mjs";
@@ -654,5 +654,10 @@ function createGlassboxRoutes(config) {
654
654
  return { proxy, stream };
655
655
  }
656
656
  export {
657
- createGlassboxRoutes
657
+ COUNTERFACTUAL_MAX_RESULTS,
658
+ COUNTERFACTUAL_MIN_SAVINGS_RATIO,
659
+ computeCounterfactuals,
660
+ createGlassboxRoutes,
661
+ rowToDetail,
662
+ rowToSummary
658
663
  };
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as CompilePolicy, N as NormalizedResponse, A as ApiKeys, P as ProviderOverrides, a as CompiledRequest, b as PromptIR, c as CallOptions, d as CallResult, S as SectionRewrite, R as RecordInput, e as RecordOutcomeInput, O as OutcomeResult, f as OracleScore, g as CompileResult, B as BestPracticeAdvisory, h as Adapter, i as PerAxisMetrics, j as Provider, k as ChainEntry, G as Grounding } from './ir-De2AQtlr.mjs';
2
- export { l as CallAttempt, m as CallError, n as ChainWithGrounding, o as Constraints, F as FallbackReason, H as HistoryCachePolicy, I as IntentDeclaration, M as Message, p as MutationApplied, q as NormalizedTokens, r as OutcomeKind, s as PerAxisMetricsByModel, t as PromptSection, u as SectionKind, T as ToolCall, v as ToolDefinition } from './ir-De2AQtlr.mjs';
1
+ import { C as CompilePolicy, N as NormalizedResponse, A as ApiKeys, P as ProviderOverrides, a as CompiledRequest, b as PromptIR, c as CallOptions, d as CallResult, S as SystemModelMessage, e as CompileResult, f as SectionRewrite, R as RecordInput, g as RecordOutcomeInput, O as OutcomeResult, h as OracleScore, B as BestPracticeAdvisory, i as Adapter, j as PerAxisMetrics, k as Provider, l as ChainEntry, G as Grounding } from './ir-DubC20e3.mjs';
2
+ export { m as CallAttempt, n as CallError, o as ChainWithGrounding, p as Constraints, F as FallbackReason, H as HistoryCachePolicy, I as IntentDeclaration, M as Message, q as MutationApplied, r as NormalizedTokens, s as OutcomeKind, t as PerAxisMetricsByModel, u as PromptSection, v as SectionKind, T as ToolCall, w as ToolDefinition } from './ir-DubC20e3.mjs';
3
3
  import { ModelProfile } from './profiles.mjs';
4
4
  export { ALIASES, CacheStrategy, CliffRule, LoweringSpec, RecoveryRule, StructuredOutputCapability, SystemPromptMode, allProfiles, getProfile, profilesByProvider, tryGetProfile } from './profiles.mjs';
5
5
  import { IntentArchetypeName } from './dialect.mjs';
@@ -94,6 +94,89 @@ declare function execute(request: CompiledRequest, opts?: ExecuteOptions): Promi
94
94
  */
95
95
  declare function call(ir: PromptIR, opts?: CallOptions): Promise<CallResult>;
96
96
 
97
+ /**
98
+ * alpha.33 — AI-SDK streamText helpers.
99
+ *
100
+ * The cross-consumer pattern surfaced 2026-05-20 (`streamText-cache-marker-
101
+ * propagation-gap` on `command-center/interfaces/kgauto.md ## Requested`):
102
+ * AI-SDK consumers using `streamText({ system: <string>, messages:
103
+ * convertToModelMessages(messages), model })` silently drop the Anthropic
104
+ * `cache_control` markers the compiler emits on `result.request.messages`.
105
+ * Two losses on that line:
106
+ * (a) `convertToModelMessages()` reads raw inputs not the lowered output,
107
+ * dropping per-message providerOptions; and
108
+ * (b) `streamText({ system: '<string>' })` strips any providerOptions
109
+ * on the system prefix.
110
+ *
111
+ * Net effect prior to this surface: `cache_read_input_tokens = 0` across
112
+ * every measured production call by IC + tt-intel even though both
113
+ * consumers had `historyCachePolicy: { strategy: 'all-but-latest' }` wired
114
+ * since alpha.5. The compiler did the right thing; the consumer integration
115
+ * pattern lost the markers at the wire boundary.
116
+ *
117
+ * This helper closes the gap. Pass the consumer's already-converted messages
118
+ * + the kgauto CompileResult and get back a `{ system, messages }` pair
119
+ * with cacheControl re-attached at the deterministic indices the compiler
120
+ * computed (`diagnostics.historyCacheMarkIndex` + `systemMessages` with
121
+ * its own cacheControl markers).
122
+ *
123
+ * No I/O. Pure transform. Idempotent — calling twice with the same inputs
124
+ * produces structurally-identical output.
125
+ */
126
+
127
+ /**
128
+ * AI-SDK-shaped converted-message structure. Matches what
129
+ * `convertToModelMessages()` returns at the wire layer. We don't import
130
+ * the AI-SDK type to avoid pulling that dep into the kgauto-compiler
131
+ * package — consumers pass their own already-converted messages.
132
+ */
133
+ interface AISDKConvertedMessage {
134
+ role: 'system' | 'user' | 'assistant' | 'tool';
135
+ content: unknown;
136
+ providerOptions?: {
137
+ anthropic?: {
138
+ cacheControl?: {
139
+ type: 'ephemeral';
140
+ };
141
+ };
142
+ };
143
+ }
144
+ /**
145
+ * Result of `attachCacheControlToStreamTextInput()` — ready to spread into
146
+ * `streamText(...)` directly.
147
+ *
148
+ * The `system` field is either the structured `SystemModelMessage[]` form
149
+ * (when the compiler computed at least one cacheable section + chose
150
+ * Anthropic) or the flat-string concatenation (when no cacheable sections
151
+ * exist OR the provider isn't Anthropic). Consumers can pass either form
152
+ * to `streamText({ system })` — the AI-SDK accepts both.
153
+ */
154
+ interface AttachCacheControlResult {
155
+ system: string | SystemModelMessage[];
156
+ messages: AISDKConvertedMessage[];
157
+ }
158
+ /**
159
+ * Attach Anthropic cache_control markers to a streamText input that the
160
+ * consumer has already prepared via `convertToModelMessages()`. Reads
161
+ * `result.diagnostics.historyCacheMarkIndex` for the position-on-history
162
+ * marker and `result.systemMessages` for the per-section system markers.
163
+ *
164
+ * The flat-string `system` form is returned when:
165
+ * - the compiler produced no `systemMessages` (e.g., zero sections kept), or
166
+ * - the chosen provider is not Anthropic, so cacheControl wouldn't
167
+ * achieve anything at the wire layer (other providers cache implicitly
168
+ * based on prefix shape, no marker needed).
169
+ *
170
+ * Otherwise the structured `SystemModelMessage[]` form is returned —
171
+ * preserves the per-section cacheControl markers across `streamText`.
172
+ *
173
+ * @param result - kgauto CompileResult from `compile(ir, opts)`
174
+ * @param convertedMessages - the consumer's already-converted messages
175
+ * (from `convertToModelMessages(rawMessages)` in their AI-SDK call site)
176
+ * @returns `{ system, messages }` ready to spread into `streamText(...)`
177
+ */
178
+ declare function attachCacheControlToStreamTextInput(result: CompileResult, convertedMessages: AISDKConvertedMessage[]): AttachCacheControlResult;
179
+
97
180
  /**
98
181
  * alpha.11 — opt-in nested config for brain-query mode (chains / archetype
99
182
  * perf / pricing / models registry). Enabled by default when endpoint is
@@ -1419,4 +1502,4 @@ declare const loadAliasesFromBrain: () => Record<string, string>;
1419
1502
  */
1420
1503
  declare function compile(ir: PromptIR, opts?: CompileOptions): CompileResult;
1421
1504
 
1422
- export { ABSOLUTE_FLOOR, ARCHETYPE_FLOOR_DEFAULT, type ActionableAdvisory, Adapter, type AdvisoryResolutionSource, type AdvisorySeverity, type AdvisoryStatus, type AdvisorySuggestedFix, ApiKeys, type AppOracle, type ApplySectionRewritesArgs, type ApplySectionRewritesResult, type ArchetypePerfMap, type ArchetypePerfNMap, type ArchetypePerfScoreResult, BestPracticeAdvisory, type BrainConfig, type BrainQueryConfig, CallOptions, CallResult, ChainEntry, type CompatibilityIntent, type CompileOptions, CompilePolicy, CompileResult, CompiledRequest, type ExecuteErr, type ExecuteOk, type ExecuteOptions, type ExecuteResult, type FallbackPosture, type GetActionableAdvisoriesOptions, type GetDefaultFallbackChainOpts, type GetPerAxisMetricsOpts, Grounding, IntentArchetypeName, type LLMJudgeOptions, MEASURED_GROUNDING_MIN_N, type MarkAdvisoryResolvedOptions, type ModelBrainRow, type ModelCompatibility, ModelProfile, NormalizedResponse, type OracleContext, OracleScore, type OutcomePayload, OutcomeResult, PROVIDER_ENV_KEYS, PerAxisMetrics, type PricingRow, type ProfileToRowOptions, PromptIR, Provider, ProviderOverrides, type ProviderReachability, RULE_SEQUENTIAL_TOOL_CLIFF, type ReachabilityOpts, RecordInput, RecordOutcomeInput, type RunAdvisorPhase2Context, SectionRewrite, type SupportedProvider, TRANSLATOR_FLOOR, applySectionRewrites, buildLLMJudge, call, clearBrain, compile, configureBrain, countTokens, execute, getActionableAdvisories, getAllStarterChains, getAllStarterChainsWithGrounding, getArchetypePerfScore, getDefaultFallbackChain, getDefaultFallbackChainWithGrounding, getModelCompatibility, getPerAxisMetrics, getReachabilityDiagnostic, getSequentialStarterChain, getSequentialStarterChainWithGrounding, getStarterChain, getStarterChainWithGrounding, isBrainQueryActiveFor, isModelReachable, isProviderReachable, loadAliasesFromBrain, loadArchetypePerfFromBrain, loadArchetypePerfNFromBrain, loadChainsFromBrain, loadModelsFromBrain, loadPricingFromBrain, markAdvisoryResolved, profileToRow, record, recordOutcome, resetTokenizer, resolvePricingAt, resolveProviderKey, runAdvisor, setTokenizer };
1505
+ export { ABSOLUTE_FLOOR, type AISDKConvertedMessage, ARCHETYPE_FLOOR_DEFAULT, type ActionableAdvisory, Adapter, type AdvisoryResolutionSource, type AdvisorySeverity, type AdvisoryStatus, type AdvisorySuggestedFix, ApiKeys, type AppOracle, type ApplySectionRewritesArgs, type ApplySectionRewritesResult, type ArchetypePerfMap, type ArchetypePerfNMap, type ArchetypePerfScoreResult, type AttachCacheControlResult, BestPracticeAdvisory, type BrainConfig, type BrainQueryConfig, CallOptions, CallResult, ChainEntry, type CompatibilityIntent, type CompileOptions, CompilePolicy, CompileResult, CompiledRequest, type ExecuteErr, type ExecuteOk, type ExecuteOptions, type ExecuteResult, type FallbackPosture, type GetActionableAdvisoriesOptions, type GetDefaultFallbackChainOpts, type GetPerAxisMetricsOpts, Grounding, IntentArchetypeName, type LLMJudgeOptions, MEASURED_GROUNDING_MIN_N, type MarkAdvisoryResolvedOptions, type ModelBrainRow, type ModelCompatibility, ModelProfile, NormalizedResponse, type OracleContext, OracleScore, type OutcomePayload, OutcomeResult, PROVIDER_ENV_KEYS, PerAxisMetrics, type PricingRow, type ProfileToRowOptions, PromptIR, Provider, ProviderOverrides, type ProviderReachability, RULE_SEQUENTIAL_TOOL_CLIFF, type ReachabilityOpts, RecordInput, RecordOutcomeInput, type RunAdvisorPhase2Context, SectionRewrite, type SupportedProvider, SystemModelMessage, TRANSLATOR_FLOOR, applySectionRewrites, attachCacheControlToStreamTextInput, buildLLMJudge, call, clearBrain, compile, configureBrain, countTokens, execute, getActionableAdvisories, getAllStarterChains, getAllStarterChainsWithGrounding, getArchetypePerfScore, getDefaultFallbackChain, getDefaultFallbackChainWithGrounding, getModelCompatibility, getPerAxisMetrics, getReachabilityDiagnostic, getSequentialStarterChain, getSequentialStarterChainWithGrounding, getStarterChain, getStarterChainWithGrounding, isBrainQueryActiveFor, isModelReachable, isProviderReachable, loadAliasesFromBrain, loadArchetypePerfFromBrain, loadArchetypePerfNFromBrain, loadChainsFromBrain, loadModelsFromBrain, loadPricingFromBrain, markAdvisoryResolved, profileToRow, record, recordOutcome, resetTokenizer, resolvePricingAt, resolveProviderKey, runAdvisor, setTokenizer };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as CompilePolicy, N as NormalizedResponse, A as ApiKeys, P as ProviderOverrides, a as CompiledRequest, b as PromptIR, c as CallOptions, d as CallResult, S as SectionRewrite, R as RecordInput, e as RecordOutcomeInput, O as OutcomeResult, f as OracleScore, g as CompileResult, B as BestPracticeAdvisory, h as Adapter, i as PerAxisMetrics, j as Provider, k as ChainEntry, G as Grounding } from './ir-BIAT9gJk.js';
2
- export { l as CallAttempt, m as CallError, n as ChainWithGrounding, o as Constraints, F as FallbackReason, H as HistoryCachePolicy, I as IntentDeclaration, M as Message, p as MutationApplied, q as NormalizedTokens, r as OutcomeKind, s as PerAxisMetricsByModel, t as PromptSection, u as SectionKind, T as ToolCall, v as ToolDefinition } from './ir-BIAT9gJk.js';
1
+ import { C as CompilePolicy, N as NormalizedResponse, A as ApiKeys, P as ProviderOverrides, a as CompiledRequest, b as PromptIR, c as CallOptions, d as CallResult, S as SystemModelMessage, e as CompileResult, f as SectionRewrite, R as RecordInput, g as RecordOutcomeInput, O as OutcomeResult, h as OracleScore, B as BestPracticeAdvisory, i as Adapter, j as PerAxisMetrics, k as Provider, l as ChainEntry, G as Grounding } from './ir-GnYPkpGo.js';
2
+ export { m as CallAttempt, n as CallError, o as ChainWithGrounding, p as Constraints, F as FallbackReason, H as HistoryCachePolicy, I as IntentDeclaration, M as Message, q as MutationApplied, r as NormalizedTokens, s as OutcomeKind, t as PerAxisMetricsByModel, u as PromptSection, v as SectionKind, T as ToolCall, w as ToolDefinition } from './ir-GnYPkpGo.js';
3
3
  import { ModelProfile } from './profiles.js';
4
4
  export { ALIASES, CacheStrategy, CliffRule, LoweringSpec, RecoveryRule, StructuredOutputCapability, SystemPromptMode, allProfiles, getProfile, profilesByProvider, tryGetProfile } from './profiles.js';
5
5
  import { IntentArchetypeName } from './dialect.js';
@@ -94,6 +94,89 @@ declare function execute(request: CompiledRequest, opts?: ExecuteOptions): Promi
94
94
  */
95
95
  declare function call(ir: PromptIR, opts?: CallOptions): Promise<CallResult>;
96
96
 
97
+ /**
98
+ * alpha.33 — AI-SDK streamText helpers.
99
+ *
100
+ * The cross-consumer pattern surfaced 2026-05-20 (`streamText-cache-marker-
101
+ * propagation-gap` on `command-center/interfaces/kgauto.md ## Requested`):
102
+ * AI-SDK consumers using `streamText({ system: <string>, messages:
103
+ * convertToModelMessages(messages), model })` silently drop the Anthropic
104
+ * `cache_control` markers the compiler emits on `result.request.messages`.
105
+ * Two losses on that line:
106
+ * (a) `convertToModelMessages()` reads raw inputs not the lowered output,
107
+ * dropping per-message providerOptions; and
108
+ * (b) `streamText({ system: '<string>' })` strips any providerOptions
109
+ * on the system prefix.
110
+ *
111
+ * Net effect prior to this surface: `cache_read_input_tokens = 0` across
112
+ * every measured production call by IC + tt-intel even though both
113
+ * consumers had `historyCachePolicy: { strategy: 'all-but-latest' }` wired
114
+ * since alpha.5. The compiler did the right thing; the consumer integration
115
+ * pattern lost the markers at the wire boundary.
116
+ *
117
+ * This helper closes the gap. Pass the consumer's already-converted messages
118
+ * + the kgauto CompileResult and get back a `{ system, messages }` pair
119
+ * with cacheControl re-attached at the deterministic indices the compiler
120
+ * computed (`diagnostics.historyCacheMarkIndex` + `systemMessages` with
121
+ * its own cacheControl markers).
122
+ *
123
+ * No I/O. Pure transform. Idempotent — calling twice with the same inputs
124
+ * produces structurally-identical output.
125
+ */
126
+
127
+ /**
128
+ * AI-SDK-shaped converted-message structure. Matches what
129
+ * `convertToModelMessages()` returns at the wire layer. We don't import
130
+ * the AI-SDK type to avoid pulling that dep into the kgauto-compiler
131
+ * package — consumers pass their own already-converted messages.
132
+ */
133
+ interface AISDKConvertedMessage {
134
+ role: 'system' | 'user' | 'assistant' | 'tool';
135
+ content: unknown;
136
+ providerOptions?: {
137
+ anthropic?: {
138
+ cacheControl?: {
139
+ type: 'ephemeral';
140
+ };
141
+ };
142
+ };
143
+ }
144
+ /**
145
+ * Result of `attachCacheControlToStreamTextInput()` — ready to spread into
146
+ * `streamText(...)` directly.
147
+ *
148
+ * The `system` field is either the structured `SystemModelMessage[]` form
149
+ * (when the compiler computed at least one cacheable section + chose
150
+ * Anthropic) or the flat-string concatenation (when no cacheable sections
151
+ * exist OR the provider isn't Anthropic). Consumers can pass either form
152
+ * to `streamText({ system })` — the AI-SDK accepts both.
153
+ */
154
+ interface AttachCacheControlResult {
155
+ system: string | SystemModelMessage[];
156
+ messages: AISDKConvertedMessage[];
157
+ }
158
+ /**
159
+ * Attach Anthropic cache_control markers to a streamText input that the
160
+ * consumer has already prepared via `convertToModelMessages()`. Reads
161
+ * `result.diagnostics.historyCacheMarkIndex` for the position-on-history
162
+ * marker and `result.systemMessages` for the per-section system markers.
163
+ *
164
+ * The flat-string `system` form is returned when:
165
+ * - the compiler produced no `systemMessages` (e.g., zero sections kept), or
166
+ * - the chosen provider is not Anthropic, so cacheControl wouldn't
167
+ * achieve anything at the wire layer (other providers cache implicitly
168
+ * based on prefix shape, no marker needed).
169
+ *
170
+ * Otherwise the structured `SystemModelMessage[]` form is returned —
171
+ * preserves the per-section cacheControl markers across `streamText`.
172
+ *
173
+ * @param result - kgauto CompileResult from `compile(ir, opts)`
174
+ * @param convertedMessages - the consumer's already-converted messages
175
+ * (from `convertToModelMessages(rawMessages)` in their AI-SDK call site)
176
+ * @returns `{ system, messages }` ready to spread into `streamText(...)`
177
+ */
178
+ declare function attachCacheControlToStreamTextInput(result: CompileResult, convertedMessages: AISDKConvertedMessage[]): AttachCacheControlResult;
179
+
97
180
  /**
98
181
  * alpha.11 — opt-in nested config for brain-query mode (chains / archetype
99
182
  * perf / pricing / models registry). Enabled by default when endpoint is
@@ -1419,4 +1502,4 @@ declare const loadAliasesFromBrain: () => Record<string, string>;
1419
1502
  */
1420
1503
  declare function compile(ir: PromptIR, opts?: CompileOptions): CompileResult;
1421
1504
 
1422
- export { ABSOLUTE_FLOOR, ARCHETYPE_FLOOR_DEFAULT, type ActionableAdvisory, Adapter, type AdvisoryResolutionSource, type AdvisorySeverity, type AdvisoryStatus, type AdvisorySuggestedFix, ApiKeys, type AppOracle, type ApplySectionRewritesArgs, type ApplySectionRewritesResult, type ArchetypePerfMap, type ArchetypePerfNMap, type ArchetypePerfScoreResult, BestPracticeAdvisory, type BrainConfig, type BrainQueryConfig, CallOptions, CallResult, ChainEntry, type CompatibilityIntent, type CompileOptions, CompilePolicy, CompileResult, CompiledRequest, type ExecuteErr, type ExecuteOk, type ExecuteOptions, type ExecuteResult, type FallbackPosture, type GetActionableAdvisoriesOptions, type GetDefaultFallbackChainOpts, type GetPerAxisMetricsOpts, Grounding, IntentArchetypeName, type LLMJudgeOptions, MEASURED_GROUNDING_MIN_N, type MarkAdvisoryResolvedOptions, type ModelBrainRow, type ModelCompatibility, ModelProfile, NormalizedResponse, type OracleContext, OracleScore, type OutcomePayload, OutcomeResult, PROVIDER_ENV_KEYS, PerAxisMetrics, type PricingRow, type ProfileToRowOptions, PromptIR, Provider, ProviderOverrides, type ProviderReachability, RULE_SEQUENTIAL_TOOL_CLIFF, type ReachabilityOpts, RecordInput, RecordOutcomeInput, type RunAdvisorPhase2Context, SectionRewrite, type SupportedProvider, TRANSLATOR_FLOOR, applySectionRewrites, buildLLMJudge, call, clearBrain, compile, configureBrain, countTokens, execute, getActionableAdvisories, getAllStarterChains, getAllStarterChainsWithGrounding, getArchetypePerfScore, getDefaultFallbackChain, getDefaultFallbackChainWithGrounding, getModelCompatibility, getPerAxisMetrics, getReachabilityDiagnostic, getSequentialStarterChain, getSequentialStarterChainWithGrounding, getStarterChain, getStarterChainWithGrounding, isBrainQueryActiveFor, isModelReachable, isProviderReachable, loadAliasesFromBrain, loadArchetypePerfFromBrain, loadArchetypePerfNFromBrain, loadChainsFromBrain, loadModelsFromBrain, loadPricingFromBrain, markAdvisoryResolved, profileToRow, record, recordOutcome, resetTokenizer, resolvePricingAt, resolveProviderKey, runAdvisor, setTokenizer };
1505
+ export { ABSOLUTE_FLOOR, type AISDKConvertedMessage, ARCHETYPE_FLOOR_DEFAULT, type ActionableAdvisory, Adapter, type AdvisoryResolutionSource, type AdvisorySeverity, type AdvisoryStatus, type AdvisorySuggestedFix, ApiKeys, type AppOracle, type ApplySectionRewritesArgs, type ApplySectionRewritesResult, type ArchetypePerfMap, type ArchetypePerfNMap, type ArchetypePerfScoreResult, type AttachCacheControlResult, BestPracticeAdvisory, type BrainConfig, type BrainQueryConfig, CallOptions, CallResult, ChainEntry, type CompatibilityIntent, type CompileOptions, CompilePolicy, CompileResult, CompiledRequest, type ExecuteErr, type ExecuteOk, type ExecuteOptions, type ExecuteResult, type FallbackPosture, type GetActionableAdvisoriesOptions, type GetDefaultFallbackChainOpts, type GetPerAxisMetricsOpts, Grounding, IntentArchetypeName, type LLMJudgeOptions, MEASURED_GROUNDING_MIN_N, type MarkAdvisoryResolvedOptions, type ModelBrainRow, type ModelCompatibility, ModelProfile, NormalizedResponse, type OracleContext, OracleScore, type OutcomePayload, OutcomeResult, PROVIDER_ENV_KEYS, PerAxisMetrics, type PricingRow, type ProfileToRowOptions, PromptIR, Provider, ProviderOverrides, type ProviderReachability, RULE_SEQUENTIAL_TOOL_CLIFF, type ReachabilityOpts, RecordInput, RecordOutcomeInput, type RunAdvisorPhase2Context, SectionRewrite, type SupportedProvider, SystemModelMessage, TRANSLATOR_FLOOR, applySectionRewrites, attachCacheControlToStreamTextInput, buildLLMJudge, call, clearBrain, compile, configureBrain, countTokens, execute, getActionableAdvisories, getAllStarterChains, getAllStarterChainsWithGrounding, getArchetypePerfScore, getDefaultFallbackChain, getDefaultFallbackChainWithGrounding, getModelCompatibility, getPerAxisMetrics, getReachabilityDiagnostic, getSequentialStarterChain, getSequentialStarterChainWithGrounding, getStarterChain, getStarterChainWithGrounding, isBrainQueryActiveFor, isModelReachable, isProviderReachable, loadAliasesFromBrain, loadArchetypePerfFromBrain, loadArchetypePerfNFromBrain, loadChainsFromBrain, loadModelsFromBrain, loadPricingFromBrain, markAdvisoryResolved, profileToRow, record, recordOutcome, resetTokenizer, resolvePricingAt, resolveProviderKey, runAdvisor, setTokenizer };
package/dist/index.js CHANGED
@@ -33,6 +33,7 @@ __export(index_exports, {
33
33
  TRANSLATOR_FLOOR: () => TRANSLATOR_FLOOR,
34
34
  allProfiles: () => allProfiles,
35
35
  applySectionRewrites: () => applySectionRewrites,
36
+ attachCacheControlToStreamTextInput: () => attachCacheControlToStreamTextInput,
36
37
  bucketContext: () => bucketContext,
37
38
  bucketHistory: () => bucketHistory,
38
39
  bucketToolCount: () => bucketToolCount,
@@ -2771,6 +2772,9 @@ function compile(ir, opts = {}) {
2771
2772
  const handle = makeHandle();
2772
2773
  const finalShape = computeShape(workingIR, inputTokens);
2773
2774
  const _learningKey = learningKey(ir.intent.archetype, profile.id, finalShape);
2775
+ const historyCacheMarkIndex = computeHistoryCacheMarkIndex(workingIR);
2776
+ const systemMessages = buildSystemMessages(workingIR, profile.provider);
2777
+ const systemCacheMarkIndex = lastCacheableSystemIndex(systemMessages);
2774
2778
  const diagnostics = {
2775
2779
  sectionsKept: workingIR.sections.length,
2776
2780
  sectionsDropped: ir.sections.length - workingIR.sections.length,
@@ -2784,7 +2788,10 @@ function compile(ir, opts = {}) {
2784
2788
  historyTokensTotal: compressed.historyTokensTotal,
2785
2789
  // alpha.20 E3: mirror the consumer's declared mode for Glass-Box +
2786
2790
  // brain observability. Undefined when not declared (pre-alpha.20).
2787
- toolOrchestration: ir.constraints?.toolOrchestration
2791
+ toolOrchestration: ir.constraints?.toolOrchestration,
2792
+ // alpha.33 — see top-of-block comment.
2793
+ historyCacheMarkIndex,
2794
+ systemCacheMarkIndex
2788
2795
  };
2789
2796
  if (ir.intent.archetype === "hunt" && ir.constraints?.toolOrchestration === "sequential") {
2790
2797
  accumulatedMutations.push({
@@ -2834,9 +2841,45 @@ function compile(ir, opts = {}) {
2834
2841
  advisories,
2835
2842
  diagnostics,
2836
2843
  sectionRewritesApplied,
2837
- wireOverrides
2844
+ wireOverrides,
2845
+ systemMessages
2838
2846
  };
2839
2847
  }
2848
+ function computeHistoryCacheMarkIndex(ir) {
2849
+ const policy = ir.historyCachePolicy;
2850
+ if (!policy || policy.strategy === "none") return void 0;
2851
+ const historyLen = ir.history?.length ?? 0;
2852
+ if (historyLen === 0) return void 0;
2853
+ if (policy.strategy === "all-but-latest") {
2854
+ return historyLen - 1;
2855
+ }
2856
+ if (policy.strategy === "fixed-suffix") {
2857
+ const idx = historyLen - 1 - policy.suffix;
2858
+ if (idx < 0) return void 0;
2859
+ return idx;
2860
+ }
2861
+ return void 0;
2862
+ }
2863
+ function buildSystemMessages(ir, provider) {
2864
+ const sections = ir.sections;
2865
+ if (!sections || sections.length === 0) return [];
2866
+ return sections.map((s) => {
2867
+ const base = { role: "system", content: s.text };
2868
+ if (provider === "anthropic" && s.cacheable) {
2869
+ base.providerOptions = { anthropic: { cacheControl: { type: "ephemeral" } } };
2870
+ }
2871
+ return base;
2872
+ });
2873
+ }
2874
+ function lastCacheableSystemIndex(systemMessages) {
2875
+ for (let i = systemMessages.length - 1; i >= 0; i--) {
2876
+ const entry = systemMessages[i];
2877
+ if (entry && entry.providerOptions?.anthropic?.cacheControl) {
2878
+ return i;
2879
+ }
2880
+ }
2881
+ return void 0;
2882
+ }
2840
2883
  function validateIR(ir) {
2841
2884
  if (!ir.appId) throw new Error("compile(): ir.appId is required");
2842
2885
  if (!ir.intent || !ir.intent.archetype) {
@@ -3581,7 +3624,8 @@ var STARTER_CHAINS_GROUNDED = {
3581
3624
  { id: "claude-sonnet-4-6", grounding: "judgment", reason: "Reasoning + cost balance \u2014 engineer pick" },
3582
3625
  { id: "claude-opus-4-7", grounding: "judgment", reason: 'Same-provider walk-UP on 429 (rare exception to "always cheaper")' },
3583
3626
  { id: "gemini-2.5-pro", grounding: "judgment", reason: "Cross-provider anchor" },
3584
- { id: "deepseek-v4-pro", grounding: "judgment", reason: "Tier 3 cost floor \u2014 no brain evidence yet" }
3627
+ { id: "deepseek-v4-pro", grounding: "judgment", reason: "Tier 3 cost floor \u2014 no brain evidence yet" },
3628
+ { id: "gpt-5.4", grounding: "judgment", reason: "alpha.33: third-provider tail (archetypePerf=7) \u2014 closes openai-in-default-fallback-chains" }
3585
3629
  ],
3586
3630
  // Quality + cost match.
3587
3631
  generate: [
@@ -3612,7 +3656,8 @@ var STARTER_CHAINS_GROUNDED = {
3612
3656
  { id: "claude-sonnet-4-6", grounding: "judgment", reason: "Quality anchor \u2014 engineer pick" },
3613
3657
  { id: "claude-haiku-4-5", grounding: "judgment", reason: "Same-provider step-down" },
3614
3658
  { id: "gemini-2.5-pro", grounding: "judgment", reason: "Cross-provider anchor" },
3615
- { id: "gemini-2.5-flash", grounding: "judgment", reason: "Cost floor \u2014 forgiving archetype tolerates Flash" }
3659
+ { id: "gemini-2.5-flash", grounding: "judgment", reason: "Cost floor \u2014 forgiving archetype tolerates Flash" },
3660
+ { id: "gpt-5.4-mini", grounding: "judgment", reason: "alpha.33: third-provider tail (archetypePerf=7) \u2014 closes openai-in-default-fallback-chains" }
3616
3661
  ],
3617
3662
  // Parallel-tool throughput champion — Flash leads on the L-040 cliff
3618
3663
  // (capability-fact: Flash 15-75 parallel calls/step vs DeepSeek 7-8).
@@ -3620,21 +3665,24 @@ var STARTER_CHAINS_GROUNDED = {
3620
3665
  { id: "gemini-2.5-flash", grounding: "capability-fact", reason: "L-040 parallel-tool throughput champion (15-75 calls/step)" },
3621
3666
  { id: "gemini-2.5-pro", grounding: "capability-fact", reason: "Cross-provider tier 1 with strong parallel-tool support" },
3622
3667
  { id: "claude-sonnet-4-6", grounding: "judgment", reason: "Quality safety net for blocked-Flash case" },
3623
- { id: "claude-haiku-4-5", grounding: "judgment", reason: "Reduced tool budget \u2014 cliff at 16 fires" }
3668
+ { id: "claude-haiku-4-5", grounding: "judgment", reason: "Reduced tool budget \u2014 cliff at 16 fires" },
3669
+ { id: "gpt-5.4-mini", grounding: "judgment", reason: "alpha.33: third-provider tail \u2014 OpenAI parallel-tool capable archetype" }
3624
3670
  ],
3625
3671
  // Cost-sensitive + tolerant. DeepSeek brain-evidence tier 1.
3626
3672
  summarize: [
3627
3673
  { id: "gemini-2.5-flash", grounding: "judgment", reason: "Cost-sensitive primary \u2014 engineer pick" },
3628
3674
  { id: "deepseek-v4-flash", grounding: "measured", reason: "Brain-validated tier 1 for cost-sensitive summarize workloads", n: 169 },
3629
3675
  { id: "claude-haiku-4-5", grounding: "judgment", reason: "Quality safety net" },
3630
- { id: "gemini-2.5-flash-lite", grounding: "judgment", reason: "Emergency floor \u2014 onboarded s22, no brain evidence yet" }
3676
+ { id: "gemini-2.5-flash-lite", grounding: "judgment", reason: "Emergency floor \u2014 onboarded s22, no brain evidence yet" },
3677
+ { id: "gpt-5.4-nano", grounding: "judgment", reason: "alpha.33: third-provider tail (archetypePerf=6) \u2014 cheapest OpenAI, matches summarize cost-band" }
3631
3678
  ],
3632
3679
  // Brain-validated DeepSeek tier 1 (169 rows, 0% empty rate).
3633
3680
  classify: [
3634
3681
  { id: "gemini-2.5-flash", grounding: "judgment", reason: "Cost-sensitive primary \u2014 engineer pick" },
3635
3682
  { id: "deepseek-v4-flash", grounding: "measured", reason: "Brain-validated tier 1 (169 rows, 0% empty rate)", n: 169 },
3636
3683
  { id: "claude-haiku-4-5", grounding: "judgment", reason: "Quality safety net" },
3637
- { id: "gemini-2.5-flash-lite", grounding: "judgment", reason: "Cache-discount 10\xD7 floor for repeat-prompt workloads" }
3684
+ { id: "gemini-2.5-flash-lite", grounding: "judgment", reason: "Cache-discount 10\xD7 floor for repeat-prompt workloads" },
3685
+ { id: "gpt-5.4-nano", grounding: "judgment", reason: "alpha.33: third-provider tail (archetypePerf=6) \u2014 cheapest OpenAI for classify" }
3638
3686
  ]
3639
3687
  };
3640
3688
  var STARTER_CHAINS = (() => {
@@ -3689,7 +3737,7 @@ function resolveStarterForMode(archetype, toolOrchestration, allChains) {
3689
3737
  return allChains[archetype];
3690
3738
  }
3691
3739
  function getDefaultFallbackChain(opts) {
3692
- const { archetype, primary, maxDepth = 3, policy, reachability, toolOrchestration } = opts;
3740
+ const { archetype, primary, maxDepth = 4, policy, reachability, toolOrchestration } = opts;
3693
3741
  if (maxDepth < 1) {
3694
3742
  throw new Error(
3695
3743
  `getDefaultFallbackChain: maxDepth must be >= 1, got ${maxDepth}`
@@ -4521,6 +4569,34 @@ function safeEmit(fn) {
4521
4569
  }
4522
4570
  }
4523
4571
 
4572
+ // src/streamtext-helpers.ts
4573
+ function attachCacheControlToStreamTextInput(result, convertedMessages) {
4574
+ const messages = convertedMessages.map((m) => ({ ...m }));
4575
+ const markIdx = result.diagnostics.historyCacheMarkIndex;
4576
+ if (result.provider === "anthropic" && typeof markIdx === "number" && markIdx >= 0 && markIdx < messages.length) {
4577
+ const target = messages[markIdx];
4578
+ if (target) {
4579
+ messages[markIdx] = {
4580
+ role: target.role,
4581
+ content: target.content,
4582
+ providerOptions: {
4583
+ ...target.providerOptions ?? {},
4584
+ anthropic: {
4585
+ ...target.providerOptions?.anthropic ?? {},
4586
+ cacheControl: { type: "ephemeral" }
4587
+ }
4588
+ }
4589
+ };
4590
+ }
4591
+ }
4592
+ const systemMessages = result.systemMessages;
4593
+ const hasStructuredSystemCacheControl = result.provider === "anthropic" && systemMessages.some(
4594
+ (m) => m.providerOptions?.anthropic?.cacheControl !== void 0
4595
+ );
4596
+ const system = hasStructuredSystemCacheControl ? systemMessages : systemMessages.map((m) => m.content).join("\n\n");
4597
+ return { system, messages };
4598
+ }
4599
+
4524
4600
  // src/oracle.ts
4525
4601
  var DEFAULT_DIMENSIONS = ["correctness", "completeness", "conciseness", "format"];
4526
4602
  var judgeCallTimes = [];
@@ -5021,6 +5097,7 @@ function compile2(ir, opts) {
5021
5097
  TRANSLATOR_FLOOR,
5022
5098
  allProfiles,
5023
5099
  applySectionRewrites,
5100
+ attachCacheControlToStreamTextInput,
5024
5101
  bucketContext,
5025
5102
  bucketHistory,
5026
5103
  bucketToolCount,
package/dist/index.mjs CHANGED
@@ -32,7 +32,7 @@ import {
32
32
  isProviderReachable,
33
33
  loadChainsFromBrain,
34
34
  resolveProviderKey
35
- } from "./chunk-WXCFWUCN.mjs";
35
+ } from "./chunk-XJZRDGHF.mjs";
36
36
  import {
37
37
  ALIASES,
38
38
  _setProfileBrainHook,
@@ -1197,6 +1197,9 @@ function compile(ir, opts = {}) {
1197
1197
  const handle = makeHandle();
1198
1198
  const finalShape = computeShape(workingIR, inputTokens);
1199
1199
  const _learningKey = learningKey(ir.intent.archetype, profile.id, finalShape);
1200
+ const historyCacheMarkIndex = computeHistoryCacheMarkIndex(workingIR);
1201
+ const systemMessages = buildSystemMessages(workingIR, profile.provider);
1202
+ const systemCacheMarkIndex = lastCacheableSystemIndex(systemMessages);
1200
1203
  const diagnostics = {
1201
1204
  sectionsKept: workingIR.sections.length,
1202
1205
  sectionsDropped: ir.sections.length - workingIR.sections.length,
@@ -1210,7 +1213,10 @@ function compile(ir, opts = {}) {
1210
1213
  historyTokensTotal: compressed.historyTokensTotal,
1211
1214
  // alpha.20 E3: mirror the consumer's declared mode for Glass-Box +
1212
1215
  // brain observability. Undefined when not declared (pre-alpha.20).
1213
- toolOrchestration: ir.constraints?.toolOrchestration
1216
+ toolOrchestration: ir.constraints?.toolOrchestration,
1217
+ // alpha.33 — see top-of-block comment.
1218
+ historyCacheMarkIndex,
1219
+ systemCacheMarkIndex
1214
1220
  };
1215
1221
  if (ir.intent.archetype === "hunt" && ir.constraints?.toolOrchestration === "sequential") {
1216
1222
  accumulatedMutations.push({
@@ -1260,9 +1266,45 @@ function compile(ir, opts = {}) {
1260
1266
  advisories,
1261
1267
  diagnostics,
1262
1268
  sectionRewritesApplied,
1263
- wireOverrides
1269
+ wireOverrides,
1270
+ systemMessages
1264
1271
  };
1265
1272
  }
1273
+ function computeHistoryCacheMarkIndex(ir) {
1274
+ const policy = ir.historyCachePolicy;
1275
+ if (!policy || policy.strategy === "none") return void 0;
1276
+ const historyLen = ir.history?.length ?? 0;
1277
+ if (historyLen === 0) return void 0;
1278
+ if (policy.strategy === "all-but-latest") {
1279
+ return historyLen - 1;
1280
+ }
1281
+ if (policy.strategy === "fixed-suffix") {
1282
+ const idx = historyLen - 1 - policy.suffix;
1283
+ if (idx < 0) return void 0;
1284
+ return idx;
1285
+ }
1286
+ return void 0;
1287
+ }
1288
+ function buildSystemMessages(ir, provider) {
1289
+ const sections = ir.sections;
1290
+ if (!sections || sections.length === 0) return [];
1291
+ return sections.map((s) => {
1292
+ const base = { role: "system", content: s.text };
1293
+ if (provider === "anthropic" && s.cacheable) {
1294
+ base.providerOptions = { anthropic: { cacheControl: { type: "ephemeral" } } };
1295
+ }
1296
+ return base;
1297
+ });
1298
+ }
1299
+ function lastCacheableSystemIndex(systemMessages) {
1300
+ for (let i = systemMessages.length - 1; i >= 0; i--) {
1301
+ const entry = systemMessages[i];
1302
+ if (entry && entry.providerOptions?.anthropic?.cacheControl) {
1303
+ return i;
1304
+ }
1305
+ }
1306
+ return void 0;
1307
+ }
1266
1308
  function validateIR(ir) {
1267
1309
  if (!ir.appId) throw new Error("compile(): ir.appId is required");
1268
1310
  if (!ir.intent || !ir.intent.archetype) {
@@ -2247,6 +2289,34 @@ function safeEmit(fn) {
2247
2289
  }
2248
2290
  }
2249
2291
 
2292
+ // src/streamtext-helpers.ts
2293
+ function attachCacheControlToStreamTextInput(result, convertedMessages) {
2294
+ const messages = convertedMessages.map((m) => ({ ...m }));
2295
+ const markIdx = result.diagnostics.historyCacheMarkIndex;
2296
+ if (result.provider === "anthropic" && typeof markIdx === "number" && markIdx >= 0 && markIdx < messages.length) {
2297
+ const target = messages[markIdx];
2298
+ if (target) {
2299
+ messages[markIdx] = {
2300
+ role: target.role,
2301
+ content: target.content,
2302
+ providerOptions: {
2303
+ ...target.providerOptions ?? {},
2304
+ anthropic: {
2305
+ ...target.providerOptions?.anthropic ?? {},
2306
+ cacheControl: { type: "ephemeral" }
2307
+ }
2308
+ }
2309
+ };
2310
+ }
2311
+ }
2312
+ const systemMessages = result.systemMessages;
2313
+ const hasStructuredSystemCacheControl = result.provider === "anthropic" && systemMessages.some(
2314
+ (m) => m.providerOptions?.anthropic?.cacheControl !== void 0
2315
+ );
2316
+ const system = hasStructuredSystemCacheControl ? systemMessages : systemMessages.map((m) => m.content).join("\n\n");
2317
+ return { system, messages };
2318
+ }
2319
+
2250
2320
  // src/oracle.ts
2251
2321
  var DEFAULT_DIMENSIONS = ["correctness", "completeness", "conciseness", "format"];
2252
2322
  var judgeCallTimes = [];
@@ -2746,6 +2816,7 @@ export {
2746
2816
  TRANSLATOR_FLOOR,
2747
2817
  allProfiles,
2748
2818
  applySectionRewrites,
2819
+ attachCacheControlToStreamTextInput,
2749
2820
  bucketContext,
2750
2821
  bucketHistory,
2751
2822
  bucketToolCount,
@@ -564,6 +564,86 @@ interface CompileResult {
564
564
  * treat as 'parallel' equivalent for back-compat.
565
565
  */
566
566
  toolOrchestration?: 'parallel' | 'sequential' | 'either';
567
+ /**
568
+ * alpha.33. Zero-based index into the resolved (post-compression) history
569
+ * array at which Anthropic prompt-cache marker should land — i.e., the
570
+ * last message that belongs to the stable cacheable prefix. Consumers
571
+ * using AI-SDK's `streamText({ messages: convertToModelMessages(...) })`
572
+ * lose the per-message `providerOptions.anthropic.cacheControl` markers
573
+ * the compiler emits on `result.request.messages`, because
574
+ * `convertToModelMessages` reads raw input not the lowered output.
575
+ * This index gives the consumer a single deterministic position to
576
+ * attach `cacheControl: { type: 'ephemeral' }` after their own conversion.
577
+ *
578
+ * Computation:
579
+ * - `historyCachePolicy.strategy === 'all-but-latest'`: history.length - 1
580
+ * (or undefined if history is empty)
581
+ * - `historyCachePolicy.strategy === 'fixed-suffix'` with `suffix: N`:
582
+ * history.length - 1 - N (undefined if N exceeds history length)
583
+ * - `historyCachePolicy.strategy === 'none'` or omitted: undefined
584
+ *
585
+ * The companion helper `attachCacheControlToStreamTextInput()` reads
586
+ * this field + the consumer's converted messages to perform the per-
587
+ * attempt mutation correctly. Filed by IC + tt-intel cross-consumer
588
+ * pattern 2026-05-20 (`streamText-cache-marker-propagation-gap`).
589
+ */
590
+ historyCacheMarkIndex?: number;
591
+ /**
592
+ * alpha.33. Zero-based index into the structured `systemMessages` array
593
+ * (see top-level `systemMessages` field) at which the cacheable system
594
+ * prefix ends. Useful when the consumer is building a multi-block
595
+ * system parameter for Anthropic streamText — they can attach
596
+ * `providerOptions.anthropic.cacheControl` to `systemMessages[index]`.
597
+ *
598
+ * Undefined when no section had `cacheable: true` OR `systemMessages` is
599
+ * empty. Matches `historyCacheMarkIndex` semantics on the history axis.
600
+ */
601
+ systemCacheMarkIndex?: number;
602
+ };
603
+ /**
604
+ * alpha.33. Structured `system` for AI-SDK `streamText({ system })`
605
+ * consumers. When the consumer's lowered request has cacheable section
606
+ * markers, the flat `system: string` form loses the marker assignment
607
+ * (every `streamText({ system: '<string>' })` call silently strips
608
+ * providerOptions). Pass `systemMessages` instead to `streamText({
609
+ * system: result.systemMessages })` so the cacheable prefix is structurally
610
+ * preserved.
611
+ *
612
+ * Each entry is a `SystemModelMessage`-shaped object:
613
+ * { role: 'system', content: string, providerOptions?: { anthropic?:
614
+ * { cacheControl: { type: 'ephemeral' } } } }
615
+ *
616
+ * Provider-agnostic on emit: only Anthropic actually consumes the
617
+ * cacheControl block; Gemini / OpenAI / DeepSeek receive the same
618
+ * shape but ignore the marker (matching their implicit-caching semantics).
619
+ *
620
+ * Empty array when the IR carried zero sections (rare; usually means the
621
+ * compiler dropped everything for the chosen intent). Consumers can fall
622
+ * back to `result.systemMessages.length === 0 ? '' : result.systemMessages`
623
+ * or use the helper `attachCacheControlToStreamTextInput()` which handles
624
+ * both shapes.
625
+ */
626
+ systemMessages: SystemModelMessage[];
627
+ }
628
+ /**
629
+ * alpha.33. AI-SDK-compatible system-message shape carried on
630
+ * `CompileResult.systemMessages`. Matches the AI-SDK `streamText({ system })`
631
+ * structured form — consumers can pass these directly without conversion.
632
+ *
633
+ * The `providerOptions` field is set ONLY for entries that came from a
634
+ * section with `cacheable: true` AND the chosen provider is Anthropic AND
635
+ * the compiler computed a non-zero `cacheableTokens`. Other providers see
636
+ * `providerOptions: undefined` (or omitted entirely).
637
+ */
638
+ interface SystemModelMessage {
639
+ role: 'system';
640
+ content: string;
641
+ providerOptions?: {
642
+ anthropic?: {
643
+ cacheControl: {
644
+ type: 'ephemeral';
645
+ };
646
+ };
567
647
  };
568
648
  }
569
649
  /**
@@ -1028,4 +1108,4 @@ interface PerAxisMetrics {
1028
1108
  /** Per-axis metrics keyed by model — used for chain-comparison views. */
1029
1109
  type PerAxisMetricsByModel = Record<string, PerAxisMetrics>;
1030
1110
 
1031
- export { type ApiKeys as A, type BestPracticeAdvisory as B, type CompilePolicy as C, type FallbackReason as F, type Grounding as G, type HistoryCachePolicy as H, type IntentDeclaration as I, type Message as M, type NormalizedResponse as N, type OutcomeResult as O, type ProviderOverrides as P, type RecordInput as R, type SectionRewrite as S, type ToolCall as T, type CompiledRequest as a, type PromptIR as b, type CallOptions as c, type CallResult as d, type RecordOutcomeInput as e, type OracleScore as f, type CompileResult as g, type Adapter as h, type PerAxisMetrics as i, type Provider as j, type ChainEntry as k, type CallAttempt as l, CallError as m, type ChainWithGrounding as n, type Constraints as o, type MutationApplied as p, type NormalizedTokens as q, type OutcomeKind as r, type PerAxisMetricsByModel as s, type PromptSection as t, type SectionKind as u, type ToolDefinition as v };
1111
+ export { type ApiKeys as A, type BestPracticeAdvisory as B, type CompilePolicy as C, type FallbackReason as F, type Grounding as G, type HistoryCachePolicy as H, type IntentDeclaration as I, type Message as M, type NormalizedResponse as N, type OutcomeResult as O, type ProviderOverrides as P, type RecordInput as R, type SystemModelMessage as S, type ToolCall as T, type CompiledRequest as a, type PromptIR as b, type CallOptions as c, type CallResult as d, type CompileResult as e, type SectionRewrite as f, type RecordOutcomeInput as g, type OracleScore as h, type Adapter as i, type PerAxisMetrics as j, type Provider as k, type ChainEntry as l, type CallAttempt as m, CallError as n, type ChainWithGrounding as o, type Constraints as p, type MutationApplied as q, type NormalizedTokens as r, type OutcomeKind as s, type PerAxisMetricsByModel as t, type PromptSection as u, type SectionKind as v, type ToolDefinition as w };
@@ -564,6 +564,86 @@ interface CompileResult {
564
564
  * treat as 'parallel' equivalent for back-compat.
565
565
  */
566
566
  toolOrchestration?: 'parallel' | 'sequential' | 'either';
567
+ /**
568
+ * alpha.33. Zero-based index into the resolved (post-compression) history
569
+ * array at which Anthropic prompt-cache marker should land — i.e., the
570
+ * last message that belongs to the stable cacheable prefix. Consumers
571
+ * using AI-SDK's `streamText({ messages: convertToModelMessages(...) })`
572
+ * lose the per-message `providerOptions.anthropic.cacheControl` markers
573
+ * the compiler emits on `result.request.messages`, because
574
+ * `convertToModelMessages` reads raw input not the lowered output.
575
+ * This index gives the consumer a single deterministic position to
576
+ * attach `cacheControl: { type: 'ephemeral' }` after their own conversion.
577
+ *
578
+ * Computation:
579
+ * - `historyCachePolicy.strategy === 'all-but-latest'`: history.length - 1
580
+ * (or undefined if history is empty)
581
+ * - `historyCachePolicy.strategy === 'fixed-suffix'` with `suffix: N`:
582
+ * history.length - 1 - N (undefined if N exceeds history length)
583
+ * - `historyCachePolicy.strategy === 'none'` or omitted: undefined
584
+ *
585
+ * The companion helper `attachCacheControlToStreamTextInput()` reads
586
+ * this field + the consumer's converted messages to perform the per-
587
+ * attempt mutation correctly. Filed by IC + tt-intel cross-consumer
588
+ * pattern 2026-05-20 (`streamText-cache-marker-propagation-gap`).
589
+ */
590
+ historyCacheMarkIndex?: number;
591
+ /**
592
+ * alpha.33. Zero-based index into the structured `systemMessages` array
593
+ * (see top-level `systemMessages` field) at which the cacheable system
594
+ * prefix ends. Useful when the consumer is building a multi-block
595
+ * system parameter for Anthropic streamText — they can attach
596
+ * `providerOptions.anthropic.cacheControl` to `systemMessages[index]`.
597
+ *
598
+ * Undefined when no section had `cacheable: true` OR `systemMessages` is
599
+ * empty. Matches `historyCacheMarkIndex` semantics on the history axis.
600
+ */
601
+ systemCacheMarkIndex?: number;
602
+ };
603
+ /**
604
+ * alpha.33. Structured `system` for AI-SDK `streamText({ system })`
605
+ * consumers. When the consumer's lowered request has cacheable section
606
+ * markers, the flat `system: string` form loses the marker assignment
607
+ * (every `streamText({ system: '<string>' })` call silently strips
608
+ * providerOptions). Pass `systemMessages` instead to `streamText({
609
+ * system: result.systemMessages })` so the cacheable prefix is structurally
610
+ * preserved.
611
+ *
612
+ * Each entry is a `SystemModelMessage`-shaped object:
613
+ * { role: 'system', content: string, providerOptions?: { anthropic?:
614
+ * { cacheControl: { type: 'ephemeral' } } } }
615
+ *
616
+ * Provider-agnostic on emit: only Anthropic actually consumes the
617
+ * cacheControl block; Gemini / OpenAI / DeepSeek receive the same
618
+ * shape but ignore the marker (matching their implicit-caching semantics).
619
+ *
620
+ * Empty array when the IR carried zero sections (rare; usually means the
621
+ * compiler dropped everything for the chosen intent). Consumers can fall
622
+ * back to `result.systemMessages.length === 0 ? '' : result.systemMessages`
623
+ * or use the helper `attachCacheControlToStreamTextInput()` which handles
624
+ * both shapes.
625
+ */
626
+ systemMessages: SystemModelMessage[];
627
+ }
628
+ /**
629
+ * alpha.33. AI-SDK-compatible system-message shape carried on
630
+ * `CompileResult.systemMessages`. Matches the AI-SDK `streamText({ system })`
631
+ * structured form — consumers can pass these directly without conversion.
632
+ *
633
+ * The `providerOptions` field is set ONLY for entries that came from a
634
+ * section with `cacheable: true` AND the chosen provider is Anthropic AND
635
+ * the compiler computed a non-zero `cacheableTokens`. Other providers see
636
+ * `providerOptions: undefined` (or omitted entirely).
637
+ */
638
+ interface SystemModelMessage {
639
+ role: 'system';
640
+ content: string;
641
+ providerOptions?: {
642
+ anthropic?: {
643
+ cacheControl: {
644
+ type: 'ephemeral';
645
+ };
646
+ };
567
647
  };
568
648
  }
569
649
  /**
@@ -1028,4 +1108,4 @@ interface PerAxisMetrics {
1028
1108
  /** Per-axis metrics keyed by model — used for chain-comparison views. */
1029
1109
  type PerAxisMetricsByModel = Record<string, PerAxisMetrics>;
1030
1110
 
1031
- export { type ApiKeys as A, type BestPracticeAdvisory as B, type CompilePolicy as C, type FallbackReason as F, type Grounding as G, type HistoryCachePolicy as H, type IntentDeclaration as I, type Message as M, type NormalizedResponse as N, type OutcomeResult as O, type ProviderOverrides as P, type RecordInput as R, type SectionRewrite as S, type ToolCall as T, type CompiledRequest as a, type PromptIR as b, type CallOptions as c, type CallResult as d, type RecordOutcomeInput as e, type OracleScore as f, type CompileResult as g, type Adapter as h, type PerAxisMetrics as i, type Provider as j, type ChainEntry as k, type CallAttempt as l, CallError as m, type ChainWithGrounding as n, type Constraints as o, type MutationApplied as p, type NormalizedTokens as q, type OutcomeKind as r, type PerAxisMetricsByModel as s, type PromptSection as t, type SectionKind as u, type ToolDefinition as v };
1111
+ export { type ApiKeys as A, type BestPracticeAdvisory as B, type CompilePolicy as C, type FallbackReason as F, type Grounding as G, type HistoryCachePolicy as H, type IntentDeclaration as I, type Message as M, type NormalizedResponse as N, type OutcomeResult as O, type ProviderOverrides as P, type RecordInput as R, type SystemModelMessage as S, type ToolCall as T, type CompiledRequest as a, type PromptIR as b, type CallOptions as c, type CallResult as d, type CompileResult as e, type SectionRewrite as f, type RecordOutcomeInput as g, type OracleScore as h, type Adapter as i, type PerAxisMetrics as j, type Provider as k, type ChainEntry as l, type CallAttempt as m, CallError as n, type ChainWithGrounding as o, type Constraints as p, type MutationApplied as q, type NormalizedTokens as r, type OutcomeKind as s, type PerAxisMetricsByModel as t, type PromptSection as u, type SectionKind as v, type ToolDefinition as w };
@@ -1,4 +1,4 @@
1
- import { j as Provider } from './ir-De2AQtlr.mjs';
1
+ import { k as Provider } from './ir-DubC20e3.mjs';
2
2
  import { IntentArchetypeName } from './dialect.mjs';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { j as Provider } from './ir-BIAT9gJk.js';
1
+ import { k as Provider } from './ir-GnYPkpGo.js';
2
2
  import { IntentArchetypeName } from './dialect.js';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { p as MutationApplied, B as BestPracticeAdvisory, F as FallbackReason, l as CallAttempt } from './ir-De2AQtlr.mjs';
1
+ import { q as MutationApplied, B as BestPracticeAdvisory, F as FallbackReason, m as CallAttempt } from './ir-DubC20e3.mjs';
2
2
 
3
3
  /**
4
4
  * Glass-Box observability types (alpha.17).
@@ -1,4 +1,4 @@
1
- import { p as MutationApplied, B as BestPracticeAdvisory, F as FallbackReason, l as CallAttempt } from './ir-BIAT9gJk.js';
1
+ import { q as MutationApplied, B as BestPracticeAdvisory, F as FallbackReason, m as CallAttempt } from './ir-GnYPkpGo.js';
2
2
 
3
3
  /**
4
4
  * Glass-Box observability types (alpha.17).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warmdrift/kgauto-compiler",
3
- "version": "2.0.0-alpha.31",
3
+ "version": "2.0.0-alpha.33",
4
4
  "description": "Prompt compiler + central learning brain for multi-model AI apps. Swap models without rewriting prompts.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",