@warmdrift/kgauto-compiler 2.0.0-alpha.37 → 2.0.0-alpha.38

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/dist/index.d.mts CHANGED
@@ -203,11 +203,28 @@ interface BrainQueryConfig {
203
203
  pricing?: boolean;
204
204
  /** Default true when endpoint set. Brain-driven model registry + aliases. */
205
205
  models?: boolean;
206
+ /**
207
+ * alpha.38 — opt-in compile-time advisor for stale exclusions. Default
208
+ * `true` when endpoint is set. When enabled, the library reads
209
+ * `exclusion_findings` from the central kgauto-dashboard for the consumer's
210
+ * `app_id` (no consumer-side proxy work required) and surfaces a
211
+ * `stale-exclusion-candidate` advisory when compile()'s archetype has a
212
+ * recommend-probe finding open. Set `false` to silence (no fetch, no
213
+ * advisory).
214
+ */
215
+ findingsExclusions?: boolean;
206
216
  /** SWR window in ms. Default 300_000 (5 min). */
207
217
  cacheTtlMs?: number;
208
218
  /** Override the GET URL when the read endpoint differs from the write one.
209
219
  * Defaults to `${endpoint}/v2/config` when omitted. */
210
220
  configEndpoint?: string;
221
+ /**
222
+ * alpha.38 — override the findings endpoint when the consumer wants to
223
+ * proxy `exclusion_findings` reads through their own service rather than
224
+ * reading directly from the kgauto-dashboard. Library appends `?app_id=X`.
225
+ * Defaults to `https://kgauto-dashboard.vercel.app/api/kgauto-v2/findings/exclusions`.
226
+ */
227
+ findingsEndpoint?: string;
211
228
  }
212
229
  interface BrainConfig {
213
230
  /** Brain HTTP endpoint base URL (e.g., https://kgauto-brain.vercel.app/api). */
@@ -1465,6 +1482,105 @@ declare const loadModelsFromBrain: () => Map<string, ModelProfile>;
1465
1482
  */
1466
1483
  declare const loadAliasesFromBrain: () => Record<string, string>;
1467
1484
 
1485
+ /**
1486
+ * exclusion-findings-brain — alpha.38 KG-19 adapter.
1487
+ *
1488
+ * Per-tenant SWR cache for the `exclusion_findings` table populated by the
1489
+ * `kgauto-exclusion-re-evaluation-watch` cron (alpha.37 substrate). Distinct
1490
+ * from the cross-tenant `brain-query.ts` snapshot because exclusion findings
1491
+ * are scoped per `app_id` — one process = one consumer = one appId, but the
1492
+ * cache key supports multi-app processes by keying snapshots by appId.
1493
+ *
1494
+ * Architecture mirrors `brain-query.ts` but with a per-(appId) snapshot:
1495
+ *
1496
+ * - **Sync API surface.** `getStaleExclusionFindings({ appId, archetype })`
1497
+ * returns `ExclusionFindingRow[]` immediately. First call returns the
1498
+ * bundled fallback (empty array); async refresh fires in background;
1499
+ * subsequent calls within TTL return brain data.
1500
+ *
1501
+ * - **Per-appId snapshot.** Each appId gets its own cache entry. One fetch
1502
+ * per appId per TTL window. Tests can reset between cases.
1503
+ *
1504
+ * - **Tolerant.** Brain down / endpoint misconfigured / unexpected shape →
1505
+ * silent bundled fallback (empty array). Never throws. Warns once per
1506
+ * process per error to avoid log spam.
1507
+ *
1508
+ * - **Opt-in.** Activation gated on `configureExclusionFindingsBrain()`
1509
+ * having been called with a runtime. The public `configureBrain()` in
1510
+ * brain.ts wires this up automatically when `BrainConfig.brainQuery
1511
+ * .findingsExclusions !== false`.
1512
+ *
1513
+ * Default endpoint:
1514
+ * `https://kgauto-dashboard.vercel.app/api/kgauto-v2/findings/exclusions`
1515
+ * The route accepts `?app_id=X` and returns a JSON array of findings
1516
+ * for that app filtered to `resolved_at IS NULL`. Public read; data
1517
+ * carries no consumer PII (app id, archetype, model id, cost ratio,
1518
+ * savings estimate).
1519
+ */
1520
+ /**
1521
+ * Shape of one row from the `exclusion_findings` cache table. Mirrors the
1522
+ * snake_case JSONB returned by the brain RPC + the dashboard endpoint.
1523
+ * Camel-case mapping happens at the boundary (rowToFinding) so the in-memory
1524
+ * shape stays consistent with the rest of the library.
1525
+ */
1526
+ interface ExclusionFindingRow {
1527
+ /** Intent archetype the finding applies to (e.g. 'hunt', 'classify'). */
1528
+ archetype: string;
1529
+ /** Canonical model id that the consumer has excluded (zero traffic in window). */
1530
+ excludedModel: string;
1531
+ /** Provider of the excluded model (e.g. 'deepseek', 'openai'). */
1532
+ excludedProvider: string;
1533
+ /** Detection verdict — alpha.37 ships 'recommend-probe' only. */
1534
+ verdict: 'recommend-probe' | 'unblock' | 'stay-excluded' | 'inconclusive';
1535
+ /**
1536
+ * Estimated 30-day savings in USD if the excluded model becomes primary
1537
+ * on this archetype. Null when pricing is incomplete or excluded model is
1538
+ * more expensive than the leader.
1539
+ */
1540
+ estimatedSavingsUsd30d: number | null;
1541
+ /** Renderable summary; produced by the detector / RPC. */
1542
+ message: string;
1543
+ /** Actionable recommendation; produced by the detector / RPC. */
1544
+ suggestion: string;
1545
+ /** Detector confidence tier. */
1546
+ confidence: 'high' | 'medium' | 'low';
1547
+ /**
1548
+ * Free-form evidence pack (cost ratio, leader info, promo flags, parallel-
1549
+ * tool hint, etc.). Surfaced verbatim to advisor rules for richer messages.
1550
+ * Optional — older detector runs may not populate every field.
1551
+ */
1552
+ evidence?: Record<string, unknown>;
1553
+ }
1554
+ /**
1555
+ * Default endpoint hosted on the kgauto-dashboard. Public read — data carries
1556
+ * no PII (app id, archetype, model id, cost ratio, savings estimate). Mirrors
1557
+ * the cross-tenant `/api/kgauto-v2/config` pattern.
1558
+ */
1559
+ declare const DEFAULT_FINDINGS_ENDPOINT = "https://kgauto-dashboard.vercel.app/api/kgauto-v2/findings/exclusions";
1560
+ /**
1561
+ * Sync introspection — is the findings-brain active? Used by advisor rules
1562
+ * to decide whether to even attempt a read.
1563
+ */
1564
+ declare function isExclusionFindingsBrainActive(): boolean;
1565
+ interface GetExclusionFindingsOpts {
1566
+ /** App id to read findings for. Required. */
1567
+ appId: string;
1568
+ /**
1569
+ * Optional archetype filter. When set, returns only findings where
1570
+ * `archetype` matches. When omitted, returns all findings for the app.
1571
+ */
1572
+ archetype?: string;
1573
+ }
1574
+ /**
1575
+ * Sync reader. Returns the cached findings for `appId`, optionally filtered
1576
+ * to a single archetype. First call returns empty array and triggers async
1577
+ * refresh; subsequent calls within TTL return brain data.
1578
+ *
1579
+ * NEVER throws. Brain down / endpoint misconfigured / mapper exception →
1580
+ * empty array.
1581
+ */
1582
+ declare function getStaleExclusionFindings(opts: GetExclusionFindingsOpts): ExclusionFindingRow[];
1583
+
1468
1584
  /**
1469
1585
  * @warmdrift/kgauto v2 — prompt compiler + central learning brain.
1470
1586
  *
@@ -1511,4 +1627,4 @@ declare const loadAliasesFromBrain: () => Record<string, string>;
1511
1627
  */
1512
1628
  declare function compile(ir: PromptIR, opts?: CompileOptions): CompileResult;
1513
1629
 
1514
- export { ABSOLUTE_FLOOR, type AISDKConvertedMessage, ARCHETYPE_FLOOR_DEFAULT, type ActionableAdvisory, Adapter, type AdvisoryResolutionSource, type AdvisorySeverity, type AdvisoryStatus, type AdvisorySuggestedFix, ApiKeys, type AppOracle, type ApplySectionRewritesArgs, type ApplySectionRewritesResult, type ArchetypePerfMap, type ArchetypePerfNMap, type ArchetypePerfScoreResult, type AttachCacheControlResult, BestPracticeAdvisory, type BrainConfig, type BrainQueryConfig, CallOptions, CallResult, ChainEntry, type CompatibilityIntent, type CompileOptions, CompilePolicy, CompileResult, CompiledRequest, type ExecuteErr, type ExecuteOk, type ExecuteOptions, type ExecuteResult, type FallbackPosture, type GetActionableAdvisoriesOptions, type GetDefaultFallbackChainOpts, type GetPerAxisMetricsOpts, Grounding, IntentArchetypeName, type LLMJudgeOptions, MEASURED_GROUNDING_MIN_N, type MarkAdvisoryResolvedOptions, type ModelBrainRow, type ModelCompatibility, ModelProfile, NormalizedResponse, type OracleContext, OracleScore, type OutcomePayload, OutcomeResult, PROVIDER_ENV_KEYS, PerAxisMetrics, type PricingRow, type ProfileToRowOptions, PromptIR, Provider, ProviderOverrides, type ProviderReachability, RULE_SEQUENTIAL_TOOL_CLIFF, type ReachabilityOpts, RecordInput, RecordOutcomeInput, type RunAdvisorPhase2Context, SectionRewrite, type SupportedProvider, SystemModelMessage, TRANSLATOR_FLOOR, applySectionRewrites, attachCacheControlToStreamTextInput, buildLLMJudge, call, clearBrain, compile, configureBrain, countTokens, execute, getActionableAdvisories, getAllStarterChains, getAllStarterChainsWithGrounding, getArchetypePerfScore, getDefaultFallbackChain, getDefaultFallbackChainWithGrounding, getModelCompatibility, getPerAxisMetrics, getReachabilityDiagnostic, getSequentialStarterChain, getSequentialStarterChainWithGrounding, getStarterChain, getStarterChainWithGrounding, isBrainQueryActiveFor, isModelReachable, isProviderReachable, loadAliasesFromBrain, loadArchetypePerfFromBrain, loadArchetypePerfNFromBrain, loadChainsFromBrain, loadModelsFromBrain, loadPricingFromBrain, markAdvisoryResolved, profileToRow, record, recordOutcome, resetTokenizer, resolvePricingAt, resolveProviderKey, runAdvisor, setTokenizer };
1630
+ export { ABSOLUTE_FLOOR, type AISDKConvertedMessage, ARCHETYPE_FLOOR_DEFAULT, type ActionableAdvisory, Adapter, type AdvisoryResolutionSource, type AdvisorySeverity, type AdvisoryStatus, type AdvisorySuggestedFix, ApiKeys, type AppOracle, type ApplySectionRewritesArgs, type ApplySectionRewritesResult, type ArchetypePerfMap, type ArchetypePerfNMap, type ArchetypePerfScoreResult, type AttachCacheControlResult, BestPracticeAdvisory, type BrainConfig, type BrainQueryConfig, CallOptions, CallResult, ChainEntry, type CompatibilityIntent, type CompileOptions, CompilePolicy, CompileResult, CompiledRequest, DEFAULT_FINDINGS_ENDPOINT, type ExclusionFindingRow, type ExecuteErr, type ExecuteOk, type ExecuteOptions, type ExecuteResult, type FallbackPosture, type GetActionableAdvisoriesOptions, type GetDefaultFallbackChainOpts, type GetPerAxisMetricsOpts, Grounding, IntentArchetypeName, type LLMJudgeOptions, MEASURED_GROUNDING_MIN_N, type MarkAdvisoryResolvedOptions, type ModelBrainRow, type ModelCompatibility, ModelProfile, NormalizedResponse, type OracleContext, OracleScore, type OutcomePayload, OutcomeResult, PROVIDER_ENV_KEYS, PerAxisMetrics, type PricingRow, type ProfileToRowOptions, PromptIR, Provider, ProviderOverrides, type ProviderReachability, RULE_SEQUENTIAL_TOOL_CLIFF, type ReachabilityOpts, RecordInput, RecordOutcomeInput, type RunAdvisorPhase2Context, SectionRewrite, type SupportedProvider, SystemModelMessage, TRANSLATOR_FLOOR, applySectionRewrites, attachCacheControlToStreamTextInput, buildLLMJudge, call, clearBrain, compile, configureBrain, countTokens, execute, getActionableAdvisories, getAllStarterChains, getAllStarterChainsWithGrounding, getArchetypePerfScore, getDefaultFallbackChain, getDefaultFallbackChainWithGrounding, getModelCompatibility, getPerAxisMetrics, getReachabilityDiagnostic, getSequentialStarterChain, getSequentialStarterChainWithGrounding, getStaleExclusionFindings, getStarterChain, getStarterChainWithGrounding, isBrainQueryActiveFor, isExclusionFindingsBrainActive, isModelReachable, isProviderReachable, loadAliasesFromBrain, loadArchetypePerfFromBrain, loadArchetypePerfNFromBrain, loadChainsFromBrain, loadModelsFromBrain, loadPricingFromBrain, markAdvisoryResolved, profileToRow, record, recordOutcome, resetTokenizer, resolvePricingAt, resolveProviderKey, runAdvisor, setTokenizer };
package/dist/index.d.ts CHANGED
@@ -203,11 +203,28 @@ interface BrainQueryConfig {
203
203
  pricing?: boolean;
204
204
  /** Default true when endpoint set. Brain-driven model registry + aliases. */
205
205
  models?: boolean;
206
+ /**
207
+ * alpha.38 — opt-in compile-time advisor for stale exclusions. Default
208
+ * `true` when endpoint is set. When enabled, the library reads
209
+ * `exclusion_findings` from the central kgauto-dashboard for the consumer's
210
+ * `app_id` (no consumer-side proxy work required) and surfaces a
211
+ * `stale-exclusion-candidate` advisory when compile()'s archetype has a
212
+ * recommend-probe finding open. Set `false` to silence (no fetch, no
213
+ * advisory).
214
+ */
215
+ findingsExclusions?: boolean;
206
216
  /** SWR window in ms. Default 300_000 (5 min). */
207
217
  cacheTtlMs?: number;
208
218
  /** Override the GET URL when the read endpoint differs from the write one.
209
219
  * Defaults to `${endpoint}/v2/config` when omitted. */
210
220
  configEndpoint?: string;
221
+ /**
222
+ * alpha.38 — override the findings endpoint when the consumer wants to
223
+ * proxy `exclusion_findings` reads through their own service rather than
224
+ * reading directly from the kgauto-dashboard. Library appends `?app_id=X`.
225
+ * Defaults to `https://kgauto-dashboard.vercel.app/api/kgauto-v2/findings/exclusions`.
226
+ */
227
+ findingsEndpoint?: string;
211
228
  }
212
229
  interface BrainConfig {
213
230
  /** Brain HTTP endpoint base URL (e.g., https://kgauto-brain.vercel.app/api). */
@@ -1465,6 +1482,105 @@ declare const loadModelsFromBrain: () => Map<string, ModelProfile>;
1465
1482
  */
1466
1483
  declare const loadAliasesFromBrain: () => Record<string, string>;
1467
1484
 
1485
+ /**
1486
+ * exclusion-findings-brain — alpha.38 KG-19 adapter.
1487
+ *
1488
+ * Per-tenant SWR cache for the `exclusion_findings` table populated by the
1489
+ * `kgauto-exclusion-re-evaluation-watch` cron (alpha.37 substrate). Distinct
1490
+ * from the cross-tenant `brain-query.ts` snapshot because exclusion findings
1491
+ * are scoped per `app_id` — one process = one consumer = one appId, but the
1492
+ * cache key supports multi-app processes by keying snapshots by appId.
1493
+ *
1494
+ * Architecture mirrors `brain-query.ts` but with a per-(appId) snapshot:
1495
+ *
1496
+ * - **Sync API surface.** `getStaleExclusionFindings({ appId, archetype })`
1497
+ * returns `ExclusionFindingRow[]` immediately. First call returns the
1498
+ * bundled fallback (empty array); async refresh fires in background;
1499
+ * subsequent calls within TTL return brain data.
1500
+ *
1501
+ * - **Per-appId snapshot.** Each appId gets its own cache entry. One fetch
1502
+ * per appId per TTL window. Tests can reset between cases.
1503
+ *
1504
+ * - **Tolerant.** Brain down / endpoint misconfigured / unexpected shape →
1505
+ * silent bundled fallback (empty array). Never throws. Warns once per
1506
+ * process per error to avoid log spam.
1507
+ *
1508
+ * - **Opt-in.** Activation gated on `configureExclusionFindingsBrain()`
1509
+ * having been called with a runtime. The public `configureBrain()` in
1510
+ * brain.ts wires this up automatically when `BrainConfig.brainQuery
1511
+ * .findingsExclusions !== false`.
1512
+ *
1513
+ * Default endpoint:
1514
+ * `https://kgauto-dashboard.vercel.app/api/kgauto-v2/findings/exclusions`
1515
+ * The route accepts `?app_id=X` and returns a JSON array of findings
1516
+ * for that app filtered to `resolved_at IS NULL`. Public read; data
1517
+ * carries no consumer PII (app id, archetype, model id, cost ratio,
1518
+ * savings estimate).
1519
+ */
1520
+ /**
1521
+ * Shape of one row from the `exclusion_findings` cache table. Mirrors the
1522
+ * snake_case JSONB returned by the brain RPC + the dashboard endpoint.
1523
+ * Camel-case mapping happens at the boundary (rowToFinding) so the in-memory
1524
+ * shape stays consistent with the rest of the library.
1525
+ */
1526
+ interface ExclusionFindingRow {
1527
+ /** Intent archetype the finding applies to (e.g. 'hunt', 'classify'). */
1528
+ archetype: string;
1529
+ /** Canonical model id that the consumer has excluded (zero traffic in window). */
1530
+ excludedModel: string;
1531
+ /** Provider of the excluded model (e.g. 'deepseek', 'openai'). */
1532
+ excludedProvider: string;
1533
+ /** Detection verdict — alpha.37 ships 'recommend-probe' only. */
1534
+ verdict: 'recommend-probe' | 'unblock' | 'stay-excluded' | 'inconclusive';
1535
+ /**
1536
+ * Estimated 30-day savings in USD if the excluded model becomes primary
1537
+ * on this archetype. Null when pricing is incomplete or excluded model is
1538
+ * more expensive than the leader.
1539
+ */
1540
+ estimatedSavingsUsd30d: number | null;
1541
+ /** Renderable summary; produced by the detector / RPC. */
1542
+ message: string;
1543
+ /** Actionable recommendation; produced by the detector / RPC. */
1544
+ suggestion: string;
1545
+ /** Detector confidence tier. */
1546
+ confidence: 'high' | 'medium' | 'low';
1547
+ /**
1548
+ * Free-form evidence pack (cost ratio, leader info, promo flags, parallel-
1549
+ * tool hint, etc.). Surfaced verbatim to advisor rules for richer messages.
1550
+ * Optional — older detector runs may not populate every field.
1551
+ */
1552
+ evidence?: Record<string, unknown>;
1553
+ }
1554
+ /**
1555
+ * Default endpoint hosted on the kgauto-dashboard. Public read — data carries
1556
+ * no PII (app id, archetype, model id, cost ratio, savings estimate). Mirrors
1557
+ * the cross-tenant `/api/kgauto-v2/config` pattern.
1558
+ */
1559
+ declare const DEFAULT_FINDINGS_ENDPOINT = "https://kgauto-dashboard.vercel.app/api/kgauto-v2/findings/exclusions";
1560
+ /**
1561
+ * Sync introspection — is the findings-brain active? Used by advisor rules
1562
+ * to decide whether to even attempt a read.
1563
+ */
1564
+ declare function isExclusionFindingsBrainActive(): boolean;
1565
+ interface GetExclusionFindingsOpts {
1566
+ /** App id to read findings for. Required. */
1567
+ appId: string;
1568
+ /**
1569
+ * Optional archetype filter. When set, returns only findings where
1570
+ * `archetype` matches. When omitted, returns all findings for the app.
1571
+ */
1572
+ archetype?: string;
1573
+ }
1574
+ /**
1575
+ * Sync reader. Returns the cached findings for `appId`, optionally filtered
1576
+ * to a single archetype. First call returns empty array and triggers async
1577
+ * refresh; subsequent calls within TTL return brain data.
1578
+ *
1579
+ * NEVER throws. Brain down / endpoint misconfigured / mapper exception →
1580
+ * empty array.
1581
+ */
1582
+ declare function getStaleExclusionFindings(opts: GetExclusionFindingsOpts): ExclusionFindingRow[];
1583
+
1468
1584
  /**
1469
1585
  * @warmdrift/kgauto v2 — prompt compiler + central learning brain.
1470
1586
  *
@@ -1511,4 +1627,4 @@ declare const loadAliasesFromBrain: () => Record<string, string>;
1511
1627
  */
1512
1628
  declare function compile(ir: PromptIR, opts?: CompileOptions): CompileResult;
1513
1629
 
1514
- export { ABSOLUTE_FLOOR, type AISDKConvertedMessage, ARCHETYPE_FLOOR_DEFAULT, type ActionableAdvisory, Adapter, type AdvisoryResolutionSource, type AdvisorySeverity, type AdvisoryStatus, type AdvisorySuggestedFix, ApiKeys, type AppOracle, type ApplySectionRewritesArgs, type ApplySectionRewritesResult, type ArchetypePerfMap, type ArchetypePerfNMap, type ArchetypePerfScoreResult, type AttachCacheControlResult, BestPracticeAdvisory, type BrainConfig, type BrainQueryConfig, CallOptions, CallResult, ChainEntry, type CompatibilityIntent, type CompileOptions, CompilePolicy, CompileResult, CompiledRequest, type ExecuteErr, type ExecuteOk, type ExecuteOptions, type ExecuteResult, type FallbackPosture, type GetActionableAdvisoriesOptions, type GetDefaultFallbackChainOpts, type GetPerAxisMetricsOpts, Grounding, IntentArchetypeName, type LLMJudgeOptions, MEASURED_GROUNDING_MIN_N, type MarkAdvisoryResolvedOptions, type ModelBrainRow, type ModelCompatibility, ModelProfile, NormalizedResponse, type OracleContext, OracleScore, type OutcomePayload, OutcomeResult, PROVIDER_ENV_KEYS, PerAxisMetrics, type PricingRow, type ProfileToRowOptions, PromptIR, Provider, ProviderOverrides, type ProviderReachability, RULE_SEQUENTIAL_TOOL_CLIFF, type ReachabilityOpts, RecordInput, RecordOutcomeInput, type RunAdvisorPhase2Context, SectionRewrite, type SupportedProvider, SystemModelMessage, TRANSLATOR_FLOOR, applySectionRewrites, attachCacheControlToStreamTextInput, buildLLMJudge, call, clearBrain, compile, configureBrain, countTokens, execute, getActionableAdvisories, getAllStarterChains, getAllStarterChainsWithGrounding, getArchetypePerfScore, getDefaultFallbackChain, getDefaultFallbackChainWithGrounding, getModelCompatibility, getPerAxisMetrics, getReachabilityDiagnostic, getSequentialStarterChain, getSequentialStarterChainWithGrounding, getStarterChain, getStarterChainWithGrounding, isBrainQueryActiveFor, isModelReachable, isProviderReachable, loadAliasesFromBrain, loadArchetypePerfFromBrain, loadArchetypePerfNFromBrain, loadChainsFromBrain, loadModelsFromBrain, loadPricingFromBrain, markAdvisoryResolved, profileToRow, record, recordOutcome, resetTokenizer, resolvePricingAt, resolveProviderKey, runAdvisor, setTokenizer };
1630
+ export { ABSOLUTE_FLOOR, type AISDKConvertedMessage, ARCHETYPE_FLOOR_DEFAULT, type ActionableAdvisory, Adapter, type AdvisoryResolutionSource, type AdvisorySeverity, type AdvisoryStatus, type AdvisorySuggestedFix, ApiKeys, type AppOracle, type ApplySectionRewritesArgs, type ApplySectionRewritesResult, type ArchetypePerfMap, type ArchetypePerfNMap, type ArchetypePerfScoreResult, type AttachCacheControlResult, BestPracticeAdvisory, type BrainConfig, type BrainQueryConfig, CallOptions, CallResult, ChainEntry, type CompatibilityIntent, type CompileOptions, CompilePolicy, CompileResult, CompiledRequest, DEFAULT_FINDINGS_ENDPOINT, type ExclusionFindingRow, type ExecuteErr, type ExecuteOk, type ExecuteOptions, type ExecuteResult, type FallbackPosture, type GetActionableAdvisoriesOptions, type GetDefaultFallbackChainOpts, type GetPerAxisMetricsOpts, Grounding, IntentArchetypeName, type LLMJudgeOptions, MEASURED_GROUNDING_MIN_N, type MarkAdvisoryResolvedOptions, type ModelBrainRow, type ModelCompatibility, ModelProfile, NormalizedResponse, type OracleContext, OracleScore, type OutcomePayload, OutcomeResult, PROVIDER_ENV_KEYS, PerAxisMetrics, type PricingRow, type ProfileToRowOptions, PromptIR, Provider, ProviderOverrides, type ProviderReachability, RULE_SEQUENTIAL_TOOL_CLIFF, type ReachabilityOpts, RecordInput, RecordOutcomeInput, type RunAdvisorPhase2Context, SectionRewrite, type SupportedProvider, SystemModelMessage, TRANSLATOR_FLOOR, applySectionRewrites, attachCacheControlToStreamTextInput, buildLLMJudge, call, clearBrain, compile, configureBrain, countTokens, execute, getActionableAdvisories, getAllStarterChains, getAllStarterChainsWithGrounding, getArchetypePerfScore, getDefaultFallbackChain, getDefaultFallbackChainWithGrounding, getModelCompatibility, getPerAxisMetrics, getReachabilityDiagnostic, getSequentialStarterChain, getSequentialStarterChainWithGrounding, getStaleExclusionFindings, getStarterChain, getStarterChainWithGrounding, isBrainQueryActiveFor, isExclusionFindingsBrainActive, isModelReachable, isProviderReachable, loadAliasesFromBrain, loadArchetypePerfFromBrain, loadArchetypePerfNFromBrain, loadChainsFromBrain, loadModelsFromBrain, loadPricingFromBrain, markAdvisoryResolved, profileToRow, record, recordOutcome, resetTokenizer, resolvePricingAt, resolveProviderKey, runAdvisor, setTokenizer };
package/dist/index.js CHANGED
@@ -25,6 +25,7 @@ __export(index_exports, {
25
25
  ALL_ARCHETYPES: () => ALL_ARCHETYPES,
26
26
  ARCHETYPE_FLOOR_DEFAULT: () => ARCHETYPE_FLOOR_DEFAULT,
27
27
  CallError: () => CallError,
28
+ DEFAULT_FINDINGS_ENDPOINT: () => DEFAULT_FINDINGS_ENDPOINT,
28
29
  DIALECT_VERSION: () => DIALECT_VERSION,
29
30
  INTENT_ARCHETYPES: () => INTENT_ARCHETYPES,
30
31
  MEASURED_GROUNDING_MIN_N: () => MEASURED_GROUNDING_MIN_N,
@@ -56,11 +57,13 @@ __export(index_exports, {
56
57
  getReachabilityDiagnostic: () => getReachabilityDiagnostic,
57
58
  getSequentialStarterChain: () => getSequentialStarterChain,
58
59
  getSequentialStarterChainWithGrounding: () => getSequentialStarterChainWithGrounding,
60
+ getStaleExclusionFindings: () => getStaleExclusionFindings,
59
61
  getStarterChain: () => getStarterChain,
60
62
  getStarterChainWithGrounding: () => getStarterChainWithGrounding,
61
63
  hashShape: () => hashShape,
62
64
  isArchetype: () => isArchetype,
63
65
  isBrainQueryActiveFor: () => isBrainQueryActiveFor,
66
+ isExclusionFindingsBrainActive: () => isExclusionFindingsBrainActive,
64
67
  isModelReachable: () => isModelReachable,
65
68
  isProviderReachable: () => isProviderReachable,
66
69
  learningKey: () => learningKey,
@@ -2400,6 +2403,125 @@ function getModelCompatibility(modelId, intent) {
2400
2403
  };
2401
2404
  }
2402
2405
 
2406
+ // src/exclusion-findings-brain.ts
2407
+ function isValidVerdict(v) {
2408
+ return v === "recommend-probe" || v === "unblock" || v === "stay-excluded" || v === "inconclusive";
2409
+ }
2410
+ function isValidConfidence(v) {
2411
+ return v === "high" || v === "medium" || v === "low";
2412
+ }
2413
+ function isRawFindingRow(x) {
2414
+ if (!x || typeof x !== "object") return false;
2415
+ const r = x;
2416
+ return typeof r.intent_archetype === "string" && typeof r.excluded_model === "string" && typeof r.excluded_provider === "string" && typeof r.verdict === "string" && typeof r.message === "string" && typeof r.suggestion === "string" && typeof r.confidence === "string";
2417
+ }
2418
+ function mapRowsToFindings(rows) {
2419
+ const out = [];
2420
+ for (const row of rows) {
2421
+ if (!isRawFindingRow(row)) continue;
2422
+ if (!isValidVerdict(row.verdict)) continue;
2423
+ if (!isValidConfidence(row.confidence)) continue;
2424
+ let savings = null;
2425
+ if (typeof row.estimated_savings_usd_30d === "number") {
2426
+ savings = Number.isFinite(row.estimated_savings_usd_30d) ? row.estimated_savings_usd_30d : null;
2427
+ } else if (typeof row.estimated_savings_usd_30d === "string") {
2428
+ const n = Number(row.estimated_savings_usd_30d);
2429
+ savings = Number.isFinite(n) ? n : null;
2430
+ }
2431
+ out.push({
2432
+ archetype: row.intent_archetype,
2433
+ excludedModel: row.excluded_model,
2434
+ excludedProvider: row.excluded_provider,
2435
+ verdict: row.verdict,
2436
+ estimatedSavingsUsd30d: savings,
2437
+ message: row.message,
2438
+ suggestion: row.suggestion,
2439
+ confidence: row.confidence,
2440
+ evidence: row.evidence && typeof row.evidence === "object" ? row.evidence : void 0
2441
+ });
2442
+ }
2443
+ return out;
2444
+ }
2445
+ var snapshots = /* @__PURE__ */ new Map();
2446
+ var runtime2;
2447
+ var warnedOnce = false;
2448
+ var DEFAULT_FINDINGS_ENDPOINT = "https://kgauto-dashboard.vercel.app/api/kgauto-v2/findings/exclusions";
2449
+ function configureExclusionFindingsBrain(rt) {
2450
+ runtime2 = rt;
2451
+ snapshots.clear();
2452
+ warnedOnce = false;
2453
+ }
2454
+ function isExclusionFindingsBrainActive() {
2455
+ return runtime2 !== void 0;
2456
+ }
2457
+ function getStaleExclusionFindings(opts) {
2458
+ const rt = runtime2;
2459
+ if (!rt) return [];
2460
+ const appId = opts.appId;
2461
+ if (!appId) return [];
2462
+ let snap = snapshots.get(appId);
2463
+ if (!snap) {
2464
+ snap = { data: [], expiresAt: 0, refreshing: false };
2465
+ snapshots.set(appId, snap);
2466
+ }
2467
+ const now = Date.now();
2468
+ const stale = snap.expiresAt <= now;
2469
+ if (stale && !snap.refreshing) {
2470
+ snap.refreshing = true;
2471
+ void asyncRefresh2(rt, appId);
2472
+ }
2473
+ if (opts.archetype) {
2474
+ return snap.data.filter((f) => f.archetype === opts.archetype);
2475
+ }
2476
+ return snap.data;
2477
+ }
2478
+ var pendingRefreshes = /* @__PURE__ */ new Map();
2479
+ async function asyncRefresh2(rt, appId) {
2480
+ const promise = doRefresh2(rt, appId);
2481
+ pendingRefreshes.set(appId, promise);
2482
+ try {
2483
+ await promise;
2484
+ } finally {
2485
+ if (pendingRefreshes.get(appId) === promise) {
2486
+ pendingRefreshes.delete(appId);
2487
+ }
2488
+ }
2489
+ }
2490
+ async function doRefresh2(rt, appId) {
2491
+ const url = `${rt.endpoint}?app_id=${encodeURIComponent(appId)}`;
2492
+ let snap = snapshots.get(appId);
2493
+ if (!snap) {
2494
+ snap = { data: [], expiresAt: 0, refreshing: false };
2495
+ snapshots.set(appId, snap);
2496
+ }
2497
+ try {
2498
+ const res = await rt.fetchImpl(url, { method: "GET" });
2499
+ if (!res.ok) {
2500
+ throw new Error(`findings ${res.status}: ${res.statusText}`);
2501
+ }
2502
+ const body = await res.json();
2503
+ if (runtime2 !== rt) return;
2504
+ const rows = Array.isArray(body) ? mapRowsToFindings(body) : [];
2505
+ snap.data = rows;
2506
+ snap.expiresAt = Date.now() + rt.ttlMs;
2507
+ snap.refreshing = false;
2508
+ } catch (err) {
2509
+ if (runtime2 !== rt) return;
2510
+ snap.refreshing = false;
2511
+ snap.expiresAt = Date.now() + rt.ttlMs;
2512
+ if (!warnedOnce) {
2513
+ warnedOnce = true;
2514
+ (rt.onError ?? defaultOnError2)(err);
2515
+ }
2516
+ }
2517
+ }
2518
+ function defaultOnError2(err) {
2519
+ console.warn(
2520
+ "[kgauto] exclusion-findings fetch failed (using empty fallback):",
2521
+ err
2522
+ );
2523
+ }
2524
+
2403
2525
  // src/advisor.ts
2404
2526
  var QUALITY_FLOOR_FOR_RECOMMENDATION = 6;
2405
2527
  var TIER_DOWN_COST_RATIO = 0.5;
@@ -2419,6 +2541,9 @@ function runAdvisor(ir, result, profile, policy, phase2) {
2419
2541
  if (!translatorClearedToolCallCliff(phase2)) {
2420
2542
  out.push(...detectArchetypePerfFloorBreach(ir, profile));
2421
2543
  }
2544
+ if (policy?.posture !== "locked") {
2545
+ out.push(...detectStaleExclusionCandidate(ir));
2546
+ }
2422
2547
  return out;
2423
2548
  }
2424
2549
  function translatorClearedToolCallCliff(phase2) {
@@ -2627,6 +2752,39 @@ function detectArchetypePerfFloorBreach(ir, profile) {
2627
2752
  }
2628
2753
  ];
2629
2754
  }
2755
+ function detectStaleExclusionCandidate(ir) {
2756
+ if (!isExclusionFindingsBrainActive()) return [];
2757
+ if (!ir.appId) return [];
2758
+ const findings = getStaleExclusionFindings({
2759
+ appId: ir.appId,
2760
+ archetype: ir.intent.archetype
2761
+ });
2762
+ if (findings.length === 0) return [];
2763
+ const ranked = [...findings].sort((a, b) => {
2764
+ const sa = a.estimatedSavingsUsd30d ?? -Infinity;
2765
+ const sb = b.estimatedSavingsUsd30d ?? -Infinity;
2766
+ if (sa !== sb) return sb - sa;
2767
+ return confidenceRank(b.confidence) - confidenceRank(a.confidence);
2768
+ });
2769
+ const top = ranked[0];
2770
+ const extraCount = findings.length - 1;
2771
+ const extraNote = extraCount > 0 ? ` (+ ${extraCount} more excluded model${extraCount === 1 ? "" : "s"} for this archetype)` : "";
2772
+ return [
2773
+ {
2774
+ level: "info",
2775
+ code: "stale-exclusion-candidate",
2776
+ message: `${top.message}${extraNote}`,
2777
+ suggestion: top.suggestion,
2778
+ recommendationType: "tier-down",
2779
+ docsUrl: "https://github.com/stue/command-center/blob/main/interfaces/kgauto.md#best-practice-advisories"
2780
+ }
2781
+ ];
2782
+ }
2783
+ function confidenceRank(c) {
2784
+ if (c === "high") return 3;
2785
+ if (c === "medium") return 2;
2786
+ return 1;
2787
+ }
2630
2788
 
2631
2789
  // src/translator.ts
2632
2790
  var TRANSLATOR_FLOOR = ARCHETYPE_FLOOR_DEFAULT;
@@ -2990,20 +3148,31 @@ function configureBrain(config) {
2990
3148
  }
2991
3149
  if (enabledTables.size === 0) {
2992
3150
  configureBrainQuery(void 0);
2993
- return;
3151
+ } else {
3152
+ configureBrainQuery({
3153
+ endpoint,
3154
+ configEndpoint: bq.configEndpoint,
3155
+ ttlMs: bq.cacheTtlMs ?? 3e5,
3156
+ fetchImpl: config.fetchImpl ?? fetch,
3157
+ enabledTables,
3158
+ onError: config.onError
3159
+ });
3160
+ }
3161
+ if (bq.findingsExclusions !== false) {
3162
+ configureExclusionFindingsBrain({
3163
+ endpoint: bq.findingsEndpoint ?? DEFAULT_FINDINGS_ENDPOINT,
3164
+ ttlMs: bq.cacheTtlMs ?? 3e5,
3165
+ fetchImpl: config.fetchImpl ?? fetch,
3166
+ onError: config.onError
3167
+ });
3168
+ } else {
3169
+ configureExclusionFindingsBrain(void 0);
2994
3170
  }
2995
- configureBrainQuery({
2996
- endpoint,
2997
- configEndpoint: bq.configEndpoint,
2998
- ttlMs: bq.cacheTtlMs ?? 3e5,
2999
- fetchImpl: config.fetchImpl ?? fetch,
3000
- enabledTables,
3001
- onError: config.onError
3002
- });
3003
3171
  }
3004
3172
  function clearBrain() {
3005
3173
  activeConfig = void 0;
3006
3174
  configureBrainQuery(void 0);
3175
+ configureExclusionFindingsBrain(void 0);
3007
3176
  }
3008
3177
  var compileRegistry = /* @__PURE__ */ new Map();
3009
3178
  var REGISTRY_MAX_ENTRIES = 1e4;
@@ -3107,7 +3276,7 @@ async function record(input) {
3107
3276
  }
3108
3277
  outcomeId = await tryExtractOutcomeId(res);
3109
3278
  } catch (err) {
3110
- (config.onError ?? defaultOnError2)(err);
3279
+ (config.onError ?? defaultOnError3)(err);
3111
3280
  return;
3112
3281
  }
3113
3282
  const advisories = input.advisories ?? reg?.advisoriesFromCompile;
@@ -3129,7 +3298,7 @@ async function record(input) {
3129
3298
  throw new Error(`brain advisories ${res.status}: ${text}`);
3130
3299
  }
3131
3300
  } catch (err) {
3132
- (config.onError ?? defaultOnError2)(err);
3301
+ (config.onError ?? defaultOnError3)(err);
3133
3302
  }
3134
3303
  };
3135
3304
  if (config.sync) {
@@ -3138,7 +3307,7 @@ async function record(input) {
3138
3307
  void send();
3139
3308
  }
3140
3309
  }
3141
- function defaultOnError2(err) {
3310
+ function defaultOnError3(err) {
3142
3311
  console.warn("[kgauto] brain record failed:", err);
3143
3312
  }
3144
3313
  function buildPayload(input, reg) {
@@ -3270,12 +3439,12 @@ async function recordOutcome(input) {
3270
3439
  if (!res.ok) {
3271
3440
  const text = await res.text().catch(() => "<no body>");
3272
3441
  const err = new Error(`brain ${res.status}: ${text}`);
3273
- (config.onError ?? defaultOnError2)(err);
3442
+ (config.onError ?? defaultOnError3)(err);
3274
3443
  return { ok: false, reason: "persistence_failed" };
3275
3444
  }
3276
3445
  return { ok: true };
3277
3446
  } catch (err) {
3278
- (config.onError ?? defaultOnError2)(err);
3447
+ (config.onError ?? defaultOnError3)(err);
3279
3448
  return { ok: false, reason: "persistence_failed" };
3280
3449
  }
3281
3450
  };
@@ -5397,6 +5566,7 @@ function compile2(ir, opts) {
5397
5566
  ALL_ARCHETYPES,
5398
5567
  ARCHETYPE_FLOOR_DEFAULT,
5399
5568
  CallError,
5569
+ DEFAULT_FINDINGS_ENDPOINT,
5400
5570
  DIALECT_VERSION,
5401
5571
  INTENT_ARCHETYPES,
5402
5572
  MEASURED_GROUNDING_MIN_N,
@@ -5428,11 +5598,13 @@ function compile2(ir, opts) {
5428
5598
  getReachabilityDiagnostic,
5429
5599
  getSequentialStarterChain,
5430
5600
  getSequentialStarterChainWithGrounding,
5601
+ getStaleExclusionFindings,
5431
5602
  getStarterChain,
5432
5603
  getStarterChainWithGrounding,
5433
5604
  hashShape,
5434
5605
  isArchetype,
5435
5606
  isBrainQueryActiveFor,
5607
+ isExclusionFindingsBrainActive,
5436
5608
  isModelReachable,
5437
5609
  isProviderReachable,
5438
5610
  learningKey,
package/dist/index.mjs CHANGED
@@ -825,6 +825,125 @@ function getArchetypePerfScore(modelId, archetype) {
825
825
  return { score, n, grounding };
826
826
  }
827
827
 
828
+ // src/exclusion-findings-brain.ts
829
+ function isValidVerdict(v) {
830
+ return v === "recommend-probe" || v === "unblock" || v === "stay-excluded" || v === "inconclusive";
831
+ }
832
+ function isValidConfidence(v) {
833
+ return v === "high" || v === "medium" || v === "low";
834
+ }
835
+ function isRawFindingRow(x) {
836
+ if (!x || typeof x !== "object") return false;
837
+ const r = x;
838
+ return typeof r.intent_archetype === "string" && typeof r.excluded_model === "string" && typeof r.excluded_provider === "string" && typeof r.verdict === "string" && typeof r.message === "string" && typeof r.suggestion === "string" && typeof r.confidence === "string";
839
+ }
840
+ function mapRowsToFindings(rows) {
841
+ const out = [];
842
+ for (const row of rows) {
843
+ if (!isRawFindingRow(row)) continue;
844
+ if (!isValidVerdict(row.verdict)) continue;
845
+ if (!isValidConfidence(row.confidence)) continue;
846
+ let savings = null;
847
+ if (typeof row.estimated_savings_usd_30d === "number") {
848
+ savings = Number.isFinite(row.estimated_savings_usd_30d) ? row.estimated_savings_usd_30d : null;
849
+ } else if (typeof row.estimated_savings_usd_30d === "string") {
850
+ const n = Number(row.estimated_savings_usd_30d);
851
+ savings = Number.isFinite(n) ? n : null;
852
+ }
853
+ out.push({
854
+ archetype: row.intent_archetype,
855
+ excludedModel: row.excluded_model,
856
+ excludedProvider: row.excluded_provider,
857
+ verdict: row.verdict,
858
+ estimatedSavingsUsd30d: savings,
859
+ message: row.message,
860
+ suggestion: row.suggestion,
861
+ confidence: row.confidence,
862
+ evidence: row.evidence && typeof row.evidence === "object" ? row.evidence : void 0
863
+ });
864
+ }
865
+ return out;
866
+ }
867
+ var snapshots = /* @__PURE__ */ new Map();
868
+ var runtime;
869
+ var warnedOnce = false;
870
+ var DEFAULT_FINDINGS_ENDPOINT = "https://kgauto-dashboard.vercel.app/api/kgauto-v2/findings/exclusions";
871
+ function configureExclusionFindingsBrain(rt) {
872
+ runtime = rt;
873
+ snapshots.clear();
874
+ warnedOnce = false;
875
+ }
876
+ function isExclusionFindingsBrainActive() {
877
+ return runtime !== void 0;
878
+ }
879
+ function getStaleExclusionFindings(opts) {
880
+ const rt = runtime;
881
+ if (!rt) return [];
882
+ const appId = opts.appId;
883
+ if (!appId) return [];
884
+ let snap = snapshots.get(appId);
885
+ if (!snap) {
886
+ snap = { data: [], expiresAt: 0, refreshing: false };
887
+ snapshots.set(appId, snap);
888
+ }
889
+ const now = Date.now();
890
+ const stale = snap.expiresAt <= now;
891
+ if (stale && !snap.refreshing) {
892
+ snap.refreshing = true;
893
+ void asyncRefresh(rt, appId);
894
+ }
895
+ if (opts.archetype) {
896
+ return snap.data.filter((f) => f.archetype === opts.archetype);
897
+ }
898
+ return snap.data;
899
+ }
900
+ var pendingRefreshes = /* @__PURE__ */ new Map();
901
+ async function asyncRefresh(rt, appId) {
902
+ const promise = doRefresh(rt, appId);
903
+ pendingRefreshes.set(appId, promise);
904
+ try {
905
+ await promise;
906
+ } finally {
907
+ if (pendingRefreshes.get(appId) === promise) {
908
+ pendingRefreshes.delete(appId);
909
+ }
910
+ }
911
+ }
912
+ async function doRefresh(rt, appId) {
913
+ const url = `${rt.endpoint}?app_id=${encodeURIComponent(appId)}`;
914
+ let snap = snapshots.get(appId);
915
+ if (!snap) {
916
+ snap = { data: [], expiresAt: 0, refreshing: false };
917
+ snapshots.set(appId, snap);
918
+ }
919
+ try {
920
+ const res = await rt.fetchImpl(url, { method: "GET" });
921
+ if (!res.ok) {
922
+ throw new Error(`findings ${res.status}: ${res.statusText}`);
923
+ }
924
+ const body = await res.json();
925
+ if (runtime !== rt) return;
926
+ const rows = Array.isArray(body) ? mapRowsToFindings(body) : [];
927
+ snap.data = rows;
928
+ snap.expiresAt = Date.now() + rt.ttlMs;
929
+ snap.refreshing = false;
930
+ } catch (err) {
931
+ if (runtime !== rt) return;
932
+ snap.refreshing = false;
933
+ snap.expiresAt = Date.now() + rt.ttlMs;
934
+ if (!warnedOnce) {
935
+ warnedOnce = true;
936
+ (rt.onError ?? defaultOnError)(err);
937
+ }
938
+ }
939
+ }
940
+ function defaultOnError(err) {
941
+ console.warn(
942
+ "[kgauto] exclusion-findings fetch failed (using empty fallback):",
943
+ err
944
+ );
945
+ }
946
+
828
947
  // src/advisor.ts
829
948
  var QUALITY_FLOOR_FOR_RECOMMENDATION = 6;
830
949
  var TIER_DOWN_COST_RATIO = 0.5;
@@ -844,6 +963,9 @@ function runAdvisor(ir, result, profile, policy, phase2) {
844
963
  if (!translatorClearedToolCallCliff(phase2)) {
845
964
  out.push(...detectArchetypePerfFloorBreach(ir, profile));
846
965
  }
966
+ if (policy?.posture !== "locked") {
967
+ out.push(...detectStaleExclusionCandidate(ir));
968
+ }
847
969
  return out;
848
970
  }
849
971
  function translatorClearedToolCallCliff(phase2) {
@@ -1052,6 +1174,39 @@ function detectArchetypePerfFloorBreach(ir, profile) {
1052
1174
  }
1053
1175
  ];
1054
1176
  }
1177
+ function detectStaleExclusionCandidate(ir) {
1178
+ if (!isExclusionFindingsBrainActive()) return [];
1179
+ if (!ir.appId) return [];
1180
+ const findings = getStaleExclusionFindings({
1181
+ appId: ir.appId,
1182
+ archetype: ir.intent.archetype
1183
+ });
1184
+ if (findings.length === 0) return [];
1185
+ const ranked = [...findings].sort((a, b) => {
1186
+ const sa = a.estimatedSavingsUsd30d ?? -Infinity;
1187
+ const sb = b.estimatedSavingsUsd30d ?? -Infinity;
1188
+ if (sa !== sb) return sb - sa;
1189
+ return confidenceRank(b.confidence) - confidenceRank(a.confidence);
1190
+ });
1191
+ const top = ranked[0];
1192
+ const extraCount = findings.length - 1;
1193
+ const extraNote = extraCount > 0 ? ` (+ ${extraCount} more excluded model${extraCount === 1 ? "" : "s"} for this archetype)` : "";
1194
+ return [
1195
+ {
1196
+ level: "info",
1197
+ code: "stale-exclusion-candidate",
1198
+ message: `${top.message}${extraNote}`,
1199
+ suggestion: top.suggestion,
1200
+ recommendationType: "tier-down",
1201
+ docsUrl: "https://github.com/stue/command-center/blob/main/interfaces/kgauto.md#best-practice-advisories"
1202
+ }
1203
+ ];
1204
+ }
1205
+ function confidenceRank(c) {
1206
+ if (c === "high") return 3;
1207
+ if (c === "medium") return 2;
1208
+ return 1;
1209
+ }
1055
1210
 
1056
1211
  // src/translator.ts
1057
1212
  var TRANSLATOR_FLOOR = ARCHETYPE_FLOOR_DEFAULT;
@@ -1415,20 +1570,31 @@ function configureBrain(config) {
1415
1570
  }
1416
1571
  if (enabledTables.size === 0) {
1417
1572
  configureBrainQuery(void 0);
1418
- return;
1573
+ } else {
1574
+ configureBrainQuery({
1575
+ endpoint,
1576
+ configEndpoint: bq.configEndpoint,
1577
+ ttlMs: bq.cacheTtlMs ?? 3e5,
1578
+ fetchImpl: config.fetchImpl ?? fetch,
1579
+ enabledTables,
1580
+ onError: config.onError
1581
+ });
1582
+ }
1583
+ if (bq.findingsExclusions !== false) {
1584
+ configureExclusionFindingsBrain({
1585
+ endpoint: bq.findingsEndpoint ?? DEFAULT_FINDINGS_ENDPOINT,
1586
+ ttlMs: bq.cacheTtlMs ?? 3e5,
1587
+ fetchImpl: config.fetchImpl ?? fetch,
1588
+ onError: config.onError
1589
+ });
1590
+ } else {
1591
+ configureExclusionFindingsBrain(void 0);
1419
1592
  }
1420
- configureBrainQuery({
1421
- endpoint,
1422
- configEndpoint: bq.configEndpoint,
1423
- ttlMs: bq.cacheTtlMs ?? 3e5,
1424
- fetchImpl: config.fetchImpl ?? fetch,
1425
- enabledTables,
1426
- onError: config.onError
1427
- });
1428
1593
  }
1429
1594
  function clearBrain() {
1430
1595
  activeConfig = void 0;
1431
1596
  configureBrainQuery(void 0);
1597
+ configureExclusionFindingsBrain(void 0);
1432
1598
  }
1433
1599
  var compileRegistry = /* @__PURE__ */ new Map();
1434
1600
  var REGISTRY_MAX_ENTRIES = 1e4;
@@ -1532,7 +1698,7 @@ async function record(input) {
1532
1698
  }
1533
1699
  outcomeId = await tryExtractOutcomeId(res);
1534
1700
  } catch (err) {
1535
- (config.onError ?? defaultOnError)(err);
1701
+ (config.onError ?? defaultOnError2)(err);
1536
1702
  return;
1537
1703
  }
1538
1704
  const advisories = input.advisories ?? reg?.advisoriesFromCompile;
@@ -1554,7 +1720,7 @@ async function record(input) {
1554
1720
  throw new Error(`brain advisories ${res.status}: ${text}`);
1555
1721
  }
1556
1722
  } catch (err) {
1557
- (config.onError ?? defaultOnError)(err);
1723
+ (config.onError ?? defaultOnError2)(err);
1558
1724
  }
1559
1725
  };
1560
1726
  if (config.sync) {
@@ -1563,7 +1729,7 @@ async function record(input) {
1563
1729
  void send();
1564
1730
  }
1565
1731
  }
1566
- function defaultOnError(err) {
1732
+ function defaultOnError2(err) {
1567
1733
  console.warn("[kgauto] brain record failed:", err);
1568
1734
  }
1569
1735
  function buildPayload(input, reg) {
@@ -1695,12 +1861,12 @@ async function recordOutcome(input) {
1695
1861
  if (!res.ok) {
1696
1862
  const text = await res.text().catch(() => "<no body>");
1697
1863
  const err = new Error(`brain ${res.status}: ${text}`);
1698
- (config.onError ?? defaultOnError)(err);
1864
+ (config.onError ?? defaultOnError2)(err);
1699
1865
  return { ok: false, reason: "persistence_failed" };
1700
1866
  }
1701
1867
  return { ok: true };
1702
1868
  } catch (err) {
1703
- (config.onError ?? defaultOnError)(err);
1869
+ (config.onError ?? defaultOnError2)(err);
1704
1870
  return { ok: false, reason: "persistence_failed" };
1705
1871
  }
1706
1872
  };
@@ -3116,6 +3282,7 @@ export {
3116
3282
  ALL_ARCHETYPES,
3117
3283
  ARCHETYPE_FLOOR_DEFAULT,
3118
3284
  CallError,
3285
+ DEFAULT_FINDINGS_ENDPOINT,
3119
3286
  DIALECT_VERSION,
3120
3287
  INTENT_ARCHETYPES,
3121
3288
  MEASURED_GROUNDING_MIN_N,
@@ -3147,11 +3314,13 @@ export {
3147
3314
  getReachabilityDiagnostic,
3148
3315
  getSequentialStarterChain,
3149
3316
  getSequentialStarterChainWithGrounding,
3317
+ getStaleExclusionFindings,
3150
3318
  getStarterChain,
3151
3319
  getStarterChainWithGrounding,
3152
3320
  hashShape,
3153
3321
  isArchetype,
3154
3322
  isBrainQueryActiveFor,
3323
+ isExclusionFindingsBrainActive,
3155
3324
  isModelReachable,
3156
3325
  isProviderReachable,
3157
3326
  learningKey,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warmdrift/kgauto-compiler",
3
- "version": "2.0.0-alpha.37",
3
+ "version": "2.0.0-alpha.38",
4
4
  "description": "Prompt compiler + central learning brain for multi-model AI apps. Swap models without rewriting prompts.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",