@warmdrift/kgauto-compiler 2.0.0-alpha.42 → 2.0.0-alpha.44

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.mjs CHANGED
@@ -33,7 +33,7 @@ import {
33
33
  loadChainsFromBrain,
34
34
  readBrainReadEnv,
35
35
  resolveProviderKey
36
- } from "./chunk-KCNQUMHN.mjs";
36
+ } from "./chunk-6MSJQCAP.mjs";
37
37
  import {
38
38
  ALIASES,
39
39
  _setProfileBrainHook,
@@ -42,7 +42,7 @@ import {
42
42
  getProfile,
43
43
  profilesByProvider,
44
44
  tryGetProfile
45
- } from "./chunk-JQGRWJZO.mjs";
45
+ } from "./chunk-ZHUD3I52.mjs";
46
46
  import {
47
47
  emitAdvisoryFired,
48
48
  emitCompileDone,
@@ -52,6 +52,380 @@ import {
52
52
  emitFallbackWalked
53
53
  } from "./chunk-NBO4R5PC.mjs";
54
54
 
55
+ // src/models-brain.ts
56
+ function isModelRow(x) {
57
+ if (!x || typeof x !== "object") return false;
58
+ const r = x;
59
+ return typeof r.model_id === "string" && typeof r.provider === "string";
60
+ }
61
+ function isAliasRow(x) {
62
+ if (!x || typeof x !== "object") return false;
63
+ const r = x;
64
+ return typeof r.alias_id === "string" && typeof r.canonical_id === "string";
65
+ }
66
+ function rowToProfile(row) {
67
+ try {
68
+ if (row.cliffs !== void 0 && row.cliffs !== null && !Array.isArray(row.cliffs)) {
69
+ return null;
70
+ }
71
+ if (row.recovery !== void 0 && row.recovery !== null && !Array.isArray(row.recovery)) {
72
+ return null;
73
+ }
74
+ if (row.lowering !== void 0 && row.lowering !== null && (typeof row.lowering !== "object" || Array.isArray(row.lowering))) {
75
+ return null;
76
+ }
77
+ return {
78
+ id: row.model_id,
79
+ provider: row.provider,
80
+ status: row.status ?? "current",
81
+ maxContextTokens: row.max_context_tokens ?? 0,
82
+ maxOutputTokens: row.max_output_tokens ?? 0,
83
+ maxTools: row.max_tools ?? 0,
84
+ parallelToolCalls: row.parallel_tool_calls ?? false,
85
+ structuredOutput: row.structured_output ?? "none",
86
+ systemPromptMode: row.system_prompt_mode ?? "inline",
87
+ streaming: row.streaming ?? true,
88
+ cliffs: row.cliffs ?? [],
89
+ costInputPer1m: row.cost_input_per_1m ?? 0,
90
+ costOutputPer1m: row.cost_output_per_1m ?? 0,
91
+ lowering: row.lowering ?? { system: { mode: "inline" }, cache: { strategy: "unsupported" } },
92
+ recovery: row.recovery ?? [],
93
+ strengths: row.strengths ?? [],
94
+ weaknesses: row.weaknesses ?? [],
95
+ notes: row.notes ?? void 0,
96
+ verifiedAgainstDocs: row.verified_against_docs ?? void 0,
97
+ archetypePerf: row.archetype_perf ?? void 0,
98
+ // alpha.41 — family-resolution fields. `family` may be null pre-
99
+ // migration 024; runtime falls back to deriveFamilyFromModelId at
100
+ // resolution time (see family-resolution.ts, G1).
101
+ family: row.family ?? void 0,
102
+ versionAdded: row.version_added ?? void 0,
103
+ active: row.active ?? void 0
104
+ };
105
+ } catch {
106
+ return null;
107
+ }
108
+ }
109
+ function profileToRow(profile, opts = {}) {
110
+ const row = {
111
+ model_id: profile.id,
112
+ provider: profile.provider,
113
+ status: profile.status,
114
+ max_context_tokens: profile.maxContextTokens,
115
+ max_output_tokens: profile.maxOutputTokens,
116
+ max_tools: profile.maxTools,
117
+ parallel_tool_calls: profile.parallelToolCalls,
118
+ structured_output: profile.structuredOutput,
119
+ system_prompt_mode: profile.systemPromptMode,
120
+ streaming: profile.streaming,
121
+ cliffs: profile.cliffs,
122
+ cost_input_per_1m: profile.costInputPer1m,
123
+ cost_output_per_1m: profile.costOutputPer1m,
124
+ lowering: profile.lowering,
125
+ recovery: profile.recovery,
126
+ strengths: profile.strengths,
127
+ weaknesses: profile.weaknesses,
128
+ notes: profile.notes ?? null,
129
+ archetype_perf: profile.archetypePerf ?? null,
130
+ active: opts.active ?? profile.active ?? true,
131
+ // alpha.41 — round-trip family + version_added when present on profile.
132
+ // version_added is operator-controlled via opts; profile-side value is
133
+ // used only when opts didn't override.
134
+ family: profile.family ?? null
135
+ };
136
+ if (opts.verifiedAgainstDocs !== void 0) {
137
+ row.verified_against_docs = opts.verifiedAgainstDocs;
138
+ } else if (profile.verifiedAgainstDocs !== void 0) {
139
+ const v = profile.verifiedAgainstDocs;
140
+ row.verified_against_docs = /^\d{4}-\d{2}-\d{2}/.test(v) ? v : null;
141
+ }
142
+ if (opts.versionAdded !== void 0) row.version_added = opts.versionAdded;
143
+ else if (profile.versionAdded !== void 0) row.version_added = profile.versionAdded;
144
+ if (opts.versionRemoved !== void 0) row.version_removed = opts.versionRemoved;
145
+ return row;
146
+ }
147
+ function mapRowsToModels(rows) {
148
+ const out = /* @__PURE__ */ new Map();
149
+ for (const row of rows) {
150
+ if (!isModelRow(row)) continue;
151
+ const profile = rowToProfile(row);
152
+ if (profile) out.set(profile.id, profile);
153
+ }
154
+ return out;
155
+ }
156
+ function mapRowsToAliases(rows) {
157
+ const out = {};
158
+ for (const row of rows) {
159
+ if (!isAliasRow(row)) continue;
160
+ out[row.alias_id] = row.canonical_id;
161
+ }
162
+ return out;
163
+ }
164
+ function bundledModels() {
165
+ return new Map(allProfilesRaw().map((p) => [p.id, p]));
166
+ }
167
+ function bundledAliases() {
168
+ return { ...ALIASES };
169
+ }
170
+ var loadModelsFromBrain = createBrainQueryCache({
171
+ table: "kgauto_models",
172
+ mapRows: mapRowsToModels,
173
+ bundledFallback: bundledModels
174
+ });
175
+ var loadAliasesFromBrain = createBrainQueryCache({
176
+ table: "kgauto_aliases",
177
+ mapRows: mapRowsToAliases,
178
+ bundledFallback: bundledAliases
179
+ });
180
+ _setProfileBrainHook({
181
+ getProfile: (canonical) => loadModelsFromBrain().get(canonical),
182
+ resolveAlias: (id) => loadAliasesFromBrain()[id]
183
+ });
184
+
185
+ // src/exclusion-findings-brain.ts
186
+ function isValidVerdict(v) {
187
+ return v === "recommend-probe" || v === "unblock" || v === "stay-excluded" || v === "inconclusive";
188
+ }
189
+ function isValidConfidence(v) {
190
+ return v === "high" || v === "medium" || v === "low";
191
+ }
192
+ function isRawFindingRow(x) {
193
+ if (!x || typeof x !== "object") return false;
194
+ const r = x;
195
+ 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";
196
+ }
197
+ function mapRowsToFindings(rows) {
198
+ const out = [];
199
+ for (const row of rows) {
200
+ if (!isRawFindingRow(row)) continue;
201
+ if (!isValidVerdict(row.verdict)) continue;
202
+ if (!isValidConfidence(row.confidence)) continue;
203
+ let savings = null;
204
+ if (typeof row.estimated_savings_usd_30d === "number") {
205
+ savings = Number.isFinite(row.estimated_savings_usd_30d) ? row.estimated_savings_usd_30d : null;
206
+ } else if (typeof row.estimated_savings_usd_30d === "string") {
207
+ const n = Number(row.estimated_savings_usd_30d);
208
+ savings = Number.isFinite(n) ? n : null;
209
+ }
210
+ out.push({
211
+ archetype: row.intent_archetype,
212
+ excludedModel: row.excluded_model,
213
+ excludedProvider: row.excluded_provider,
214
+ verdict: row.verdict,
215
+ estimatedSavingsUsd30d: savings,
216
+ message: row.message,
217
+ suggestion: row.suggestion,
218
+ confidence: row.confidence,
219
+ evidence: row.evidence && typeof row.evidence === "object" ? row.evidence : void 0
220
+ });
221
+ }
222
+ return out;
223
+ }
224
+ var snapshots = /* @__PURE__ */ new Map();
225
+ var runtime;
226
+ var warnedOnce = false;
227
+ var DEFAULT_FINDINGS_ENDPOINT = "https://kgauto-dashboard.vercel.app/api/kgauto-v2/findings/exclusions";
228
+ function configureExclusionFindingsBrain(rt) {
229
+ runtime = rt;
230
+ snapshots.clear();
231
+ warnedOnce = false;
232
+ }
233
+ function isExclusionFindingsBrainActive() {
234
+ return runtime !== void 0;
235
+ }
236
+ function getStaleExclusionFindings(opts) {
237
+ const rt = runtime;
238
+ if (!rt) return [];
239
+ const appId = opts.appId;
240
+ if (!appId) return [];
241
+ let snap = snapshots.get(appId);
242
+ if (!snap) {
243
+ snap = { data: [], expiresAt: 0, refreshing: false };
244
+ snapshots.set(appId, snap);
245
+ }
246
+ const now = Date.now();
247
+ const stale = snap.expiresAt <= now;
248
+ if (stale && !snap.refreshing) {
249
+ snap.refreshing = true;
250
+ void asyncRefresh(rt, appId);
251
+ }
252
+ if (opts.archetype) {
253
+ return snap.data.filter((f) => f.archetype === opts.archetype);
254
+ }
255
+ return snap.data;
256
+ }
257
+ var pendingRefreshes = /* @__PURE__ */ new Map();
258
+ async function asyncRefresh(rt, appId) {
259
+ const promise = doRefresh(rt, appId);
260
+ pendingRefreshes.set(appId, promise);
261
+ try {
262
+ await promise;
263
+ } finally {
264
+ if (pendingRefreshes.get(appId) === promise) {
265
+ pendingRefreshes.delete(appId);
266
+ }
267
+ }
268
+ }
269
+ async function doRefresh(rt, appId) {
270
+ const url = `${rt.endpoint}?app_id=${encodeURIComponent(appId)}`;
271
+ let snap = snapshots.get(appId);
272
+ if (!snap) {
273
+ snap = { data: [], expiresAt: 0, refreshing: false };
274
+ snapshots.set(appId, snap);
275
+ }
276
+ try {
277
+ const res = await rt.fetchImpl(url, { method: "GET" });
278
+ if (!res.ok) {
279
+ throw new Error(`findings ${res.status}: ${res.statusText}`);
280
+ }
281
+ const body = await res.json();
282
+ if (runtime !== rt) return;
283
+ const rows = Array.isArray(body) ? mapRowsToFindings(body) : [];
284
+ snap.data = rows;
285
+ snap.expiresAt = Date.now() + rt.ttlMs;
286
+ snap.refreshing = false;
287
+ } catch (err) {
288
+ if (runtime !== rt) return;
289
+ snap.refreshing = false;
290
+ snap.expiresAt = Date.now() + rt.ttlMs;
291
+ if (!warnedOnce) {
292
+ warnedOnce = true;
293
+ (rt.onError ?? defaultOnError)(err);
294
+ }
295
+ }
296
+ }
297
+ function defaultOnError(err) {
298
+ console.warn(
299
+ "[kgauto] exclusion-findings fetch failed (using empty fallback):",
300
+ err
301
+ );
302
+ }
303
+
304
+ // src/family-resolution.ts
305
+ var FamilyResolutionError = class extends Error {
306
+ family;
307
+ cause;
308
+ constructor(family, cause) {
309
+ super(
310
+ `Family "${family}" did not resolve to any current+active model. ${cause}. Pass a literal model id in ir.models, or call getRecommendedPrimary({ family, fallback }) at IR-construction time.`
311
+ );
312
+ this.name = "FamilyResolutionError";
313
+ this.family = family;
314
+ this.cause = cause;
315
+ }
316
+ };
317
+ function deriveFamilyFromModelId(modelId) {
318
+ if (typeof modelId !== "string" || modelId.length === 0) return null;
319
+ if (modelId.startsWith("claude-opus-")) return "claude-opus";
320
+ if (modelId.startsWith("claude-sonnet-")) return "claude-sonnet";
321
+ if (modelId.startsWith("claude-haiku-")) return "claude-haiku";
322
+ if (modelId.startsWith("gemini-") && modelId.includes("flash-lite")) {
323
+ return "gemini-flash-lite";
324
+ }
325
+ if (modelId.startsWith("gemini-") && modelId.includes("flash")) {
326
+ return "gemini-flash";
327
+ }
328
+ if (modelId.startsWith("gemini-") && modelId.includes("pro")) {
329
+ return "gemini-pro";
330
+ }
331
+ if (modelId.startsWith("deepseek-") && modelId.includes("pro")) {
332
+ return "deepseek-reasoner";
333
+ }
334
+ if (modelId.startsWith("deepseek-")) return "deepseek-chat";
335
+ if (modelId.startsWith("gpt-")) return "openai-gpt";
336
+ return null;
337
+ }
338
+ function familyOf(profile) {
339
+ return profile.family ?? deriveFamilyFromModelId(profile.id);
340
+ }
341
+ function archetypePerfFor(profile, archetype) {
342
+ if (!archetype) return 0;
343
+ const score = profile.archetypePerf?.[archetype];
344
+ return typeof score === "number" ? score : 5;
345
+ }
346
+ function selectCandidates(registry, family, archetype, appId) {
347
+ const out = [];
348
+ const excluded = /* @__PURE__ */ new Set();
349
+ if (appId && archetype) {
350
+ const findings = getStaleExclusionFindings({ appId, archetype });
351
+ for (const f of findings) {
352
+ if (f.verdict === "stay-excluded") excluded.add(f.excludedModel);
353
+ }
354
+ }
355
+ for (const profile of registry.values()) {
356
+ if (familyOf(profile) !== family) continue;
357
+ if (profile.status !== "current") continue;
358
+ if (profile.active === false) continue;
359
+ if (archetype) {
360
+ if (archetypePerfFor(profile, archetype) < ARCHETYPE_FLOOR_DEFAULT) continue;
361
+ }
362
+ if (excluded.has(profile.id)) continue;
363
+ out.push(profile);
364
+ }
365
+ return out;
366
+ }
367
+ function sortCandidates(candidates, archetype) {
368
+ const sorted = [...candidates];
369
+ sorted.sort((a, b) => {
370
+ const perfA = archetypePerfFor(a, archetype);
371
+ const perfB = archetypePerfFor(b, archetype);
372
+ if (perfA !== perfB) return perfB - perfA;
373
+ const vA = a.versionAdded ?? "";
374
+ const vB = b.versionAdded ?? "";
375
+ if (vA !== vB) return vA < vB ? 1 : -1;
376
+ return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
377
+ });
378
+ return sorted;
379
+ }
380
+ function getRecommendedPrimary(opts) {
381
+ if (opts.posture === "locked") return opts.fallback;
382
+ const registry = loadModelsFromBrain();
383
+ const candidates = selectCandidates(
384
+ registry,
385
+ opts.family,
386
+ opts.archetype,
387
+ opts.appId
388
+ );
389
+ if (candidates.length === 0) return opts.fallback;
390
+ const sorted = sortCandidates(candidates, opts.archetype);
391
+ return sorted[0]?.id ?? opts.fallback;
392
+ }
393
+ function resolveFamilyEntry(family, ctx) {
394
+ if (typeof family !== "string" || family.length === 0) {
395
+ throw new FamilyResolutionError(
396
+ String(family),
397
+ "Family tag must be a non-empty string"
398
+ );
399
+ }
400
+ const registry = loadModelsFromBrain();
401
+ const candidates = selectCandidates(
402
+ registry,
403
+ family,
404
+ ctx.archetype,
405
+ ctx.appId
406
+ );
407
+ if (candidates.length === 0) {
408
+ let anyInFamily = false;
409
+ for (const profile of registry.values()) {
410
+ if (familyOf(profile) === family) {
411
+ anyInFamily = true;
412
+ break;
413
+ }
414
+ }
415
+ const cause = anyInFamily ? `Family has registered models but none are current+active${ctx.archetype ? ` at archetype-perf >= ${ARCHETYPE_FLOOR_DEFAULT} for "${ctx.archetype}"` : ""}${ctx.appId ? ` and not excluded for app "${ctx.appId}"` : ""}` : `No models in brain registry carry family="${family}". Check the taxonomy table in family-resolution.ts or migration 024`;
416
+ throw new FamilyResolutionError(family, cause);
417
+ }
418
+ const sorted = sortCandidates(candidates, ctx.archetype);
419
+ const winner = sorted[0];
420
+ if (!winner) {
421
+ throw new FamilyResolutionError(
422
+ family,
423
+ "Candidates non-empty but sort returned undefined \u2014 internal invariant violation"
424
+ );
425
+ }
426
+ return winner.id;
427
+ }
428
+
55
429
  // src/tokenizer.ts
56
430
  var tokenizerImpl = defaultCharBasedCounter;
57
431
  function defaultCharBasedCounter(text) {
@@ -450,6 +824,175 @@ function simpleHash(s) {
450
824
  }
451
825
  return (h >>> 0).toString(36);
452
826
  }
827
+ function resolveConventionsForProfile(profile) {
828
+ const own = profile.archetypeConventions ?? [];
829
+ const family = profile.family ?? deriveFamilyFromModelId(profile.id);
830
+ if (!family) return own;
831
+ return own;
832
+ }
833
+ function applyArchetypeConvention(promptText, archetype, family) {
834
+ if (typeof promptText !== "string" || promptText.length === 0) return promptText;
835
+ const repId = familyRepId(family);
836
+ if (!repId) return promptText;
837
+ const profile = tryGetProfile(repId);
838
+ if (!profile || !profile.archetypeConventions) return promptText;
839
+ const conventions = profile.archetypeConventions.filter((c) => c.archetype === archetype);
840
+ if (conventions.length === 0) return promptText;
841
+ let next = promptText;
842
+ for (const c of conventions) {
843
+ if (c.promptPrefix) {
844
+ if (!next.startsWith(c.promptPrefix)) {
845
+ next = c.promptPrefix + next;
846
+ }
847
+ }
848
+ if (c.promptSuffix) {
849
+ if (!next.endsWith(c.promptSuffix)) {
850
+ next = next + c.promptSuffix;
851
+ }
852
+ }
853
+ }
854
+ return next;
855
+ }
856
+ function familyRepId(family) {
857
+ switch (family) {
858
+ case "deepseek-reasoner":
859
+ return "deepseek-v4-pro";
860
+ case "deepseek-chat":
861
+ return "deepseek-v4-flash";
862
+ default:
863
+ return void 0;
864
+ }
865
+ }
866
+ function passApplyConventions(ir, profile) {
867
+ const mutations = [];
868
+ const cliffWarnings = [];
869
+ const structuredOutputHints = [];
870
+ const own = profile.archetypeConventions ?? [];
871
+ let effective = own;
872
+ if (effective.length === 0) {
873
+ const family2 = profile.family ?? deriveFamilyFromModelId(profile.id);
874
+ if (family2) {
875
+ const repId = familyRepId(family2);
876
+ if (repId && repId !== profile.id) {
877
+ const repProfile = tryGetProfile(repId);
878
+ if (repProfile && repProfile.archetypeConventions) {
879
+ effective = repProfile.archetypeConventions;
880
+ }
881
+ }
882
+ }
883
+ }
884
+ if (effective.length === 0) {
885
+ return {
886
+ value: { ir, cliffWarnings, structuredOutputHints },
887
+ mutations
888
+ };
889
+ }
890
+ const archetype = ir.intent.archetype;
891
+ const matching = effective.filter((c) => c.archetype === archetype);
892
+ if (matching.length === 0) {
893
+ return {
894
+ value: { ir, cliffWarnings, structuredOutputHints },
895
+ mutations
896
+ };
897
+ }
898
+ const family = profile.family ?? deriveFamilyFromModelId(profile.id) ?? "unknown";
899
+ let nextIR = ir;
900
+ for (const convention of matching) {
901
+ let touched = false;
902
+ if (convention.promptPrefix) {
903
+ const sections = nextIR.sections ?? [];
904
+ const alreadyPresent = sections.some(
905
+ (s) => s.text.includes(convention.promptPrefix)
906
+ );
907
+ if (!alreadyPresent) {
908
+ const prefixSection = {
909
+ id: `convention-prefix-${family}-${archetype}`,
910
+ text: convention.promptPrefix
911
+ };
912
+ nextIR = { ...nextIR, sections: [prefixSection, ...sections] };
913
+ touched = true;
914
+ }
915
+ }
916
+ if (convention.promptSuffix) {
917
+ const history = nextIR.history ?? [];
918
+ let lastUserIdx = -1;
919
+ for (let i = history.length - 1; i >= 0; i--) {
920
+ if (history[i]?.role === "user") {
921
+ lastUserIdx = i;
922
+ break;
923
+ }
924
+ }
925
+ if (lastUserIdx >= 0) {
926
+ const target = history[lastUserIdx];
927
+ if (!target.content.endsWith(convention.promptSuffix)) {
928
+ const newHistory = history.slice();
929
+ newHistory[lastUserIdx] = {
930
+ ...target,
931
+ content: target.content + convention.promptSuffix
932
+ };
933
+ nextIR = { ...nextIR, history: newHistory };
934
+ touched = true;
935
+ }
936
+ } else if (nextIR.currentTurn && nextIR.currentTurn.role === "user") {
937
+ const target = nextIR.currentTurn;
938
+ if (!target.content.endsWith(convention.promptSuffix)) {
939
+ nextIR = {
940
+ ...nextIR,
941
+ currentTurn: {
942
+ ...target,
943
+ content: target.content + convention.promptSuffix
944
+ }
945
+ };
946
+ touched = true;
947
+ }
948
+ } else {
949
+ nextIR = {
950
+ ...nextIR,
951
+ currentTurn: {
952
+ role: "user",
953
+ content: convention.promptSuffix.trim()
954
+ }
955
+ };
956
+ touched = true;
957
+ }
958
+ }
959
+ if (convention.structuredOutputHint) {
960
+ const wantsStructured = !!nextIR.constraints?.structuredOutput;
961
+ const shouldSurface = convention.structuredOutputHint === "avoid" && wantsStructured || convention.structuredOutputHint === "enforce" && !wantsStructured;
962
+ if (shouldSurface) {
963
+ structuredOutputHints.push({
964
+ archetype,
965
+ hint: convention.structuredOutputHint,
966
+ reason: convention.reason
967
+ });
968
+ if (convention.cliffWarning) {
969
+ cliffWarnings.push(`${profile.id}: ${convention.cliffWarning}`);
970
+ }
971
+ touched = true;
972
+ }
973
+ }
974
+ if (convention.cliffWarning && !convention.structuredOutputHint) {
975
+ const toolCount = nextIR.tools?.length ?? 0;
976
+ const thresholdOk = convention.whenToolCountAtLeast === void 0 || toolCount >= convention.whenToolCountAtLeast;
977
+ if (thresholdOk) {
978
+ cliffWarnings.push(`${profile.id}: ${convention.cliffWarning}`);
979
+ touched = true;
980
+ }
981
+ }
982
+ if (touched) {
983
+ mutations.push({
984
+ id: `apply-convention-${family}-${archetype}`,
985
+ source: "archetype_convention",
986
+ passName: "apply_conventions",
987
+ description: `${profile.id}: applied ${family}-family convention for archetype=${archetype} \u2014 ${convention.reason}`
988
+ });
989
+ }
990
+ }
991
+ return {
992
+ value: { ir: nextIR, cliffWarnings, structuredOutputHints },
993
+ mutations
994
+ };
995
+ }
453
996
 
454
997
  // src/lower.ts
455
998
  function lower(ir, profile, hints = {}) {
@@ -827,125 +1370,6 @@ function getArchetypePerfScore(modelId, archetype) {
827
1370
  return { score, n, grounding };
828
1371
  }
829
1372
 
830
- // src/exclusion-findings-brain.ts
831
- function isValidVerdict(v) {
832
- return v === "recommend-probe" || v === "unblock" || v === "stay-excluded" || v === "inconclusive";
833
- }
834
- function isValidConfidence(v) {
835
- return v === "high" || v === "medium" || v === "low";
836
- }
837
- function isRawFindingRow(x) {
838
- if (!x || typeof x !== "object") return false;
839
- const r = x;
840
- 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";
841
- }
842
- function mapRowsToFindings(rows) {
843
- const out = [];
844
- for (const row of rows) {
845
- if (!isRawFindingRow(row)) continue;
846
- if (!isValidVerdict(row.verdict)) continue;
847
- if (!isValidConfidence(row.confidence)) continue;
848
- let savings = null;
849
- if (typeof row.estimated_savings_usd_30d === "number") {
850
- savings = Number.isFinite(row.estimated_savings_usd_30d) ? row.estimated_savings_usd_30d : null;
851
- } else if (typeof row.estimated_savings_usd_30d === "string") {
852
- const n = Number(row.estimated_savings_usd_30d);
853
- savings = Number.isFinite(n) ? n : null;
854
- }
855
- out.push({
856
- archetype: row.intent_archetype,
857
- excludedModel: row.excluded_model,
858
- excludedProvider: row.excluded_provider,
859
- verdict: row.verdict,
860
- estimatedSavingsUsd30d: savings,
861
- message: row.message,
862
- suggestion: row.suggestion,
863
- confidence: row.confidence,
864
- evidence: row.evidence && typeof row.evidence === "object" ? row.evidence : void 0
865
- });
866
- }
867
- return out;
868
- }
869
- var snapshots = /* @__PURE__ */ new Map();
870
- var runtime;
871
- var warnedOnce = false;
872
- var DEFAULT_FINDINGS_ENDPOINT = "https://kgauto-dashboard.vercel.app/api/kgauto-v2/findings/exclusions";
873
- function configureExclusionFindingsBrain(rt) {
874
- runtime = rt;
875
- snapshots.clear();
876
- warnedOnce = false;
877
- }
878
- function isExclusionFindingsBrainActive() {
879
- return runtime !== void 0;
880
- }
881
- function getStaleExclusionFindings(opts) {
882
- const rt = runtime;
883
- if (!rt) return [];
884
- const appId = opts.appId;
885
- if (!appId) return [];
886
- let snap = snapshots.get(appId);
887
- if (!snap) {
888
- snap = { data: [], expiresAt: 0, refreshing: false };
889
- snapshots.set(appId, snap);
890
- }
891
- const now = Date.now();
892
- const stale = snap.expiresAt <= now;
893
- if (stale && !snap.refreshing) {
894
- snap.refreshing = true;
895
- void asyncRefresh(rt, appId);
896
- }
897
- if (opts.archetype) {
898
- return snap.data.filter((f) => f.archetype === opts.archetype);
899
- }
900
- return snap.data;
901
- }
902
- var pendingRefreshes = /* @__PURE__ */ new Map();
903
- async function asyncRefresh(rt, appId) {
904
- const promise = doRefresh(rt, appId);
905
- pendingRefreshes.set(appId, promise);
906
- try {
907
- await promise;
908
- } finally {
909
- if (pendingRefreshes.get(appId) === promise) {
910
- pendingRefreshes.delete(appId);
911
- }
912
- }
913
- }
914
- async function doRefresh(rt, appId) {
915
- const url = `${rt.endpoint}?app_id=${encodeURIComponent(appId)}`;
916
- let snap = snapshots.get(appId);
917
- if (!snap) {
918
- snap = { data: [], expiresAt: 0, refreshing: false };
919
- snapshots.set(appId, snap);
920
- }
921
- try {
922
- const res = await rt.fetchImpl(url, { method: "GET" });
923
- if (!res.ok) {
924
- throw new Error(`findings ${res.status}: ${res.statusText}`);
925
- }
926
- const body = await res.json();
927
- if (runtime !== rt) return;
928
- const rows = Array.isArray(body) ? mapRowsToFindings(body) : [];
929
- snap.data = rows;
930
- snap.expiresAt = Date.now() + rt.ttlMs;
931
- snap.refreshing = false;
932
- } catch (err) {
933
- if (runtime !== rt) return;
934
- snap.refreshing = false;
935
- snap.expiresAt = Date.now() + rt.ttlMs;
936
- if (!warnedOnce) {
937
- warnedOnce = true;
938
- (rt.onError ?? defaultOnError)(err);
939
- }
940
- }
941
- }
942
- function defaultOnError(err) {
943
- console.warn(
944
- "[kgauto] exclusion-findings fetch failed (using empty fallback):",
945
- err
946
- );
947
- }
948
-
949
1373
  // src/promote-ready-brain.ts
950
1374
  function isRawPromoteReadyRow(x) {
951
1375
  if (!x || typeof x !== "object") return false;
@@ -1333,6 +1757,77 @@ function advisorRuleConsumerOnStaleModel(ir) {
1333
1757
  ];
1334
1758
  }
1335
1759
 
1760
+ // src/archetype-fits.ts
1761
+ var ARCHETYPE_FAMILY_FITS = Object.freeze([
1762
+ {
1763
+ archetype: "plan",
1764
+ betterFitFamily: "deepseek-reasoner",
1765
+ reason: "Plan archetype is reasoning-shaped (multi-step chains, hypothesis-and-check, sub-goal decomposition) \u2014 exactly where reasoner-family models excel. Sonnet/Opus produce plans but at higher cost; reasoners produce equivalent-or-better plans at 7-17x lower cost at current promo pricing (deepseek-v4-pro $0.435/$0.87 per 1M promo through 2026-05-31 vs sonnet $3/$15).",
1766
+ costGuidance: "substantially cheaper at current pricing (deepseek-v4-pro promo: ~7-17x cheaper than sonnet)"
1767
+ },
1768
+ {
1769
+ archetype: "critique",
1770
+ betterFitFamily: "deepseek-reasoner",
1771
+ reason: "Critique archetype rewards epistemic humility and explicit reasoning \u2014 reasoner-family default behavior. Sonnet/Opus over-confident on critique tasks; reasoners surface uncertainty productively.",
1772
+ costGuidance: "comparable or cheaper at current pricing"
1773
+ }
1774
+ ]);
1775
+ function findBetterFit(archetype, currentFamily) {
1776
+ for (const fit of ARCHETYPE_FAMILY_FITS) {
1777
+ if (fit.archetype !== archetype) continue;
1778
+ if (fit.betterFitFamily === currentFamily) return null;
1779
+ return fit;
1780
+ }
1781
+ return null;
1782
+ }
1783
+
1784
+ // src/advisor-rules/cross-family-fit.ts
1785
+ function familyHasCurrentActiveModel(family) {
1786
+ for (const profile of allProfiles()) {
1787
+ const profileFamily = profile.family ?? deriveFamilyFromModelId(profile.id);
1788
+ if (profileFamily !== family) continue;
1789
+ if (profile.status !== "current") continue;
1790
+ if (profile.active === false) continue;
1791
+ return true;
1792
+ }
1793
+ return false;
1794
+ }
1795
+ function listCandidatesInFamily(family) {
1796
+ const candidates = [];
1797
+ for (const profile of allProfiles()) {
1798
+ const profileFamily = profile.family ?? deriveFamilyFromModelId(profile.id);
1799
+ if (profileFamily !== family) continue;
1800
+ if (profile.status !== "current") continue;
1801
+ if (profile.active === false) continue;
1802
+ candidates.push(profile.id);
1803
+ if (candidates.length >= 3) break;
1804
+ }
1805
+ return candidates;
1806
+ }
1807
+ function advisorRuleCrossFamilyFit(ctx) {
1808
+ if (!ctx.resolvedPrimary) return [];
1809
+ const currentFamily = deriveFamilyFromModelId(ctx.resolvedPrimary);
1810
+ if (!currentFamily) return [];
1811
+ const fit = findBetterFit(ctx.archetype, currentFamily);
1812
+ if (!fit) return [];
1813
+ if (!familyHasCurrentActiveModel(fit.betterFitFamily)) return [];
1814
+ const candidates = listCandidatesInFamily(fit.betterFitFamily);
1815
+ if (candidates.length === 0) return [];
1816
+ const candidateStr = candidates.join(", ");
1817
+ const message = `Your ${currentFamily} call on ${ctx.archetype} could shift to ${fit.betterFitFamily} \u2014 typically better quality + ${fit.costGuidance}. Suggested candidates: ${candidateStr}.`;
1818
+ return [
1819
+ {
1820
+ level: "info",
1821
+ code: "cross-family-fit-candidate",
1822
+ ownership: "consumer-actionable",
1823
+ message,
1824
+ suggestion: `Swap the model literal in \`ir.models\` to one of: ${candidateStr}. Or call \`getRecommendedPrimary({ family: '${fit.betterFitFamily}', archetype: '${ctx.archetype}', fallback: { id: '${candidates[0]}', reason: 'cross-family-fit-recommendation' } })\` to let kgauto resolve to the current+active family member.`,
1825
+ recommendationType: "model-swap",
1826
+ docsUrl: "https://github.com/stue/command-center/blob/main/interfaces/kgauto.md#best-practice-advisories"
1827
+ }
1828
+ ];
1829
+ }
1830
+
1336
1831
  // src/advisor.ts
1337
1832
  var QUALITY_FLOOR_FOR_RECOMMENDATION = 6;
1338
1833
  var TIER_DOWN_COST_RATIO = 0.5;
@@ -1372,6 +1867,14 @@ function runAdvisor(ir, result, profile, policy, phase2) {
1372
1867
  );
1373
1868
  out.push(...advisorRuleConsumerOnStaleModel(ir));
1374
1869
  }
1870
+ if (policy?.posture !== "locked") {
1871
+ out.push(
1872
+ ...advisorRuleCrossFamilyFit({
1873
+ archetype: ir.intent.archetype,
1874
+ resolvedPrimary: profile.id
1875
+ })
1876
+ );
1877
+ }
1375
1878
  return out;
1376
1879
  }
1377
1880
  function translatorClearedToolCallCliff(phase2) {
@@ -1683,261 +2186,6 @@ ${originalText}`;
1683
2186
  return { rewrittenIR, rewrites };
1684
2187
  }
1685
2188
 
1686
- // src/models-brain.ts
1687
- function isModelRow(x) {
1688
- if (!x || typeof x !== "object") return false;
1689
- const r = x;
1690
- return typeof r.model_id === "string" && typeof r.provider === "string";
1691
- }
1692
- function isAliasRow(x) {
1693
- if (!x || typeof x !== "object") return false;
1694
- const r = x;
1695
- return typeof r.alias_id === "string" && typeof r.canonical_id === "string";
1696
- }
1697
- function rowToProfile(row) {
1698
- try {
1699
- if (row.cliffs !== void 0 && row.cliffs !== null && !Array.isArray(row.cliffs)) {
1700
- return null;
1701
- }
1702
- if (row.recovery !== void 0 && row.recovery !== null && !Array.isArray(row.recovery)) {
1703
- return null;
1704
- }
1705
- if (row.lowering !== void 0 && row.lowering !== null && (typeof row.lowering !== "object" || Array.isArray(row.lowering))) {
1706
- return null;
1707
- }
1708
- return {
1709
- id: row.model_id,
1710
- provider: row.provider,
1711
- status: row.status ?? "current",
1712
- maxContextTokens: row.max_context_tokens ?? 0,
1713
- maxOutputTokens: row.max_output_tokens ?? 0,
1714
- maxTools: row.max_tools ?? 0,
1715
- parallelToolCalls: row.parallel_tool_calls ?? false,
1716
- structuredOutput: row.structured_output ?? "none",
1717
- systemPromptMode: row.system_prompt_mode ?? "inline",
1718
- streaming: row.streaming ?? true,
1719
- cliffs: row.cliffs ?? [],
1720
- costInputPer1m: row.cost_input_per_1m ?? 0,
1721
- costOutputPer1m: row.cost_output_per_1m ?? 0,
1722
- lowering: row.lowering ?? { system: { mode: "inline" }, cache: { strategy: "unsupported" } },
1723
- recovery: row.recovery ?? [],
1724
- strengths: row.strengths ?? [],
1725
- weaknesses: row.weaknesses ?? [],
1726
- notes: row.notes ?? void 0,
1727
- verifiedAgainstDocs: row.verified_against_docs ?? void 0,
1728
- archetypePerf: row.archetype_perf ?? void 0,
1729
- // alpha.41 — family-resolution fields. `family` may be null pre-
1730
- // migration 024; runtime falls back to deriveFamilyFromModelId at
1731
- // resolution time (see family-resolution.ts, G1).
1732
- family: row.family ?? void 0,
1733
- versionAdded: row.version_added ?? void 0,
1734
- active: row.active ?? void 0
1735
- };
1736
- } catch {
1737
- return null;
1738
- }
1739
- }
1740
- function profileToRow(profile, opts = {}) {
1741
- const row = {
1742
- model_id: profile.id,
1743
- provider: profile.provider,
1744
- status: profile.status,
1745
- max_context_tokens: profile.maxContextTokens,
1746
- max_output_tokens: profile.maxOutputTokens,
1747
- max_tools: profile.maxTools,
1748
- parallel_tool_calls: profile.parallelToolCalls,
1749
- structured_output: profile.structuredOutput,
1750
- system_prompt_mode: profile.systemPromptMode,
1751
- streaming: profile.streaming,
1752
- cliffs: profile.cliffs,
1753
- cost_input_per_1m: profile.costInputPer1m,
1754
- cost_output_per_1m: profile.costOutputPer1m,
1755
- lowering: profile.lowering,
1756
- recovery: profile.recovery,
1757
- strengths: profile.strengths,
1758
- weaknesses: profile.weaknesses,
1759
- notes: profile.notes ?? null,
1760
- archetype_perf: profile.archetypePerf ?? null,
1761
- active: opts.active ?? profile.active ?? true,
1762
- // alpha.41 — round-trip family + version_added when present on profile.
1763
- // version_added is operator-controlled via opts; profile-side value is
1764
- // used only when opts didn't override.
1765
- family: profile.family ?? null
1766
- };
1767
- if (opts.verifiedAgainstDocs !== void 0) {
1768
- row.verified_against_docs = opts.verifiedAgainstDocs;
1769
- } else if (profile.verifiedAgainstDocs !== void 0) {
1770
- const v = profile.verifiedAgainstDocs;
1771
- row.verified_against_docs = /^\d{4}-\d{2}-\d{2}/.test(v) ? v : null;
1772
- }
1773
- if (opts.versionAdded !== void 0) row.version_added = opts.versionAdded;
1774
- else if (profile.versionAdded !== void 0) row.version_added = profile.versionAdded;
1775
- if (opts.versionRemoved !== void 0) row.version_removed = opts.versionRemoved;
1776
- return row;
1777
- }
1778
- function mapRowsToModels(rows) {
1779
- const out = /* @__PURE__ */ new Map();
1780
- for (const row of rows) {
1781
- if (!isModelRow(row)) continue;
1782
- const profile = rowToProfile(row);
1783
- if (profile) out.set(profile.id, profile);
1784
- }
1785
- return out;
1786
- }
1787
- function mapRowsToAliases(rows) {
1788
- const out = {};
1789
- for (const row of rows) {
1790
- if (!isAliasRow(row)) continue;
1791
- out[row.alias_id] = row.canonical_id;
1792
- }
1793
- return out;
1794
- }
1795
- function bundledModels() {
1796
- return new Map(allProfilesRaw().map((p) => [p.id, p]));
1797
- }
1798
- function bundledAliases() {
1799
- return { ...ALIASES };
1800
- }
1801
- var loadModelsFromBrain = createBrainQueryCache({
1802
- table: "kgauto_models",
1803
- mapRows: mapRowsToModels,
1804
- bundledFallback: bundledModels
1805
- });
1806
- var loadAliasesFromBrain = createBrainQueryCache({
1807
- table: "kgauto_aliases",
1808
- mapRows: mapRowsToAliases,
1809
- bundledFallback: bundledAliases
1810
- });
1811
- _setProfileBrainHook({
1812
- getProfile: (canonical) => loadModelsFromBrain().get(canonical),
1813
- resolveAlias: (id) => loadAliasesFromBrain()[id]
1814
- });
1815
-
1816
- // src/family-resolution.ts
1817
- var FamilyResolutionError = class extends Error {
1818
- family;
1819
- cause;
1820
- constructor(family, cause) {
1821
- super(
1822
- `Family "${family}" did not resolve to any current+active model. ${cause}. Pass a literal model id in ir.models, or call getRecommendedPrimary({ family, fallback }) at IR-construction time.`
1823
- );
1824
- this.name = "FamilyResolutionError";
1825
- this.family = family;
1826
- this.cause = cause;
1827
- }
1828
- };
1829
- function deriveFamilyFromModelId(modelId) {
1830
- if (typeof modelId !== "string" || modelId.length === 0) return null;
1831
- if (modelId.startsWith("claude-opus-")) return "claude-opus";
1832
- if (modelId.startsWith("claude-sonnet-")) return "claude-sonnet";
1833
- if (modelId.startsWith("claude-haiku-")) return "claude-haiku";
1834
- if (modelId.startsWith("gemini-") && modelId.includes("flash-lite")) {
1835
- return "gemini-flash-lite";
1836
- }
1837
- if (modelId.startsWith("gemini-") && modelId.includes("flash")) {
1838
- return "gemini-flash";
1839
- }
1840
- if (modelId.startsWith("gemini-") && modelId.includes("pro")) {
1841
- return "gemini-pro";
1842
- }
1843
- if (modelId.startsWith("deepseek-") && modelId.includes("pro")) {
1844
- return "deepseek-reasoner";
1845
- }
1846
- if (modelId.startsWith("deepseek-")) return "deepseek-chat";
1847
- if (modelId.startsWith("gpt-")) return "openai-gpt";
1848
- return null;
1849
- }
1850
- function familyOf(profile) {
1851
- return profile.family ?? deriveFamilyFromModelId(profile.id);
1852
- }
1853
- function archetypePerfFor(profile, archetype) {
1854
- if (!archetype) return 0;
1855
- const score = profile.archetypePerf?.[archetype];
1856
- return typeof score === "number" ? score : 5;
1857
- }
1858
- function selectCandidates(registry, family, archetype, appId) {
1859
- const out = [];
1860
- const excluded = /* @__PURE__ */ new Set();
1861
- if (appId && archetype) {
1862
- const findings = getStaleExclusionFindings({ appId, archetype });
1863
- for (const f of findings) {
1864
- if (f.verdict === "stay-excluded") excluded.add(f.excludedModel);
1865
- }
1866
- }
1867
- for (const profile of registry.values()) {
1868
- if (familyOf(profile) !== family) continue;
1869
- if (profile.status !== "current") continue;
1870
- if (profile.active === false) continue;
1871
- if (archetype) {
1872
- if (archetypePerfFor(profile, archetype) < ARCHETYPE_FLOOR_DEFAULT) continue;
1873
- }
1874
- if (excluded.has(profile.id)) continue;
1875
- out.push(profile);
1876
- }
1877
- return out;
1878
- }
1879
- function sortCandidates(candidates, archetype) {
1880
- const sorted = [...candidates];
1881
- sorted.sort((a, b) => {
1882
- const perfA = archetypePerfFor(a, archetype);
1883
- const perfB = archetypePerfFor(b, archetype);
1884
- if (perfA !== perfB) return perfB - perfA;
1885
- const vA = a.versionAdded ?? "";
1886
- const vB = b.versionAdded ?? "";
1887
- if (vA !== vB) return vA < vB ? 1 : -1;
1888
- return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
1889
- });
1890
- return sorted;
1891
- }
1892
- function getRecommendedPrimary(opts) {
1893
- if (opts.posture === "locked") return opts.fallback;
1894
- const registry = loadModelsFromBrain();
1895
- const candidates = selectCandidates(
1896
- registry,
1897
- opts.family,
1898
- opts.archetype,
1899
- opts.appId
1900
- );
1901
- if (candidates.length === 0) return opts.fallback;
1902
- const sorted = sortCandidates(candidates, opts.archetype);
1903
- return sorted[0]?.id ?? opts.fallback;
1904
- }
1905
- function resolveFamilyEntry(family, ctx) {
1906
- if (typeof family !== "string" || family.length === 0) {
1907
- throw new FamilyResolutionError(
1908
- String(family),
1909
- "Family tag must be a non-empty string"
1910
- );
1911
- }
1912
- const registry = loadModelsFromBrain();
1913
- const candidates = selectCandidates(
1914
- registry,
1915
- family,
1916
- ctx.archetype,
1917
- ctx.appId
1918
- );
1919
- if (candidates.length === 0) {
1920
- let anyInFamily = false;
1921
- for (const profile of registry.values()) {
1922
- if (familyOf(profile) === family) {
1923
- anyInFamily = true;
1924
- break;
1925
- }
1926
- }
1927
- const cause = anyInFamily ? `Family has registered models but none are current+active${ctx.archetype ? ` at archetype-perf >= ${ARCHETYPE_FLOOR_DEFAULT} for "${ctx.archetype}"` : ""}${ctx.appId ? ` and not excluded for app "${ctx.appId}"` : ""}` : `No models in brain registry carry family="${family}". Check the taxonomy table in family-resolution.ts or migration 024`;
1928
- throw new FamilyResolutionError(family, cause);
1929
- }
1930
- const sorted = sortCandidates(candidates, ctx.archetype);
1931
- const winner = sorted[0];
1932
- if (!winner) {
1933
- throw new FamilyResolutionError(
1934
- family,
1935
- "Candidates non-empty but sort returned undefined \u2014 internal invariant violation"
1936
- );
1937
- }
1938
- return winner.id;
1939
- }
1940
-
1941
2189
  // src/compile.ts
1942
2190
  var counter = 0;
1943
2191
  function makeHandle() {
@@ -1982,6 +2230,9 @@ function compile(ir, opts = {}) {
1982
2230
  const cliffs = passApplyCliffs(workingIR, profile, inputTokens);
1983
2231
  workingIR = cliffs.value.ir;
1984
2232
  accumulatedMutations.push(...cliffs.mutations);
2233
+ const conventions = passApplyConventions(workingIR, profile);
2234
+ workingIR = conventions.value.ir;
2235
+ accumulatedMutations.push(...conventions.mutations);
1985
2236
  const translated = applySectionRewrites({
1986
2237
  ir: workingIR,
1987
2238
  profile,
@@ -2033,7 +2284,15 @@ function compile(ir, opts = {}) {
2033
2284
  toolOrchestration: ir.constraints?.toolOrchestration,
2034
2285
  // alpha.33 — see top-of-block comment.
2035
2286
  historyCacheMarkIndex,
2036
- systemCacheMarkIndex
2287
+ systemCacheMarkIndex,
2288
+ // alpha.43 — cliff-style warnings emitted by passApplyConventions.
2289
+ // Merge convention-pass cliffWarnings with any cliff-guard quality
2290
+ // warnings the cliff pass surfaced (the same shape — informational
2291
+ // text the consumer can route on without changing behavior).
2292
+ cliffWarnings: [
2293
+ ...cliffs.value.loweringHints.qualityWarning ?? [],
2294
+ ...conventions.value.cliffWarnings
2295
+ ]
2037
2296
  };
2038
2297
  if (ir.intent.archetype === "hunt" && ir.constraints?.toolOrchestration === "sequential") {
2039
2298
  accumulatedMutations.push({
@@ -3344,7 +3603,12 @@ async function call(ir, opts = {}) {
3344
3603
  fallbackReason,
3345
3604
  unreachableFiltered,
3346
3605
  policyBlockedFiltered,
3347
- traceId
3606
+ traceId,
3607
+ // alpha.44: surface the served compile's advisories so call()
3608
+ // consumers (agent paths) can logAdvisories() like compile()
3609
+ // consumers (chat/intake) do. activeCompile, not initial — parity
3610
+ // with mutationsApplied above on fallback. Closes IC's side-finding.
3611
+ advisories: activeCompile.advisories
3348
3612
  };
3349
3613
  }
3350
3614
  attempts.push({
@@ -3917,6 +4181,7 @@ export {
3917
4181
  ABSOLUTE_FLOOR,
3918
4182
  ALIASES,
3919
4183
  ALL_ARCHETYPES,
4184
+ ARCHETYPE_FAMILY_FITS,
3920
4185
  ARCHETYPE_FLOOR_DEFAULT,
3921
4186
  CallError,
3922
4187
  DEFAULT_FINDINGS_ENDPOINT,
@@ -3929,6 +4194,7 @@ export {
3929
4194
  RULE_SEQUENTIAL_TOOL_CLIFF,
3930
4195
  TRANSLATOR_FLOOR,
3931
4196
  allProfiles,
4197
+ applyArchetypeConvention,
3932
4198
  applySectionRewrites,
3933
4199
  attachCacheControlToStreamTextInput,
3934
4200
  bucketContext,
@@ -3943,6 +4209,7 @@ export {
3943
4209
  deriveFamilyFromModelId,
3944
4210
  deriveOwnership,
3945
4211
  execute,
4212
+ findBetterFit,
3946
4213
  getActionableAdvisories,
3947
4214
  getAllStarterChains,
3948
4215
  getAllStarterChainsWithGrounding,
@@ -3981,6 +4248,7 @@ export {
3981
4248
  record,
3982
4249
  recordOutcome,
3983
4250
  resetTokenizer,
4251
+ resolveConventionsForProfile,
3984
4252
  resolvePricingAt,
3985
4253
  resolveProviderKey,
3986
4254
  runAdvisor,