@warmdrift/kgauto-compiler 2.0.0-alpha.6 → 2.0.0-alpha.61

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 (50) hide show
  1. package/README.md +158 -46
  2. package/dist/brain-proxy.d.mts +113 -0
  3. package/dist/brain-proxy.d.ts +113 -0
  4. package/dist/brain-proxy.js +189 -0
  5. package/dist/brain-proxy.mjs +6 -0
  6. package/dist/chunk-3RMLZCUK.mjs +190 -0
  7. package/dist/chunk-IIMPJZNH.mjs +694 -0
  8. package/dist/chunk-IUWFML6Z.mjs +165 -0
  9. package/dist/chunk-NBO4R5PC.mjs +313 -0
  10. package/dist/chunk-P3TOAEG4.mjs +56 -0
  11. package/dist/chunk-QKXTMVCT.mjs +1470 -0
  12. package/dist/chunk-RO22VFIF.mjs +29 -0
  13. package/dist/glassbox/index.d.mts +59 -0
  14. package/dist/glassbox/index.d.ts +59 -0
  15. package/dist/glassbox/index.js +312 -0
  16. package/dist/glassbox/index.mjs +12 -0
  17. package/dist/glassbox-routes/format.d.mts +24 -0
  18. package/dist/glassbox-routes/format.d.ts +24 -0
  19. package/dist/glassbox-routes/format.js +86 -0
  20. package/dist/glassbox-routes/format.mjs +18 -0
  21. package/dist/glassbox-routes/index.d.mts +191 -0
  22. package/dist/glassbox-routes/index.d.ts +191 -0
  23. package/dist/glassbox-routes/index.js +2714 -0
  24. package/dist/glassbox-routes/index.mjs +663 -0
  25. package/dist/glassbox-routes/react/index.d.mts +74 -0
  26. package/dist/glassbox-routes/react/index.d.ts +74 -0
  27. package/dist/glassbox-routes/react/index.js +819 -0
  28. package/dist/glassbox-routes/react/index.mjs +754 -0
  29. package/dist/index.d.mts +2236 -17
  30. package/dist/index.d.ts +2236 -17
  31. package/dist/index.js +7402 -1596
  32. package/dist/index.mjs +3580 -164
  33. package/dist/ir-DAKlQsVb.d.mts +1386 -0
  34. package/dist/ir-DmUuJsWc.d.ts +1386 -0
  35. package/dist/key-health.d.mts +131 -0
  36. package/dist/key-health.d.ts +131 -0
  37. package/dist/key-health.js +215 -0
  38. package/dist/key-health.mjs +6 -0
  39. package/dist/profiles.d.mts +292 -2
  40. package/dist/profiles.d.ts +292 -2
  41. package/dist/profiles.js +1081 -16
  42. package/dist/profiles.mjs +9 -1
  43. package/dist/types-B8X1Pyhx.d.ts +149 -0
  44. package/dist/types-CssWqd0X.d.mts +131 -0
  45. package/dist/types-DR62iPcO.d.ts +131 -0
  46. package/dist/types-MRMBUqzY.d.mts +149 -0
  47. package/package.json +54 -8
  48. package/dist/chunk-MBEI5UOM.mjs +0 -409
  49. package/dist/profiles-CQnLkQ7b.d.ts +0 -611
  50. package/dist/profiles-zm6diETo.d.mts +0 -611
@@ -0,0 +1,1386 @@
1
+ import { IntentArchetypeName } from './dialect.js';
2
+
3
+ /**
4
+ * Intermediate Representation — the structured form of a prompt.
5
+ *
6
+ * Everything kgauto v2 does, it does on the IR. The IR is constructed by the
7
+ * caller (or by `parse()` from a string-style prompt for backwards-compat),
8
+ * transformed by the compiler passes, and lowered to a target-specific wire
9
+ * request only at the very end.
10
+ *
11
+ * The IR carries STRUCTURE, not just text. Sections are first-class. Tools
12
+ * carry per-intent relevance. History knows its turn-age. Constraints are
13
+ * explicit. This is what lets passes do real work.
14
+ */
15
+
16
+ /**
17
+ * A semantically-named section of the system prompt. Sections enable
18
+ * intent-aware slicing (drop sections not tagged for this intent), dedupe
19
+ * (collapse identical sections across files), and cache marking (identify
20
+ * the stable prefix).
21
+ */
22
+ interface PromptSection {
23
+ /** Stable identifier — used for slicing, dedupe, and cache markers. */
24
+ id: string;
25
+ /** Section text. */
26
+ text: string;
27
+ /**
28
+ * Which intents this section applies to. Empty = applies to all intents.
29
+ * Pass `compile()` will drop sections whose intents array doesn't include
30
+ * the current intent.
31
+ */
32
+ intents?: IntentArchetypeName[];
33
+ /**
34
+ * If true, this section is part of the stable cacheable prefix. The lower
35
+ * pass uses this to place cache markers correctly per target.
36
+ */
37
+ cacheable?: boolean;
38
+ /**
39
+ * Section weight when ordering — lower = earlier in the assembled prompt.
40
+ * Defaults to insertion order.
41
+ */
42
+ weight?: number;
43
+ /**
44
+ * alpha.29+ — declares the section's semantic kind so kgauto can apply
45
+ * model-aware rewrites at compile time. Default `'arbitrary'` (when
46
+ * unset) for full back-compat — pre-alpha.29 sections continue working
47
+ * unchanged.
48
+ *
49
+ * alpha.29 ships rewrites for `tool_call_contract` only. Other kinds are
50
+ * type-accepted but pass through. alpha.30+ will add rewrites for
51
+ * `narration_contract`, `role_intro`, etc.
52
+ *
53
+ * See `translator.ts` for the rewrite engine that consumes this field.
54
+ */
55
+ kind?: SectionKind;
56
+ }
57
+ /**
58
+ * alpha.29+ — semantic kind tag for a `PromptSection`. The translator
59
+ * (`v2/src/translator.ts`) consumes this to apply model-aware rewrites at
60
+ * compile time. CLOSED union; future kinds extend it explicitly in named
61
+ * alpha releases.
62
+ *
63
+ * alpha.29 ships rewrites for `tool_call_contract` only. Other kinds are
64
+ * type-accepted but pass through.
65
+ *
66
+ * - `role_intro` — "You are a helpful assistant", persona blocks
67
+ * - `tool_call_contract` — tool-use rules ("call X then Y"); the alpha.29
68
+ * translator rewrites this for models with a
69
+ * sequential-tool cliff on the active archetype
70
+ * - `narration_contract` — output-format rules ("don't narrate your steps");
71
+ * alpha.30+ candidate
72
+ * - `user_turn` — when sections carry user content rather than
73
+ * system context (rare)
74
+ * - `reference` — supporting reference data the model may consult
75
+ * - `arbitrary` — explicit pass-through (default when unset)
76
+ */
77
+ type SectionKind = 'role_intro' | 'tool_call_contract' | 'narration_contract' | 'user_turn' | 'reference' | 'arbitrary';
78
+ interface ToolDefinition {
79
+ name: string;
80
+ description?: string;
81
+ parameters?: Record<string, unknown>;
82
+ /**
83
+ * Per-intent relevance scores. Compile uses these to drop irrelevant tools.
84
+ * Missing intents default to 0.5 (neutral).
85
+ */
86
+ relevanceByIntent?: Partial<Record<IntentArchetypeName, number>>;
87
+ /** Pass-through for provider-specific fields (Anthropic input_schema, etc.). */
88
+ [key: string]: unknown;
89
+ }
90
+ interface Message {
91
+ role: 'system' | 'user' | 'assistant' | 'tool';
92
+ content: string;
93
+ /** Optional structured parts (tool calls, results) — passed through to lowering. */
94
+ parts?: unknown[];
95
+ /** For tool messages — which tool this corresponds to. */
96
+ toolName?: string;
97
+ /** For tool messages — the call id. */
98
+ toolCallId?: string;
99
+ }
100
+ /**
101
+ * The compile-time intent declaration. `name` is the app's local label;
102
+ * `archetype` is the canonical dialect-v1 archetype the app maps it to.
103
+ *
104
+ * Apps with their own intent vocabulary (tt-intelligence's "ask"/"hunt"/
105
+ * "dashboard") declare the mapping here. The brain learns by archetype, not
106
+ * by app-local name.
107
+ */
108
+ interface IntentDeclaration {
109
+ /** App-local intent name (free-form, for app's own debugging). */
110
+ name: string;
111
+ /** Canonical dialect-v1 archetype. Required for cross-app learning. */
112
+ archetype: IntentArchetypeName;
113
+ }
114
+ /**
115
+ * alpha.57 — dialect-level reasoning-effort tier (data-first).
116
+ *
117
+ * Vocabulary is a portfolio-level tier ladder (low → max), NOT any provider's
118
+ * wire value — mapping to `reasoning_effort` (OpenAI) / thinking budgets
119
+ * (Anthropic) / `thinkingConfig` (Gemini) stays consumer-side until
120
+ * routing-on-effort ships. Declaring it records the tier on the brain row
121
+ * (`compile_outcomes.effort`, migration 033) so effort×archetype quality
122
+ * evidence accumulates BEFORE any routing logic exists — same data-first
123
+ * sequencing as `tool_orchestration` (alpha.20).
124
+ */
125
+ type EffortLevel = 'low' | 'medium' | 'high' | 'xhigh' | 'max';
126
+ interface Constraints {
127
+ /** Hard latency ceiling — compiler will down-rank slow models. Advisory. */
128
+ maxLatencyMs?: number;
129
+ /** Hard cost ceiling per call (USD). Advisory. */
130
+ maxCostUsd?: number;
131
+ /**
132
+ * alpha.57 (data-first): the reasoning-effort tier the consumer ran (or
133
+ * intends to run) this call at. RECORDED, NOT APPLIED — the compiler does
134
+ * not emit provider thinking/effort params from this field and does not
135
+ * route on it yet; it flows to `compile_outcomes.effort` via record()'s
136
+ * registry auto-enrich (same pattern as `mutationsApplied`/advisories).
137
+ * Declare it truthfully: this is consumer-reported ground truth, like
138
+ * `tokensIn`/`latencyMs`. Does NOT enter the shape key (no learning-key
139
+ * fragmentation).
140
+ */
141
+ effort?: EffortLevel;
142
+ /** Caller wants structured (JSON) output. */
143
+ structuredOutput?: boolean;
144
+ /** Hint: caller expects a short response (used to disable thinking on Gemini). */
145
+ expectedShortOutput?: boolean;
146
+ /** Hint: max response words. */
147
+ maxResponseWords?: number;
148
+ /** Override target model selection — if set, compiler uses this instead of routing. */
149
+ forceModel?: string;
150
+ /**
151
+ * alpha.20: consumer-declared tool-orchestration shape for this call.
152
+ * - 'parallel': model may fire multiple tool calls per step (current
153
+ * default behavior; the L-040 cliff applies — DeepSeek's
154
+ * `tool_count >= 1` cliff trims tools because parallel-tool throughput
155
+ * collapses to sequential semantics).
156
+ * - 'sequential': consumer commits to one tool call per step (the agentic
157
+ * loop pattern). DeepSeek V4-Flash + V4-Pro can compete cleanly in
158
+ * this mode — the L-040 cliff is silenced and the hunt chain shifts
159
+ * to a DeepSeek-tier-1 ordering.
160
+ * - 'either': consumer doesn't care; library picks the parallel chain
161
+ * (status-quo default) and may upgrade to brain-driven per-mode perf
162
+ * selection in a future release.
163
+ *
164
+ * Affects:
165
+ * - Chain composition for `archetype: 'hunt'` (see
166
+ * `getDefaultFallbackChain` and `STARTER_CHAINS_BY_MODE`).
167
+ * - L-040 cliff in `passApplyCliffs` (silent when 'sequential').
168
+ *
169
+ * Default (when undefined): equivalent to 'parallel' for back-compat
170
+ * with every pre-alpha.20 caller.
171
+ */
172
+ toolOrchestration?: 'parallel' | 'sequential' | 'either';
173
+ }
174
+ /**
175
+ * Cache marker policy for the messages array (history + currentTurn).
176
+ *
177
+ * Anthropic positional caching: a `cache_control` marker on a content block
178
+ * tells the API "remember the prefix up through this block." On a subsequent
179
+ * request whose first N tokens match, those N billed at the cached rate
180
+ * (10% of the input price). Without a marker, every call re-pays for the
181
+ * entire history.
182
+ *
183
+ * - `'none'` (default when omitted): no history cache marker. System-level
184
+ * cache markers from `PromptSection.cacheable=true` still apply.
185
+ * - `'all-but-latest'`: marks the message immediately preceding `currentTurn`
186
+ * (the last history entry). On the next call, that entire history prefix
187
+ * is cacheable. Good fit for chat/agent loops where every prior turn is
188
+ * stable.
189
+ * - `'fixed-suffix'`: marks the message `suffix` positions from the end of
190
+ * `history`. Use when the last few turns are volatile (e.g., scratchpad,
191
+ * draft revisions) but the earlier prefix is stable.
192
+ *
193
+ * For non-Anthropic providers, no wire-format marker is emitted (Gemini /
194
+ * OpenAI / DeepSeek implicit caching takes effect automatically when a
195
+ * stable prefix is reused). The compiler still computes
196
+ * `diagnostics.historyCacheableTokens` for telemetry on every provider.
197
+ *
198
+ * alpha.5.
199
+ */
200
+ type HistoryCachePolicy = {
201
+ strategy: 'none';
202
+ } | {
203
+ strategy: 'all-but-latest';
204
+ } | {
205
+ strategy: 'fixed-suffix';
206
+ suffix: number;
207
+ };
208
+ /**
209
+ * Consumer-declared policy for model selection. Lives outside the IR
210
+ * (passed via CompileOptions) because it's a SESSION/APP-level constraint,
211
+ * not a per-call shape.
212
+ *
213
+ * The original tt-intelligence scenario (s11): user capped Anthropic
214
+ * spending on Sonnet for cost reasons. v2 compile() kept picking Sonnet
215
+ * as the best target, Hunter's preflight hit the cap and fell back to
216
+ * Flash — every single call. CompilePolicy.blockedModels lets the
217
+ * consumer tell kgauto "don't pick Sonnet right now" and the compiler
218
+ * routes to the next-best option directly. No wasted preflight tax.
219
+ *
220
+ * This is the "coach knows the constraints" feature — kgauto stops
221
+ * recommending things the consumer has already ruled out.
222
+ */
223
+ interface CompilePolicy {
224
+ /**
225
+ * Model IDs the consumer has gated. Compile() will never select these.
226
+ * Use for: cost caps, account-level rate limits, "this model is broken
227
+ * for our workload" decisions.
228
+ */
229
+ blockedModels?: string[];
230
+ /**
231
+ * Hard ceiling on estimated input cost per call (USD). Models whose
232
+ * estimated cost exceeds this are rejected. Use for: budget enforcement
233
+ * on high-volume routes.
234
+ */
235
+ maxCostPerCallUsd?: number;
236
+ /**
237
+ * Model IDs the consumer prefers. When multiple models fit, preferred
238
+ * models get a rank boost (large enough to overcome small quality
239
+ * differences but not large enough to override hard rejects).
240
+ */
241
+ preferredModels?: string[];
242
+ /**
243
+ * Customer-posture tag (master plan §1.2, alpha.9).
244
+ *
245
+ * - `'locked'` — compliance/contract/brand-promise. Caller passes
246
+ * exactly one model; no fallback is desired. kgauto
247
+ * never walks the chain.
248
+ * - `'preferred'` — user-selected primary, fallback chain as safety
249
+ * net. On 429/5xx, walk the chain and surface
250
+ * `fellOverFrom` so the consumer can show "Claude
251
+ * was busy; we used Pro for this answer."
252
+ * - `'open'` — library picks the chain. Model identity is
253
+ * irrelevant; output is the contract.
254
+ *
255
+ * The field is **informational** — kgauto's execution path is already
256
+ * determined by the shape of `ir.models`. Posture surfaces in
257
+ * telemetry so the cost-watcher can distinguish "locked failed, no
258
+ * fallback was tried" from "open chain exhausted." Default: when
259
+ * `ir.models.length === 1` posture is treated as `'locked'` by the
260
+ * advisor; otherwise unspecified.
261
+ */
262
+ posture?: 'locked' | 'preferred' | 'open';
263
+ }
264
+ /**
265
+ * alpha.41 — entry in `PromptIR.models[]`. Either a literal model id (the
266
+ * pre-alpha.41 shape, fully preserved) or a `{ family: string }` alias that
267
+ * resolves at compile() time to the latest-current model in that family.
268
+ *
269
+ * Family entries resolve via `resolveFamilyEntry` (internal twin of the
270
+ * public `getRecommendedPrimary`). Resolution fails CLOSED — a family that
271
+ * matches no current+active candidate throws `FamilyResolutionError` at
272
+ * compile time. Consumers who want a literal fallback should call
273
+ * `getRecommendedPrimary({ family, fallback, ... })` at IR-construction time
274
+ * and inline the resolved id, rather than passing `{ family }` into the IR.
275
+ *
276
+ * Family taxonomy is defined in `family-resolution.ts`; see also migration
277
+ * 024 (`kgauto_models.family` column + index).
278
+ */
279
+ type ChainModelEntry = string | {
280
+ family: string;
281
+ };
282
+ /**
283
+ * The IR — the input to compile().
284
+ */
285
+ interface PromptIR {
286
+ /** App identifier — required for multi-tenant brain. */
287
+ appId: string;
288
+ /** Intent declaration — what is this call doing? */
289
+ intent: IntentDeclaration;
290
+ /** Structured system prompt sections. */
291
+ sections: PromptSection[];
292
+ /** Available tools (compiler may drop based on intent relevance + budget). */
293
+ tools?: ToolDefinition[];
294
+ /** Conversation history (compiler may compress old turns). */
295
+ history?: Message[];
296
+ /** The user's current turn — never dropped. */
297
+ currentTurn?: Message;
298
+ /**
299
+ * Allowed model IDs (or family aliases — alpha.41+), in caller-preference
300
+ * order. Compiler resolves family entries to literal ids before scoring
301
+ * and picks among them. See {@link ChainModelEntry}.
302
+ *
303
+ * Internal passes downstream of compile()'s family-resolution step
304
+ * receive a narrowed `string[]` shape — `string` is a subtype of
305
+ * `ChainModelEntry`, so a `string[]` IS a `ChainModelEntry[]` at the
306
+ * type level. Code that needs to access string ids (passes.ts) reads
307
+ * via `getModelIds(ir)` from `models-runtime.ts` rather than narrowing
308
+ * inline.
309
+ */
310
+ models: ChainModelEntry[];
311
+ /** Compile constraints. */
312
+ constraints?: Constraints;
313
+ /**
314
+ * Cache marker placement policy for the messages array. Default = no
315
+ * history cache markers. See `HistoryCachePolicy` for semantics.
316
+ * alpha.5.
317
+ */
318
+ historyCachePolicy?: HistoryCachePolicy;
319
+ }
320
+ type Provider = 'anthropic' | 'google' | 'openai' | 'deepseek' | 'mistral' | 'xai';
321
+ /**
322
+ * Mutation IDs that fired during compile. Empty in v1 (no mutation engine
323
+ * yet). Populated when the brain is online and pushing mutations.
324
+ */
325
+ type MutationApplied = {
326
+ id: string;
327
+ source: string;
328
+ passName: string;
329
+ description: string;
330
+ };
331
+ /**
332
+ * Target-specific wire request. Shape varies by provider — caller passes the
333
+ * right field to the right SDK.
334
+ */
335
+ type CompiledRequest = {
336
+ provider: 'anthropic';
337
+ model: string;
338
+ system: Array<{
339
+ type: 'text';
340
+ text: string;
341
+ cache_control?: {
342
+ type: 'ephemeral';
343
+ };
344
+ }>;
345
+ messages: Array<{
346
+ role: string;
347
+ content: unknown;
348
+ }>;
349
+ tools?: unknown[];
350
+ max_tokens?: number;
351
+ /**
352
+ * alpha.29 — emitted only when the translator's wire-overrides set
353
+ * `parallelToolCalls = false`. Shape per Anthropic Messages API docs:
354
+ * `{ type: 'auto', disable_parallel_tool_use: true }`. kgauto defaults
355
+ * to omitting `tool_choice` entirely (Anthropic defaults to auto + parallel),
356
+ * so this field's presence signals an explicit override.
357
+ */
358
+ tool_choice?: {
359
+ type: 'auto' | 'any' | 'tool' | 'none';
360
+ disable_parallel_tool_use?: boolean;
361
+ name?: string;
362
+ };
363
+ } | {
364
+ provider: 'google';
365
+ model: string;
366
+ systemInstruction?: {
367
+ role: 'system';
368
+ parts: Array<{
369
+ text: string;
370
+ }>;
371
+ };
372
+ contents: Array<{
373
+ role: string;
374
+ parts: unknown[];
375
+ }>;
376
+ tools?: unknown[];
377
+ generationConfig?: Record<string, unknown>;
378
+ cachedContent?: string;
379
+ } | {
380
+ provider: 'openai';
381
+ model: string;
382
+ messages: Array<{
383
+ role: string;
384
+ content: unknown;
385
+ }>;
386
+ tools?: unknown[];
387
+ response_format?: unknown;
388
+ reasoning_effort?: string;
389
+ /**
390
+ * alpha.29 — emitted only when the translator's wire-overrides set
391
+ * `parallelToolCalls = false`. OpenAI defaults parallel_tool_calls=true
392
+ * server-side; we explicit-set to false only when overriding.
393
+ */
394
+ parallel_tool_calls?: boolean;
395
+ } | {
396
+ provider: 'deepseek';
397
+ model: string;
398
+ messages: Array<{
399
+ role: string;
400
+ content: unknown;
401
+ }>;
402
+ tools?: unknown[];
403
+ };
404
+ /**
405
+ * Best-practice advisory emitted by the compiler at compile time. Non-fatal —
406
+ * consumers log, surface in dev tools, gate on `level === 'critical'` in CI,
407
+ * or ignore. The advisor inspects the IR + selected profile + diagnostics
408
+ * and emits one entry per detected gap.
409
+ *
410
+ * Codes are stable across releases. `suggestion` and `docsUrl` are optional
411
+ * but encouraged: suggestion = the actionable diff; docsUrl = the
412
+ * interfaces/kgauto.md anchor for context.
413
+ *
414
+ * alpha.6 Phase 1 starter rules:
415
+ * - `caching-off-on-claude` (warn) system >2000 chars on Anthropic, no cacheable=true
416
+ * - `single-chunk-system` (info) Anthropic, only one PromptSection >1000 chars
417
+ * - `tool-bloat` (warn) >10 tools on a short-output archetype
418
+ * - `history-uncached-on-claude` (warn) Anthropic, ≥2 history messages, no historyCachePolicy
419
+ *
420
+ * Phase 2 (catalog as `bestPractices` block in profiles) and Phase 3 (brain
421
+ * telemetry on `advisories_fired`) are alpha.7+ territory.
422
+ */
423
+ interface BestPracticeAdvisory {
424
+ /**
425
+ * Severity. `info` = informational; `warn` = behavioral pattern that's
426
+ * usually expensive or wrong; `critical` = likely bug or production-grade
427
+ * misuse. Phase 1 ships info + warn only.
428
+ */
429
+ level: 'info' | 'warn' | 'critical';
430
+ /** Stable kebab-case code. Consumers filter / gate by this. */
431
+ code: string;
432
+ /** Human-readable explanation of what was detected. */
433
+ message: string;
434
+ /** Optional: how to fix — actionable diff or pattern. */
435
+ suggestion?: string;
436
+ /** Optional: link to docs anchor for more context. */
437
+ docsUrl?: string;
438
+ /**
439
+ * alpha.20 — actionable category for routing/dashboard surfacing. When set,
440
+ * the brain persists this as `recommendation_type` on
441
+ * `compile_outcome_advisories` so consumers can filter "show me all
442
+ * client-side issues that are caching-fix recommendations." Optional;
443
+ * absent on legacy or uncategorized rules.
444
+ *
445
+ * - `'model-swap'` — swap to a different model fixes this
446
+ * - `'prompt-fix'` — restructure prompt (sections, tools, format)
447
+ * - `'caching-fix'` — add cache markers (system or history)
448
+ * - `'no-ai-needed'` — the call shouldn't be using an AI model
449
+ * - `'tier-down'` — current model is overkill for this archetype
450
+ * - `'architecture-change'` — the issue isn't fixable at the kgauto layer
451
+ */
452
+ recommendationType?: 'model-swap' | 'prompt-fix' | 'caching-fix' | 'no-ai-needed' | 'tier-down' | 'architecture-change';
453
+ /**
454
+ * alpha.36 — architectural recommendation when the call shouldn't be an
455
+ * AI call at all, or should be a cheaper non-AI substitute. Optional and
456
+ * orthogonal to {@link recommendationType}: when set, narrows the
457
+ * `no-ai-needed` / `architecture-change` rec-type into an actionable
458
+ * pattern the consumer can implement.
459
+ *
460
+ * - `'lookup-table'` — deterministic input → output mapping (≥95% agreement at high N). Build a domain table; fall back to AI for novel inputs.
461
+ * - `'memoization-cache'` — same canonical input recurs across sessions with equivalent output. Add an edge/KV cache keyed on canonical input.
462
+ * - `'tier-down'` — cheaper model tier delivers equal-or-better oracle score on this shape. Move primary to the cheaper tier.
463
+ * - `'deterministic-parser'` — `constraints.structuredOutput: true` calls where the schema is regex/JSON-extractable from the input.
464
+ * - `'precompute'` — input is derivable at build / cron / batch time; eliminate the per-request call entirely.
465
+ *
466
+ * Operator-side detection lives in `v2/scripts/no-ai-needed-detector.mjs`
467
+ * (alpha.36); a compile-time advisor rule that consumes the brain-side
468
+ * findings cache follows in a later alpha. Today populated only by the
469
+ * operator-side detector + the brain RPC `get_no_ai_needed_candidates`
470
+ * (migration 021).
471
+ */
472
+ recommendedArchitecture?: 'lookup-table' | 'memoization-cache' | 'tier-down' | 'deterministic-parser' | 'precompute';
473
+ /**
474
+ * alpha.28 — when a rule wants to surface a specific structural adaptation
475
+ * (not just a swap or a prompt fix), it attaches the adapter shape here.
476
+ * Shape is the canonical {@link Adapter} discriminated union defined in
477
+ * this module; `compatibility.ts` re-exports it so
478
+ * `getModelCompatibility()` and `BestPracticeAdvisory.suggestedAdaptation`
479
+ * share one source of truth.
480
+ *
481
+ * Today fired by `archetype-perf-floor-breach` (alpha.28) when a
482
+ * documented adapter exists for the chosen model's archetype cliff.
483
+ * Absent on rules without a structural adapter (caching-off-on-claude,
484
+ * tool-bloat, etc.) and on the `reject` branch of
485
+ * `archetype-perf-floor-breach` where no adapter would help.
486
+ *
487
+ * CLOSED discriminated union (R3 from consultation doc) — future adapter
488
+ * parameters extend the union in `compatibility.ts` in named alpha
489
+ * releases. No `| string` escape hatch; consumer code can write
490
+ * exhaustive `switch (suggestedAdaptation.parameter)`.
491
+ *
492
+ * Phase 2 cross-builder coherence: Builder A's
493
+ * `AdvisoryRecord.suggestedAdaptation` (in `glassbox-routes/types.ts`)
494
+ * MUST type to the same union. Phase 2 integration verifies.
495
+ */
496
+ suggestedAdaptation?: Adapter;
497
+ /**
498
+ * alpha.42 — the kgauto request handle that produced this advisory. Stamped
499
+ * by `compile()` after `runAdvisor()` returns, sourced from
500
+ * `CompileResult.handle`. Lets a consumer's admin UI pivot from advisory
501
+ * row → original trace (Glass-Box card, brain `compile_outcomes` lookup).
502
+ *
503
+ * Absent when the advisory was constructed outside the full `compile()`
504
+ * pipeline (e.g., a direct `runAdvisor()` call in tests). Always present
505
+ * on advisories returned from `compile().advisories`.
506
+ */
507
+ kgautoRequestId?: string;
508
+ /**
509
+ * alpha.42 — who is positioned to act on this advisory.
510
+ *
511
+ * - `'consumer-actionable'` (Class A): the consumer can fix this by
512
+ * changing their wire-up — add `cacheable: true` markers, swap their
513
+ * model literal, declare a section, etc. The admin UI should surface
514
+ * a one-click apply or a "fix it" CTA.
515
+ * - `'producer-owned'` (Class B): kgauto needs to ship a code or data
516
+ * change — update a profile, promote a model in the chain, fix a
517
+ * wire contract. The admin UI should surface this as informational
518
+ * ("kgauto is on it") and not present a consumer-side action.
519
+ *
520
+ * Stamped by `compile()` after `runAdvisor()` returns. Rules can self-
521
+ * declare via the matching field on their return; otherwise the stamp
522
+ * consults the static `PRODUCER_OWNED_RULE_CODES` set in `advisor.ts`,
523
+ * defaulting to `'consumer-actionable'` when the code isn't listed.
524
+ *
525
+ * Closes the s47 dogfood gap where the tt-intel admin UI conflated the
526
+ * two classes — consumers couldn't tell whether they should act or wait.
527
+ */
528
+ ownership?: 'consumer-actionable' | 'producer-owned';
529
+ }
530
+ /**
531
+ * alpha.28 — adapter shape attached to advisories and returned by
532
+ * `getModelCompatibility()`. A CLOSED discriminated union: future adapter
533
+ * parameters extend it explicitly in named alpha releases. NO `| string`
534
+ * escape hatch — consumer policy code SHOULD write exhaustive
535
+ * `switch (adapter.parameter)` and rely on the compiler to flag
536
+ * "I added a new adapter parameter and forgot to update consumer policy."
537
+ *
538
+ * Defined here (in `ir.ts`, the foundational types module) and re-exported
539
+ * from `compatibility.ts` for ergonomic consumer imports. Anchoring it
540
+ * here avoids the import cycle that would form if both files tried to be
541
+ * the source of truth (ir.ts → compatibility.ts → profiles.ts → ir.ts).
542
+ *
543
+ * alpha.28 variants:
544
+ * - `{ parameter: 'toolOrchestration'; value: 'sequential'; consequence }`
545
+ * Lifts DeepSeek V4-family on `hunt` from the sequential-tool cliff
546
+ * (L-040). `consequence` is consumer-renderable plain English.
547
+ *
548
+ * Future alpha releases will add e.g. `parallelToolCalls`, `maxTools`,
549
+ * `thinkingBudget` (per tt-intel-Cairn priority list).
550
+ */
551
+ type Adapter = {
552
+ parameter: 'toolOrchestration';
553
+ value: 'sequential';
554
+ consequence: string;
555
+ };
556
+ /**
557
+ * alpha.29+ — record of a single section rewrite fired by the translator at
558
+ * compile time. Surfaces on `CompileResult.sectionRewritesApplied` and (in
559
+ * scrubbed wire form, without original/transformed text) on
560
+ * `TraceDetail.sectionRewritesApplied` for Glass-Box Coaching-card rendering.
561
+ *
562
+ * `originalText` / `transformedText` stay package-internal — they may carry
563
+ * consumer PII. The wire-shape variant (`TraceSectionRewrite` in
564
+ * `glassbox-routes/types.ts`) carries only `summary` for renderer use.
565
+ */
566
+ interface SectionRewrite {
567
+ /** Stable id of the `PromptSection` that was rewritten. */
568
+ sectionId: string;
569
+ /** The `kind` discriminator that matched the rewrite rule. */
570
+ kind: SectionKind;
571
+ /**
572
+ * Stable identifier of the rule that fired (e.g.
573
+ * `'sequential-tool-cliff-below-floor'`). Future rules add named ids; the
574
+ * brain aggregates by this value for cross-app learning.
575
+ */
576
+ rule: string;
577
+ /** The section's text BEFORE the rewrite fired. */
578
+ originalText: string;
579
+ /** The text the translator emitted into the IR for this section. */
580
+ transformedText: string;
581
+ /**
582
+ * Wire-level overrides emitted alongside the text rewrite. Merged into
583
+ * `CompileResult.wireOverrides` by `applySectionRewrites`. alpha.29 ships
584
+ * `parallelToolCalls`; the union extends as more wire-overrides surface.
585
+ */
586
+ wireOverrides?: {
587
+ parallelToolCalls?: boolean;
588
+ };
589
+ }
590
+ interface CompileResult {
591
+ /** Unique handle for this call — pass to record() to correlate the outcome. */
592
+ handle: string;
593
+ /** Selected target model id. */
594
+ target: string;
595
+ /** Selected provider. */
596
+ provider: Provider;
597
+ /** The wire request — pass the appropriate fields to your SDK. */
598
+ request: CompiledRequest;
599
+ /** Estimated tokens (input). */
600
+ tokensIn: number;
601
+ /** Estimated cost in USD (input portion). */
602
+ estimatedCostUsd: number;
603
+ /** Mutations that fired during compile (informational). */
604
+ mutationsApplied: MutationApplied[];
605
+ /** Fallback chain — try these in order if target fails. */
606
+ fallbackChain: string[];
607
+ /**
608
+ * Best-practice advisories emitted by the compiler. Non-fatal. Empty
609
+ * array when no rules fired. alpha.6 Phase 1.
610
+ */
611
+ advisories: BestPracticeAdvisory[];
612
+ /**
613
+ * alpha.29+ — per-section rewrites applied by the translator at compile
614
+ * time. Empty array means no rewrites fired (or pre-alpha.29 behavior —
615
+ * all sections default `kind: 'arbitrary'`, which is pass-through).
616
+ *
617
+ * Surfaces to:
618
+ * - Glass-Box Coaching card (via `TraceDetail.sectionRewritesApplied`,
619
+ * scrubbed of original/transformed text)
620
+ * - brain `compile_outcomes.section_rewrites_applied` (migration 019)
621
+ * for cross-app learning
622
+ */
623
+ sectionRewritesApplied: SectionRewrite[];
624
+ /**
625
+ * alpha.29+ — wire-level overrides emitted by translator rewrites. The
626
+ * provider lowering pass threads these through to the wire request before
627
+ * emit. Today only `parallelToolCalls: boolean`; the type extends as more
628
+ * wire-overrides surface.
629
+ *
630
+ * Undefined when no rewrite emitted overrides — the common case.
631
+ */
632
+ wireOverrides?: {
633
+ parallelToolCalls?: boolean;
634
+ };
635
+ /** Diagnostics for caller-side logging. */
636
+ diagnostics: {
637
+ sectionsKept: number;
638
+ sectionsDropped: number;
639
+ toolsKept: number;
640
+ toolsDropped: number;
641
+ historyKept: number;
642
+ historyDropped: number;
643
+ cacheableTokens: number;
644
+ estimatedCacheSavingsUsd: number;
645
+ /**
646
+ * Tokens in `history` (and `currentTurn` when before the marker) that
647
+ * fall within the cacheable prefix per `historyCachePolicy`. Always
648
+ * computed; only Anthropic actually emits a wire-format marker. For
649
+ * Gemini / OpenAI / DeepSeek, this represents the theoretical cacheable
650
+ * prefix that implicit caching may pick up — useful telemetry for the
651
+ * brain to learn which (app, model, archetype) tuples benefit most
652
+ * from history caching. alpha.5.
653
+ */
654
+ historyCacheableTokens: number;
655
+ /**
656
+ * Total tokens in input `history` (pre-compression). Computed regardless
657
+ * of whether `passCompressHistory` fired — surfaces how close a tuple is
658
+ * to its `compressHistoryAboveTokens` threshold so dashboards / cost-
659
+ * watchers can see the bloat axis the count-based threshold misses.
660
+ * 0 when history is empty. alpha.7.
661
+ */
662
+ historyTokensTotal: number;
663
+ /**
664
+ * alpha.20 E3. Consumer-declared tool-orchestration mode for this call,
665
+ * mirrored from `ir.constraints.toolOrchestration` for downstream
666
+ * observability (Glass-Box panel, brain telemetry, advisor logs).
667
+ * Undefined when the consumer hadn't adopted the constraint yet —
668
+ * treat as 'parallel' equivalent for back-compat.
669
+ */
670
+ toolOrchestration?: 'parallel' | 'sequential' | 'either';
671
+ /**
672
+ * alpha.33. Zero-based index into the resolved (post-compression) history
673
+ * array at which Anthropic prompt-cache marker should land — i.e., the
674
+ * last message that belongs to the stable cacheable prefix. Consumers
675
+ * using AI-SDK's `streamText({ messages: convertToModelMessages(...) })`
676
+ * lose the per-message `providerOptions.anthropic.cacheControl` markers
677
+ * the compiler emits on `result.request.messages`, because
678
+ * `convertToModelMessages` reads raw input not the lowered output.
679
+ * This index gives the consumer a single deterministic position to
680
+ * attach `cacheControl: { type: 'ephemeral' }` after their own conversion.
681
+ *
682
+ * Computation:
683
+ * - `historyCachePolicy.strategy === 'all-but-latest'`: history.length - 1
684
+ * (or undefined if history is empty)
685
+ * - `historyCachePolicy.strategy === 'fixed-suffix'` with `suffix: N`:
686
+ * history.length - 1 - N (undefined if N exceeds history length)
687
+ * - `historyCachePolicy.strategy === 'none'` or omitted: undefined
688
+ *
689
+ * The companion helper `attachCacheControlToStreamTextInput()` reads
690
+ * this field + the consumer's converted messages to perform the per-
691
+ * attempt mutation correctly. Filed by IC + tt-intel cross-consumer
692
+ * pattern 2026-05-20 (`streamText-cache-marker-propagation-gap`).
693
+ */
694
+ historyCacheMarkIndex?: number;
695
+ /**
696
+ * alpha.33. Zero-based index into the structured `systemMessages` array
697
+ * (see top-level `systemMessages` field) at which the cacheable system
698
+ * prefix ends. Useful when the consumer is building a multi-block
699
+ * system parameter for Anthropic streamText — they can attach
700
+ * `providerOptions.anthropic.cacheControl` to `systemMessages[index]`.
701
+ *
702
+ * Undefined when no section had `cacheable: true` OR `systemMessages` is
703
+ * empty. Matches `historyCacheMarkIndex` semantics on the history axis.
704
+ */
705
+ systemCacheMarkIndex?: number;
706
+ /**
707
+ * alpha.43. Cliff-style warnings surfaced by the convention pass
708
+ * (`passApplyConventions`) when the selected profile + archetype carry
709
+ * a `cliffWarning` whose preconditions are met. These are informational
710
+ * — they describe a structural mismatch between the call's shape and
711
+ * the chosen family (e.g. "reasoner family is wrong for parallel-tool
712
+ * hunt") so consumers can route differently next time.
713
+ *
714
+ * Empty array when no convention fired or no warnings surfaced.
715
+ * Separate from `cliff_guard` mutations in `mutationsApplied` — those
716
+ * are profile.cliffs[] runtime triggers; these are convention-level
717
+ * advisory text. Both can fire on the same call.
718
+ */
719
+ cliffWarnings: string[];
720
+ };
721
+ /**
722
+ * alpha.33. Structured `system` for AI-SDK `streamText({ system })`
723
+ * consumers. When the consumer's lowered request has cacheable section
724
+ * markers, the flat `system: string` form loses the marker assignment
725
+ * (every `streamText({ system: '<string>' })` call silently strips
726
+ * providerOptions). Pass `systemMessages` instead to `streamText({
727
+ * system: result.systemMessages })` so the cacheable prefix is structurally
728
+ * preserved.
729
+ *
730
+ * Each entry is a `SystemModelMessage`-shaped object:
731
+ * { role: 'system', content: string, providerOptions?: { anthropic?:
732
+ * { cacheControl: { type: 'ephemeral' } } } }
733
+ *
734
+ * Provider-agnostic on emit: only Anthropic actually consumes the
735
+ * cacheControl block; Gemini / OpenAI / DeepSeek receive the same
736
+ * shape but ignore the marker (matching their implicit-caching semantics).
737
+ *
738
+ * Empty array when the IR carried zero sections (rare; usually means the
739
+ * compiler dropped everything for the chosen intent). Consumers can fall
740
+ * back to `result.systemMessages.length === 0 ? '' : result.systemMessages`
741
+ * or use the helper `attachCacheControlToStreamTextInput()` which handles
742
+ * both shapes.
743
+ */
744
+ systemMessages: SystemModelMessage[];
745
+ }
746
+ /**
747
+ * alpha.33. AI-SDK-compatible system-message shape carried on
748
+ * `CompileResult.systemMessages`. Matches the AI-SDK `streamText({ system })`
749
+ * structured form — consumers can pass these directly without conversion.
750
+ *
751
+ * The `providerOptions` field is set ONLY for entries that came from a
752
+ * section with `cacheable: true` AND the chosen provider is Anthropic AND
753
+ * the compiler computed a non-zero `cacheableTokens`. Other providers see
754
+ * `providerOptions: undefined` (or omitted entirely).
755
+ */
756
+ interface SystemModelMessage {
757
+ role: 'system';
758
+ content: string;
759
+ providerOptions?: {
760
+ anthropic?: {
761
+ cacheControl: {
762
+ type: 'ephemeral';
763
+ };
764
+ };
765
+ };
766
+ }
767
+ /**
768
+ * Token usage normalized across providers. `cached` and `cacheCreated` are
769
+ * Anthropic prompt-cache reads/writes (Gemini implicit caching populates
770
+ * `cached` from `usageMetadata.cachedContentTokenCount`; OpenAI populates
771
+ * from `prompt_tokens_details.cached_tokens`).
772
+ */
773
+ interface NormalizedTokens {
774
+ input: number;
775
+ output: number;
776
+ total: number;
777
+ cached?: number;
778
+ cacheCreated?: number;
779
+ }
780
+ /**
781
+ * Tool call in a provider-agnostic shape. Anthropic `tool_use` blocks,
782
+ * Google `functionCall` parts, and OpenAI/DeepSeek `tool_calls[]` all
783
+ * collapse to this.
784
+ */
785
+ interface ToolCall {
786
+ id: string;
787
+ name: string;
788
+ args: Record<string, unknown>;
789
+ }
790
+ interface NormalizedResponse {
791
+ /** Main text body. Empty string if response had no text content. */
792
+ text: string;
793
+ /**
794
+ * Parsed structured output. Populated when ir.constraints.structuredOutput
795
+ * is true and JSON.parse(text) succeeds. Null otherwise.
796
+ */
797
+ structuredOutput: unknown | null;
798
+ /** Tool calls in normalized shape. Empty array if none. */
799
+ toolCalls: ToolCall[];
800
+ tokens: NormalizedTokens;
801
+ /** Provider-specific finish reason, passed through unchanged. */
802
+ finishReason?: string;
803
+ /** Untouched provider response — escape hatch for consumers needing fields not yet normalized. */
804
+ raw: unknown;
805
+ /** Set when structuredOutput parsing was attempted and failed. */
806
+ parseError?: string;
807
+ }
808
+ interface ApiKeys {
809
+ anthropic?: string;
810
+ google?: string;
811
+ openai?: string;
812
+ deepseek?: string;
813
+ }
814
+ /**
815
+ * Per-provider override fields shallow-merged into the lowered request before
816
+ * execution. Lets consumers reach Gemini `safetySettings`, Anthropic
817
+ * `tool_choice`, OpenAI `seed` etc. without bypassing kgauto.
818
+ */
819
+ interface ProviderOverrides {
820
+ anthropic?: Record<string, unknown>;
821
+ google?: Record<string, unknown>;
822
+ openai?: Record<string, unknown>;
823
+ deepseek?: Record<string, unknown>;
824
+ }
825
+ /**
826
+ * Full-IR inline shadow-probe config (Shape B, Phase 1 — 2026-05-29 s51).
827
+ *
828
+ * When set on `call()`, after the primary response is served kgauto re-lowers
829
+ * the SAME in-memory PromptIR to each candidate and runs it, persisting a
830
+ * `probe_outcomes` row with `replay_source='inline-full-ir'` and
831
+ * `prompt_fidelity=1.0` — a fair, full-prompt measurement (vs the watchers'
832
+ * lossy `prompt_preview` replay). The probe NEVER blocks the user response and
833
+ * NEVER persists the raw prompt (system/context/payload) — only response
834
+ * previews + metadata, same policy the brain already holds.
835
+ *
836
+ * This is the trustworthy path that earns the right to a quality verdict;
837
+ * `prompt_preview` replay is retired for verdicts (see CLAUDE.md).
838
+ *
839
+ * Phase 1 enforces `sampleRate` and runs the candidate with `judge: 'off'`
840
+ * (responses stored for an offline batch judge). `judge: 'opus'` (inline
841
+ * verdict) and `maxPerDay` (per-tuple daily cap, needs a brain-count read)
842
+ * are accepted by the type but ENFORCED IN PHASE 2.
843
+ */
844
+ interface ShadowProbeConfig {
845
+ /** Model id(s) or family alias(es) to shadow-test against the served model, on the same IR. */
846
+ candidates: string | string[];
847
+ /** Probability [0,1] that any given call fires a probe. Default 0.05. */
848
+ sampleRate?: number;
849
+ /**
850
+ * 'off' (Phase 1 default): run candidate + store both responses for an
851
+ * offline batch judge. 'opus': judge candidate-vs-served inline (Phase 2).
852
+ */
853
+ judge?: 'opus' | 'off';
854
+ /** Per-(appId, archetype, candidate) daily cap. Phase 2 (needs brain-count read). Default 20. */
855
+ maxPerDay?: number;
856
+ /**
857
+ * alpha — latency budget (ms) for the probe leg. **Only enforced in sync mode**
858
+ * (`BrainConfig.sync === true`), where `call()` awaits the probe before returning
859
+ * the served response (PB-class Edge consumers, L-086) and the candidate's
860
+ * latency therefore lands on the user-facing critical path.
861
+ *
862
+ * The probe path races against this budget: if the candidate(s) don't finish
863
+ * within `maxLatencyMs`, the probe aborts, `call()` returns the already-served
864
+ * response immediately, and an `outcome='aborted_latency_budget'` row is
865
+ * recorded (no verdict, no false quality data). **The user is never delayed
866
+ * past the budget.** Default `15000`.
867
+ *
868
+ * No-op for fire-and-forget consumers (`sync` unset/false, and every
869
+ * `probeShadow()` caller fired from `after()`/`waitUntil()`) — they don't block
870
+ * the user, so there's no latency to bound. The probe runs to completion there.
871
+ *
872
+ * Root cause this closes (PB s57 dogfood incident, 2026-06-05): PB arms the
873
+ * probe inline with `sync:true` on a `maxDuration:120` analyze route; arming a
874
+ * `latency_tier='slow'` candidate (deepseek-v4-pro, ~78–84s) pushed total
875
+ * handler time past the frontend's patience and the served analysis came back
876
+ * empty. A sync probe had no latency budget — this field is the budget.
877
+ */
878
+ maxLatencyMs?: number;
879
+ /**
880
+ * alpha — when true (the default) **in sync mode**, skip a candidate whose
881
+ * registry `latency_tier === 'slow'` *before starting it*: a slow-tier model
882
+ * (e.g. deepseek-v4-pro / deepseek-v4-flash, both `slow` = ~24s+ p50) cannot
883
+ * fit a sane inline budget, so starting it just to abort it wastes a provider
884
+ * call. An `outcome='skipped_slow_tier_sync'` row is recorded so the offline
885
+ * rollup can see the skip (not a silent drop, not a false verdict). Fail-safe.
886
+ *
887
+ * **The deeper rule (slow-reasoner → offline-mode):** inline shadow-probing is
888
+ * for FAST candidates only. To evaluate a slow reasoner you need the offline /
889
+ * async probe path (the Phase-2 batch direction) which runs off the response
890
+ * entirely — never the inline sync probe. Set this `false` only if you've moved
891
+ * the budget high enough that a slow candidate genuinely fits (rare), or you're
892
+ * in a non-sync consumer where this flag is a no-op anyway.
893
+ *
894
+ * No-op for fire-and-forget consumers (`sync` unset/false; `probeShadow()`):
895
+ * there's no user latency to protect, so slow candidates run normally. Default
896
+ * `true`.
897
+ */
898
+ skipSlowTierInSync?: boolean;
899
+ }
900
+ interface CallOptions {
901
+ /** Forwarded to compile(). */
902
+ policy?: CompilePolicy;
903
+ /**
904
+ * alpha (s51 Phase 1) — full-IR inline shadow-probe. When set, kgauto
905
+ * measures the candidate(s) on the same IR after serving the primary,
906
+ * fire-and-forget. See {@link ShadowProbeConfig}.
907
+ */
908
+ shadowProbe?: ShadowProbeConfig;
909
+ toolRelevanceThreshold?: number;
910
+ compressHistoryAfter?: number;
911
+ /** Override API keys (defaults: process.env). */
912
+ apiKeys?: ApiKeys;
913
+ /** Provider-specific request fields shallow-merged into the lowered request. */
914
+ providerOverrides?: ProviderOverrides;
915
+ /** Override fetch (for tests). */
916
+ fetchImpl?: typeof fetch;
917
+ /** Disable retry/fallback walk on retryable errors. Default: enabled. */
918
+ noFallback?: boolean;
919
+ /**
920
+ * alpha.10. Disable the silent auto-filter of unreachable models from the
921
+ * fallback walk. Default: false (filter ON). Opt-out exists for tests +
922
+ * the rare consumer that wants the legacy "fail at execute() with auth
923
+ * error" behavior. When ON (default), models whose provider has no
924
+ * resolvable API key are dropped from `targetsToTry` before the first
925
+ * network call; if the chain empties entirely, throws CallError with
926
+ * `lastErrorCode = 'no_reachable_models'`.
927
+ *
928
+ * Reachability source: `apiKeys` (this CallOptions) + `process.env` (via
929
+ * `PROVIDER_ENV_KEYS`). Override env via env.ts's `ReachabilityOpts.envSource`
930
+ * is not exposed here — `call()` always uses process.env. Use
931
+ * `getDefaultFallbackChain({ reachability: { envSource } })` upstream
932
+ * for hermetic test runs.
933
+ */
934
+ noAutoFilter?: boolean;
935
+ /**
936
+ * alpha.34. When provided AND the chosen provider supports streaming
937
+ * (`profile.streaming === true`) AND `noStream` is not set, kgauto
938
+ * enables provider-native SSE streaming at the wire layer and invokes
939
+ * `onChunk(delta)` once per provider stream event. `delta` is the text
940
+ * since the previous `onChunk` call (NOT cumulative) — provider
941
+ * stream-shape headache normalized in kgauto's lowering layer.
942
+ *
943
+ * `CallResult.response.text` is still populated with the full assembled
944
+ * response — kgauto buffers internally regardless of the callback.
945
+ * Consumers can use either the streaming side-effect OR the final
946
+ * `response.text`, doesn't matter.
947
+ *
948
+ * Tool calls + finish reason + usage are collected from stream events
949
+ * and returned in the final `CallResult` exactly as the non-streaming
950
+ * path would shape them. Brain telemetry latency = time-to-stream-end.
951
+ *
952
+ * Chain-walk semantics: if the streaming target fails mid-stream
953
+ * (network error, retryable provider error), kgauto walks to the next
954
+ * fallback target and restarts streaming from its first chunk —
955
+ * `onChunk` fires fresh from the new target. Consumer detects via the
956
+ * post-call `CallResult.fellOverFrom`. To opt out of fallback for
957
+ * streaming, set `noFallback: true` alongside `onChunk`.
958
+ *
959
+ * Filed by playbacksam s42 (2026-05-22) as `streaming-output-callback-
960
+ * on-callresult` for ComposeDrawer SSE; perceived-latency UX win
961
+ * during 10-30s draft assembly.
962
+ */
963
+ onChunk?: (chunk: string) => void;
964
+ /**
965
+ * alpha.34. Explicit opt-out of streaming even when `onChunk` is
966
+ * provided. Default: false (streaming enabled when `onChunk` is set).
967
+ * Use when the consumer wants to pass `onChunk` conditionally without
968
+ * branching the call site (e.g., capture chunks for instrumentation
969
+ * without engaging streaming wire format).
970
+ */
971
+ noStream?: boolean;
972
+ }
973
+ interface CallAttempt {
974
+ model: string;
975
+ status: 'success' | 'retryable' | 'terminal';
976
+ errorCode?: string;
977
+ message?: string;
978
+ }
979
+ /**
980
+ * Why fallback fired. Normalized for `CallResult.fallbackReason` (alpha.9).
981
+ *
982
+ * - `rate_limit` provider returned 429
983
+ * - `provider_error` 5xx, network, or other retryable upstream issue
984
+ * - `cost_cap` preflight policy.maxCostPerCallUsd rejected target
985
+ * - `cliff` alpha.8 contract violation (MAX_TOKENS on
986
+ * structured output, parse-failed JSON)
987
+ * - `contract_violation` other compile-time-contract failures (reserved
988
+ * for alpha.10+ — e.g. mid-stream policy rejects)
989
+ * - `provider_auth_failed` alpha.14 — initial provider returned 401/403
990
+ * (upstream key revocation, malformed-but-truthy
991
+ * key, billing lapse). The chain walks to the
992
+ * next non-same-provider target instead of
993
+ * short-circuiting; same-provider remaining
994
+ * entries skip with errorCode='auth_inferred'.
995
+ */
996
+ type FallbackReason = 'rate_limit' | 'provider_error' | 'cost_cap' | 'cliff' | 'contract_violation' | 'provider_auth_failed';
997
+ interface CallResult {
998
+ /** Compile handle (still valid for record() if consumer wants to add oracle scores later). */
999
+ handle: string;
1000
+ /** The model that ACTUALLY served the response (post-fallback). */
1001
+ actualModel: string;
1002
+ /** What compile() originally targeted. */
1003
+ requestedModel: string;
1004
+ provider: Provider;
1005
+ response: NormalizedResponse;
1006
+ latencyMs: number;
1007
+ /** Mutations that fired during compile (informational, mirrors CompileResult.mutationsApplied). */
1008
+ mutationsApplied: MutationApplied[];
1009
+ /** One entry per provider attempt — observability for retry/fallback walks. */
1010
+ attempts: CallAttempt[];
1011
+ /**
1012
+ * Alpha.9 normalization of fallback-walk telemetry. When the chain
1013
+ * succeeded on the first attempt, these collapse to:
1014
+ * - `servedBy === requestedModel`
1015
+ * - `fellOverFrom` undefined
1016
+ * - `fallbackReason` undefined
1017
+ *
1018
+ * When fallback fired:
1019
+ * - `servedBy` = `actualModel` (the model that produced the response)
1020
+ * - `fellOverFrom` = `requestedModel` (what the caller / compile() asked for)
1021
+ * - `fallbackReason` = normalized cause derived from the first
1022
+ * non-success attempt's `errorCode`
1023
+ *
1024
+ * Consumer UX use: show "Claude was busy; we used Pro for this answer"
1025
+ * when `fellOverFrom` is set (master plan §3.6).
1026
+ */
1027
+ /** Model that actually answered. Equal to `actualModel`; kept distinct for clarity. */
1028
+ servedBy: string;
1029
+ /** Set only when fallback fired. Equal to `requestedModel` in that case. */
1030
+ fellOverFrom?: string;
1031
+ /** Set only when fallback fired. Normalized cause. */
1032
+ fallbackReason?: FallbackReason;
1033
+ /**
1034
+ * alpha.10. Models that auto-filter dropped from the fallback walk because
1035
+ * their provider had no reachable API key. Empty when nothing was filtered
1036
+ * (the common case once consumers have all the keys they need). Surfaces
1037
+ * silent self-heal so consumers can log/audit what happened without
1038
+ * defeating the "kgauto just gets" UX.
1039
+ *
1040
+ * Empty array (not undefined) when filter ran but dropped nothing —
1041
+ * distinguishes "filter ran cleanly" from "filter was disabled" (`undefined`
1042
+ * when `noAutoFilter: true`).
1043
+ */
1044
+ unreachableFiltered?: string[];
1045
+ /**
1046
+ * alpha.16. Models that policy.blockedModels filtering dropped from the
1047
+ * fallback walk. Defense-in-depth at the call() boundary — compile()'s
1048
+ * passScoreTargets already excludes blocked entries from the initial
1049
+ * target + fallbackChain, but if a consumer re-shapes the chain and
1050
+ * threads policy through only partially, this filter catches the gap.
1051
+ *
1052
+ * Resolves TT-40 follow-on `policy-block-not-enforced-on-fallback-chain`
1053
+ * (2026-05-15) where mutations_applied recorded the block intent but
1054
+ * the call walker landed on the blocked model anyway.
1055
+ *
1056
+ * Undefined when no filter ran (no blockedModels set). Populated only
1057
+ * when filter ran AND dropped at least one entry — empty drops are
1058
+ * stored as `undefined` to keep brain telemetry quiet on the common
1059
+ * case.
1060
+ */
1061
+ policyBlockedFiltered?: string[];
1062
+ /**
1063
+ * alpha.17. Unique identifier for this call() invocation, generated at
1064
+ * call() entry via crypto.randomUUID(). Returned on success and emitted
1065
+ * as the routing key for Glass-Box observability events
1066
+ * (compile.start, compile.done, execute.attempt, execute.success,
1067
+ * fallback.walked, advisory.fired). Pass the same id to
1068
+ * `subscribe(traceId)` from `@warmdrift/kgauto-compiler/glassbox` to
1069
+ * tap the in-flight event stream.
1070
+ *
1071
+ * Always present on success. Additive, non-breaking.
1072
+ */
1073
+ traceId: string;
1074
+ /**
1075
+ * alpha.44. Best-practice advisories emitted by the compile that actually
1076
+ * served the response (mirrors `CompileResult.advisories`; uses the SERVED
1077
+ * compile on fallback, same as `mutationsApplied`). Empty array when no
1078
+ * rules fired.
1079
+ *
1080
+ * Closes IC's `callForAgent` side-finding (2026-05-26): call() consumers
1081
+ * (agent paths — sweep / dyad / session-title) previously had no way to
1082
+ * `logAdvisories('[kgauto-v2 ...]', advisories)` like compile() consumers
1083
+ * (chat / intake) do, because the advisories were consumed internally
1084
+ * (trace events, brain record) but never returned. Additive, non-breaking.
1085
+ */
1086
+ advisories: BestPracticeAdvisory[];
1087
+ }
1088
+ /**
1089
+ * Thrown when call() exhausts the fallback chain without success.
1090
+ * `attempts` carries every model tried + classification.
1091
+ */
1092
+ declare class CallError extends Error {
1093
+ readonly attempts: CallAttempt[];
1094
+ readonly lastErrorCode?: string;
1095
+ readonly lastStatus?: number;
1096
+ constructor(message: string, attempts: CallAttempt[], lastStatus?: number, lastErrorCode?: string);
1097
+ }
1098
+ interface OracleScore {
1099
+ /** 0..1 overall quality. */
1100
+ score: number;
1101
+ /** Optional per-dimension breakdown. */
1102
+ dimensions?: Record<string, number>;
1103
+ /** Free-form explanation for debugging. */
1104
+ rationale?: string;
1105
+ }
1106
+ interface RecordInput {
1107
+ /** Handle from CompileResult. */
1108
+ handle: string;
1109
+ /** Actual tokens consumed (post-call). */
1110
+ tokensIn: number;
1111
+ tokensOut: number;
1112
+ /** Wall-clock latency in ms. */
1113
+ latencyMs: number;
1114
+ /** True iff the call returned a usable response. */
1115
+ success: boolean;
1116
+ /** True iff the call returned 0 output tokens despite success. */
1117
+ emptyResponse?: boolean;
1118
+ /** Provider error code if any. */
1119
+ errorType?: string;
1120
+ /** Tools actually invoked by the model. */
1121
+ toolsCalled?: string[];
1122
+ /** Oracle quality score — required for learning to fire. */
1123
+ oracleScore?: OracleScore;
1124
+ /** Optional: scrubbed prompt/response previews for debugging. */
1125
+ promptPreview?: string;
1126
+ responsePreview?: string;
1127
+ /**
1128
+ * The model that ACTUALLY RAN. Set this when consumer-side fallback ran
1129
+ * a different model than v2 compile() targeted. Brain stores this as
1130
+ * `model` (the truth) and the original target as `requested_model`.
1131
+ *
1132
+ * Omit when no fallback occurred — brain stores compile target as `model`
1133
+ * (still the truth in that case) and `requested_model` stays NULL.
1134
+ *
1135
+ * s11 fix: prevents the brain from misattributing fallback traffic to
1136
+ * the originally-requested model.
1137
+ */
1138
+ actualModel?: string;
1139
+ /**
1140
+ * Override `mutations_applied` for this outcome. Set by `call()` when
1141
+ * fallback fires — the served compile's mutations (which actually shaped
1142
+ * the request that went on the wire) replace the initial compile's
1143
+ * mutations (registered against the handle). Without this override, fallback
1144
+ * traffic is attributed to the initial compile's mutations and the brain's
1145
+ * mutation effectiveness stats become misleading.
1146
+ *
1147
+ * alpha.4: extends s11 truth-in-logging to mutations.
1148
+ */
1149
+ mutationsApplied?: string[];
1150
+ /**
1151
+ * Cache read input tokens, when supported by the provider.
1152
+ * - Anthropic: `usage.cache_read_input_tokens`
1153
+ * - Google (implicit caching): `usageMetadata.cachedContentTokenCount`
1154
+ * - OpenAI: `usage.prompt_tokens_details.cached_tokens`
1155
+ *
1156
+ * Powers the cost-and-efficiency-watcher (interfaces/kgauto.md, alpha.4):
1157
+ * `tokens_in - cache_read_input_tokens` is the un-cached new context per call.
1158
+ */
1159
+ cacheReadInputTokens?: number;
1160
+ /**
1161
+ * Cache creation input tokens (Anthropic-specific).
1162
+ * `usage.cache_creation_input_tokens`. The first call that pays the 25%
1163
+ * upcharge to write a cache marker; subsequent calls hit `cacheRead`.
1164
+ */
1165
+ cacheCreationInputTokens?: number;
1166
+ /**
1167
+ * Time to first token (ms). Optional; populated when the provider/SDK
1168
+ * surfaces it. Distinct from `latencyMs` (end-to-end wall clock).
1169
+ */
1170
+ ttftMs?: number;
1171
+ /**
1172
+ * alpha.57 (data-first) — the reasoning-effort tier this call actually ran
1173
+ * at. Overrides the compile-declared `constraints.effort` when both are
1174
+ * present (input wins — same precedence as `mutationsApplied`/`advisories`).
1175
+ * When omitted, record() auto-enriches from the registry-cached compile
1176
+ * declaration. Undefined end-to-end → the `effort` key is absent from the
1177
+ * outcome payload entirely (safe against pre-migration-033 brains).
1178
+ */
1179
+ effort?: EffortLevel;
1180
+ /**
1181
+ * alpha.20 — advisories fired at compile() time. Persisted to the brain's
1182
+ * `compile_outcome_advisories` sibling table via a second POST that fires
1183
+ * AFTER the primary outcome insert succeeds. Best-effort: a failed
1184
+ * advisory POST is logged via onError but does NOT throw or roll back the
1185
+ * primary outcome row.
1186
+ *
1187
+ * Pass `result.advisories` from the CompileResult directly. The brain
1188
+ * uses these to compute the `empty_rate_clean` comparator (rows with
1189
+ * zero advisories fired) so consumers can distinguish "model is bad"
1190
+ * from "client sent a bloated/uncached/malformed request."
1191
+ *
1192
+ * Empty array / undefined → no second POST fires.
1193
+ */
1194
+ advisories?: BestPracticeAdvisory[];
1195
+ /**
1196
+ * alpha.28 — Glass-Box renderer substrate fields (migration 018).
1197
+ *
1198
+ * All optional. When omitted, brain stores NULL and the renderer falls
1199
+ * back to "—" / hidden rows. Library callers (`call.ts`) populate what
1200
+ * they observe; adapter / SDK consumers can populate the rest from their
1201
+ * own provider response surface.
1202
+ */
1203
+ /**
1204
+ * Provider finish reason. Captured from NormalizedResponse.finishReason
1205
+ * (Anthropic `stop_reason`, Google `finishReason`, OpenAI `finish_reason`).
1206
+ * Lower-case canonicalization is the brain's job; consumers can pass
1207
+ * raw provider strings.
1208
+ */
1209
+ finishReason?: string;
1210
+ /**
1211
+ * End-to-end wall-clock latency in ms. Distinct from `latencyMs` only
1212
+ * insofar as `latencyMs` was the historical name for the same metric;
1213
+ * `totalMs` is the new column on `compile_outcomes` (migration 018).
1214
+ * When omitted, brain mirrors `latency_ms`.
1215
+ */
1216
+ totalMs?: number;
1217
+ /** Tools kept after the tool-relevance pass. */
1218
+ toolsCount?: number;
1219
+ /** Number of history messages at compile time. */
1220
+ historyDepth?: number;
1221
+ /** Rendered system prompt size in characters. */
1222
+ systemPromptChars?: number;
1223
+ /** Model originally targeted when a fallback fired. */
1224
+ fellOverFrom?: string;
1225
+ /**
1226
+ * Why the fallback fired. Closed set mirroring CallResult.fallbackReason —
1227
+ * keep in sync with the wire-contract enum (TraceDetail.fallbackReason).
1228
+ */
1229
+ fallbackReason?: 'rate_limit' | 'provider_auth_failed' | 'provider_error' | 'cliff' | 'cost_cap' | 'contract_violation';
1230
+ }
1231
+ /**
1232
+ * alpha.20 Entry 4: kinds of consumer-declared outcomes feeding the quality
1233
+ * loop. Surfaces in `recordOutcome()` as the verdict the consumer's UX is
1234
+ * forwarding to the brain.
1235
+ *
1236
+ * - `approved` user explicitly approved (thumbs up, "looks good", accepted)
1237
+ * - `rejected` user explicitly rejected (thumbs down, "redo", discarded)
1238
+ * - `partial` accepted with edits or partial use (mixed signal)
1239
+ * - `engaged` user engaged with the output (copy/scroll/dwell)
1240
+ * - `abandoned` user abandoned the response (closed, navigated away)
1241
+ * - `unknown` verdict could not be inferred — recorded for completeness
1242
+ */
1243
+ type OutcomeKind = 'approved' | 'rejected' | 'partial' | 'engaged' | 'abandoned' | 'unknown';
1244
+ /**
1245
+ * Input to `recordOutcome()` — consumer's verdict on a previously-compiled
1246
+ * call. Joins to the original `compile_outcomes` row via outcomeId,
1247
+ * enabling per-(model, archetype) approve-rate measurement once N ≥ 10
1248
+ * outcomes accumulate.
1249
+ */
1250
+ interface RecordOutcomeInput {
1251
+ /**
1252
+ * Joins to compile_outcomes.id. Pass the compile `handle` string
1253
+ * (CompileResult.handle / CallResult.handle) — consumer proxies resolve
1254
+ * handle → compile_outcomes.id via the `compile_outcomes.handle` column
1255
+ * (reference implementations: PB `api/kgauto-v2/compile_outcome_quality.js`,
1256
+ * tt-intel/IC `app/api/kgauto/v2/compile_outcome_quality/route.ts`). A
1257
+ * numeric compile_outcomes.id also works if the caller already has it.
1258
+ * (There is no `CompileResult.outcomeId` field — the brain assigns the row
1259
+ * id at insert; `handle` is the consumer-visible correlator.)
1260
+ */
1261
+ outcomeId: number | string;
1262
+ /** What did the user / system do with this output? */
1263
+ outcome: OutcomeKind;
1264
+ /** Optional 1-5 user rating (e.g., thumbs up/down with intensity, NPS-style). */
1265
+ rating?: 1 | 2 | 3 | 4 | 5;
1266
+ /** Optional free-text reason (e.g., user-typed feedback, system-inferred cause). */
1267
+ reason?: string;
1268
+ /**
1269
+ * Optional model-reported confidence at compile time (0..1). Used for
1270
+ * Brier-score calibration in later phases (alpha.21+) — pair this with
1271
+ * the actual `outcome` to compute calibration error.
1272
+ */
1273
+ observedConfidence?: number;
1274
+ }
1275
+ /**
1276
+ * Return shape of `recordOutcome()`. Never throws — persistence failures
1277
+ * surface as `ok: false` with a stable `reason` string.
1278
+ */
1279
+ interface OutcomeResult {
1280
+ /**
1281
+ * `true` — the POST was acknowledged 2xx (sync mode only).
1282
+ * `'queued'` (alpha.61) — fire-and-forget mode: the write was handed to the
1283
+ * runtime but NOT acknowledged; delivery is unknown at return time. Read
1284
+ * `brainHealth()` or set `BrainConfig.sync` for delivery evidence.
1285
+ * `false` — brain not configured, or the POST failed (sync mode).
1286
+ * Both truthy values pass `if (result.ok)`; pre-alpha.61 code that treated
1287
+ * the fire-and-forget `true` as an ack was reading a false signal.
1288
+ */
1289
+ ok: boolean | 'queued';
1290
+ /** Stable reason code when ok=false. One of: 'brain_not_configured' | 'persistence_failed'. */
1291
+ reason?: string;
1292
+ }
1293
+ /**
1294
+ * alpha.21 (s78 Entry 1): provenance label on a chain entry. Surfaces WHY
1295
+ * an entry sits where it sits so consumers can distinguish:
1296
+ *
1297
+ * - 'measured' brain has N>=10 rows with a measurable quality
1298
+ * outcome backing this placement. The number lives on
1299
+ * `ChainEntry.n`.
1300
+ * - 'capability-fact' inclusion or exclusion driven by a published or
1301
+ * measured CAPABILITY (L-040 cliff, ctx window cap,
1302
+ * structured-output support). Not an opinion — a
1303
+ * fact about what the model can/can't do.
1304
+ * - 'judgment' engineer's pick, no measured backing yet. Cold-start
1305
+ * prior; entirely valid until evidence accumulates.
1306
+ *
1307
+ * "Judgment" is HONEST, not a downgrade. Most of `STARTER_CHAINS` lands here
1308
+ * in alpha.21 — that's the point: consumers can SEE the grounding gap and
1309
+ * prioritize the measurement work that would graduate them to 'measured'.
1310
+ */
1311
+ type Grounding = 'measured' | 'capability-fact' | 'judgment';
1312
+ /**
1313
+ * alpha.21 (s78 Entry 1): a single position in a fallback chain, carrying its
1314
+ * provenance label and an optional human-readable reason. The shape replaces
1315
+ * the old `string[]` representation everywhere chains are surfaced externally.
1316
+ *
1317
+ * `n` is REQUIRED when `grounding === 'measured'` — the runtime helper
1318
+ * `makeMeasuredEntry()` enforces this. For 'capability-fact' and 'judgment'
1319
+ * entries, `n` is undefined.
1320
+ */
1321
+ interface ChainEntry {
1322
+ /** Canonical model id (post-alias). */
1323
+ id: string;
1324
+ /** Why this entry sits in this position. */
1325
+ grounding: Grounding;
1326
+ /**
1327
+ * Optional one-liner explaining the grounding decision. The inline comments
1328
+ * that historically lived next to STARTER_CHAINS entries are now expressed
1329
+ * here as machine-readable text.
1330
+ */
1331
+ reason?: string;
1332
+ /**
1333
+ * When `grounding === 'measured'`, the brain row count that backs this
1334
+ * placement. Undefined for 'capability-fact' and 'judgment' entries.
1335
+ */
1336
+ n?: number;
1337
+ }
1338
+ /**
1339
+ * alpha.21 introspection shape — a per-archetype chain with grounding on
1340
+ * every position. Consumers reading this never see naked string ids;
1341
+ * everything carries provenance.
1342
+ */
1343
+ interface ChainWithGrounding {
1344
+ archetype: IntentArchetypeName;
1345
+ /** Ordered: position 0 = primary, rising index = fallback positions. */
1346
+ entries: ChainEntry[];
1347
+ }
1348
+ /** alpha.23 (s78 Phase 3): per-axis metrics returned by the brain RPC. */
1349
+ interface PerAxisMetrics {
1350
+ appId: string;
1351
+ archetype: string;
1352
+ model: string;
1353
+ windowDays: number;
1354
+ /** Total brain rows for this tuple in the window. */
1355
+ nRows: number;
1356
+ /** Subset of nRows with zero advisories fired — the "clean signal" comparator. */
1357
+ nRowsClean: number;
1358
+ /** Count of compile_outcome_quality entries joining to this tuple's outcomes. */
1359
+ nQualityOutcomes: number;
1360
+ /** Approve rate from quality outcomes. null when nQualityOutcomes === 0. */
1361
+ magicRate: number | null;
1362
+ /** Whether magicRate >= consumer-declared qualityFloor. null when no floor declared OR no outcomes. */
1363
+ qualityFloorMet: boolean | null;
1364
+ costEfficiency: {
1365
+ avgCostUsd: number | null;
1366
+ avgCostUsdClean: number | null;
1367
+ avgInputTokens: number | null;
1368
+ avgOutputTokens: number | null;
1369
+ inputTokenRatio: number | null;
1370
+ };
1371
+ timeEfficiency: {
1372
+ avgLatencyMs: number | null;
1373
+ avgTtftMs: number | null;
1374
+ };
1375
+ reliability: {
1376
+ successRate: number | null;
1377
+ successRateClean: number | null;
1378
+ emptyRate: number | null;
1379
+ emptyRateClean: number | null;
1380
+ };
1381
+ evidenceFreshnessDays: number | null;
1382
+ }
1383
+ /** Per-axis metrics keyed by model — used for chain-comparison views. */
1384
+ type PerAxisMetricsByModel = Record<string, PerAxisMetrics>;
1385
+
1386
+ export { type ApiKeys as A, type BestPracticeAdvisory as B, type CompilePolicy as C, type EffortLevel as E, 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 ChainModelEntry as o, type ChainWithGrounding as p, type Constraints as q, type MutationApplied as r, type NormalizedTokens as s, type OutcomeKind as t, type PerAxisMetricsByModel as u, type PromptSection as v, type SectionKind as w, type ShadowProbeConfig as x, type ToolDefinition as y };