@warmdrift/kgauto-compiler 2.0.0-alpha.60 → 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.
package/README.md CHANGED
@@ -1,28 +1,48 @@
1
- # @warmdrift/kgauto-compiler — v2.0.0-alpha.6
1
+ # @warmdrift/kgauto-compiler — v2 (alpha)
2
2
 
3
- > Prompt compiler + central learning brain for multi-model AI apps.
3
+ > Prompt compiler with executable provider knowledge for multi-model AI apps.
4
4
  > **Swap models without rewriting prompts.**
5
5
 
6
- Greenfield rewrite of `@warmdrift/kgauto` v1. v1 was a behavioral patcher
7
- with telemetry; v2 is a real prompt compiler with a self-improving learning
8
- layer designed for cross-app pollination.
9
-
10
- The "compiler" name is deliberate every optimization is a pass on a
11
- structured Intermediate Representation (IR), not string surgery on a
12
- rendered prompt. This unlocks slicing, dedupe, intent-aware tool relevance,
13
- target-correct lowering with cache markers, and (in v2.1) outcome-driven
14
- mutations.
6
+ What this package delivers today, and nothing it doesn't:
7
+
8
+ - **A prompt compiler** — every optimization is a pass on a structured
9
+ Intermediate Representation (IR), not string surgery on a rendered prompt:
10
+ slicing, dedupe, intent-aware tool relevance, history compression,
11
+ target-correct lowering with cache markers.
12
+ - **Executable provider knowledge** model cliffs, lowering rules, and
13
+ recovery handlers as code that fires at compile time, curated against
14
+ provider docs with grounding labels. Seven-plus frontier model transitions
15
+ absorbed centrally with zero consumer prompt rewrites.
16
+ - **Normalized multi-provider transport** — `call()` walks a fallback chain
17
+ across Anthropic / Google / OpenAI / DeepSeek with a provider-error
18
+ taxonomy (429 / 404 / 401-auth-walk / parse-fail / MAX_TOKENS), recompiling
19
+ per fallback target. (Scope: the `call()` path. Streaming consumers drive
20
+ their own wire and get compile-time guards, not transport resilience.)
21
+ - **A flight recorder** — opt-in telemetry (`record()` / `probeShadow()` /
22
+ key-health) that has repeatedly caught real production defects: empty-response
23
+ cliffs, dead API keys, cache-miss regressions, silent model deprecations.
24
+ - **A curated model registry** — capability + pricing data with verification
25
+ stamps, a release watcher, and price-truth test gates.
26
+
27
+ **What it does not do (yet):** routing does not change itself from measured
28
+ outcomes. There is no automatic learning loop in the shipped package — model
29
+ promotion is evidence-*informed* but operator-*driven*. The eval-driven
30
+ quality-floor-guarded swap architecture is specced (2026-07-17) and is the
31
+ current engineering arc; the learning claims return to this README when they
32
+ are code, not before.
33
+
34
+ Greenfield rewrite of `@warmdrift/kgauto` v1 (a behavioral patcher with
35
+ telemetry).
15
36
 
16
37
  ## Status
17
38
 
18
- - **Package:** alpha — coexists with v1 (`@warmdrift/kgauto@1.2.0`) under
19
- the temporary name `@warmdrift/kgauto-compiler`. Renames to v2 final once
20
- v1 is fully retired from production.
21
- - **Tests:** 201/201 passing
22
- - **Build:** clean (47KB ESM, 68KB CJS)
23
- - **Brain:** schema ready (see `brain/migrations/001_initial_schema.sql`);
24
- awaiting dedicated Supabase provisioning.
25
- - **Mutation engine:** v2.1 (after enough outcome data accumulates).
39
+ - **Package:** alpha — coexists with v1 (`@warmdrift/kgauto`) under the
40
+ temporary name `@warmdrift/kgauto-compiler`. Renames to v2 final once v1
41
+ is fully retired from production.
42
+ - **Tests:** 1400+ passing (see CI for the current count)
43
+ - **Brain:** live multi-tenant Supabase substrate (telemetry + curated
44
+ config tables), consumed by four production apps.
45
+ - **Learning engine:** not shipped. See "What's next."
26
46
 
27
47
  ## Quickstart
28
48
 
@@ -203,10 +223,10 @@ APP (any consumer)
203
223
  └── kg.record(handle, outcome) ── async POST to brain
204
224
 
205
225
  BRAIN (centralized Supabase)
206
- ├── compile_outcomes (multi-tenant from day 1)
207
- ├── mutations (active rules empty in v2.0; engine in v2.1)
208
- ├── apps (consumer registry)
209
- └── digest_runs (weekly summary audit trail)
226
+ ├── compile_outcomes (multi-tenant telemetry)
227
+ ├── probe_outcomes / compile_outcome_quality (shadow-probe + quality rows)
228
+ ├── kgauto_models / kgauto_chains / kgauto_pricing (curated config, operator-maintained)
229
+ └── apps (consumer registry)
210
230
  ```
211
231
 
212
232
  ## Dialect-v1 (cross-app vocabulary)
@@ -216,12 +236,10 @@ Apps tag every call with an **intent archetype** (`ask`, `hunt`, `classify`,
216
236
  compiler computes a **shape signature** (context bucket × tool count × history
217
237
  depth × output mode × examples flag).
218
238
 
219
- The `(archetype, model, shape)` tuple is the **learning key**. Apps that
220
- declare the same tuple inherit each other's mutations even apps that have
221
- never seen each other's data.
222
-
223
- That's how *"what works for the dashboard, should be insights for the next
224
- dashboard"* becomes mechanical instead of aspirational.
239
+ The `(archetype, model, shape)` tuple is the **learning key** the shared
240
+ grouping vocabulary for telemetry aggregation across apps. It is the
241
+ substrate a future cross-app learning engine would key on; today it powers
242
+ per-tuple cost/latency observability, nothing more.
225
243
 
226
244
  ## Profiles — executable model knowledge
227
245
 
@@ -308,27 +326,26 @@ is a `pg_dump` away.
308
326
 
309
327
  ## What's next
310
328
 
311
- - **v2.0.x:** real-app integrations (tt-intelligence, inspire-central,
312
- playbacksam, inspirato/incantato). Brain accumulates outcome data.
313
- - **v2.1:** mutation engine. Shadow-test statistical gate promote → auto-rollback.
314
- - **v2.2:** weekly digest reporting back to the operator.
315
- - **v2.x:** dialect-v2 expanded with archetypes that emerge from real usage.
329
+ The current arc (specced 2026-07-17, after an adversarial promise review)
330
+ is **eval-driven quality-floor-guarded model swap**: golden sets of real
331
+ IRs per consumer surface, a pairwise judge archetype, a non-inferiority
332
+ promotion rule, and a rollback guard evidence generated on demand instead
333
+ of waiting for organic traffic volume that doesn't exist. A model replaces
334
+ another on a surface only by demonstrating same-or-better quality on that
335
+ surface's real workload. Each stage lands in this README **when it ships**,
336
+ with its gate evidence — the promise follows the code.
316
337
 
317
338
  ## Why this exists
318
339
 
319
340
  The previous version (v1) treated prompts as opaque strings and could only
320
- *append* behavioral patches. It also tried to learn quality from structural
321
- signals (token counts) but quality is semantic, not structural.
322
-
323
- v2 treats prompts as structured IR, makes every model-specific quirk
324
- *executable* (cliffs, lowering, recovery), and makes oracle scoring a
325
- first-class contract so the brain learns from quality data, not its proxies.
326
-
327
- The whole point: every multi-model AI app needs a compiler. Building it
328
- inline ships one app's value. Building it portable with a shared brain
329
- ships every app's value to every other app.
330
-
331
- Communicating vessels — finally accurate to the name.
341
+ *append* behavioral patches. v2 treats prompts as structured IR and makes
342
+ every model-specific quirk *executable* (cliffs, lowering, recovery).
343
+
344
+ The felt pain this solves is real and recurring: every frontier model
345
+ release, deprecation, price change, or silent alias flip lands on every
346
+ multi-model app at once. Building the absorption layer inline ships one
347
+ app's fix. Building it portable — one compiler, one curated registry, one
348
+ watcher set, one telemetry substrate ships the fix to every app at once.
332
349
 
333
350
  ## License
334
351
 
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var LIBRARY_VERSION = "2.0.0-alpha.60";
2
+ var LIBRARY_VERSION = "2.0.0-alpha.61";
3
3
 
4
4
  // src/key-health.ts
5
5
  var JSON_HEADERS = { "Content-Type": "application/json" };
@@ -1,6 +1,6 @@
1
- import { G as GlassboxEvent } from '../types-CRy90cjp.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-CRy90cjp.mjs';
3
- import '../ir-BC4uDL98.mjs';
1
+ import { G as GlassboxEvent } from '../types-CssWqd0X.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-CssWqd0X.mjs';
3
+ import '../ir-DAKlQsVb.mjs';
4
4
  import '../dialect.mjs';
5
5
 
6
6
  /**
@@ -1,6 +1,6 @@
1
- import { G as GlassboxEvent } from '../types-CsB2YASc.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-CsB2YASc.js';
3
- import '../ir-B2h0GAEL.js';
1
+ import { G as GlassboxEvent } from '../types-DR62iPcO.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-DR62iPcO.js';
3
+ import '../ir-DmUuJsWc.js';
4
4
  import '../dialect.js';
5
5
 
6
6
  /**
@@ -1,5 +1,5 @@
1
- import { T as TraceHealth } from '../types-B-pzBJKf.mjs';
2
- import '../ir-BC4uDL98.mjs';
1
+ import { T as TraceHealth } from '../types-MRMBUqzY.mjs';
2
+ import '../ir-DAKlQsVb.mjs';
3
3
  import '../dialect.mjs';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { T as TraceHealth } from '../types-CKuu7Clz.js';
2
- import '../ir-B2h0GAEL.js';
1
+ import { T as TraceHealth } from '../types-B8X1Pyhx.js';
2
+ import '../ir-DmUuJsWc.js';
3
3
  import '../dialect.js';
4
4
 
5
5
  /**
@@ -1,7 +1,7 @@
1
- import { G as GlassboxEvent } from '../types-CRy90cjp.mjs';
2
- import { a as TraceDetail, b as TraceSummary, c as TraceCounterfactual } from '../types-B-pzBJKf.mjs';
3
- export { A as AdvisoryRecord, T as TraceHealth, d as TraceSectionRewrite } from '../types-B-pzBJKf.mjs';
4
- import '../ir-BC4uDL98.mjs';
1
+ import { G as GlassboxEvent } from '../types-CssWqd0X.mjs';
2
+ import { a as TraceDetail, b as TraceSummary, c as TraceCounterfactual } from '../types-MRMBUqzY.mjs';
3
+ export { A as AdvisoryRecord, T as TraceHealth, d as TraceSectionRewrite } from '../types-MRMBUqzY.mjs';
4
+ import '../ir-DAKlQsVb.mjs';
5
5
  import '../dialect.mjs';
6
6
 
7
7
  /**
@@ -1,7 +1,7 @@
1
- import { G as GlassboxEvent } from '../types-CsB2YASc.js';
2
- import { a as TraceDetail, b as TraceSummary, c as TraceCounterfactual } from '../types-CKuu7Clz.js';
3
- export { A as AdvisoryRecord, T as TraceHealth, d as TraceSectionRewrite } from '../types-CKuu7Clz.js';
4
- import '../ir-B2h0GAEL.js';
1
+ import { G as GlassboxEvent } from '../types-DR62iPcO.js';
2
+ import { a as TraceDetail, b as TraceSummary, c as TraceCounterfactual } from '../types-B8X1Pyhx.js';
3
+ export { A as AdvisoryRecord, T as TraceHealth, d as TraceSectionRewrite } from '../types-B8X1Pyhx.js';
4
+ import '../ir-DmUuJsWc.js';
5
5
  import '../dialect.js';
6
6
 
7
7
  /**
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { a as TraceDetail } from '../../types-B-pzBJKf.mjs';
3
- import '../../ir-BC4uDL98.mjs';
2
+ import { a as TraceDetail } from '../../types-MRMBUqzY.mjs';
3
+ import '../../ir-DAKlQsVb.mjs';
4
4
  import '../../dialect.mjs';
5
5
 
6
6
  /**
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { a as TraceDetail } from '../../types-CKuu7Clz.js';
3
- import '../../ir-B2h0GAEL.js';
2
+ import { a as TraceDetail } from '../../types-B8X1Pyhx.js';
3
+ import '../../ir-DmUuJsWc.js';
4
4
  import '../../dialect.js';
5
5
 
6
6
  /**
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 SystemModelMessage, e as CompileResult, B as BestPracticeAdvisory, f as SectionRewrite, R as RecordInput, g as RecordOutcomeInput, O as OutcomeResult, h as OracleScore, i as Adapter, j as PerAxisMetrics, k as Provider, l as ChainEntry, G as Grounding } from './ir-BC4uDL98.mjs';
2
- export { m as CallAttempt, n as CallError, o as ChainModelEntry, p as ChainWithGrounding, q as Constraints, E as EffortLevel, F as FallbackReason, H as HistoryCachePolicy, I as IntentDeclaration, M as Message, r as MutationApplied, s as NormalizedTokens, t as OutcomeKind, u as PerAxisMetricsByModel, v as PromptSection, w as SectionKind, x as ShadowProbeConfig, T as ToolCall, y as ToolDefinition } from './ir-BC4uDL98.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, B as BestPracticeAdvisory, f as SectionRewrite, R as RecordInput, g as RecordOutcomeInput, O as OutcomeResult, h as OracleScore, i as Adapter, j as PerAxisMetrics, k as Provider, l as ChainEntry, G as Grounding } from './ir-DAKlQsVb.mjs';
2
+ export { m as CallAttempt, n as CallError, o as ChainModelEntry, p as ChainWithGrounding, q as Constraints, E as EffortLevel, F as FallbackReason, H as HistoryCachePolicy, I as IntentDeclaration, M as Message, r as MutationApplied, s as NormalizedTokens, t as OutcomeKind, u as PerAxisMetricsByModel, v as PromptSection, w as SectionKind, x as ShadowProbeConfig, T as ToolCall, y as ToolDefinition } from './ir-DAKlQsVb.mjs';
3
3
  import { ModelProfile, ArchetypeConvention } from './profiles.mjs';
4
4
  export { ALIASES, CacheStrategy, CliffRule, LATENCY_TIER_MS, LatencyTier, LoweringSpec, RecoveryRule, StructuredOutputCapability, SystemPromptMode, allProfiles, getProfile, latencyTierOf, profilesByProvider, tryGetProfile } from './profiles.mjs';
5
5
  export { BrainForwardConfig, BrainForwardRoutes, createBrainForwardRoutes } from './brain-proxy.mjs';
@@ -440,6 +440,65 @@ interface BrainConfig {
440
440
  }
441
441
  declare function configureBrain(config: BrainConfig): void;
442
442
  declare function clearBrain(): void;
443
+ interface BrainHealthSnapshot {
444
+ configState: 'configured' | 'not_configured';
445
+ /** Host of the configured endpoint (never the full URL — no secrets/paths). */
446
+ endpointHost?: string;
447
+ /** True when writes are awaited (BrainConfig.sync). */
448
+ sync: boolean;
449
+ /** Write POSTs attempted (all routes, primary + secondary). */
450
+ sent: number;
451
+ /** Write POSTs acknowledged 2xx without redirect. */
452
+ acked: number;
453
+ /** Write POSTs that failed (non-2xx, redirect, timeout, network throw). */
454
+ failed: number;
455
+ /** Subset of `failed` that failed the redirect check (middleware-drift class). */
456
+ redirected: number;
457
+ lastAckAt?: string;
458
+ lastFailureAt?: string;
459
+ /** Most recent failure message, truncated. */
460
+ lastFailure?: string;
461
+ deadLetterCount: number;
462
+ }
463
+ interface BrainDeadLetterEntry {
464
+ /** Brain route segment the payload was bound for. */
465
+ route: 'outcomes' | 'compile_outcome_quality' | 'probe_outcomes' | 'compile_outcome_advisories';
466
+ /**
467
+ * Endpoint the payload was originally bound for. Flush replays ONLY entries
468
+ * matching the currently-configured endpoint — a reconfigure must never
469
+ * replay another brain's payloads into the new target (caught live by
470
+ * smoke-brain-timeout: a hung-socket test payload auto-flushed into the
471
+ * real brain after the smoke re-pointed configureBrain).
472
+ */
473
+ endpoint: string;
474
+ /** The exact JSON body that failed to land. */
475
+ payload: unknown;
476
+ failedAt: string;
477
+ /** Delivery attempts so far (1 = the original failed POST). */
478
+ attempts: number;
479
+ lastError: string;
480
+ }
481
+ /**
482
+ * Process-local brain write delivery ledger. `acked` is the only number that
483
+ * means "a row landed" — fire-and-forget callers that need delivery evidence
484
+ * read this (or set `BrainConfig.sync`). Cheap enough to attach to any debug
485
+ * or health surface the consumer already exposes.
486
+ */
487
+ declare function brainHealth(): BrainHealthSnapshot;
488
+ /** Read-only view of the pending dead-letter (for consumer-side persistence). */
489
+ declare function peekBrainDeadLetter(): readonly BrainDeadLetterEntry[];
490
+ /**
491
+ * Replay pending dead-letter payloads against the configured brain. Delivered
492
+ * entries are removed; failures increment `attempts` and entries are dropped
493
+ * after 3 total attempts (bounded — never an infinite retry, per the Redis
494
+ * DLQ rule). Safe to call any time; no-ops when unconfigured or already
495
+ * flushing. Also runs opportunistically after any successful write.
496
+ */
497
+ declare function flushBrainDeadLetter(): Promise<{
498
+ attempted: number;
499
+ delivered: number;
500
+ remaining: number;
501
+ }>;
443
502
  declare function record(input: RecordInput): Promise<void>;
444
503
  /**
445
504
  * Wire shape POSTed by `record()` to the brain proxy's `/outcomes` endpoint.
@@ -522,8 +581,10 @@ interface OutcomePayload {
522
581
  * = true for runtime contexts that can't tolerate fire-and-forget teardown
523
582
  * (Vercel Edge, Cloudflare Workers, AWS Lambda) — see L-086.
524
583
  *
525
- * Returns OutcomeResult with ok: false + stable reason on persistence
526
- * failure. Never throws.
584
+ * Returns (alpha.61): `{ok: true}` only when the POST was acknowledged 2xx
585
+ * (sync mode); `{ok: 'queued'}` in fire-and-forget mode (handed to the
586
+ * runtime, NOT acked — read `brainHealth()` for delivery evidence);
587
+ * `{ok: false, reason}` on known failure. Never throws.
527
588
  */
528
589
  declare function recordOutcome(input: RecordOutcomeInput): Promise<OutcomeResult>;
529
590
  /**
@@ -639,7 +700,7 @@ declare function recordShadowProbe(input: ShadowProbeRecordInput): Promise<void>
639
700
  * guard in `tests/version.test.ts` fails the suite (and therefore
640
701
  * `prepublishOnly`) when they diverge — a stale constant cannot reach npm.
641
702
  */
642
- declare const LIBRARY_VERSION = "2.0.0-alpha.60";
703
+ declare const LIBRARY_VERSION = "2.0.0-alpha.61";
643
704
 
644
705
  /**
645
706
  * Oracle contract — how an app tells the brain whether a response was good.
@@ -2428,4 +2489,4 @@ declare function markPromoteReadyHandled(opts: MarkPromoteReadyHandledOptions):
2428
2489
  */
2429
2490
  declare function compile(ir: PromptIR, opts?: CompileOptions): CompileResult;
2430
2491
 
2431
- export { ABSOLUTE_FLOOR, type AISDKConvertedMessage, ARCHETYPE_FAMILY_FITS, ARCHETYPE_FLOOR_DEFAULT, type ActionableAdvisory, Adapter, type AdvisoryResolutionSource, type AdvisorySeverity, type AdvisoryStatus, type AdvisorySuggestedFix, ApiKeys, type AppOracle, type ApplySectionRewritesArgs, type ApplySectionRewritesResult, ArchetypeConvention, type ArchetypeFamilyFit, type ArchetypePerfMap, type ArchetypePerfNMap, type ArchetypePerfScoreResult, type AttachCacheControlResult, BestPracticeAdvisory, type BrainConfig, type BrainQueryConfig, type BrainReadEnv, CallOptions, CallResult, ChainEntry, type CompatibilityIntent, type CompileForAISDKv6Result, type CompileOptions, CompilePolicy, CompileResult, CompiledRequest, DEFAULT_FINDINGS_ENDPOINT, type ExclusionFindingRow, type ExclusionResolutionSource, type ExecuteErr, type ExecuteOk, type ExecuteOptions, type ExecuteResult, type FallbackPosture, FamilyResolutionError, type GetActionableAdvisoriesOptions, type GetDefaultFallbackChainOpts, type GetPerAxisMetricsOpts, type GetRecommendedPrimaryOptions, Grounding, IntentArchetypeName, LIBRARY_VERSION, type LLMJudgeOptions, MEASURED_GROUNDING_MIN_N, type MarkAdvisoryResolvedOptions, type MarkExclusionFindingHandledOptions, type MarkPromoteReadyHandledOptions, type ModelBrainRow, type ModelCompatibility, ModelProfile, NormalizedResponse, type OracleContext, OracleScore, type OutcomePayload, OutcomeResult, PRODUCER_OWNED_RULE_CODES, PROVIDER_ENV_KEYS, PerAxisMetrics, type PricingRow, type ProbeShadowOptions, type ProbeShadowServed, type ProfileToRowOptions, type PromoteReadyFindingRow, type PromoteReadyResolution, PromptIR, Provider, ProviderOverrides, type ProviderReachability, RULE_SEQUENTIAL_TOOL_CLIFF, type ReachabilityOpts, RecordInput, RecordOutcomeInput, type RunAdvisorPhase2Context, SectionRewrite, type ShadowProbeRecordInput, type SupportedProvider, SystemModelMessage, TRANSLATOR_FLOOR, applyArchetypeConvention, applySectionRewrites, attachCacheControlToStreamTextInput, buildLLMJudge, buildShadowProbeRow, call, clearBrain, compile, compileForAISDKv6, configureBrain, countTokens, deriveFamilyFromModelId, deriveOwnership, execute, findBetterFit, getActionableAdvisories, getAllStarterChains, getAllStarterChainsWithGrounding, getArchetypePerfScore, getDefaultFallbackChain, getDefaultFallbackChainWithGrounding, getModelCompatibility, getPerAxisMetrics, getReachabilityDiagnostic, getRecommendedPrimary, getSequentialStarterChain, getSequentialStarterChainWithGrounding, getStaleExclusionFindings, getStarterChain, getStarterChainWithGrounding, isBrainQueryActiveFor, isBrainSync, isExclusionFindingsBrainActive, isModelReachable, isProviderReachable, loadAliasesFromBrain, loadArchetypePerfFromBrain, loadArchetypePerfNFromBrain, loadChainsFromBrain, loadModelsFromBrain, loadPricingFromBrain, markAdvisoryResolved, markExclusionFindingHandled, markPromoteReadyHandled, probeShadow, profileToRow, readBrainReadEnv, record, recordOutcome, recordShadowProbe, resetTokenizer, resolveConventionsForProfile, resolvePricingAt, resolveProviderKey, runAdvisor, setTokenizer };
2492
+ export { ABSOLUTE_FLOOR, type AISDKConvertedMessage, ARCHETYPE_FAMILY_FITS, ARCHETYPE_FLOOR_DEFAULT, type ActionableAdvisory, Adapter, type AdvisoryResolutionSource, type AdvisorySeverity, type AdvisoryStatus, type AdvisorySuggestedFix, ApiKeys, type AppOracle, type ApplySectionRewritesArgs, type ApplySectionRewritesResult, ArchetypeConvention, type ArchetypeFamilyFit, type ArchetypePerfMap, type ArchetypePerfNMap, type ArchetypePerfScoreResult, type AttachCacheControlResult, BestPracticeAdvisory, type BrainConfig, type BrainDeadLetterEntry, type BrainHealthSnapshot, type BrainQueryConfig, type BrainReadEnv, CallOptions, CallResult, ChainEntry, type CompatibilityIntent, type CompileForAISDKv6Result, type CompileOptions, CompilePolicy, CompileResult, CompiledRequest, DEFAULT_FINDINGS_ENDPOINT, type ExclusionFindingRow, type ExclusionResolutionSource, type ExecuteErr, type ExecuteOk, type ExecuteOptions, type ExecuteResult, type FallbackPosture, FamilyResolutionError, type GetActionableAdvisoriesOptions, type GetDefaultFallbackChainOpts, type GetPerAxisMetricsOpts, type GetRecommendedPrimaryOptions, Grounding, IntentArchetypeName, LIBRARY_VERSION, type LLMJudgeOptions, MEASURED_GROUNDING_MIN_N, type MarkAdvisoryResolvedOptions, type MarkExclusionFindingHandledOptions, type MarkPromoteReadyHandledOptions, type ModelBrainRow, type ModelCompatibility, ModelProfile, NormalizedResponse, type OracleContext, OracleScore, type OutcomePayload, OutcomeResult, PRODUCER_OWNED_RULE_CODES, PROVIDER_ENV_KEYS, PerAxisMetrics, type PricingRow, type ProbeShadowOptions, type ProbeShadowServed, type ProfileToRowOptions, type PromoteReadyFindingRow, type PromoteReadyResolution, PromptIR, Provider, ProviderOverrides, type ProviderReachability, RULE_SEQUENTIAL_TOOL_CLIFF, type ReachabilityOpts, RecordInput, RecordOutcomeInput, type RunAdvisorPhase2Context, SectionRewrite, type ShadowProbeRecordInput, type SupportedProvider, SystemModelMessage, TRANSLATOR_FLOOR, applyArchetypeConvention, applySectionRewrites, attachCacheControlToStreamTextInput, brainHealth, buildLLMJudge, buildShadowProbeRow, call, clearBrain, compile, compileForAISDKv6, configureBrain, countTokens, deriveFamilyFromModelId, deriveOwnership, execute, findBetterFit, flushBrainDeadLetter, getActionableAdvisories, getAllStarterChains, getAllStarterChainsWithGrounding, getArchetypePerfScore, getDefaultFallbackChain, getDefaultFallbackChainWithGrounding, getModelCompatibility, getPerAxisMetrics, getReachabilityDiagnostic, getRecommendedPrimary, getSequentialStarterChain, getSequentialStarterChainWithGrounding, getStaleExclusionFindings, getStarterChain, getStarterChainWithGrounding, isBrainQueryActiveFor, isBrainSync, isExclusionFindingsBrainActive, isModelReachable, isProviderReachable, loadAliasesFromBrain, loadArchetypePerfFromBrain, loadArchetypePerfNFromBrain, loadChainsFromBrain, loadModelsFromBrain, loadPricingFromBrain, markAdvisoryResolved, markExclusionFindingHandled, markPromoteReadyHandled, peekBrainDeadLetter, probeShadow, profileToRow, readBrainReadEnv, record, recordOutcome, recordShadowProbe, resetTokenizer, resolveConventionsForProfile, 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 SystemModelMessage, e as CompileResult, B as BestPracticeAdvisory, f as SectionRewrite, R as RecordInput, g as RecordOutcomeInput, O as OutcomeResult, h as OracleScore, i as Adapter, j as PerAxisMetrics, k as Provider, l as ChainEntry, G as Grounding } from './ir-B2h0GAEL.js';
2
- export { m as CallAttempt, n as CallError, o as ChainModelEntry, p as ChainWithGrounding, q as Constraints, E as EffortLevel, F as FallbackReason, H as HistoryCachePolicy, I as IntentDeclaration, M as Message, r as MutationApplied, s as NormalizedTokens, t as OutcomeKind, u as PerAxisMetricsByModel, v as PromptSection, w as SectionKind, x as ShadowProbeConfig, T as ToolCall, y as ToolDefinition } from './ir-B2h0GAEL.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, B as BestPracticeAdvisory, f as SectionRewrite, R as RecordInput, g as RecordOutcomeInput, O as OutcomeResult, h as OracleScore, i as Adapter, j as PerAxisMetrics, k as Provider, l as ChainEntry, G as Grounding } from './ir-DmUuJsWc.js';
2
+ export { m as CallAttempt, n as CallError, o as ChainModelEntry, p as ChainWithGrounding, q as Constraints, E as EffortLevel, F as FallbackReason, H as HistoryCachePolicy, I as IntentDeclaration, M as Message, r as MutationApplied, s as NormalizedTokens, t as OutcomeKind, u as PerAxisMetricsByModel, v as PromptSection, w as SectionKind, x as ShadowProbeConfig, T as ToolCall, y as ToolDefinition } from './ir-DmUuJsWc.js';
3
3
  import { ModelProfile, ArchetypeConvention } from './profiles.js';
4
4
  export { ALIASES, CacheStrategy, CliffRule, LATENCY_TIER_MS, LatencyTier, LoweringSpec, RecoveryRule, StructuredOutputCapability, SystemPromptMode, allProfiles, getProfile, latencyTierOf, profilesByProvider, tryGetProfile } from './profiles.js';
5
5
  export { BrainForwardConfig, BrainForwardRoutes, createBrainForwardRoutes } from './brain-proxy.js';
@@ -440,6 +440,65 @@ interface BrainConfig {
440
440
  }
441
441
  declare function configureBrain(config: BrainConfig): void;
442
442
  declare function clearBrain(): void;
443
+ interface BrainHealthSnapshot {
444
+ configState: 'configured' | 'not_configured';
445
+ /** Host of the configured endpoint (never the full URL — no secrets/paths). */
446
+ endpointHost?: string;
447
+ /** True when writes are awaited (BrainConfig.sync). */
448
+ sync: boolean;
449
+ /** Write POSTs attempted (all routes, primary + secondary). */
450
+ sent: number;
451
+ /** Write POSTs acknowledged 2xx without redirect. */
452
+ acked: number;
453
+ /** Write POSTs that failed (non-2xx, redirect, timeout, network throw). */
454
+ failed: number;
455
+ /** Subset of `failed` that failed the redirect check (middleware-drift class). */
456
+ redirected: number;
457
+ lastAckAt?: string;
458
+ lastFailureAt?: string;
459
+ /** Most recent failure message, truncated. */
460
+ lastFailure?: string;
461
+ deadLetterCount: number;
462
+ }
463
+ interface BrainDeadLetterEntry {
464
+ /** Brain route segment the payload was bound for. */
465
+ route: 'outcomes' | 'compile_outcome_quality' | 'probe_outcomes' | 'compile_outcome_advisories';
466
+ /**
467
+ * Endpoint the payload was originally bound for. Flush replays ONLY entries
468
+ * matching the currently-configured endpoint — a reconfigure must never
469
+ * replay another brain's payloads into the new target (caught live by
470
+ * smoke-brain-timeout: a hung-socket test payload auto-flushed into the
471
+ * real brain after the smoke re-pointed configureBrain).
472
+ */
473
+ endpoint: string;
474
+ /** The exact JSON body that failed to land. */
475
+ payload: unknown;
476
+ failedAt: string;
477
+ /** Delivery attempts so far (1 = the original failed POST). */
478
+ attempts: number;
479
+ lastError: string;
480
+ }
481
+ /**
482
+ * Process-local brain write delivery ledger. `acked` is the only number that
483
+ * means "a row landed" — fire-and-forget callers that need delivery evidence
484
+ * read this (or set `BrainConfig.sync`). Cheap enough to attach to any debug
485
+ * or health surface the consumer already exposes.
486
+ */
487
+ declare function brainHealth(): BrainHealthSnapshot;
488
+ /** Read-only view of the pending dead-letter (for consumer-side persistence). */
489
+ declare function peekBrainDeadLetter(): readonly BrainDeadLetterEntry[];
490
+ /**
491
+ * Replay pending dead-letter payloads against the configured brain. Delivered
492
+ * entries are removed; failures increment `attempts` and entries are dropped
493
+ * after 3 total attempts (bounded — never an infinite retry, per the Redis
494
+ * DLQ rule). Safe to call any time; no-ops when unconfigured or already
495
+ * flushing. Also runs opportunistically after any successful write.
496
+ */
497
+ declare function flushBrainDeadLetter(): Promise<{
498
+ attempted: number;
499
+ delivered: number;
500
+ remaining: number;
501
+ }>;
443
502
  declare function record(input: RecordInput): Promise<void>;
444
503
  /**
445
504
  * Wire shape POSTed by `record()` to the brain proxy's `/outcomes` endpoint.
@@ -522,8 +581,10 @@ interface OutcomePayload {
522
581
  * = true for runtime contexts that can't tolerate fire-and-forget teardown
523
582
  * (Vercel Edge, Cloudflare Workers, AWS Lambda) — see L-086.
524
583
  *
525
- * Returns OutcomeResult with ok: false + stable reason on persistence
526
- * failure. Never throws.
584
+ * Returns (alpha.61): `{ok: true}` only when the POST was acknowledged 2xx
585
+ * (sync mode); `{ok: 'queued'}` in fire-and-forget mode (handed to the
586
+ * runtime, NOT acked — read `brainHealth()` for delivery evidence);
587
+ * `{ok: false, reason}` on known failure. Never throws.
527
588
  */
528
589
  declare function recordOutcome(input: RecordOutcomeInput): Promise<OutcomeResult>;
529
590
  /**
@@ -639,7 +700,7 @@ declare function recordShadowProbe(input: ShadowProbeRecordInput): Promise<void>
639
700
  * guard in `tests/version.test.ts` fails the suite (and therefore
640
701
  * `prepublishOnly`) when they diverge — a stale constant cannot reach npm.
641
702
  */
642
- declare const LIBRARY_VERSION = "2.0.0-alpha.60";
703
+ declare const LIBRARY_VERSION = "2.0.0-alpha.61";
643
704
 
644
705
  /**
645
706
  * Oracle contract — how an app tells the brain whether a response was good.
@@ -2428,4 +2489,4 @@ declare function markPromoteReadyHandled(opts: MarkPromoteReadyHandledOptions):
2428
2489
  */
2429
2490
  declare function compile(ir: PromptIR, opts?: CompileOptions): CompileResult;
2430
2491
 
2431
- export { ABSOLUTE_FLOOR, type AISDKConvertedMessage, ARCHETYPE_FAMILY_FITS, ARCHETYPE_FLOOR_DEFAULT, type ActionableAdvisory, Adapter, type AdvisoryResolutionSource, type AdvisorySeverity, type AdvisoryStatus, type AdvisorySuggestedFix, ApiKeys, type AppOracle, type ApplySectionRewritesArgs, type ApplySectionRewritesResult, ArchetypeConvention, type ArchetypeFamilyFit, type ArchetypePerfMap, type ArchetypePerfNMap, type ArchetypePerfScoreResult, type AttachCacheControlResult, BestPracticeAdvisory, type BrainConfig, type BrainQueryConfig, type BrainReadEnv, CallOptions, CallResult, ChainEntry, type CompatibilityIntent, type CompileForAISDKv6Result, type CompileOptions, CompilePolicy, CompileResult, CompiledRequest, DEFAULT_FINDINGS_ENDPOINT, type ExclusionFindingRow, type ExclusionResolutionSource, type ExecuteErr, type ExecuteOk, type ExecuteOptions, type ExecuteResult, type FallbackPosture, FamilyResolutionError, type GetActionableAdvisoriesOptions, type GetDefaultFallbackChainOpts, type GetPerAxisMetricsOpts, type GetRecommendedPrimaryOptions, Grounding, IntentArchetypeName, LIBRARY_VERSION, type LLMJudgeOptions, MEASURED_GROUNDING_MIN_N, type MarkAdvisoryResolvedOptions, type MarkExclusionFindingHandledOptions, type MarkPromoteReadyHandledOptions, type ModelBrainRow, type ModelCompatibility, ModelProfile, NormalizedResponse, type OracleContext, OracleScore, type OutcomePayload, OutcomeResult, PRODUCER_OWNED_RULE_CODES, PROVIDER_ENV_KEYS, PerAxisMetrics, type PricingRow, type ProbeShadowOptions, type ProbeShadowServed, type ProfileToRowOptions, type PromoteReadyFindingRow, type PromoteReadyResolution, PromptIR, Provider, ProviderOverrides, type ProviderReachability, RULE_SEQUENTIAL_TOOL_CLIFF, type ReachabilityOpts, RecordInput, RecordOutcomeInput, type RunAdvisorPhase2Context, SectionRewrite, type ShadowProbeRecordInput, type SupportedProvider, SystemModelMessage, TRANSLATOR_FLOOR, applyArchetypeConvention, applySectionRewrites, attachCacheControlToStreamTextInput, buildLLMJudge, buildShadowProbeRow, call, clearBrain, compile, compileForAISDKv6, configureBrain, countTokens, deriveFamilyFromModelId, deriveOwnership, execute, findBetterFit, getActionableAdvisories, getAllStarterChains, getAllStarterChainsWithGrounding, getArchetypePerfScore, getDefaultFallbackChain, getDefaultFallbackChainWithGrounding, getModelCompatibility, getPerAxisMetrics, getReachabilityDiagnostic, getRecommendedPrimary, getSequentialStarterChain, getSequentialStarterChainWithGrounding, getStaleExclusionFindings, getStarterChain, getStarterChainWithGrounding, isBrainQueryActiveFor, isBrainSync, isExclusionFindingsBrainActive, isModelReachable, isProviderReachable, loadAliasesFromBrain, loadArchetypePerfFromBrain, loadArchetypePerfNFromBrain, loadChainsFromBrain, loadModelsFromBrain, loadPricingFromBrain, markAdvisoryResolved, markExclusionFindingHandled, markPromoteReadyHandled, probeShadow, profileToRow, readBrainReadEnv, record, recordOutcome, recordShadowProbe, resetTokenizer, resolveConventionsForProfile, resolvePricingAt, resolveProviderKey, runAdvisor, setTokenizer };
2492
+ export { ABSOLUTE_FLOOR, type AISDKConvertedMessage, ARCHETYPE_FAMILY_FITS, ARCHETYPE_FLOOR_DEFAULT, type ActionableAdvisory, Adapter, type AdvisoryResolutionSource, type AdvisorySeverity, type AdvisoryStatus, type AdvisorySuggestedFix, ApiKeys, type AppOracle, type ApplySectionRewritesArgs, type ApplySectionRewritesResult, ArchetypeConvention, type ArchetypeFamilyFit, type ArchetypePerfMap, type ArchetypePerfNMap, type ArchetypePerfScoreResult, type AttachCacheControlResult, BestPracticeAdvisory, type BrainConfig, type BrainDeadLetterEntry, type BrainHealthSnapshot, type BrainQueryConfig, type BrainReadEnv, CallOptions, CallResult, ChainEntry, type CompatibilityIntent, type CompileForAISDKv6Result, type CompileOptions, CompilePolicy, CompileResult, CompiledRequest, DEFAULT_FINDINGS_ENDPOINT, type ExclusionFindingRow, type ExclusionResolutionSource, type ExecuteErr, type ExecuteOk, type ExecuteOptions, type ExecuteResult, type FallbackPosture, FamilyResolutionError, type GetActionableAdvisoriesOptions, type GetDefaultFallbackChainOpts, type GetPerAxisMetricsOpts, type GetRecommendedPrimaryOptions, Grounding, IntentArchetypeName, LIBRARY_VERSION, type LLMJudgeOptions, MEASURED_GROUNDING_MIN_N, type MarkAdvisoryResolvedOptions, type MarkExclusionFindingHandledOptions, type MarkPromoteReadyHandledOptions, type ModelBrainRow, type ModelCompatibility, ModelProfile, NormalizedResponse, type OracleContext, OracleScore, type OutcomePayload, OutcomeResult, PRODUCER_OWNED_RULE_CODES, PROVIDER_ENV_KEYS, PerAxisMetrics, type PricingRow, type ProbeShadowOptions, type ProbeShadowServed, type ProfileToRowOptions, type PromoteReadyFindingRow, type PromoteReadyResolution, PromptIR, Provider, ProviderOverrides, type ProviderReachability, RULE_SEQUENTIAL_TOOL_CLIFF, type ReachabilityOpts, RecordInput, RecordOutcomeInput, type RunAdvisorPhase2Context, SectionRewrite, type ShadowProbeRecordInput, type SupportedProvider, SystemModelMessage, TRANSLATOR_FLOOR, applyArchetypeConvention, applySectionRewrites, attachCacheControlToStreamTextInput, brainHealth, buildLLMJudge, buildShadowProbeRow, call, clearBrain, compile, compileForAISDKv6, configureBrain, countTokens, deriveFamilyFromModelId, deriveOwnership, execute, findBetterFit, flushBrainDeadLetter, getActionableAdvisories, getAllStarterChains, getAllStarterChainsWithGrounding, getArchetypePerfScore, getDefaultFallbackChain, getDefaultFallbackChainWithGrounding, getModelCompatibility, getPerAxisMetrics, getReachabilityDiagnostic, getRecommendedPrimary, getSequentialStarterChain, getSequentialStarterChainWithGrounding, getStaleExclusionFindings, getStarterChain, getStarterChainWithGrounding, isBrainQueryActiveFor, isBrainSync, isExclusionFindingsBrainActive, isModelReachable, isProviderReachable, loadAliasesFromBrain, loadArchetypePerfFromBrain, loadArchetypePerfNFromBrain, loadChainsFromBrain, loadModelsFromBrain, loadPricingFromBrain, markAdvisoryResolved, markExclusionFindingHandled, markPromoteReadyHandled, peekBrainDeadLetter, probeShadow, profileToRow, readBrainReadEnv, record, recordOutcome, recordShadowProbe, resetTokenizer, resolveConventionsForProfile, resolvePricingAt, resolveProviderKey, runAdvisor, setTokenizer };
package/dist/index.js CHANGED
@@ -41,6 +41,7 @@ __export(index_exports, {
41
41
  applyArchetypeConvention: () => applyArchetypeConvention,
42
42
  applySectionRewrites: () => applySectionRewrites,
43
43
  attachCacheControlToStreamTextInput: () => attachCacheControlToStreamTextInput,
44
+ brainHealth: () => brainHealth,
44
45
  bucketContext: () => bucketContext,
45
46
  bucketHistory: () => bucketHistory,
46
47
  bucketToolCount: () => bucketToolCount,
@@ -58,6 +59,7 @@ __export(index_exports, {
58
59
  deriveOwnership: () => deriveOwnership,
59
60
  execute: () => execute,
60
61
  findBetterFit: () => findBetterFit,
62
+ flushBrainDeadLetter: () => flushBrainDeadLetter,
61
63
  getActionableAdvisories: () => getActionableAdvisories,
62
64
  getAllStarterChains: () => getAllStarterChains,
63
65
  getAllStarterChainsWithGrounding: () => getAllStarterChainsWithGrounding,
@@ -92,6 +94,7 @@ __export(index_exports, {
92
94
  markAdvisoryResolved: () => markAdvisoryResolved,
93
95
  markExclusionFindingHandled: () => markExclusionFindingHandled,
94
96
  markPromoteReadyHandled: () => markPromoteReadyHandled,
97
+ peekBrainDeadLetter: () => peekBrainDeadLetter,
95
98
  probeShadow: () => probeShadow,
96
99
  profileToRow: () => profileToRow,
97
100
  profilesByProvider: () => profilesByProvider,
@@ -4468,6 +4471,134 @@ function clearBrain() {
4468
4471
  configureBrainQuery(void 0);
4469
4472
  configureExclusionFindingsBrain(void 0);
4470
4473
  }
4474
+ var DEAD_LETTER_MAX_ENTRIES = 50;
4475
+ var DEAD_LETTER_MAX_ATTEMPTS = 3;
4476
+ var ledger = {
4477
+ sent: 0,
4478
+ acked: 0,
4479
+ failed: 0,
4480
+ redirected: 0,
4481
+ lastAckAt: void 0,
4482
+ lastFailureAt: void 0,
4483
+ lastFailure: void 0
4484
+ };
4485
+ var deadLetter = [];
4486
+ var flushing = false;
4487
+ function noteSent() {
4488
+ ledger.sent += 1;
4489
+ }
4490
+ function noteAck() {
4491
+ ledger.acked += 1;
4492
+ ledger.lastAckAt = (/* @__PURE__ */ new Date()).toISOString();
4493
+ }
4494
+ function noteFailure(err) {
4495
+ ledger.failed += 1;
4496
+ ledger.lastFailureAt = (/* @__PURE__ */ new Date()).toISOString();
4497
+ const msg = err instanceof Error ? err.message : String(err);
4498
+ ledger.lastFailure = msg.length > 300 ? `${msg.slice(0, 300)}\u2026` : msg;
4499
+ }
4500
+ function assertNotRedirected(res, route) {
4501
+ if (!res.redirected) return;
4502
+ ledger.redirected += 1;
4503
+ throw new Error(
4504
+ `brain ${route} POST was redirected to ${res.url} \u2014 the write did NOT land. Likely cause: consumer middleware (auth/login allowlist) intercepts the brain proxy path. Add your kgauto proxy routes to the middleware public paths (the 2026-07-02 tt-intel/IC middleware-drift class).`
4505
+ );
4506
+ }
4507
+ function pushDeadLetter(route, endpoint, payload, err) {
4508
+ if (deadLetter.length >= DEAD_LETTER_MAX_ENTRIES) deadLetter.shift();
4509
+ deadLetter.push({
4510
+ route,
4511
+ endpoint,
4512
+ payload,
4513
+ failedAt: (/* @__PURE__ */ new Date()).toISOString(),
4514
+ attempts: 1,
4515
+ lastError: err instanceof Error ? err.message : String(err)
4516
+ });
4517
+ }
4518
+ function maybeAutoFlush() {
4519
+ if (deadLetter.length === 0 || flushing) return;
4520
+ void flushBrainDeadLetter();
4521
+ }
4522
+ function brainHealth() {
4523
+ let endpointHost;
4524
+ if (activeConfig) {
4525
+ try {
4526
+ endpointHost = new URL(activeConfig.endpoint).host;
4527
+ } catch {
4528
+ endpointHost = void 0;
4529
+ }
4530
+ }
4531
+ return {
4532
+ configState: activeConfig ? "configured" : "not_configured",
4533
+ endpointHost,
4534
+ sync: activeConfig?.sync === true,
4535
+ sent: ledger.sent,
4536
+ acked: ledger.acked,
4537
+ failed: ledger.failed,
4538
+ redirected: ledger.redirected,
4539
+ lastAckAt: ledger.lastAckAt,
4540
+ lastFailureAt: ledger.lastFailureAt,
4541
+ lastFailure: ledger.lastFailure,
4542
+ deadLetterCount: deadLetter.length
4543
+ };
4544
+ }
4545
+ function peekBrainDeadLetter() {
4546
+ return deadLetter.slice();
4547
+ }
4548
+ async function flushBrainDeadLetter() {
4549
+ if (!activeConfig || flushing || deadLetter.length === 0) {
4550
+ return { attempted: 0, delivered: 0, remaining: deadLetter.length };
4551
+ }
4552
+ flushing = true;
4553
+ const config = activeConfig;
4554
+ const fetchFn = brainWriteFetch(config);
4555
+ let attempted = 0;
4556
+ let delivered = 0;
4557
+ try {
4558
+ const batch = deadLetter.filter((e) => e.endpoint === config.endpoint);
4559
+ for (const entry of batch) {
4560
+ attempted += 1;
4561
+ noteSent();
4562
+ try {
4563
+ const res = await fetchFn(`${config.endpoint}/${entry.route}`, {
4564
+ method: "POST",
4565
+ headers: {
4566
+ "Content-Type": "application/json",
4567
+ // Replay never chains a secondary — minimal is correct for all routes.
4568
+ Prefer: "return=minimal",
4569
+ ...config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : {}
4570
+ },
4571
+ body: JSON.stringify(entry.payload)
4572
+ });
4573
+ assertNotRedirected(res, entry.route);
4574
+ if (!res.ok) {
4575
+ const text = await res.text().catch(() => "<no body>");
4576
+ throw new Error(describeBrainWriteFailure(res.status, entry.route, text));
4577
+ }
4578
+ noteAck();
4579
+ delivered += 1;
4580
+ const idx = deadLetter.indexOf(entry);
4581
+ if (idx !== -1) deadLetter.splice(idx, 1);
4582
+ } catch (err) {
4583
+ noteFailure(err);
4584
+ entry.attempts += 1;
4585
+ entry.lastError = err instanceof Error ? err.message : String(err);
4586
+ if (entry.attempts >= DEAD_LETTER_MAX_ATTEMPTS) {
4587
+ const idx = deadLetter.indexOf(entry);
4588
+ if (idx !== -1) deadLetter.splice(idx, 1);
4589
+ (config.onError ?? defaultOnError5)(
4590
+ new Error(
4591
+ `brain dead-letter: dropping ${entry.route} payload after ${entry.attempts} attempts \u2014 last error: ${entry.lastError}`
4592
+ )
4593
+ );
4594
+ }
4595
+ }
4596
+ }
4597
+ } finally {
4598
+ flushing = false;
4599
+ }
4600
+ return { attempted, delivered, remaining: deadLetter.length };
4601
+ }
4471
4602
  var compileRegistry = /* @__PURE__ */ new Map();
4472
4603
  var REGISTRY_MAX_ENTRIES = 1e4;
4473
4604
  function registerCompile(appId, archetype, ir, result) {
@@ -4575,6 +4706,7 @@ async function record(input) {
4575
4706
  const fetchFn = brainWriteFetch(config);
4576
4707
  const send = async () => {
4577
4708
  let outcomeId;
4709
+ noteSent();
4578
4710
  try {
4579
4711
  const res = await fetchFn(`${config.endpoint}/outcomes`, {
4580
4712
  method: "POST",
@@ -4594,20 +4726,26 @@ async function record(input) {
4594
4726
  },
4595
4727
  body: JSON.stringify(payload)
4596
4728
  });
4729
+ assertNotRedirected(res, "outcomes");
4597
4730
  if (!res.ok) {
4598
4731
  const text = await res.text().catch(() => "<no body>");
4599
4732
  throw new Error(describeBrainWriteFailure(res.status, "outcomes", text));
4600
4733
  }
4734
+ noteAck();
4601
4735
  outcomeId = await tryExtractOutcomeId(res);
4602
4736
  } catch (err) {
4737
+ noteFailure(err);
4738
+ pushDeadLetter("outcomes", config.endpoint, payload, err);
4603
4739
  (config.onError ?? defaultOnError5)(err);
4604
4740
  return;
4605
4741
  }
4742
+ maybeAutoFlush();
4606
4743
  const advisories = input.advisories ?? reg?.advisoriesFromCompile;
4607
4744
  if (!advisories || advisories.length === 0) return;
4608
4745
  if (outcomeId === void 0) return;
4746
+ const advisoryPayload = advisories.map((a) => buildAdvisoryRow(outcomeId, a));
4747
+ noteSent();
4609
4748
  try {
4610
- const advisoryPayload = advisories.map((a) => buildAdvisoryRow(outcomeId, a));
4611
4749
  const res = await fetchFn(`${config.endpoint}/compile_outcome_advisories`, {
4612
4750
  method: "POST",
4613
4751
  headers: {
@@ -4617,11 +4755,15 @@ async function record(input) {
4617
4755
  },
4618
4756
  body: JSON.stringify(advisoryPayload)
4619
4757
  });
4758
+ assertNotRedirected(res, "compile_outcome_advisories");
4620
4759
  if (!res.ok) {
4621
4760
  const text = await res.text().catch(() => "<no body>");
4622
4761
  throw new Error(`brain advisories ${res.status}: ${text}`);
4623
4762
  }
4763
+ noteAck();
4624
4764
  } catch (err) {
4765
+ noteFailure(err);
4766
+ pushDeadLetter("compile_outcome_advisories", config.endpoint, advisoryPayload, err);
4625
4767
  (config.onError ?? defaultOnError5)(err);
4626
4768
  }
4627
4769
  };
@@ -4760,6 +4902,7 @@ async function recordOutcome(input) {
4760
4902
  observed_confidence: input.observedConfidence ?? null
4761
4903
  };
4762
4904
  const send = async () => {
4905
+ noteSent();
4763
4906
  try {
4764
4907
  const res = await fetchFn(`${config.endpoint}/compile_outcome_quality`, {
4765
4908
  method: "POST",
@@ -4769,16 +4912,19 @@ async function recordOutcome(input) {
4769
4912
  },
4770
4913
  body: JSON.stringify(payload)
4771
4914
  });
4915
+ assertNotRedirected(res, "compile_outcome_quality");
4772
4916
  if (!res.ok) {
4773
4917
  const text = await res.text().catch(() => "<no body>");
4774
- const err = new Error(
4918
+ throw new Error(
4775
4919
  describeBrainWriteFailure(res.status, "compile_outcome_quality", text)
4776
4920
  );
4777
- (config.onError ?? defaultOnError5)(err);
4778
- return { ok: false, reason: "persistence_failed" };
4779
4921
  }
4922
+ noteAck();
4923
+ maybeAutoFlush();
4780
4924
  return { ok: true };
4781
4925
  } catch (err) {
4926
+ noteFailure(err);
4927
+ pushDeadLetter("compile_outcome_quality", config.endpoint, payload, err);
4782
4928
  (config.onError ?? defaultOnError5)(err);
4783
4929
  return { ok: false, reason: "persistence_failed" };
4784
4930
  }
@@ -4787,7 +4933,7 @@ async function recordOutcome(input) {
4787
4933
  return send();
4788
4934
  }
4789
4935
  void send();
4790
- return { ok: true };
4936
+ return { ok: "queued" };
4791
4937
  }
4792
4938
  function isBrainSync() {
4793
4939
  return activeConfig?.sync === true;
@@ -4829,6 +4975,7 @@ async function recordShadowProbe(input) {
4829
4975
  const fetchFn = brainWriteFetch(config);
4830
4976
  const row = buildShadowProbeRow(input);
4831
4977
  const send = async () => {
4978
+ noteSent();
4832
4979
  try {
4833
4980
  const res = await fetchFn(`${config.endpoint}/probe_outcomes`, {
4834
4981
  method: "POST",
@@ -4839,11 +4986,16 @@ async function recordShadowProbe(input) {
4839
4986
  },
4840
4987
  body: JSON.stringify(row)
4841
4988
  });
4989
+ assertNotRedirected(res, "probe_outcomes");
4842
4990
  if (!res.ok) {
4843
4991
  const text = await res.text().catch(() => "<no body>");
4844
4992
  throw new Error(describeBrainWriteFailure(res.status, "probe_outcomes", text));
4845
4993
  }
4994
+ noteAck();
4995
+ maybeAutoFlush();
4846
4996
  } catch (err) {
4997
+ noteFailure(err);
4998
+ pushDeadLetter("probe_outcomes", config.endpoint, row, err);
4847
4999
  (config.onError ?? defaultOnError5)(err);
4848
5000
  }
4849
5001
  };
@@ -6947,7 +7099,7 @@ function createBrainForwardRoutes(config) {
6947
7099
  }
6948
7100
 
6949
7101
  // src/version.ts
6950
- var LIBRARY_VERSION = "2.0.0-alpha.60";
7102
+ var LIBRARY_VERSION = "2.0.0-alpha.61";
6951
7103
 
6952
7104
  // src/key-health.ts
6953
7105
  var JSON_HEADERS2 = { "Content-Type": "application/json" };
@@ -7581,6 +7733,7 @@ function compile2(ir, opts) {
7581
7733
  applyArchetypeConvention,
7582
7734
  applySectionRewrites,
7583
7735
  attachCacheControlToStreamTextInput,
7736
+ brainHealth,
7584
7737
  bucketContext,
7585
7738
  bucketHistory,
7586
7739
  bucketToolCount,
@@ -7598,6 +7751,7 @@ function compile2(ir, opts) {
7598
7751
  deriveOwnership,
7599
7752
  execute,
7600
7753
  findBetterFit,
7754
+ flushBrainDeadLetter,
7601
7755
  getActionableAdvisories,
7602
7756
  getAllStarterChains,
7603
7757
  getAllStarterChainsWithGrounding,
@@ -7632,6 +7786,7 @@ function compile2(ir, opts) {
7632
7786
  markAdvisoryResolved,
7633
7787
  markExclusionFindingHandled,
7634
7788
  markPromoteReadyHandled,
7789
+ peekBrainDeadLetter,
7635
7790
  probeShadow,
7636
7791
  profileToRow,
7637
7792
  profilesByProvider,
package/dist/index.mjs CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  import {
16
16
  LIBRARY_VERSION,
17
17
  createKeyHealthRoute
18
- } from "./chunk-RQ3BUUB6.mjs";
18
+ } from "./chunk-3RMLZCUK.mjs";
19
19
  import {
20
20
  ABSOLUTE_FLOOR,
21
21
  ARCHETYPE_FLOOR_DEFAULT,
@@ -2626,6 +2626,134 @@ function clearBrain() {
2626
2626
  configureBrainQuery(void 0);
2627
2627
  configureExclusionFindingsBrain(void 0);
2628
2628
  }
2629
+ var DEAD_LETTER_MAX_ENTRIES = 50;
2630
+ var DEAD_LETTER_MAX_ATTEMPTS = 3;
2631
+ var ledger = {
2632
+ sent: 0,
2633
+ acked: 0,
2634
+ failed: 0,
2635
+ redirected: 0,
2636
+ lastAckAt: void 0,
2637
+ lastFailureAt: void 0,
2638
+ lastFailure: void 0
2639
+ };
2640
+ var deadLetter = [];
2641
+ var flushing = false;
2642
+ function noteSent() {
2643
+ ledger.sent += 1;
2644
+ }
2645
+ function noteAck() {
2646
+ ledger.acked += 1;
2647
+ ledger.lastAckAt = (/* @__PURE__ */ new Date()).toISOString();
2648
+ }
2649
+ function noteFailure(err) {
2650
+ ledger.failed += 1;
2651
+ ledger.lastFailureAt = (/* @__PURE__ */ new Date()).toISOString();
2652
+ const msg = err instanceof Error ? err.message : String(err);
2653
+ ledger.lastFailure = msg.length > 300 ? `${msg.slice(0, 300)}\u2026` : msg;
2654
+ }
2655
+ function assertNotRedirected(res, route) {
2656
+ if (!res.redirected) return;
2657
+ ledger.redirected += 1;
2658
+ throw new Error(
2659
+ `brain ${route} POST was redirected to ${res.url} \u2014 the write did NOT land. Likely cause: consumer middleware (auth/login allowlist) intercepts the brain proxy path. Add your kgauto proxy routes to the middleware public paths (the 2026-07-02 tt-intel/IC middleware-drift class).`
2660
+ );
2661
+ }
2662
+ function pushDeadLetter(route, endpoint, payload, err) {
2663
+ if (deadLetter.length >= DEAD_LETTER_MAX_ENTRIES) deadLetter.shift();
2664
+ deadLetter.push({
2665
+ route,
2666
+ endpoint,
2667
+ payload,
2668
+ failedAt: (/* @__PURE__ */ new Date()).toISOString(),
2669
+ attempts: 1,
2670
+ lastError: err instanceof Error ? err.message : String(err)
2671
+ });
2672
+ }
2673
+ function maybeAutoFlush() {
2674
+ if (deadLetter.length === 0 || flushing) return;
2675
+ void flushBrainDeadLetter();
2676
+ }
2677
+ function brainHealth() {
2678
+ let endpointHost;
2679
+ if (activeConfig) {
2680
+ try {
2681
+ endpointHost = new URL(activeConfig.endpoint).host;
2682
+ } catch {
2683
+ endpointHost = void 0;
2684
+ }
2685
+ }
2686
+ return {
2687
+ configState: activeConfig ? "configured" : "not_configured",
2688
+ endpointHost,
2689
+ sync: activeConfig?.sync === true,
2690
+ sent: ledger.sent,
2691
+ acked: ledger.acked,
2692
+ failed: ledger.failed,
2693
+ redirected: ledger.redirected,
2694
+ lastAckAt: ledger.lastAckAt,
2695
+ lastFailureAt: ledger.lastFailureAt,
2696
+ lastFailure: ledger.lastFailure,
2697
+ deadLetterCount: deadLetter.length
2698
+ };
2699
+ }
2700
+ function peekBrainDeadLetter() {
2701
+ return deadLetter.slice();
2702
+ }
2703
+ async function flushBrainDeadLetter() {
2704
+ if (!activeConfig || flushing || deadLetter.length === 0) {
2705
+ return { attempted: 0, delivered: 0, remaining: deadLetter.length };
2706
+ }
2707
+ flushing = true;
2708
+ const config = activeConfig;
2709
+ const fetchFn = brainWriteFetch(config);
2710
+ let attempted = 0;
2711
+ let delivered = 0;
2712
+ try {
2713
+ const batch = deadLetter.filter((e) => e.endpoint === config.endpoint);
2714
+ for (const entry of batch) {
2715
+ attempted += 1;
2716
+ noteSent();
2717
+ try {
2718
+ const res = await fetchFn(`${config.endpoint}/${entry.route}`, {
2719
+ method: "POST",
2720
+ headers: {
2721
+ "Content-Type": "application/json",
2722
+ // Replay never chains a secondary — minimal is correct for all routes.
2723
+ Prefer: "return=minimal",
2724
+ ...config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : {}
2725
+ },
2726
+ body: JSON.stringify(entry.payload)
2727
+ });
2728
+ assertNotRedirected(res, entry.route);
2729
+ if (!res.ok) {
2730
+ const text = await res.text().catch(() => "<no body>");
2731
+ throw new Error(describeBrainWriteFailure(res.status, entry.route, text));
2732
+ }
2733
+ noteAck();
2734
+ delivered += 1;
2735
+ const idx = deadLetter.indexOf(entry);
2736
+ if (idx !== -1) deadLetter.splice(idx, 1);
2737
+ } catch (err) {
2738
+ noteFailure(err);
2739
+ entry.attempts += 1;
2740
+ entry.lastError = err instanceof Error ? err.message : String(err);
2741
+ if (entry.attempts >= DEAD_LETTER_MAX_ATTEMPTS) {
2742
+ const idx = deadLetter.indexOf(entry);
2743
+ if (idx !== -1) deadLetter.splice(idx, 1);
2744
+ (config.onError ?? defaultOnError4)(
2745
+ new Error(
2746
+ `brain dead-letter: dropping ${entry.route} payload after ${entry.attempts} attempts \u2014 last error: ${entry.lastError}`
2747
+ )
2748
+ );
2749
+ }
2750
+ }
2751
+ }
2752
+ } finally {
2753
+ flushing = false;
2754
+ }
2755
+ return { attempted, delivered, remaining: deadLetter.length };
2756
+ }
2629
2757
  var compileRegistry = /* @__PURE__ */ new Map();
2630
2758
  var REGISTRY_MAX_ENTRIES = 1e4;
2631
2759
  function registerCompile(appId, archetype, ir, result) {
@@ -2733,6 +2861,7 @@ async function record(input) {
2733
2861
  const fetchFn = brainWriteFetch(config);
2734
2862
  const send = async () => {
2735
2863
  let outcomeId;
2864
+ noteSent();
2736
2865
  try {
2737
2866
  const res = await fetchFn(`${config.endpoint}/outcomes`, {
2738
2867
  method: "POST",
@@ -2752,20 +2881,26 @@ async function record(input) {
2752
2881
  },
2753
2882
  body: JSON.stringify(payload)
2754
2883
  });
2884
+ assertNotRedirected(res, "outcomes");
2755
2885
  if (!res.ok) {
2756
2886
  const text = await res.text().catch(() => "<no body>");
2757
2887
  throw new Error(describeBrainWriteFailure(res.status, "outcomes", text));
2758
2888
  }
2889
+ noteAck();
2759
2890
  outcomeId = await tryExtractOutcomeId(res);
2760
2891
  } catch (err) {
2892
+ noteFailure(err);
2893
+ pushDeadLetter("outcomes", config.endpoint, payload, err);
2761
2894
  (config.onError ?? defaultOnError4)(err);
2762
2895
  return;
2763
2896
  }
2897
+ maybeAutoFlush();
2764
2898
  const advisories = input.advisories ?? reg?.advisoriesFromCompile;
2765
2899
  if (!advisories || advisories.length === 0) return;
2766
2900
  if (outcomeId === void 0) return;
2901
+ const advisoryPayload = advisories.map((a) => buildAdvisoryRow(outcomeId, a));
2902
+ noteSent();
2767
2903
  try {
2768
- const advisoryPayload = advisories.map((a) => buildAdvisoryRow(outcomeId, a));
2769
2904
  const res = await fetchFn(`${config.endpoint}/compile_outcome_advisories`, {
2770
2905
  method: "POST",
2771
2906
  headers: {
@@ -2775,11 +2910,15 @@ async function record(input) {
2775
2910
  },
2776
2911
  body: JSON.stringify(advisoryPayload)
2777
2912
  });
2913
+ assertNotRedirected(res, "compile_outcome_advisories");
2778
2914
  if (!res.ok) {
2779
2915
  const text = await res.text().catch(() => "<no body>");
2780
2916
  throw new Error(`brain advisories ${res.status}: ${text}`);
2781
2917
  }
2918
+ noteAck();
2782
2919
  } catch (err) {
2920
+ noteFailure(err);
2921
+ pushDeadLetter("compile_outcome_advisories", config.endpoint, advisoryPayload, err);
2783
2922
  (config.onError ?? defaultOnError4)(err);
2784
2923
  }
2785
2924
  };
@@ -2918,6 +3057,7 @@ async function recordOutcome(input) {
2918
3057
  observed_confidence: input.observedConfidence ?? null
2919
3058
  };
2920
3059
  const send = async () => {
3060
+ noteSent();
2921
3061
  try {
2922
3062
  const res = await fetchFn(`${config.endpoint}/compile_outcome_quality`, {
2923
3063
  method: "POST",
@@ -2927,16 +3067,19 @@ async function recordOutcome(input) {
2927
3067
  },
2928
3068
  body: JSON.stringify(payload)
2929
3069
  });
3070
+ assertNotRedirected(res, "compile_outcome_quality");
2930
3071
  if (!res.ok) {
2931
3072
  const text = await res.text().catch(() => "<no body>");
2932
- const err = new Error(
3073
+ throw new Error(
2933
3074
  describeBrainWriteFailure(res.status, "compile_outcome_quality", text)
2934
3075
  );
2935
- (config.onError ?? defaultOnError4)(err);
2936
- return { ok: false, reason: "persistence_failed" };
2937
3076
  }
3077
+ noteAck();
3078
+ maybeAutoFlush();
2938
3079
  return { ok: true };
2939
3080
  } catch (err) {
3081
+ noteFailure(err);
3082
+ pushDeadLetter("compile_outcome_quality", config.endpoint, payload, err);
2940
3083
  (config.onError ?? defaultOnError4)(err);
2941
3084
  return { ok: false, reason: "persistence_failed" };
2942
3085
  }
@@ -2945,7 +3088,7 @@ async function recordOutcome(input) {
2945
3088
  return send();
2946
3089
  }
2947
3090
  void send();
2948
- return { ok: true };
3091
+ return { ok: "queued" };
2949
3092
  }
2950
3093
  function isBrainSync() {
2951
3094
  return activeConfig?.sync === true;
@@ -2987,6 +3130,7 @@ async function recordShadowProbe(input) {
2987
3130
  const fetchFn = brainWriteFetch(config);
2988
3131
  const row = buildShadowProbeRow(input);
2989
3132
  const send = async () => {
3133
+ noteSent();
2990
3134
  try {
2991
3135
  const res = await fetchFn(`${config.endpoint}/probe_outcomes`, {
2992
3136
  method: "POST",
@@ -2997,11 +3141,16 @@ async function recordShadowProbe(input) {
2997
3141
  },
2998
3142
  body: JSON.stringify(row)
2999
3143
  });
3144
+ assertNotRedirected(res, "probe_outcomes");
3000
3145
  if (!res.ok) {
3001
3146
  const text = await res.text().catch(() => "<no body>");
3002
3147
  throw new Error(describeBrainWriteFailure(res.status, "probe_outcomes", text));
3003
3148
  }
3149
+ noteAck();
3150
+ maybeAutoFlush();
3004
3151
  } catch (err) {
3152
+ noteFailure(err);
3153
+ pushDeadLetter("probe_outcomes", config.endpoint, row, err);
3005
3154
  (config.onError ?? defaultOnError4)(err);
3006
3155
  }
3007
3156
  };
@@ -4675,6 +4824,7 @@ export {
4675
4824
  applyArchetypeConvention,
4676
4825
  applySectionRewrites,
4677
4826
  attachCacheControlToStreamTextInput,
4827
+ brainHealth,
4678
4828
  bucketContext,
4679
4829
  bucketHistory,
4680
4830
  bucketToolCount,
@@ -4692,6 +4842,7 @@ export {
4692
4842
  deriveOwnership,
4693
4843
  execute,
4694
4844
  findBetterFit,
4845
+ flushBrainDeadLetter,
4695
4846
  getActionableAdvisories,
4696
4847
  getAllStarterChains,
4697
4848
  getAllStarterChainsWithGrounding,
@@ -4726,6 +4877,7 @@ export {
4726
4877
  markAdvisoryResolved,
4727
4878
  markExclusionFindingHandled,
4728
4879
  markPromoteReadyHandled,
4880
+ peekBrainDeadLetter,
4729
4881
  probeShadow,
4730
4882
  profileToRow,
4731
4883
  profilesByProvider,
@@ -1277,8 +1277,16 @@ interface RecordOutcomeInput {
1277
1277
  * surface as `ok: false` with a stable `reason` string.
1278
1278
  */
1279
1279
  interface OutcomeResult {
1280
- /** True when the POST landed (2xx). False when brain not configured or POST failed. */
1281
- ok: boolean;
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';
1282
1290
  /** Stable reason code when ok=false. One of: 'brain_not_configured' | 'persistence_failed'. */
1283
1291
  reason?: string;
1284
1292
  }
@@ -1277,8 +1277,16 @@ interface RecordOutcomeInput {
1277
1277
  * surface as `ok: false` with a stable `reason` string.
1278
1278
  */
1279
1279
  interface OutcomeResult {
1280
- /** True when the POST landed (2xx). False when brain not configured or POST failed. */
1281
- ok: boolean;
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';
1282
1290
  /** Stable reason code when ok=false. One of: 'brain_not_configured' | 'persistence_failed'. */
1283
1291
  reason?: string;
1284
1292
  }
@@ -25,7 +25,7 @@ __export(key_health_exports, {
25
25
  module.exports = __toCommonJS(key_health_exports);
26
26
 
27
27
  // src/version.ts
28
- var LIBRARY_VERSION = "2.0.0-alpha.60";
28
+ var LIBRARY_VERSION = "2.0.0-alpha.61";
29
29
 
30
30
  // src/key-health.ts
31
31
  var JSON_HEADERS = { "Content-Type": "application/json" };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createKeyHealthRoute
3
- } from "./chunk-RQ3BUUB6.mjs";
3
+ } from "./chunk-3RMLZCUK.mjs";
4
4
  export {
5
5
  createKeyHealthRoute
6
6
  };
@@ -1,4 +1,4 @@
1
- import { k as Provider } from './ir-BC4uDL98.mjs';
1
+ import { k as Provider } from './ir-DAKlQsVb.mjs';
2
2
  import { IntentArchetypeName } from './dialect.mjs';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { k as Provider } from './ir-B2h0GAEL.js';
1
+ import { k as Provider } from './ir-DmUuJsWc.js';
2
2
  import { IntentArchetypeName } from './dialect.js';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { i as Adapter, w as SectionKind } from './ir-B2h0GAEL.js';
1
+ import { i as Adapter, w as SectionKind } from './ir-DmUuJsWc.js';
2
2
 
3
3
  /**
4
4
  * Internal config + hook types for createGlassboxRoutes().
@@ -1,4 +1,4 @@
1
- import { r as MutationApplied, B as BestPracticeAdvisory, F as FallbackReason, m as CallAttempt } from './ir-BC4uDL98.mjs';
1
+ import { r as MutationApplied, B as BestPracticeAdvisory, F as FallbackReason, m as CallAttempt } from './ir-DAKlQsVb.mjs';
2
2
 
3
3
  /**
4
4
  * Glass-Box observability types (alpha.17).
@@ -1,4 +1,4 @@
1
- import { r as MutationApplied, B as BestPracticeAdvisory, F as FallbackReason, m as CallAttempt } from './ir-B2h0GAEL.js';
1
+ import { r as MutationApplied, B as BestPracticeAdvisory, F as FallbackReason, m as CallAttempt } from './ir-DmUuJsWc.js';
2
2
 
3
3
  /**
4
4
  * Glass-Box observability types (alpha.17).
@@ -1,4 +1,4 @@
1
- import { i as Adapter, w as SectionKind } from './ir-BC4uDL98.mjs';
1
+ import { i as Adapter, w as SectionKind } from './ir-DAKlQsVb.mjs';
2
2
 
3
3
  /**
4
4
  * Internal config + hook types for createGlassboxRoutes().
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@warmdrift/kgauto-compiler",
3
- "version": "2.0.0-alpha.60",
4
- "description": "Prompt compiler + central learning brain for multi-model AI apps. Swap models without rewriting prompts.",
3
+ "version": "2.0.0-alpha.61",
4
+ "description": "Prompt compiler with executable provider knowledge for multi-model AI apps: normalized multi-provider transport with fallback chains, compile-time cliff guards, a curated model registry, and a telemetry flight recorder. Swap models without rewriting prompts.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
7
7
  "types": "./dist/index.d.ts",
@@ -73,7 +73,7 @@
73
73
  "gemini",
74
74
  "deepseek",
75
75
  "prompt-cache",
76
- "self-improving"
76
+ "model-fallback"
77
77
  ],
78
78
  "license": "MIT",
79
79
  "peerDependencies": {