modelrig 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/CHANGELOG.md +238 -0
  2. package/README.md +65 -3
  3. package/dist/adapters/anthropic.d.ts.map +1 -1
  4. package/dist/adapters/anthropic.js +36 -7
  5. package/dist/adapters/attempt-meta-map.d.ts +63 -0
  6. package/dist/adapters/attempt-meta-map.d.ts.map +1 -0
  7. package/dist/adapters/attempt-meta-map.js +154 -0
  8. package/dist/adapters/deepseek.d.ts.map +1 -1
  9. package/dist/adapters/deepseek.js +25 -2
  10. package/dist/adapters/gemini.d.ts +39 -0
  11. package/dist/adapters/gemini.d.ts.map +1 -1
  12. package/dist/adapters/gemini.js +82 -4
  13. package/dist/adapters/grok.d.ts.map +1 -1
  14. package/dist/adapters/grok.js +25 -2
  15. package/dist/adapters/openai-compat.d.ts.map +1 -1
  16. package/dist/adapters/openai-compat.js +25 -2
  17. package/dist/adapters/openai-stream.d.ts +2 -0
  18. package/dist/adapters/openai-stream.d.ts.map +1 -1
  19. package/dist/adapters/openai-stream.js +23 -3
  20. package/dist/adapters/openai.d.ts.map +1 -1
  21. package/dist/adapters/openai.js +36 -6
  22. package/dist/artifacts/artifact.d.ts +3 -2
  23. package/dist/artifacts/artifact.d.ts.map +1 -1
  24. package/dist/artifacts/artifact.js +35 -9
  25. package/dist/artifacts/classification.d.ts +27 -0
  26. package/dist/artifacts/classification.d.ts.map +1 -0
  27. package/dist/artifacts/classification.js +38 -0
  28. package/dist/artifacts/index.d.ts +3 -1
  29. package/dist/artifacts/index.d.ts.map +1 -1
  30. package/dist/artifacts/index.js +10 -1
  31. package/dist/artifacts/run-context.d.ts +33 -2
  32. package/dist/artifacts/run-context.d.ts.map +1 -1
  33. package/dist/artifacts/run-context.js +95 -1
  34. package/dist/artifacts/scrub.d.ts +26 -0
  35. package/dist/artifacts/scrub.d.ts.map +1 -1
  36. package/dist/artifacts/scrub.js +53 -0
  37. package/dist/artifacts/step.d.ts +9 -0
  38. package/dist/artifacts/step.d.ts.map +1 -1
  39. package/dist/artifacts/step.js +9 -0
  40. package/dist/bakeoff/engine.d.ts +46 -4
  41. package/dist/bakeoff/engine.d.ts.map +1 -1
  42. package/dist/bakeoff/engine.js +269 -19
  43. package/dist/bakeoff/eval-cases.d.ts +5 -0
  44. package/dist/bakeoff/eval-cases.d.ts.map +1 -1
  45. package/dist/bakeoff/eval-cases.js +3 -0
  46. package/dist/bakeoff/judge.d.ts +39 -0
  47. package/dist/bakeoff/judge.d.ts.map +1 -0
  48. package/dist/bakeoff/judge.js +102 -0
  49. package/dist/bakeoff/quality.d.ts +44 -0
  50. package/dist/bakeoff/quality.d.ts.map +1 -0
  51. package/dist/bakeoff/quality.js +126 -0
  52. package/dist/bakeoff/reference.d.ts +34 -0
  53. package/dist/bakeoff/reference.d.ts.map +1 -0
  54. package/dist/bakeoff/reference.js +68 -0
  55. package/dist/bakeoff/replay.d.ts +25 -0
  56. package/dist/bakeoff/replay.d.ts.map +1 -1
  57. package/dist/bakeoff/replay.js +65 -2
  58. package/dist/bakeoff/report.d.ts +8 -1
  59. package/dist/bakeoff/report.d.ts.map +1 -1
  60. package/dist/bakeoff/report.js +83 -12
  61. package/dist/bakeoff/samples.d.ts +35 -2
  62. package/dist/bakeoff/samples.d.ts.map +1 -1
  63. package/dist/bakeoff/samples.js +67 -6
  64. package/dist/bakeoff/stats.d.ts +17 -1
  65. package/dist/bakeoff/stats.d.ts.map +1 -1
  66. package/dist/bakeoff/stats.js +67 -0
  67. package/dist/bakeoff/types.d.ts +76 -5
  68. package/dist/bakeoff/types.d.ts.map +1 -1
  69. package/dist/bakeoff/types.js +4 -3
  70. package/dist/cli-query.d.ts +14 -0
  71. package/dist/cli-query.d.ts.map +1 -0
  72. package/dist/cli-query.js +59 -0
  73. package/dist/cli.d.ts +2 -1
  74. package/dist/cli.d.ts.map +1 -1
  75. package/dist/cli.js +47 -24
  76. package/dist/config.d.ts +6 -0
  77. package/dist/config.d.ts.map +1 -1
  78. package/dist/config.js +14 -0
  79. package/dist/detect/detector.d.ts +82 -0
  80. package/dist/detect/detector.d.ts.map +1 -0
  81. package/dist/detect/detector.js +23 -0
  82. package/dist/index.d.ts +34 -23
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +49 -12
  85. package/dist/query/analytics.d.ts +84 -0
  86. package/dist/query/analytics.d.ts.map +1 -0
  87. package/dist/query/analytics.js +280 -0
  88. package/dist/query/columns.d.ts +59 -0
  89. package/dist/query/columns.d.ts.map +1 -0
  90. package/dist/query/columns.js +89 -0
  91. package/dist/query/grammar.d.ts +74 -7
  92. package/dist/query/grammar.d.ts.map +1 -1
  93. package/dist/query/grammar.js +179 -71
  94. package/dist/query/saved.d.ts +26 -0
  95. package/dist/query/saved.d.ts.map +1 -0
  96. package/dist/query/saved.js +51 -0
  97. package/dist/registry/select.d.ts +59 -0
  98. package/dist/registry/select.d.ts.map +1 -1
  99. package/dist/registry/select.js +66 -0
  100. package/dist/routes/loader-warnings.d.ts +28 -0
  101. package/dist/routes/loader-warnings.d.ts.map +1 -0
  102. package/dist/routes/loader-warnings.js +56 -0
  103. package/dist/routes/loader.d.ts +1 -11
  104. package/dist/routes/loader.d.ts.map +1 -1
  105. package/dist/routes/loader.js +54 -31
  106. package/dist/routes/objective-loader.d.ts +35 -0
  107. package/dist/routes/objective-loader.d.ts.map +1 -0
  108. package/dist/routes/objective-loader.js +286 -0
  109. package/dist/run/accept.d.ts +43 -0
  110. package/dist/run/accept.d.ts.map +1 -0
  111. package/dist/run/accept.js +65 -0
  112. package/dist/run/cost.d.ts +13 -0
  113. package/dist/run/cost.d.ts.map +1 -1
  114. package/dist/run/cost.js +27 -0
  115. package/dist/run/dispatch.d.ts +24 -1
  116. package/dist/run/dispatch.d.ts.map +1 -1
  117. package/dist/run/dispatch.js +19 -0
  118. package/dist/run/ladder-key.d.ts +4 -0
  119. package/dist/run/ladder-key.d.ts.map +1 -1
  120. package/dist/run/ladder-key.js +3 -0
  121. package/dist/run/quality-gate.d.ts +39 -0
  122. package/dist/run/quality-gate.d.ts.map +1 -0
  123. package/dist/run/quality-gate.js +70 -0
  124. package/dist/run/raw-defaults.d.ts +52 -0
  125. package/dist/run/raw-defaults.d.ts.map +1 -0
  126. package/dist/run/raw-defaults.js +123 -0
  127. package/dist/run/raw.d.ts +12 -0
  128. package/dist/run/raw.d.ts.map +1 -1
  129. package/dist/run/raw.js +107 -8
  130. package/dist/run/record-attempt.d.ts.map +1 -1
  131. package/dist/run/record-attempt.js +22 -1
  132. package/dist/run/resolve.d.ts +17 -1
  133. package/dist/run/resolve.d.ts.map +1 -1
  134. package/dist/run/resolve.js +20 -4
  135. package/dist/run/routing-docs.d.ts.map +1 -1
  136. package/dist/run/routing-docs.js +12 -5
  137. package/dist/run/run.d.ts +7 -1
  138. package/dist/run/run.d.ts.map +1 -1
  139. package/dist/run/run.js +54 -69
  140. package/dist/run/variant.d.ts +43 -0
  141. package/dist/run/variant.d.ts.map +1 -0
  142. package/dist/run/variant.js +86 -0
  143. package/dist/savings/emit.d.ts +33 -0
  144. package/dist/savings/emit.d.ts.map +1 -1
  145. package/dist/savings/emit.js +75 -3
  146. package/dist/settings/index.d.ts +1 -1
  147. package/dist/settings/index.d.ts.map +1 -1
  148. package/dist/settings/index.js +2 -1
  149. package/dist/settings/task-settings.d.ts +10 -0
  150. package/dist/settings/task-settings.d.ts.map +1 -1
  151. package/dist/settings/task-settings.js +17 -0
  152. package/dist/telemetry/attempt-meta.d.ts +178 -0
  153. package/dist/telemetry/attempt-meta.d.ts.map +1 -0
  154. package/dist/telemetry/attempt-meta.js +319 -0
  155. package/dist/telemetry/exporter.d.ts.map +1 -1
  156. package/dist/telemetry/exporter.js +6 -0
  157. package/dist/telemetry/ingest-protocol.d.ts +11 -0
  158. package/dist/telemetry/ingest-protocol.d.ts.map +1 -1
  159. package/dist/telemetry/ingest-protocol.js +3 -0
  160. package/dist/telemetry/otel-map.d.ts +10 -0
  161. package/dist/telemetry/otel-map.d.ts.map +1 -1
  162. package/dist/telemetry/otel-map.js +64 -0
  163. package/dist/telemetry/store-migrations.d.ts.map +1 -1
  164. package/dist/telemetry/store-migrations.js +15 -0
  165. package/dist/telemetry/store.d.ts.map +1 -1
  166. package/dist/telemetry/store.js +25 -7
  167. package/dist/types/failures-teaching.d.ts.map +1 -1
  168. package/dist/types/failures-teaching.js +20 -0
  169. package/dist/types/failures.d.ts +1 -1
  170. package/dist/types/failures.d.ts.map +1 -1
  171. package/dist/types/failures.js +1 -0
  172. package/dist/types/provider.d.ts +9 -0
  173. package/dist/types/provider.d.ts.map +1 -1
  174. package/dist/types/quality.d.ts +41 -0
  175. package/dist/types/quality.d.ts.map +1 -0
  176. package/dist/types/quality.js +12 -0
  177. package/dist/types/route.d.ts +120 -0
  178. package/dist/types/route.d.ts.map +1 -1
  179. package/dist/types/telemetry.d.ts +13 -0
  180. package/dist/types/telemetry.d.ts.map +1 -1
  181. package/dist/validate-cli.d.ts.map +1 -1
  182. package/dist/validate-cli.js +10 -0
  183. package/dist/watch/evaluate.d.ts +27 -1
  184. package/dist/watch/evaluate.d.ts.map +1 -1
  185. package/dist/watch/evaluate.js +13 -0
  186. package/dist/watch/proposals.d.ts +28 -0
  187. package/dist/watch/proposals.d.ts.map +1 -1
  188. package/dist/watch/proposals.js +51 -0
  189. package/package.json +1 -1
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ /**
3
+ * Non-fatal loader advisories — extracted from loader.ts (kept it under the
4
+ * 700-LOC cap). Each is a pure function returning a warning line or null; the
5
+ * loader console.warns them after a bundle loads. Unit-tested directly.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.arrayRootSchemaWarning = arrayRootSchemaWarning;
9
+ exports.unreferencedTrialCandidatesWarning = unreferencedTrialCandidatesWarning;
10
+ /**
11
+ * CE-2 A5 co-item: warn (non-fatal) when a route's output schema has an ARRAY
12
+ * root. OpenAI strict structured output (`response_format: json_schema`, strict)
13
+ * requires a top-level OBJECT — an array-root schema cannot use strict
14
+ * enforcement on OpenAI candidates and silently falls back to non-strict there
15
+ * (the walkthrough §10 provider-matrix gap). The route still LOADS and serves as
16
+ * declared; the fix is to wrap the array in an object property so strict
17
+ * enforcement holds across every provider. Returns the warning line, or null.
18
+ */
19
+ function arrayRootSchemaWarning(route, outputSchema) {
20
+ if (outputSchema === null)
21
+ return null;
22
+ const rootType = outputSchema.type;
23
+ if (rootType !== "array")
24
+ return null;
25
+ return (`route "${route}" declares an output schema whose ROOT is type: "array". OpenAI strict ` +
26
+ `structured output requires a top-level object, so strict enforcement cannot apply on OpenAI ` +
27
+ `candidates (they fall back to non-strict there). Wrap the array in an object property ` +
28
+ `(e.g. { "type": "object", "properties": { "items": <your array> } }) to keep strict ` +
29
+ `enforcement across providers. The route loads and serves as declared.`);
30
+ }
31
+ /**
32
+ * Declare-first dead-declaration warning (routing-console spec §4.4): a `trial`
33
+ * candidate that no variant references can never be reached — not live (trial
34
+ * candidates are dropped on every live path) and not in a bake-off (a bake-off
35
+ * replays a NAMED variant, and no variant narrows to it). Warn so the author
36
+ * either adds the `trial-<provider>-<model>` variant the declare flow emits or
37
+ * removes the dangling candidate. Non-fatal (the route still loads and serves
38
+ * its live candidates as declared). Pure — unit-tested directly. Returns the
39
+ * warning line, or null when every trial candidate is referenced.
40
+ */
41
+ function unreferencedTrialCandidatesWarning(route, candidates, variants) {
42
+ const referenced = new Set();
43
+ for (const v of variants) {
44
+ for (const c of v.candidates ?? [])
45
+ referenced.add(`${c.provider}/${c.model}`);
46
+ }
47
+ const dangling = candidates
48
+ .filter((c) => c.trial === true && !referenced.has(`${c.provider}/${c.model}`))
49
+ .map((c) => `${c.provider}/${c.model}`);
50
+ if (dangling.length === 0)
51
+ return null;
52
+ return (`route "${route}" declares trial candidate(s) [${dangling.join(", ")}] that no variant references. ` +
53
+ `A trial candidate is declared but never served live; it is only reachable through a bake-off of a ` +
54
+ `variant that narrows to it. Add a variant (e.g. { name: "trial-${dangling[0].replace("/", "-")}", ` +
55
+ `candidates: [<that candidate>] }) to bake it off, or remove the dangling declaration.`);
56
+ }
@@ -4,17 +4,7 @@
4
4
  * resolves schema/prompt paths relative to the bundle file, freezes.
5
5
  */
6
6
  import type { RouteBundle } from "../types/route";
7
- /**
8
- * CE-2 A5 co-item: warn (non-fatal) when a route's output schema has an ARRAY
9
- * root. OpenAI strict structured output (`response_format: json_schema`, strict)
10
- * requires a top-level OBJECT — an array-root schema cannot use strict
11
- * enforcement on OpenAI candidates and silently falls back to non-strict there
12
- * (the walkthrough §10 provider-matrix gap). The route still LOADS and serves as
13
- * declared; the fix is to wrap the array in an object property so strict
14
- * enforcement holds across every provider. Returns the warning line, or null.
15
- * Pure — unit-tested directly.
16
- */
17
- export declare function arrayRootSchemaWarning(route: string, outputSchema: object | null): string | null;
7
+ export { arrayRootSchemaWarning, unreferencedTrialCandidatesWarning } from "./loader-warnings";
18
8
  /**
19
9
  * Structured config error thrown for any invalid bundle (never a raw Error).
20
10
  * Load-time problems are deliberately NOT RigFailures — the failure taxonomy
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/routes/loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,KAAK,EAKV,WAAW,EAGZ,MAAM,gBAAgB,CAAC;AAMxB;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAWhG;AAED;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;gBAEzB,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAO;CAOxF;AAiCD,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC;IAChC,IAAI,IAAI,SAAS,WAAW,EAAE,CAAC;CAChC;AA4ZD;;;;;;;GAOG;AACH;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,CAItF;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,YAAY,CAyB1F;AAED;;yBAEyB;AACzB,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CA6CtE;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,CA2C1D"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/routes/loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,KAAK,EAKV,WAAW,EAGZ,MAAM,gBAAgB,CAAC;AAUxB,OAAO,EAAE,sBAAsB,EAAE,kCAAkC,EAAE,MAAM,mBAAmB,CAAC;AAE/F;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;gBAEzB,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAO;CAOxF;AAiCD,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC;IAChC,IAAI,IAAI,SAAS,WAAW,EAAE,CAAC;CAChC;AAucD;;;;;;;GAOG;AACH;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,CAItF;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,YAAY,CAyB1F;AAED;;yBAEyB;AACzB,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CA6CtE;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,CA2C1D"}
@@ -5,8 +5,7 @@
5
5
  * resolves schema/prompt paths relative to the bundle file, freezes.
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.RouteConfigError = void 0;
9
- exports.arrayRootSchemaWarning = arrayRootSchemaWarning;
8
+ exports.RouteConfigError = exports.unreferencedTrialCandidatesWarning = exports.arrayRootSchemaWarning = void 0;
10
9
  exports.loadRoutesWithExtra = loadRoutesWithExtra;
11
10
  exports.mergeLoadedRoutes = mergeLoadedRoutes;
12
11
  exports.validateRoutesDir = validateRoutesDir;
@@ -19,28 +18,13 @@ const fingerprint_1 = require("../registry/fingerprint");
19
18
  const template_1 = require("./template");
20
19
  const cache_lint_1 = require("./cache-lint");
21
20
  const sampling_config_1 = require("./sampling-config");
22
- /**
23
- * CE-2 A5 co-item: warn (non-fatal) when a route's output schema has an ARRAY
24
- * root. OpenAI strict structured output (`response_format: json_schema`, strict)
25
- * requires a top-level OBJECT — an array-root schema cannot use strict
26
- * enforcement on OpenAI candidates and silently falls back to non-strict there
27
- * (the walkthrough §10 provider-matrix gap). The route still LOADS and serves as
28
- * declared; the fix is to wrap the array in an object property so strict
29
- * enforcement holds across every provider. Returns the warning line, or null.
30
- * Pure — unit-tested directly.
31
- */
32
- function arrayRootSchemaWarning(route, outputSchema) {
33
- if (outputSchema === null)
34
- return null;
35
- const rootType = outputSchema.type;
36
- if (rootType !== "array")
37
- return null;
38
- return (`route "${route}" declares an output schema whose ROOT is type: "array". OpenAI strict ` +
39
- `structured output requires a top-level object, so strict enforcement cannot apply on OpenAI ` +
40
- `candidates (they fall back to non-strict there). Wrap the array in an object property ` +
41
- `(e.g. { "type": "object", "properties": { "items": <your array> } }) to keep strict ` +
42
- `enforcement across providers. The route loads and serves as declared.`);
43
- }
21
+ const loader_warnings_1 = require("./loader-warnings");
22
+ const objective_loader_1 = require("./objective-loader");
23
+ // Re-exported so existing importers of "./loader" keep resolving these advisories
24
+ // (they live in ./loader-warnings to hold loader.ts under the 700-LOC cap).
25
+ var loader_warnings_2 = require("./loader-warnings");
26
+ Object.defineProperty(exports, "arrayRootSchemaWarning", { enumerable: true, get: function () { return loader_warnings_2.arrayRootSchemaWarning; } });
27
+ Object.defineProperty(exports, "unreferencedTrialCandidatesWarning", { enumerable: true, get: function () { return loader_warnings_2.unreferencedTrialCandidatesWarning; } });
44
28
  /**
45
29
  * Structured config error thrown for any invalid bundle (never a raw Error).
46
30
  * Load-time problems are deliberately NOT RigFailures — the failure taxonomy
@@ -81,7 +65,7 @@ const RETRYABLE_CLASSES = new Set([
81
65
  "network",
82
66
  "refusal",
83
67
  "cache_invalid",
84
- "timeout",
68
+ "timeout", "quality_rejected",
85
69
  ].filter((c) => !failures_1.TERMINAL_CLASSES.has(c)));
86
70
  function isRecord(v) {
87
71
  return typeof v === "object" && v !== null && !Array.isArray(v);
@@ -101,7 +85,18 @@ function parseCandidates(raw, problems) {
101
85
  problems.push(`candidates[${i}].provider "${c.provider}" is not a known provider`);
102
86
  continue;
103
87
  }
104
- out.push(Object.freeze({ provider: c.provider, model: c.model }));
88
+ // Declare-first `trial` flag (routing-console spec §4.4): declared, never
89
+ // live-served. Optional; only `true` is carried so an absent/false flag
90
+ // leaves the candidate byte-identical to a pre-R3 candidate.
91
+ if (c.trial !== undefined && typeof c.trial !== "boolean") {
92
+ problems.push(`candidates[${i}].trial must be a boolean`);
93
+ continue;
94
+ }
95
+ out.push(Object.freeze({
96
+ provider: c.provider,
97
+ model: c.model,
98
+ ...(c.trial === true ? { trial: true } : {}),
99
+ }));
105
100
  }
106
101
  return out;
107
102
  }
@@ -223,6 +218,13 @@ function parseRepair(raw, field, candidates, problems) {
223
218
  problems.push(`${field}.repair_model (${repairModel.provider}/${repairModel.model}) is not in the route's declared candidates`);
224
219
  repairModel = null;
225
220
  }
221
+ // Declare-first (spec §4.4): the repair model dispatches LIVE, so a `trial`
222
+ // candidate (declared, never live-served) must not be one — reject at load.
223
+ const rm = repairModel;
224
+ if (rm !== null && candidates.some((c) => c.provider === rm.provider && c.model === rm.model && c.trial === true)) {
225
+ problems.push(`${field}.repair_model (${rm.provider}/${rm.model}) is a trial candidate and cannot be a live repair model`);
226
+ repairModel = null;
227
+ }
226
228
  }
227
229
  if (maxRepairs === 2 && repairModel === null) {
228
230
  problems.push(`${field}.max_repairs=2 requires repair_model (attempt 2 is the designated repair model)`);
@@ -256,6 +258,10 @@ function parseVariants(raw, routeCandidates, problems) {
256
258
  problems.push(`${field}.name "default" is reserved (the route's base config)`);
257
259
  continue;
258
260
  }
261
+ if (v.name.startsWith("__")) {
262
+ problems.push(`${field}.name "${v.name}" is reserved ("__" names are synthetic bake-off arms, e.g. "__reference__")`);
263
+ continue;
264
+ }
259
265
  if (seen.has(v.name)) {
260
266
  problems.push(`duplicate variant name "${v.name}"`);
261
267
  continue;
@@ -271,6 +277,14 @@ function parseVariants(raw, routeCandidates, problems) {
271
277
  }
272
278
  }
273
279
  }
280
+ // trialOnly (routing-console spec §4.4): a variant whose candidates ALL map
281
+ // to declared `trial` candidates is a trial variant — valid for a bake-off,
282
+ // a live config error. Computed from the route-level trial flags (a variant
283
+ // narrows a subset; the flag lives on the declared candidate), so an empty
284
+ // or inherited candidate list is never trial-only.
285
+ const trialOnly = candidates !== undefined &&
286
+ candidates.length > 0 &&
287
+ candidates.every((vc) => routeCandidates.some((rc) => rc.provider === vc.provider && rc.model === vc.model && rc.trial === true));
274
288
  if (v.prompt_override !== undefined && v.prompt_append !== undefined) {
275
289
  problems.push(`${field} sets both prompt_override and prompt_append — they are mutually exclusive`);
276
290
  }
@@ -293,6 +307,7 @@ function parseVariants(raw, routeCandidates, problems) {
293
307
  ? { json: v.json }
294
308
  : {}),
295
309
  ...(repair !== undefined ? { repair } : {}),
310
+ ...(trialOnly ? { trialOnly: true } : {}),
296
311
  }));
297
312
  }
298
313
  return out;
@@ -382,6 +397,9 @@ function loadBundleFile(filePath) {
382
397
  groundingQuery = doc.grounding.query;
383
398
  }
384
399
  }
400
+ // RB-1 (near-optimal spec §3): objective knob, reference arm + judge, value
401
+ // checks — all additive; candidate-set invariant enforced in parseRb1Fields.
402
+ const rb1 = (0, objective_loader_1.parseRb1Fields)(doc, route, candidates, problems);
385
403
  let systemTemplate = "";
386
404
  let variables = [];
387
405
  if (!isRecord(doc.prompt) || typeof doc.prompt.system !== "string") {
@@ -435,15 +453,19 @@ function loadBundleFile(filePath) {
435
453
  // and is sent as declared, but Google recommends 1.0 for the family — warn so
436
454
  // the choice is deliberate, never silent (spec §3/§6).
437
455
  const geminiTempWarning = (0, sampling_config_1.gemini3LowTemperatureWarning)(route, policy, candidates);
438
- if (geminiTempWarning !== null) {
456
+ if (geminiTempWarning !== null)
439
457
  console.warn(`modelrig: ${geminiTempWarning}`);
440
- }
441
458
  // CE-2 A5 co-item: an array-root schema cannot use OpenAI strict enforcement —
442
459
  // warn once at load so the incompatibility is deliberate, never silent.
443
- const arrayRootWarning = arrayRootSchemaWarning(route, outputSchema);
444
- if (arrayRootWarning !== null) {
460
+ const arrayRootWarning = (0, loader_warnings_1.arrayRootSchemaWarning)(route, outputSchema);
461
+ if (arrayRootWarning !== null)
445
462
  console.warn(`modelrig: ${arrayRootWarning}`);
446
- }
463
+ // Declare-first dead-declaration warning (spec §4.4): a trial candidate no
464
+ // variant references is unreachable — warn so the dangling declaration is
465
+ // deliberate, never silent.
466
+ const trialWarning = (0, loader_warnings_1.unreferencedTrialCandidatesWarning)(route, candidates, variants);
467
+ if (trialWarning !== null)
468
+ console.warn(`modelrig: ${trialWarning}`);
447
469
  return Object.freeze({
448
470
  route: route,
449
471
  version: version,
@@ -462,6 +484,7 @@ function loadBundleFile(filePath) {
462
484
  // Network-effect instrumentation (spec WS6): computed once at load,
463
485
  // stamped on every telemetry row for this route.
464
486
  fingerprintCell: (0, fingerprint_1.fingerprintSchema)(outputSchema)?.cellKey ?? null,
487
+ ...rb1, // RB-1 regret-bounded objective (objective/bakeoff/valueChecks, additive)
465
488
  });
466
489
  }
467
490
  /**
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Route-bundle parsing for the RB-1 regret-bounded objective (near-optimal spec
3
+ * §3). Extracted from loader.ts (kept it under the 700-LOC cap). Each parser
4
+ * pushes teaching problems into the shared `problems` array — a non-empty array
5
+ * fails the bundle load, exactly like every other loader field. Pure functions,
6
+ * unit-tested directly.
7
+ */
8
+ import type { BakeoffConfig, CandidateSpec, RouteObjective, ValueCheck } from "../types/route";
9
+ /** All three RB-1 route fields parsed in one call (keeps loader.ts under the
10
+ * 700-LOC cap): objective, bakeoff (reference arm + judge), value_checks. Pushes
11
+ * any problems into the shared array; emits the missing-bound advisory. */
12
+ export declare function parseRb1Fields(doc: Record<string, unknown>, route: string, candidates: readonly CandidateSpec[], problems: string[]): {
13
+ objective?: RouteObjective;
14
+ bakeoff?: BakeoffConfig;
15
+ valueChecks?: readonly ValueCheck[];
16
+ };
17
+ /** Parse the `objective:` block. Absent ⇒ undefined (the engine defaults to
18
+ * quality-first with no bound: regret shown, nothing proposed). */
19
+ export declare function parseObjective(raw: unknown, problems: string[]): RouteObjective | undefined;
20
+ /** Parse the `bakeoff:` block (reference arm + judge). `candidates` is the
21
+ * route's declared set — the candidate-set invariant is enforced here (#223 F3
22
+ * for the judge; the reference must be declared unless allow-external). */
23
+ export declare function parseBakeoffConfig(raw: unknown, candidates: readonly CandidateSpec[], problems: string[]): BakeoffConfig | undefined;
24
+ /** Parse `value_checks:` — a list of {path, expect}. `path` is a JSON pointer;
25
+ * `expect` is a literal or {regex}. */
26
+ export declare function parseValueChecks(raw: unknown, problems: string[]): readonly ValueCheck[] | undefined;
27
+ /**
28
+ * Non-fatal advisory (CE-2 teaching-hint style): a route declares an objective
29
+ * with NEITHER a regret bound NOR a price ceiling, so a bake-off will REPORT
30
+ * regret but never propose anything. Warn so the missing bound is deliberate.
31
+ * Returns the warning line, or null. Only meaningful for quality-first/balanced
32
+ * (cost-first has its own gate and needs no bound).
33
+ */
34
+ export declare function missingBoundWarning(route: string, objective: RouteObjective | undefined): string | null;
35
+ //# sourceMappingURL=objective-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"objective-loader.d.ts","sourceRoot":"","sources":["../../src/routes/objective-loader.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EAGb,cAAc,EACd,UAAU,EACX,MAAM,gBAAgB,CAAC;AAExB;;2EAE2E;AAC3E,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,SAAS,aAAa,EAAE,EACpC,QAAQ,EAAE,MAAM,EAAE,GACjB;IAAE,SAAS,CAAC,EAAE,cAAc,CAAC;IAAC,OAAO,CAAC,EAAE,aAAa,CAAC;IAAC,WAAW,CAAC,EAAE,SAAS,UAAU,EAAE,CAAA;CAAE,CAe9F;AAoCD;mEACmE;AACnE,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,cAAc,GAAG,SAAS,CAwC3F;AAqCD;;2EAE2E;AAC3E,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,EACZ,UAAU,EAAE,SAAS,aAAa,EAAE,EACpC,QAAQ,EAAE,MAAM,EAAE,GACjB,aAAa,GAAG,SAAS,CA+E3B;AAED;uCACuC;AACvC,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAS,UAAU,EAAE,GAAG,SAAS,CAqCpG;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAUvG"}
@@ -0,0 +1,286 @@
1
+ "use strict";
2
+ /**
3
+ * Route-bundle parsing for the RB-1 regret-bounded objective (near-optimal spec
4
+ * §3). Extracted from loader.ts (kept it under the 700-LOC cap). Each parser
5
+ * pushes teaching problems into the shared `problems` array — a non-empty array
6
+ * fails the bundle load, exactly like every other loader field. Pure functions,
7
+ * unit-tested directly.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.parseRb1Fields = parseRb1Fields;
11
+ exports.parseObjective = parseObjective;
12
+ exports.parseBakeoffConfig = parseBakeoffConfig;
13
+ exports.parseValueChecks = parseValueChecks;
14
+ exports.missingBoundWarning = missingBoundWarning;
15
+ /** All three RB-1 route fields parsed in one call (keeps loader.ts under the
16
+ * 700-LOC cap): objective, bakeoff (reference arm + judge), value_checks. Pushes
17
+ * any problems into the shared array; emits the missing-bound advisory. */
18
+ function parseRb1Fields(doc, route, candidates, problems) {
19
+ const objective = parseObjective(doc.objective, problems);
20
+ const bakeoff = parseBakeoffConfig(doc.bakeoff, candidates, problems);
21
+ const valueChecks = parseValueChecks(doc.value_checks, problems);
22
+ // Only nag routes that OPT INTO RB-1 (declare objective/bakeoff) but omit a
23
+ // bound — a legacy route with neither block is not using regret bake-offs.
24
+ if (objective !== undefined || bakeoff !== undefined) {
25
+ const warning = missingBoundWarning(route, objective);
26
+ if (warning !== null)
27
+ console.warn(`modelrig: ${warning}`);
28
+ }
29
+ return {
30
+ ...(objective !== undefined ? { objective } : {}),
31
+ ...(bakeoff !== undefined ? { bakeoff } : {}),
32
+ ...(valueChecks !== undefined ? { valueChecks } : {}),
33
+ };
34
+ }
35
+ const OBJECTIVE_MODES = new Set([
36
+ "quality-first",
37
+ "balanced",
38
+ "cost-first",
39
+ ]);
40
+ function isRecord(v) {
41
+ return typeof v === "object" && v !== null && !Array.isArray(v);
42
+ }
43
+ function parsePriceCeiling(raw, field, problems) {
44
+ if (raw === undefined || raw === null)
45
+ return undefined;
46
+ if (!isRecord(raw)) {
47
+ problems.push(`${field} must be an object { usd_per_1k } or { usd_per_run }`);
48
+ return undefined;
49
+ }
50
+ const per1k = raw.usd_per_1k;
51
+ const perRun = raw.usd_per_run;
52
+ if (per1k !== undefined && perRun !== undefined) {
53
+ problems.push(`${field} sets both usd_per_1k and usd_per_run — pick one unit`);
54
+ return undefined;
55
+ }
56
+ if (per1k === undefined && perRun === undefined) {
57
+ problems.push(`${field} must set usd_per_1k or usd_per_run`);
58
+ return undefined;
59
+ }
60
+ const value = per1k ?? perRun;
61
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
62
+ problems.push(`${field} value must be a positive number`);
63
+ return undefined;
64
+ }
65
+ return Object.freeze(per1k !== undefined ? { usdPer1k: value } : { usdPerRun: value });
66
+ }
67
+ /** Parse the `objective:` block. Absent ⇒ undefined (the engine defaults to
68
+ * quality-first with no bound: regret shown, nothing proposed). */
69
+ function parseObjective(raw, problems) {
70
+ if (raw === undefined || raw === null)
71
+ return undefined;
72
+ if (!isRecord(raw)) {
73
+ problems.push("objective must be an object");
74
+ return undefined;
75
+ }
76
+ const mode = raw.mode ?? "quality-first";
77
+ if (typeof mode !== "string" || !OBJECTIVE_MODES.has(mode)) {
78
+ problems.push(`objective.mode "${String(mode)}" is not one of [${[...OBJECTIVE_MODES].join(", ")}]`);
79
+ return undefined;
80
+ }
81
+ let maxRegret;
82
+ if (raw.max_regret !== undefined) {
83
+ if (typeof raw.max_regret !== "number" || !(raw.max_regret >= 0 && raw.max_regret <= 1)) {
84
+ problems.push("objective.max_regret must be a number in [0, 1] (quality points)");
85
+ }
86
+ else {
87
+ maxRegret = raw.max_regret;
88
+ }
89
+ }
90
+ const priceCeiling = parsePriceCeiling(raw.price_ceiling, "objective.price_ceiling", problems);
91
+ let lambda;
92
+ if (raw.lambda !== undefined) {
93
+ if (typeof raw.lambda !== "number" || !Number.isFinite(raw.lambda) || raw.lambda < 0) {
94
+ problems.push("objective.lambda must be a non-negative number");
95
+ }
96
+ else {
97
+ lambda = raw.lambda;
98
+ }
99
+ }
100
+ if (mode !== "balanced" && lambda !== undefined) {
101
+ problems.push("objective.lambda only applies to mode: balanced");
102
+ }
103
+ if (mode === "balanced" && lambda === undefined) {
104
+ problems.push("objective.mode: balanced requires objective.lambda");
105
+ }
106
+ return Object.freeze({
107
+ mode: mode,
108
+ ...(maxRegret !== undefined ? { maxRegret } : {}),
109
+ ...(priceCeiling !== undefined ? { priceCeiling } : {}),
110
+ ...(lambda !== undefined ? { lambda } : {}),
111
+ });
112
+ }
113
+ const PROVIDERS = new Set([
114
+ "gemini",
115
+ "openai",
116
+ "deepseek",
117
+ "anthropic",
118
+ "grok",
119
+ ]);
120
+ /** "provider/model" or {provider, model} → CandidateSpec (no trial flag —
121
+ * a reference/judge is a concrete model, never a declare-first placeholder). */
122
+ function parseModelRef(raw, field, problems) {
123
+ let provider;
124
+ let model;
125
+ if (typeof raw === "string") {
126
+ const slash = raw.indexOf("/");
127
+ if (slash <= 0 || slash === raw.length - 1) {
128
+ problems.push(`${field} must be "provider/model" or {provider, model}`);
129
+ return null;
130
+ }
131
+ provider = raw.slice(0, slash);
132
+ model = raw.slice(slash + 1);
133
+ }
134
+ else if (isRecord(raw)) {
135
+ provider = raw.provider;
136
+ model = raw.model;
137
+ }
138
+ else {
139
+ problems.push(`${field} must be "provider/model" or {provider, model}`);
140
+ return null;
141
+ }
142
+ if (typeof provider !== "string" || !PROVIDERS.has(provider) || typeof model !== "string" || model === "") {
143
+ problems.push(`${field} has an unknown provider or empty model`);
144
+ return null;
145
+ }
146
+ return Object.freeze({ provider: provider, model });
147
+ }
148
+ /** Parse the `bakeoff:` block (reference arm + judge). `candidates` is the
149
+ * route's declared set — the candidate-set invariant is enforced here (#223 F3
150
+ * for the judge; the reference must be declared unless allow-external). */
151
+ function parseBakeoffConfig(raw, candidates, problems) {
152
+ if (raw === undefined || raw === null)
153
+ return undefined;
154
+ if (!isRecord(raw)) {
155
+ problems.push("bakeoff must be an object");
156
+ return undefined;
157
+ }
158
+ const declared = (c) => candidates.some((rc) => rc.provider === c.provider && rc.model === c.model);
159
+ let referenceAllowExternal = false;
160
+ if (raw.reference_allow_external !== undefined) {
161
+ if (typeof raw.reference_allow_external !== "boolean") {
162
+ problems.push("bakeoff.reference_allow_external must be a boolean");
163
+ }
164
+ else {
165
+ referenceAllowExternal = raw.reference_allow_external;
166
+ }
167
+ }
168
+ let reference;
169
+ if (raw.reference !== undefined && raw.reference !== null) {
170
+ if (raw.reference === "auto") {
171
+ reference = "auto";
172
+ }
173
+ else {
174
+ const ref = parseModelRef(raw.reference, "bakeoff.reference", problems);
175
+ if (ref !== null) {
176
+ if (!declared(ref) && !referenceAllowExternal) {
177
+ problems.push(`bakeoff.reference (${ref.provider}/${ref.model}) is not a declared candidate — ` +
178
+ "add it to candidates, or set bakeoff.reference_allow_external: true to record the exception");
179
+ }
180
+ else {
181
+ reference = { provider: ref.provider, model: ref.model };
182
+ }
183
+ }
184
+ }
185
+ }
186
+ let referenceEnvelopeUsd;
187
+ if (raw.reference_envelope_usd !== undefined) {
188
+ if (typeof raw.reference_envelope_usd !== "number" ||
189
+ !Number.isFinite(raw.reference_envelope_usd) ||
190
+ raw.reference_envelope_usd <= 0) {
191
+ problems.push("bakeoff.reference_envelope_usd must be a positive number");
192
+ }
193
+ else {
194
+ referenceEnvelopeUsd = raw.reference_envelope_usd;
195
+ }
196
+ }
197
+ let judge;
198
+ if (raw.judge !== undefined && raw.judge !== null) {
199
+ if (!isRecord(raw.judge)) {
200
+ problems.push("bakeoff.judge must be an object { model, max_samples }");
201
+ }
202
+ else {
203
+ const model = parseModelRef(raw.judge.model, "bakeoff.judge.model", problems);
204
+ const maxSamples = raw.judge.max_samples;
205
+ if (typeof maxSamples !== "number" || !Number.isInteger(maxSamples) || maxSamples < 1) {
206
+ problems.push("bakeoff.judge.max_samples must be a positive integer");
207
+ }
208
+ if (model !== null && !declared(model)) {
209
+ // #223 F3: the judge model must be a declared candidate.
210
+ problems.push(`bakeoff.judge.model (${model.provider}/${model.model}) is not a declared candidate ` +
211
+ "(a judge model must be one of the route's declared candidates, #223 F3)");
212
+ }
213
+ else if (model !== null && typeof maxSamples === "number" && Number.isInteger(maxSamples) && maxSamples >= 1) {
214
+ judge = { model, maxSamples };
215
+ }
216
+ }
217
+ }
218
+ const out = {
219
+ ...(reference !== undefined ? { reference } : {}),
220
+ ...(referenceAllowExternal ? { referenceAllowExternal: true } : {}),
221
+ ...(referenceEnvelopeUsd !== undefined ? { referenceEnvelopeUsd } : {}),
222
+ ...(judge !== undefined ? { judge } : {}),
223
+ };
224
+ return Object.freeze(out);
225
+ }
226
+ /** Parse `value_checks:` — a list of {path, expect}. `path` is a JSON pointer;
227
+ * `expect` is a literal or {regex}. */
228
+ function parseValueChecks(raw, problems) {
229
+ if (raw === undefined || raw === null)
230
+ return undefined;
231
+ if (!Array.isArray(raw)) {
232
+ problems.push("value_checks must be a list");
233
+ return undefined;
234
+ }
235
+ const out = [];
236
+ for (const [i, c] of raw.entries()) {
237
+ const field = `value_checks[${i}]`;
238
+ if (!isRecord(c)) {
239
+ problems.push(`${field} must be an object { path, expect }`);
240
+ continue;
241
+ }
242
+ if (typeof c.path !== "string" || c.path === "" || !c.path.startsWith("/")) {
243
+ problems.push(`${field}.path must be a non-empty JSON pointer starting with "/"`);
244
+ continue;
245
+ }
246
+ if (c.expect === undefined) {
247
+ problems.push(`${field}.expect is required (a literal value or { regex })`);
248
+ continue;
249
+ }
250
+ let expect;
251
+ if (isRecord(c.expect) && typeof c.expect.regex === "string") {
252
+ try {
253
+ // eslint-disable-next-line no-new
254
+ new RegExp(c.expect.regex);
255
+ }
256
+ catch (err) {
257
+ problems.push(`${field}.expect.regex is not a valid regular expression: ${err.message}`);
258
+ continue;
259
+ }
260
+ expect = { regex: c.expect.regex };
261
+ }
262
+ else {
263
+ expect = { literal: c.expect };
264
+ }
265
+ out.push(Object.freeze({ path: c.path, expect: Object.freeze(expect) }));
266
+ }
267
+ return Object.freeze(out);
268
+ }
269
+ /**
270
+ * Non-fatal advisory (CE-2 teaching-hint style): a route declares an objective
271
+ * with NEITHER a regret bound NOR a price ceiling, so a bake-off will REPORT
272
+ * regret but never propose anything. Warn so the missing bound is deliberate.
273
+ * Returns the warning line, or null. Only meaningful for quality-first/balanced
274
+ * (cost-first has its own gate and needs no bound).
275
+ */
276
+ function missingBoundWarning(route, objective) {
277
+ const mode = objective?.mode ?? "quality-first";
278
+ if (mode === "cost-first")
279
+ return null;
280
+ const hasBound = objective?.maxRegret !== undefined || objective?.priceCeiling !== undefined;
281
+ if (hasBound)
282
+ return null;
283
+ return (`route "${route}" has no objective bound (neither max_regret nor price_ceiling): a bake-off ` +
284
+ "will REPORT regret vs the reference but propose nothing. Declare objective.max_regret and/or " +
285
+ "objective.price_ceiling to let a challenger be proposed under your ceiling.");
286
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Accept-path builders, extracted from run.ts (which sits at the 700-LOC cap so
3
+ * the Q1 quality-gate seam has to pull its shared shapes out). Two pure builders:
4
+ *
5
+ * - `successAttemptRow` — the AttemptTelemetry token/cost fields for a
6
+ * SUCCESSFUL adapter result, shared by the accept path and the Q1
7
+ * quality-REJECT path (which records the same billed row with a
8
+ * `quality_rejected` failure instead of `null`).
9
+ * - `buildSuccessMeta` — the validated `RunMeta` returned on the accept path.
10
+ *
11
+ * Behavior is byte-identical to the former inline literals; nothing new is
12
+ * computed here.
13
+ */
14
+ import type { CandidateRef } from "../types/provider";
15
+ import type { AdapterUsage } from "../types/provider";
16
+ import type { FailureClass, RigFailure } from "../types/failures";
17
+ import type { RouteBundle, RunMeta } from "../types/route";
18
+ import type { AttemptTelemetry } from "./dispatch";
19
+ import type { AttemptMetaSource } from "../telemetry/attempt-meta";
20
+ /** The AttemptTelemetry for a successful adapter result. `failure` is null on the
21
+ * accept path and the `quality_rejected` failure on the Q1 reject path;
22
+ * `metaInputs` is the WI-1 attempt-meta envelope; `extraTags` carries the Q1
23
+ * quality tags (`quality` / `quality_score`). */
24
+ export declare function successAttemptRow(candidate: CandidateRef, usage: AdapterUsage, costUsd: number, latencyMs: number, pricingMissing: boolean, failure: RigFailure | null, metaInputs: AttemptMetaSource, extraTags?: Record<string, string>): AttemptTelemetry;
25
+ export interface SuccessMetaInput {
26
+ readonly inferenceId: string;
27
+ readonly route: RouteBundle;
28
+ readonly candidate: CandidateRef;
29
+ readonly usage: AdapterUsage;
30
+ readonly costUsd: number;
31
+ readonly latencyMs: number;
32
+ readonly attemptsByClass: Partial<Record<FailureClass, number>>;
33
+ readonly servedVariant: string | null;
34
+ readonly callId: string;
35
+ /** Grounding-inject citations, when the search rung served this run. */
36
+ readonly citations?: RunMeta["citations"];
37
+ /** Q1 quality verdict, when a gate ran on this run. */
38
+ readonly quality?: RunMeta["quality"];
39
+ }
40
+ /** The validated `RunMeta` for the accept path — `repairedBy` is null here (the
41
+ * repair path builds its own meta), `validated` is always true. */
42
+ export declare function buildSuccessMeta(input: SuccessMetaInput): RunMeta;
43
+ //# sourceMappingURL=accept.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accept.d.ts","sourceRoot":"","sources":["../../src/run/accept.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE;;;iDAGiD;AACjD,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,YAAY,EACvB,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,OAAO,EACvB,OAAO,EAAE,UAAU,GAAG,IAAI,EAC1B,UAAU,EAAE,iBAAiB,EAC7B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC,gBAAgB,CAiBlB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IAChE,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,wEAAwE;IACxE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1C,uDAAuD;IACvD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;CACvC;AAED;mEACmE;AACnE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAuBjE"}