@warmdrift/kgauto-compiler 2.0.0-alpha.30 → 2.0.0-alpha.32
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/glassbox-routes/index.d.mts +94 -1
- package/dist/glassbox-routes/index.d.ts +94 -1
- package/dist/glassbox-routes/index.js +18 -2
- package/dist/glassbox-routes/index.mjs +12 -1
- package/dist/index.d.mts +34 -18
- package/dist/index.d.ts +34 -18
- package/dist/index.js +41 -13
- package/dist/index.mjs +41 -13
- package/package.json +1 -1
|
@@ -148,6 +148,99 @@ interface TraceDetail extends TraceSummary {
|
|
|
148
148
|
health: TraceHealth;
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
/**
|
|
152
|
+
* proxy(req) — Glass-Box replay query handler.
|
|
153
|
+
*
|
|
154
|
+
* GET /api/glassbox/proxy?traceId=<id> → single compile_outcomes row for trace
|
|
155
|
+
* GET /api/glassbox/proxy?limit=<N> → N most-recent compile_outcomes rows
|
|
156
|
+
* GET /api/glassbox/proxy → defaults to limit=20
|
|
157
|
+
*
|
|
158
|
+
* Brain reads go through PostgREST on Supabase. We always filter by
|
|
159
|
+
* `app_id=eq.<appId>` even though the scoped JWT's RLS policy already
|
|
160
|
+
* enforces tenant isolation — the explicit filter trims the network payload
|
|
161
|
+
* and makes the query intent obvious to anyone reading logs.
|
|
162
|
+
*
|
|
163
|
+
* Scrub: the optional `scrub` hook runs on each row before responding so
|
|
164
|
+
* sensitive payloads (rendered prompts, tool calls) can be redacted at the
|
|
165
|
+
* proxy boundary. Default is identity (no-op).
|
|
166
|
+
*/
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Typed boundary transformer: compile_outcomes row (snake_case, Postgres
|
|
170
|
+
* native) → TraceSummary (camelCase, TypeScript native + extension wire
|
|
171
|
+
* contract). Single canonical mapping site — every DB-shape ↔ wire-shape
|
|
172
|
+
* crossing routes through here so renderer-expected fields can't silently
|
|
173
|
+
* go missing. See `feedback_typed_boundary_transformers.md` for the rule.
|
|
174
|
+
*/
|
|
175
|
+
declare function rowToSummary(row: Record<string, unknown>): TraceSummary;
|
|
176
|
+
/**
|
|
177
|
+
* Typed boundary transformer (L-118): compile_outcomes row → TraceDetail.
|
|
178
|
+
* Single canonical mapping site for the detail-view wire contract. Pre-018
|
|
179
|
+
* brain rows return NULL for the new columns; this transformer applies
|
|
180
|
+
* type-safe defaults (0 for token columns, undefined for optional strings)
|
|
181
|
+
* so the renderer never crashes on missing fields.
|
|
182
|
+
*
|
|
183
|
+
* alpha.28 extends the field set per the renderer design contract — every
|
|
184
|
+
* extended field has a default. The `counterfactuals` + `projectedDailyCost`
|
|
185
|
+
* fields are populated by the proxy AFTER this transformer runs (they need
|
|
186
|
+
* profile lookup / brain query / async I/O).
|
|
187
|
+
*/
|
|
188
|
+
declare function rowToDetail(row: Record<string, unknown>): TraceDetail;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* computeCounterfactuals — for a served trace, compute up to 2 cheaper
|
|
192
|
+
* alternatives that ALSO meet the archetype quality floor.
|
|
193
|
+
*
|
|
194
|
+
* Pure function. Called at detail-view time by the proxy's `rowToDetail`
|
|
195
|
+
* path. The cost-equivalent answer to "what could this have run on without
|
|
196
|
+
* tanking quality?" lets the Glass-Box render `💰 Cheaper alternatives` so a
|
|
197
|
+
* founder sees the actual cost of the routing choice rather than just the
|
|
198
|
+
* served cost.
|
|
199
|
+
*
|
|
200
|
+
* Mechanism (per design contract Phase 0 spec):
|
|
201
|
+
* 1. Walk the archetype's full default fallback chain.
|
|
202
|
+
* 2. For each model in the chain (excluding the served model):
|
|
203
|
+
* - Skip if archetypePerf[archetype] < ARCHETYPE_FLOOR_DEFAULT (6).
|
|
204
|
+
* Matches the cliff-advisor work — never recommend a swap that
|
|
205
|
+
* violates the quality floor. (Composition with Builder C is
|
|
206
|
+
* intentional.)
|
|
207
|
+
* - Skip if profile missing.
|
|
208
|
+
* - Compute estimated cost at the OBSERVED token counts:
|
|
209
|
+
* non_cached_in = tokensIn - cacheReadInputTokens
|
|
210
|
+
* cost = (non_cached_in / 1e6) * profile.costInputPer1m
|
|
211
|
+
* + (cacheable_in / 1e6) * profile.costInputPer1m
|
|
212
|
+
* * profile.lowering.cache.discount
|
|
213
|
+
* + (tokensOut / 1e6) * profile.costOutputPer1m
|
|
214
|
+
* - Only include if estimatedCostUsd ≤ 0.9 × servedCostUsd
|
|
215
|
+
* (≥10% cheaper — below that's noise of token-count estimation).
|
|
216
|
+
* 3. Sort cheapest first.
|
|
217
|
+
* 4. Cap to top 2.
|
|
218
|
+
*
|
|
219
|
+
* Edge cases:
|
|
220
|
+
* - tokensIn === 0 → return [] (can't meaningfully estimate).
|
|
221
|
+
* - servedCostUsd === 0 → return [] (no baseline to beat).
|
|
222
|
+
* - Zero matching alternatives → return [] (renderer hides the card).
|
|
223
|
+
* - Served model isn't in the chain (e.g. forceModel'd off-chain) → use
|
|
224
|
+
* the chain for the archetype anyway.
|
|
225
|
+
*/
|
|
226
|
+
|
|
227
|
+
/** Only surface swaps that save at least 10% vs. served. */
|
|
228
|
+
declare const COUNTERFACTUAL_MIN_SAVINGS_RATIO = 0.1;
|
|
229
|
+
/** Cap on alternatives surfaced per trace. */
|
|
230
|
+
declare const COUNTERFACTUAL_MAX_RESULTS = 2;
|
|
231
|
+
interface ComputeCounterfactualsArgs {
|
|
232
|
+
servedModel: string;
|
|
233
|
+
servedCostUsd: number;
|
|
234
|
+
archetype: string;
|
|
235
|
+
tokensIn: number;
|
|
236
|
+
tokensOut: number;
|
|
237
|
+
/** Defaults to 0 when caller doesn't know. */
|
|
238
|
+
cacheReadInputTokens?: number;
|
|
239
|
+
/** Reserved for future per-mode chain selection. */
|
|
240
|
+
toolOrchestration?: 'parallel' | 'sequential' | 'either';
|
|
241
|
+
}
|
|
242
|
+
declare function computeCounterfactuals(args: ComputeCounterfactualsArgs): TraceCounterfactual[];
|
|
243
|
+
|
|
151
244
|
/**
|
|
152
245
|
* Public entry point for `@warmdrift/kgauto-compiler/glassbox-routes`.
|
|
153
246
|
*
|
|
@@ -239,4 +332,4 @@ interface GlassboxRoutes {
|
|
|
239
332
|
}
|
|
240
333
|
declare function createGlassboxRoutes(config: GlassboxRoutesConfig): GlassboxRoutes;
|
|
241
334
|
|
|
242
|
-
export { type GlassboxRoutes, type GlassboxRoutesConfig, type TraceDetail, type TraceSummary, createGlassboxRoutes };
|
|
335
|
+
export { type AdvisoryRecord, COUNTERFACTUAL_MAX_RESULTS, COUNTERFACTUAL_MIN_SAVINGS_RATIO, type ComputeCounterfactualsArgs, type GlassboxRoutes, type GlassboxRoutesConfig, type TraceCounterfactual, type TraceDetail, type TraceHealth, type TraceSectionRewrite, type TraceSummary, computeCounterfactuals, createGlassboxRoutes, rowToDetail, rowToSummary };
|
|
@@ -148,6 +148,99 @@ interface TraceDetail extends TraceSummary {
|
|
|
148
148
|
health: TraceHealth;
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
/**
|
|
152
|
+
* proxy(req) — Glass-Box replay query handler.
|
|
153
|
+
*
|
|
154
|
+
* GET /api/glassbox/proxy?traceId=<id> → single compile_outcomes row for trace
|
|
155
|
+
* GET /api/glassbox/proxy?limit=<N> → N most-recent compile_outcomes rows
|
|
156
|
+
* GET /api/glassbox/proxy → defaults to limit=20
|
|
157
|
+
*
|
|
158
|
+
* Brain reads go through PostgREST on Supabase. We always filter by
|
|
159
|
+
* `app_id=eq.<appId>` even though the scoped JWT's RLS policy already
|
|
160
|
+
* enforces tenant isolation — the explicit filter trims the network payload
|
|
161
|
+
* and makes the query intent obvious to anyone reading logs.
|
|
162
|
+
*
|
|
163
|
+
* Scrub: the optional `scrub` hook runs on each row before responding so
|
|
164
|
+
* sensitive payloads (rendered prompts, tool calls) can be redacted at the
|
|
165
|
+
* proxy boundary. Default is identity (no-op).
|
|
166
|
+
*/
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Typed boundary transformer: compile_outcomes row (snake_case, Postgres
|
|
170
|
+
* native) → TraceSummary (camelCase, TypeScript native + extension wire
|
|
171
|
+
* contract). Single canonical mapping site — every DB-shape ↔ wire-shape
|
|
172
|
+
* crossing routes through here so renderer-expected fields can't silently
|
|
173
|
+
* go missing. See `feedback_typed_boundary_transformers.md` for the rule.
|
|
174
|
+
*/
|
|
175
|
+
declare function rowToSummary(row: Record<string, unknown>): TraceSummary;
|
|
176
|
+
/**
|
|
177
|
+
* Typed boundary transformer (L-118): compile_outcomes row → TraceDetail.
|
|
178
|
+
* Single canonical mapping site for the detail-view wire contract. Pre-018
|
|
179
|
+
* brain rows return NULL for the new columns; this transformer applies
|
|
180
|
+
* type-safe defaults (0 for token columns, undefined for optional strings)
|
|
181
|
+
* so the renderer never crashes on missing fields.
|
|
182
|
+
*
|
|
183
|
+
* alpha.28 extends the field set per the renderer design contract — every
|
|
184
|
+
* extended field has a default. The `counterfactuals` + `projectedDailyCost`
|
|
185
|
+
* fields are populated by the proxy AFTER this transformer runs (they need
|
|
186
|
+
* profile lookup / brain query / async I/O).
|
|
187
|
+
*/
|
|
188
|
+
declare function rowToDetail(row: Record<string, unknown>): TraceDetail;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* computeCounterfactuals — for a served trace, compute up to 2 cheaper
|
|
192
|
+
* alternatives that ALSO meet the archetype quality floor.
|
|
193
|
+
*
|
|
194
|
+
* Pure function. Called at detail-view time by the proxy's `rowToDetail`
|
|
195
|
+
* path. The cost-equivalent answer to "what could this have run on without
|
|
196
|
+
* tanking quality?" lets the Glass-Box render `💰 Cheaper alternatives` so a
|
|
197
|
+
* founder sees the actual cost of the routing choice rather than just the
|
|
198
|
+
* served cost.
|
|
199
|
+
*
|
|
200
|
+
* Mechanism (per design contract Phase 0 spec):
|
|
201
|
+
* 1. Walk the archetype's full default fallback chain.
|
|
202
|
+
* 2. For each model in the chain (excluding the served model):
|
|
203
|
+
* - Skip if archetypePerf[archetype] < ARCHETYPE_FLOOR_DEFAULT (6).
|
|
204
|
+
* Matches the cliff-advisor work — never recommend a swap that
|
|
205
|
+
* violates the quality floor. (Composition with Builder C is
|
|
206
|
+
* intentional.)
|
|
207
|
+
* - Skip if profile missing.
|
|
208
|
+
* - Compute estimated cost at the OBSERVED token counts:
|
|
209
|
+
* non_cached_in = tokensIn - cacheReadInputTokens
|
|
210
|
+
* cost = (non_cached_in / 1e6) * profile.costInputPer1m
|
|
211
|
+
* + (cacheable_in / 1e6) * profile.costInputPer1m
|
|
212
|
+
* * profile.lowering.cache.discount
|
|
213
|
+
* + (tokensOut / 1e6) * profile.costOutputPer1m
|
|
214
|
+
* - Only include if estimatedCostUsd ≤ 0.9 × servedCostUsd
|
|
215
|
+
* (≥10% cheaper — below that's noise of token-count estimation).
|
|
216
|
+
* 3. Sort cheapest first.
|
|
217
|
+
* 4. Cap to top 2.
|
|
218
|
+
*
|
|
219
|
+
* Edge cases:
|
|
220
|
+
* - tokensIn === 0 → return [] (can't meaningfully estimate).
|
|
221
|
+
* - servedCostUsd === 0 → return [] (no baseline to beat).
|
|
222
|
+
* - Zero matching alternatives → return [] (renderer hides the card).
|
|
223
|
+
* - Served model isn't in the chain (e.g. forceModel'd off-chain) → use
|
|
224
|
+
* the chain for the archetype anyway.
|
|
225
|
+
*/
|
|
226
|
+
|
|
227
|
+
/** Only surface swaps that save at least 10% vs. served. */
|
|
228
|
+
declare const COUNTERFACTUAL_MIN_SAVINGS_RATIO = 0.1;
|
|
229
|
+
/** Cap on alternatives surfaced per trace. */
|
|
230
|
+
declare const COUNTERFACTUAL_MAX_RESULTS = 2;
|
|
231
|
+
interface ComputeCounterfactualsArgs {
|
|
232
|
+
servedModel: string;
|
|
233
|
+
servedCostUsd: number;
|
|
234
|
+
archetype: string;
|
|
235
|
+
tokensIn: number;
|
|
236
|
+
tokensOut: number;
|
|
237
|
+
/** Defaults to 0 when caller doesn't know. */
|
|
238
|
+
cacheReadInputTokens?: number;
|
|
239
|
+
/** Reserved for future per-mode chain selection. */
|
|
240
|
+
toolOrchestration?: 'parallel' | 'sequential' | 'either';
|
|
241
|
+
}
|
|
242
|
+
declare function computeCounterfactuals(args: ComputeCounterfactualsArgs): TraceCounterfactual[];
|
|
243
|
+
|
|
151
244
|
/**
|
|
152
245
|
* Public entry point for `@warmdrift/kgauto-compiler/glassbox-routes`.
|
|
153
246
|
*
|
|
@@ -239,4 +332,4 @@ interface GlassboxRoutes {
|
|
|
239
332
|
}
|
|
240
333
|
declare function createGlassboxRoutes(config: GlassboxRoutesConfig): GlassboxRoutes;
|
|
241
334
|
|
|
242
|
-
export { type GlassboxRoutes, type GlassboxRoutesConfig, type TraceDetail, type TraceSummary, createGlassboxRoutes };
|
|
335
|
+
export { type AdvisoryRecord, COUNTERFACTUAL_MAX_RESULTS, COUNTERFACTUAL_MIN_SAVINGS_RATIO, type ComputeCounterfactualsArgs, type GlassboxRoutes, type GlassboxRoutesConfig, type TraceCounterfactual, type TraceDetail, type TraceHealth, type TraceSectionRewrite, type TraceSummary, computeCounterfactuals, createGlassboxRoutes, rowToDetail, rowToSummary };
|
|
@@ -20,7 +20,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/glassbox-routes/index.ts
|
|
21
21
|
var glassbox_routes_exports = {};
|
|
22
22
|
__export(glassbox_routes_exports, {
|
|
23
|
-
|
|
23
|
+
COUNTERFACTUAL_MAX_RESULTS: () => COUNTERFACTUAL_MAX_RESULTS,
|
|
24
|
+
COUNTERFACTUAL_MIN_SAVINGS_RATIO: () => COUNTERFACTUAL_MIN_SAVINGS_RATIO,
|
|
25
|
+
computeCounterfactuals: () => computeCounterfactuals,
|
|
26
|
+
createGlassboxRoutes: () => createGlassboxRoutes,
|
|
27
|
+
rowToDetail: () => rowToDetail,
|
|
28
|
+
rowToSummary: () => rowToSummary
|
|
24
29
|
});
|
|
25
30
|
module.exports = __toCommonJS(glassbox_routes_exports);
|
|
26
31
|
|
|
@@ -1815,6 +1820,12 @@ function summarizeSectionRewrite(kind, rule) {
|
|
|
1815
1820
|
if (kind === "tool_call_contract" && rule === "sequential-tool-cliff-below-floor") {
|
|
1816
1821
|
return "Sequential tool pattern applied (model cliff cleared at compile time).";
|
|
1817
1822
|
}
|
|
1823
|
+
if (kind === "narration_contract" && rule === "narration-drift-anthropic") {
|
|
1824
|
+
return "Narration tightened for Anthropic dialect (terse-log shape preserved).";
|
|
1825
|
+
}
|
|
1826
|
+
if (kind === "narration_contract" && rule === "narration-thinking-leak-deepseek") {
|
|
1827
|
+
return "Thinking-block suppression applied (DeepSeek V4 internal reasoning kept off-wire).";
|
|
1828
|
+
}
|
|
1818
1829
|
return `Translator applied rule "${rule}" to ${kind} section.`;
|
|
1819
1830
|
}
|
|
1820
1831
|
function rowToSectionRewrite(raw) {
|
|
@@ -2448,5 +2459,10 @@ function createGlassboxRoutes(config) {
|
|
|
2448
2459
|
}
|
|
2449
2460
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2450
2461
|
0 && (module.exports = {
|
|
2451
|
-
|
|
2462
|
+
COUNTERFACTUAL_MAX_RESULTS,
|
|
2463
|
+
COUNTERFACTUAL_MIN_SAVINGS_RATIO,
|
|
2464
|
+
computeCounterfactuals,
|
|
2465
|
+
createGlassboxRoutes,
|
|
2466
|
+
rowToDetail,
|
|
2467
|
+
rowToSummary
|
|
2452
2468
|
});
|
|
@@ -295,6 +295,12 @@ function summarizeSectionRewrite(kind, rule) {
|
|
|
295
295
|
if (kind === "tool_call_contract" && rule === "sequential-tool-cliff-below-floor") {
|
|
296
296
|
return "Sequential tool pattern applied (model cliff cleared at compile time).";
|
|
297
297
|
}
|
|
298
|
+
if (kind === "narration_contract" && rule === "narration-drift-anthropic") {
|
|
299
|
+
return "Narration tightened for Anthropic dialect (terse-log shape preserved).";
|
|
300
|
+
}
|
|
301
|
+
if (kind === "narration_contract" && rule === "narration-thinking-leak-deepseek") {
|
|
302
|
+
return "Thinking-block suppression applied (DeepSeek V4 internal reasoning kept off-wire).";
|
|
303
|
+
}
|
|
298
304
|
return `Translator applied rule "${rule}" to ${kind} section.`;
|
|
299
305
|
}
|
|
300
306
|
function rowToSectionRewrite(raw) {
|
|
@@ -648,5 +654,10 @@ function createGlassboxRoutes(config) {
|
|
|
648
654
|
return { proxy, stream };
|
|
649
655
|
}
|
|
650
656
|
export {
|
|
651
|
-
|
|
657
|
+
COUNTERFACTUAL_MAX_RESULTS,
|
|
658
|
+
COUNTERFACTUAL_MIN_SAVINGS_RATIO,
|
|
659
|
+
computeCounterfactuals,
|
|
660
|
+
createGlassboxRoutes,
|
|
661
|
+
rowToDetail,
|
|
662
|
+
rowToSummary
|
|
652
663
|
};
|
package/dist/index.d.mts
CHANGED
|
@@ -374,26 +374,42 @@ interface RunAdvisorPhase2Context {
|
|
|
374
374
|
declare function runAdvisor(ir: PromptIR, result: AdvisorContext, profile: ModelProfile, policy?: CompilePolicy, phase2?: RunAdvisorPhase2Context): BestPracticeAdvisory[];
|
|
375
375
|
|
|
376
376
|
/**
|
|
377
|
-
* Translator primitive — alpha.
|
|
377
|
+
* Translator primitive — alpha.31.
|
|
378
378
|
*
|
|
379
379
|
* Pure function. Walks `IR.sections`, matches each section's `kind` against
|
|
380
|
-
*
|
|
381
|
-
* a rule fires. Returns the rewritten IR + the
|
|
382
|
-
* `CompileResult.sectionRewritesApplied` and brain
|
|
380
|
+
* a per-rule dispatch table keyed on (kind, profile, archetype), and applies
|
|
381
|
+
* a model-aware rewrite when a rule fires. Returns the rewritten IR + the
|
|
382
|
+
* list of rewrites for `CompileResult.sectionRewritesApplied` and brain
|
|
383
|
+
* persistence.
|
|
383
384
|
*
|
|
384
385
|
* This is the s37 translator-framing eureka in code: kgauto graduates from
|
|
385
386
|
* "gate" (alpha.28's cliff advisor: "consumer must accept adapter") to
|
|
386
387
|
* "translator" (alpha.29: "consumer declared the section kind, kgauto
|
|
387
388
|
* applies the adapter at compile time without consumer-side branching").
|
|
388
389
|
*
|
|
389
|
-
*
|
|
390
|
+
* Rules shipped:
|
|
390
391
|
*
|
|
391
|
-
* tool_call_contract +
|
|
392
|
+
* alpha.29 — tool_call_contract + archetypePerf[archetype] < TRANSLATOR_FLOOR
|
|
392
393
|
* → prepend sequential-tool-pattern guidance
|
|
393
394
|
* → emit wireOverrides: { parallelToolCalls: false }
|
|
395
|
+
* → rule_id: 'sequential-tool-cliff-below-floor'
|
|
394
396
|
*
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
+
* alpha.31 — narration_contract + profile.provider === 'anthropic'
|
|
398
|
+
* → prepend terse-log narration guidance
|
|
399
|
+
* → no wireOverrides
|
|
400
|
+
* → rule_id: 'narration-drift-anthropic'
|
|
401
|
+
*
|
|
402
|
+
* alpha.31 — narration_contract + profile.provider === 'deepseek'
|
|
403
|
+
* → prepend <thinking>-suppression guidance
|
|
404
|
+
* → no wireOverrides
|
|
405
|
+
* → rule_id: 'narration-thinking-leak-deepseek'
|
|
406
|
+
*
|
|
407
|
+
* Per-rule walk (alpha.31 refactor): the alpha.30 short-circuit
|
|
408
|
+
* `if (!cliffFires) return passthrough` was correct when only the
|
|
409
|
+
* cliff-gated tool_call_contract rule existed; alpha.31's narration rules
|
|
410
|
+
* fire on every call regardless of cliff (narration drift is steady-state,
|
|
411
|
+
* not a cliff condition). Each section now consults the dispatch table
|
|
412
|
+
* independently — first-match wins per (section.kind, profile, archetype).
|
|
397
413
|
*
|
|
398
414
|
* **Interaction with the cliff advisor (alpha.28):** when this translator
|
|
399
415
|
* fires for a `tool_call_contract` section, the advisor's
|
|
@@ -402,8 +418,9 @@ declare function runAdvisor(ir: PromptIR, result: AdvisorContext, profile: Model
|
|
|
402
418
|
* suppression check lives in `advisor.ts` and consults the
|
|
403
419
|
* `CompileResult.sectionRewritesApplied` list.
|
|
404
420
|
*
|
|
405
|
-
* Design
|
|
421
|
+
* Design contracts:
|
|
406
422
|
* command-center/advisory/kgauto/2026-05-21_alpha-29-translator-and-advisories-api.md
|
|
423
|
+
* command-center/advisory/kgauto/2026-05-22_alpha-31-narration-contract.md
|
|
407
424
|
*/
|
|
408
425
|
|
|
409
426
|
/**
|
|
@@ -415,8 +432,9 @@ declare function runAdvisor(ir: PromptIR, result: AdvisorContext, profile: Model
|
|
|
415
432
|
declare const TRANSLATOR_FLOOR = 6;
|
|
416
433
|
/**
|
|
417
434
|
* Stable identifier of the alpha.29 sequential-tool rule. Surfaces on
|
|
418
|
-
* `SectionRewrite.rule` and in brain aggregates.
|
|
419
|
-
*
|
|
435
|
+
* `SectionRewrite.rule` and in brain aggregates. The brain treats this
|
|
436
|
+
* identifier together with the preamble string as the rule's wire
|
|
437
|
+
* fingerprint — both stay byte-stable across releases.
|
|
420
438
|
*/
|
|
421
439
|
declare const RULE_SEQUENTIAL_TOOL_CLIFF = "sequential-tool-cliff-below-floor";
|
|
422
440
|
interface ApplySectionRewritesArgs {
|
|
@@ -442,16 +460,14 @@ interface ApplySectionRewritesResult {
|
|
|
442
460
|
* Pure function. Apply model-aware section rewrites to the IR at compile time.
|
|
443
461
|
*
|
|
444
462
|
* Discipline:
|
|
445
|
-
* - Never mutates the input IR; returns a new IR with new sections array
|
|
463
|
+
* - Never mutates the input IR; returns a new IR with new sections array
|
|
464
|
+
* when at least one rewrite fired; otherwise returns the input IR by
|
|
465
|
+
* reference (referential identity preserved on no-op).
|
|
446
466
|
* - Sections without a `kind` (or `kind === 'arbitrary'`) pass through
|
|
447
467
|
* unchanged.
|
|
448
468
|
* - Empty `sections` array → returns `{ rewrittenIR: ir, rewrites: [] }`.
|
|
449
|
-
* -
|
|
450
|
-
*
|
|
451
|
-
* - Sections of the same `kind` are processed in array order; the rule
|
|
452
|
-
* fires once per matching section (today every tool_call_contract
|
|
453
|
-
* section gets the same prepend — multiple sections of the same kind
|
|
454
|
-
* ARE supported but is an unusual consumer shape).
|
|
469
|
+
* - Sections of the same `kind` are processed in array order; first-match
|
|
470
|
+
* wins per section. (Today every rule is a single-match rule.)
|
|
455
471
|
*
|
|
456
472
|
* @example
|
|
457
473
|
* ```ts
|
package/dist/index.d.ts
CHANGED
|
@@ -374,26 +374,42 @@ interface RunAdvisorPhase2Context {
|
|
|
374
374
|
declare function runAdvisor(ir: PromptIR, result: AdvisorContext, profile: ModelProfile, policy?: CompilePolicy, phase2?: RunAdvisorPhase2Context): BestPracticeAdvisory[];
|
|
375
375
|
|
|
376
376
|
/**
|
|
377
|
-
* Translator primitive — alpha.
|
|
377
|
+
* Translator primitive — alpha.31.
|
|
378
378
|
*
|
|
379
379
|
* Pure function. Walks `IR.sections`, matches each section's `kind` against
|
|
380
|
-
*
|
|
381
|
-
* a rule fires. Returns the rewritten IR + the
|
|
382
|
-
* `CompileResult.sectionRewritesApplied` and brain
|
|
380
|
+
* a per-rule dispatch table keyed on (kind, profile, archetype), and applies
|
|
381
|
+
* a model-aware rewrite when a rule fires. Returns the rewritten IR + the
|
|
382
|
+
* list of rewrites for `CompileResult.sectionRewritesApplied` and brain
|
|
383
|
+
* persistence.
|
|
383
384
|
*
|
|
384
385
|
* This is the s37 translator-framing eureka in code: kgauto graduates from
|
|
385
386
|
* "gate" (alpha.28's cliff advisor: "consumer must accept adapter") to
|
|
386
387
|
* "translator" (alpha.29: "consumer declared the section kind, kgauto
|
|
387
388
|
* applies the adapter at compile time without consumer-side branching").
|
|
388
389
|
*
|
|
389
|
-
*
|
|
390
|
+
* Rules shipped:
|
|
390
391
|
*
|
|
391
|
-
* tool_call_contract +
|
|
392
|
+
* alpha.29 — tool_call_contract + archetypePerf[archetype] < TRANSLATOR_FLOOR
|
|
392
393
|
* → prepend sequential-tool-pattern guidance
|
|
393
394
|
* → emit wireOverrides: { parallelToolCalls: false }
|
|
395
|
+
* → rule_id: 'sequential-tool-cliff-below-floor'
|
|
394
396
|
*
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
+
* alpha.31 — narration_contract + profile.provider === 'anthropic'
|
|
398
|
+
* → prepend terse-log narration guidance
|
|
399
|
+
* → no wireOverrides
|
|
400
|
+
* → rule_id: 'narration-drift-anthropic'
|
|
401
|
+
*
|
|
402
|
+
* alpha.31 — narration_contract + profile.provider === 'deepseek'
|
|
403
|
+
* → prepend <thinking>-suppression guidance
|
|
404
|
+
* → no wireOverrides
|
|
405
|
+
* → rule_id: 'narration-thinking-leak-deepseek'
|
|
406
|
+
*
|
|
407
|
+
* Per-rule walk (alpha.31 refactor): the alpha.30 short-circuit
|
|
408
|
+
* `if (!cliffFires) return passthrough` was correct when only the
|
|
409
|
+
* cliff-gated tool_call_contract rule existed; alpha.31's narration rules
|
|
410
|
+
* fire on every call regardless of cliff (narration drift is steady-state,
|
|
411
|
+
* not a cliff condition). Each section now consults the dispatch table
|
|
412
|
+
* independently — first-match wins per (section.kind, profile, archetype).
|
|
397
413
|
*
|
|
398
414
|
* **Interaction with the cliff advisor (alpha.28):** when this translator
|
|
399
415
|
* fires for a `tool_call_contract` section, the advisor's
|
|
@@ -402,8 +418,9 @@ declare function runAdvisor(ir: PromptIR, result: AdvisorContext, profile: Model
|
|
|
402
418
|
* suppression check lives in `advisor.ts` and consults the
|
|
403
419
|
* `CompileResult.sectionRewritesApplied` list.
|
|
404
420
|
*
|
|
405
|
-
* Design
|
|
421
|
+
* Design contracts:
|
|
406
422
|
* command-center/advisory/kgauto/2026-05-21_alpha-29-translator-and-advisories-api.md
|
|
423
|
+
* command-center/advisory/kgauto/2026-05-22_alpha-31-narration-contract.md
|
|
407
424
|
*/
|
|
408
425
|
|
|
409
426
|
/**
|
|
@@ -415,8 +432,9 @@ declare function runAdvisor(ir: PromptIR, result: AdvisorContext, profile: Model
|
|
|
415
432
|
declare const TRANSLATOR_FLOOR = 6;
|
|
416
433
|
/**
|
|
417
434
|
* Stable identifier of the alpha.29 sequential-tool rule. Surfaces on
|
|
418
|
-
* `SectionRewrite.rule` and in brain aggregates.
|
|
419
|
-
*
|
|
435
|
+
* `SectionRewrite.rule` and in brain aggregates. The brain treats this
|
|
436
|
+
* identifier together with the preamble string as the rule's wire
|
|
437
|
+
* fingerprint — both stay byte-stable across releases.
|
|
420
438
|
*/
|
|
421
439
|
declare const RULE_SEQUENTIAL_TOOL_CLIFF = "sequential-tool-cliff-below-floor";
|
|
422
440
|
interface ApplySectionRewritesArgs {
|
|
@@ -442,16 +460,14 @@ interface ApplySectionRewritesResult {
|
|
|
442
460
|
* Pure function. Apply model-aware section rewrites to the IR at compile time.
|
|
443
461
|
*
|
|
444
462
|
* Discipline:
|
|
445
|
-
* - Never mutates the input IR; returns a new IR with new sections array
|
|
463
|
+
* - Never mutates the input IR; returns a new IR with new sections array
|
|
464
|
+
* when at least one rewrite fired; otherwise returns the input IR by
|
|
465
|
+
* reference (referential identity preserved on no-op).
|
|
446
466
|
* - Sections without a `kind` (or `kind === 'arbitrary'`) pass through
|
|
447
467
|
* unchanged.
|
|
448
468
|
* - Empty `sections` array → returns `{ rewrittenIR: ir, rewrites: [] }`.
|
|
449
|
-
* -
|
|
450
|
-
*
|
|
451
|
-
* - Sections of the same `kind` are processed in array order; the rule
|
|
452
|
-
* fires once per matching section (today every tool_call_contract
|
|
453
|
-
* section gets the same prepend — multiple sections of the same kind
|
|
454
|
-
* ARE supported but is an unusual consumer shape).
|
|
469
|
+
* - Sections of the same `kind` are processed in array order; first-match
|
|
470
|
+
* wins per section. (Today every rule is a single-match rule.)
|
|
455
471
|
*
|
|
456
472
|
* @example
|
|
457
473
|
* ```ts
|
package/dist/index.js
CHANGED
|
@@ -2630,34 +2630,62 @@ function detectArchetypePerfFloorBreach(ir, profile) {
|
|
|
2630
2630
|
// src/translator.ts
|
|
2631
2631
|
var TRANSLATOR_FLOOR = ARCHETYPE_FLOOR_DEFAULT;
|
|
2632
2632
|
var RULE_SEQUENTIAL_TOOL_CLIFF = "sequential-tool-cliff-below-floor";
|
|
2633
|
+
var RULE_NARRATION_DRIFT_ANTHROPIC = "narration-drift-anthropic";
|
|
2634
|
+
var RULE_NARRATION_THINKING_LEAK_DEEPSEEK = "narration-thinking-leak-deepseek";
|
|
2633
2635
|
var SEQUENTIAL_TOOL_PREAMBLE = "IMPORTANT: Use one tool call per response. Wait for the tool result before deciding the next tool. Do NOT batch tool calls in parallel.";
|
|
2636
|
+
var NARRATION_DRIFT_ANTHROPIC_PREAMBLE = "Output ONLY the requested content. Do not narrate your thought process. Each line \u2264 12 words.";
|
|
2637
|
+
var NARRATION_THINKING_LEAK_DEEPSEEK_PREAMBLE = "Reasoning is internal. Output ONLY the requested content; do not emit <thinking> blocks or internal monologue as user-facing text.";
|
|
2638
|
+
function matchRule(kind, profile, archetype) {
|
|
2639
|
+
if (kind === "tool_call_contract") {
|
|
2640
|
+
if (!profile.archetypePerf) return null;
|
|
2641
|
+
const archetypeScore = profile.archetypePerf[archetype];
|
|
2642
|
+
if (typeof archetypeScore !== "number" || archetypeScore >= TRANSLATOR_FLOOR) {
|
|
2643
|
+
return null;
|
|
2644
|
+
}
|
|
2645
|
+
return {
|
|
2646
|
+
id: RULE_SEQUENTIAL_TOOL_CLIFF,
|
|
2647
|
+
preamble: SEQUENTIAL_TOOL_PREAMBLE,
|
|
2648
|
+
wireOverrides: { parallelToolCalls: false }
|
|
2649
|
+
};
|
|
2650
|
+
}
|
|
2651
|
+
if (kind === "narration_contract") {
|
|
2652
|
+
if (profile.provider === "anthropic") {
|
|
2653
|
+
return {
|
|
2654
|
+
id: RULE_NARRATION_DRIFT_ANTHROPIC,
|
|
2655
|
+
preamble: NARRATION_DRIFT_ANTHROPIC_PREAMBLE
|
|
2656
|
+
};
|
|
2657
|
+
}
|
|
2658
|
+
if (profile.provider === "deepseek") {
|
|
2659
|
+
return {
|
|
2660
|
+
id: RULE_NARRATION_THINKING_LEAK_DEEPSEEK,
|
|
2661
|
+
preamble: NARRATION_THINKING_LEAK_DEEPSEEK_PREAMBLE
|
|
2662
|
+
};
|
|
2663
|
+
}
|
|
2664
|
+
return null;
|
|
2665
|
+
}
|
|
2666
|
+
return null;
|
|
2667
|
+
}
|
|
2634
2668
|
function applySectionRewrites(args) {
|
|
2635
2669
|
const { ir, profile, archetype } = args;
|
|
2636
2670
|
if (!Array.isArray(ir.sections) || ir.sections.length === 0) {
|
|
2637
2671
|
return { rewrittenIR: ir, rewrites: [] };
|
|
2638
2672
|
}
|
|
2639
|
-
if (!profile.archetypePerf) {
|
|
2640
|
-
return { rewrittenIR: ir, rewrites: [] };
|
|
2641
|
-
}
|
|
2642
|
-
const archetypeScore = profile.archetypePerf[archetype];
|
|
2643
|
-
const cliffFires = typeof archetypeScore === "number" && archetypeScore < TRANSLATOR_FLOOR;
|
|
2644
|
-
if (!cliffFires) {
|
|
2645
|
-
return { rewrittenIR: ir, rewrites: [] };
|
|
2646
|
-
}
|
|
2647
2673
|
const rewrites = [];
|
|
2648
2674
|
const newSections = ir.sections.map((section) => {
|
|
2649
|
-
if (section.kind
|
|
2675
|
+
if (!section.kind || section.kind === "arbitrary") return section;
|
|
2676
|
+
const rule = matchRule(section.kind, profile, archetype);
|
|
2677
|
+
if (!rule) return section;
|
|
2650
2678
|
const originalText = section.text;
|
|
2651
|
-
const transformedText = `${
|
|
2679
|
+
const transformedText = `${rule.preamble}
|
|
2652
2680
|
|
|
2653
2681
|
${originalText}`;
|
|
2654
2682
|
rewrites.push({
|
|
2655
2683
|
sectionId: section.id,
|
|
2656
|
-
kind:
|
|
2657
|
-
rule:
|
|
2684
|
+
kind: section.kind,
|
|
2685
|
+
rule: rule.id,
|
|
2658
2686
|
originalText,
|
|
2659
2687
|
transformedText,
|
|
2660
|
-
wireOverrides
|
|
2688
|
+
...rule.wireOverrides ? { wireOverrides: rule.wireOverrides } : {}
|
|
2661
2689
|
});
|
|
2662
2690
|
return { ...section, text: transformedText };
|
|
2663
2691
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -1056,34 +1056,62 @@ function detectArchetypePerfFloorBreach(ir, profile) {
|
|
|
1056
1056
|
// src/translator.ts
|
|
1057
1057
|
var TRANSLATOR_FLOOR = ARCHETYPE_FLOOR_DEFAULT;
|
|
1058
1058
|
var RULE_SEQUENTIAL_TOOL_CLIFF = "sequential-tool-cliff-below-floor";
|
|
1059
|
+
var RULE_NARRATION_DRIFT_ANTHROPIC = "narration-drift-anthropic";
|
|
1060
|
+
var RULE_NARRATION_THINKING_LEAK_DEEPSEEK = "narration-thinking-leak-deepseek";
|
|
1059
1061
|
var SEQUENTIAL_TOOL_PREAMBLE = "IMPORTANT: Use one tool call per response. Wait for the tool result before deciding the next tool. Do NOT batch tool calls in parallel.";
|
|
1062
|
+
var NARRATION_DRIFT_ANTHROPIC_PREAMBLE = "Output ONLY the requested content. Do not narrate your thought process. Each line \u2264 12 words.";
|
|
1063
|
+
var NARRATION_THINKING_LEAK_DEEPSEEK_PREAMBLE = "Reasoning is internal. Output ONLY the requested content; do not emit <thinking> blocks or internal monologue as user-facing text.";
|
|
1064
|
+
function matchRule(kind, profile, archetype) {
|
|
1065
|
+
if (kind === "tool_call_contract") {
|
|
1066
|
+
if (!profile.archetypePerf) return null;
|
|
1067
|
+
const archetypeScore = profile.archetypePerf[archetype];
|
|
1068
|
+
if (typeof archetypeScore !== "number" || archetypeScore >= TRANSLATOR_FLOOR) {
|
|
1069
|
+
return null;
|
|
1070
|
+
}
|
|
1071
|
+
return {
|
|
1072
|
+
id: RULE_SEQUENTIAL_TOOL_CLIFF,
|
|
1073
|
+
preamble: SEQUENTIAL_TOOL_PREAMBLE,
|
|
1074
|
+
wireOverrides: { parallelToolCalls: false }
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1077
|
+
if (kind === "narration_contract") {
|
|
1078
|
+
if (profile.provider === "anthropic") {
|
|
1079
|
+
return {
|
|
1080
|
+
id: RULE_NARRATION_DRIFT_ANTHROPIC,
|
|
1081
|
+
preamble: NARRATION_DRIFT_ANTHROPIC_PREAMBLE
|
|
1082
|
+
};
|
|
1083
|
+
}
|
|
1084
|
+
if (profile.provider === "deepseek") {
|
|
1085
|
+
return {
|
|
1086
|
+
id: RULE_NARRATION_THINKING_LEAK_DEEPSEEK,
|
|
1087
|
+
preamble: NARRATION_THINKING_LEAK_DEEPSEEK_PREAMBLE
|
|
1088
|
+
};
|
|
1089
|
+
}
|
|
1090
|
+
return null;
|
|
1091
|
+
}
|
|
1092
|
+
return null;
|
|
1093
|
+
}
|
|
1060
1094
|
function applySectionRewrites(args) {
|
|
1061
1095
|
const { ir, profile, archetype } = args;
|
|
1062
1096
|
if (!Array.isArray(ir.sections) || ir.sections.length === 0) {
|
|
1063
1097
|
return { rewrittenIR: ir, rewrites: [] };
|
|
1064
1098
|
}
|
|
1065
|
-
if (!profile.archetypePerf) {
|
|
1066
|
-
return { rewrittenIR: ir, rewrites: [] };
|
|
1067
|
-
}
|
|
1068
|
-
const archetypeScore = profile.archetypePerf[archetype];
|
|
1069
|
-
const cliffFires = typeof archetypeScore === "number" && archetypeScore < TRANSLATOR_FLOOR;
|
|
1070
|
-
if (!cliffFires) {
|
|
1071
|
-
return { rewrittenIR: ir, rewrites: [] };
|
|
1072
|
-
}
|
|
1073
1099
|
const rewrites = [];
|
|
1074
1100
|
const newSections = ir.sections.map((section) => {
|
|
1075
|
-
if (section.kind
|
|
1101
|
+
if (!section.kind || section.kind === "arbitrary") return section;
|
|
1102
|
+
const rule = matchRule(section.kind, profile, archetype);
|
|
1103
|
+
if (!rule) return section;
|
|
1076
1104
|
const originalText = section.text;
|
|
1077
|
-
const transformedText = `${
|
|
1105
|
+
const transformedText = `${rule.preamble}
|
|
1078
1106
|
|
|
1079
1107
|
${originalText}`;
|
|
1080
1108
|
rewrites.push({
|
|
1081
1109
|
sectionId: section.id,
|
|
1082
|
-
kind:
|
|
1083
|
-
rule:
|
|
1110
|
+
kind: section.kind,
|
|
1111
|
+
rule: rule.id,
|
|
1084
1112
|
originalText,
|
|
1085
1113
|
transformedText,
|
|
1086
|
-
wireOverrides
|
|
1114
|
+
...rule.wireOverrides ? { wireOverrides: rule.wireOverrides } : {}
|
|
1087
1115
|
});
|
|
1088
1116
|
return { ...section, text: transformedText };
|
|
1089
1117
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@warmdrift/kgauto-compiler",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.32",
|
|
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",
|