modelrig 0.8.1 → 0.9.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 (245) hide show
  1. package/CHANGELOG.md +145 -0
  2. package/README.md +4 -2
  3. package/dist/artifacts/artifact.d.ts +12 -13
  4. package/dist/artifacts/artifact.d.ts.map +1 -1
  5. package/dist/artifacts/artifact.js +17 -23
  6. package/dist/artifacts/index.d.ts +13 -5
  7. package/dist/artifacts/index.d.ts.map +1 -1
  8. package/dist/artifacts/index.js +11 -4
  9. package/dist/artifacts/run-context.d.ts +3 -24
  10. package/dist/artifacts/run-context.d.ts.map +1 -1
  11. package/dist/artifacts/run-context.js +3 -39
  12. package/dist/bakeoff/engine.d.ts +29 -0
  13. package/dist/bakeoff/engine.d.ts.map +1 -1
  14. package/dist/bakeoff/engine.js +47 -0
  15. package/dist/bakeoff/eval-cases-rig.d.ts +36 -0
  16. package/dist/bakeoff/eval-cases-rig.d.ts.map +1 -0
  17. package/dist/bakeoff/eval-cases-rig.js +27 -0
  18. package/dist/bakeoff/eval-cases.d.ts +19 -0
  19. package/dist/bakeoff/eval-cases.d.ts.map +1 -1
  20. package/dist/bakeoff/eval-cases.js +18 -1
  21. package/dist/bakeoff/golden-judge.d.ts +47 -0
  22. package/dist/bakeoff/golden-judge.d.ts.map +1 -0
  23. package/dist/bakeoff/golden-judge.js +49 -0
  24. package/dist/bakeoff/quality.d.ts +30 -0
  25. package/dist/bakeoff/quality.d.ts.map +1 -1
  26. package/dist/bakeoff/quality.js +21 -0
  27. package/dist/bakeoff/replay.d.ts +11 -0
  28. package/dist/bakeoff/replay.d.ts.map +1 -1
  29. package/dist/bakeoff/replay.js +8 -0
  30. package/dist/bakeoff/report.d.ts +7 -0
  31. package/dist/bakeoff/report.d.ts.map +1 -1
  32. package/dist/bakeoff/report.js +26 -0
  33. package/dist/cli-judge.d.ts +12 -0
  34. package/dist/cli-judge.d.ts.map +1 -0
  35. package/dist/cli-judge.js +48 -0
  36. package/dist/cli.d.ts.map +1 -1
  37. package/dist/cli.js +14 -42
  38. package/dist/config.d.ts +54 -29
  39. package/dist/config.d.ts.map +1 -1
  40. package/dist/config.js +86 -47
  41. package/dist/detect/detector.d.ts +4 -2
  42. package/dist/detect/detector.d.ts.map +1 -1
  43. package/dist/detect/safe-harbor.d.ts +57 -0
  44. package/dist/detect/safe-harbor.d.ts.map +1 -0
  45. package/dist/detect/safe-harbor.js +278 -0
  46. package/dist/feedback/coverage.d.ts +11 -8
  47. package/dist/feedback/coverage.d.ts.map +1 -1
  48. package/dist/feedback/coverage.js +29 -16
  49. package/dist/feedback/grade.d.ts +51 -0
  50. package/dist/feedback/grade.d.ts.map +1 -0
  51. package/dist/feedback/grade.js +63 -0
  52. package/dist/gateway/http-protocol.d.ts +1 -1
  53. package/dist/gateway/http-protocol.d.ts.map +1 -1
  54. package/dist/gateway/http-protocol.js +1 -1
  55. package/dist/index.d.ts +44 -27
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +110 -43
  58. package/dist/init/observe-cli.js +1 -1
  59. package/dist/init/observe.d.ts +2 -2
  60. package/dist/init/observe.d.ts.map +1 -1
  61. package/dist/init/observe.js +11 -7
  62. package/dist/mask/arm.d.ts +112 -0
  63. package/dist/mask/arm.d.ts.map +1 -0
  64. package/dist/mask/arm.js +179 -0
  65. package/dist/mask/index.d.ts +2 -0
  66. package/dist/mask/index.d.ts.map +1 -1
  67. package/dist/mask/index.js +7 -1
  68. package/dist/mask/mask-policy-cli.d.ts +12 -4
  69. package/dist/mask/mask-policy-cli.d.ts.map +1 -1
  70. package/dist/mask/mask-policy-cli.js +34 -9
  71. package/dist/query/grammar.d.ts +2 -2
  72. package/dist/query/grammar.d.ts.map +1 -1
  73. package/dist/query/grammar.js +3 -1
  74. package/dist/query/saved.d.ts +13 -0
  75. package/dist/query/saved.d.ts.map +1 -1
  76. package/dist/query/saved.js +67 -1
  77. package/dist/receipts/types.d.ts +1 -1
  78. package/dist/receipts/types.d.ts.map +1 -1
  79. package/dist/receipts/types.js +1 -0
  80. package/dist/registry/build.d.ts +43 -1
  81. package/dist/registry/build.d.ts.map +1 -1
  82. package/dist/registry/build.js +52 -0
  83. package/dist/registry/pricing-shape.d.ts +29 -0
  84. package/dist/registry/pricing-shape.d.ts.map +1 -1
  85. package/dist/registry/pricing-shape.js +10 -1
  86. package/dist/registry/rows.d.ts.map +1 -1
  87. package/dist/registry/rows.js +1 -0
  88. package/dist/registry/select.d.ts +6 -1
  89. package/dist/registry/select.d.ts.map +1 -1
  90. package/dist/registry/select.js +11 -0
  91. package/dist/routes/call-config.d.ts +199 -0
  92. package/dist/routes/call-config.d.ts.map +1 -0
  93. package/dist/routes/call-config.js +343 -0
  94. package/dist/routes/loader.js +5 -3
  95. package/dist/routes/objective-loader.d.ts +12 -0
  96. package/dist/routes/objective-loader.d.ts.map +1 -1
  97. package/dist/routes/objective-loader.js +82 -0
  98. package/dist/routes/resolved-bundle.d.ts +50 -0
  99. package/dist/routes/resolved-bundle.d.ts.map +1 -1
  100. package/dist/routes/resolved-bundle.js +52 -0
  101. package/dist/routes/screen-loader.d.ts +28 -0
  102. package/dist/routes/screen-loader.d.ts.map +1 -1
  103. package/dist/routes/screen-loader.js +51 -0
  104. package/dist/run/accept.d.ts +2 -0
  105. package/dist/run/accept.d.ts.map +1 -1
  106. package/dist/run/accept.js +1 -0
  107. package/dist/run/dispatch.d.ts +42 -13
  108. package/dist/run/dispatch.d.ts.map +1 -1
  109. package/dist/run/dispatch.js +107 -25
  110. package/dist/run/grounding.d.ts +28 -2
  111. package/dist/run/grounding.d.ts.map +1 -1
  112. package/dist/run/grounding.js +54 -10
  113. package/dist/run/record-attempt.d.ts +4 -0
  114. package/dist/run/record-attempt.d.ts.map +1 -1
  115. package/dist/run/record-attempt.js +4 -0
  116. package/dist/run/routing-docs.js +1 -1
  117. package/dist/run/run.d.ts.map +1 -1
  118. package/dist/run/run.js +21 -26
  119. package/dist/savings/odometer.d.ts +4 -0
  120. package/dist/savings/odometer.d.ts.map +1 -1
  121. package/dist/savings/odometer.js +20 -1
  122. package/dist/savings/swap-execute.d.ts +7 -0
  123. package/dist/savings/swap-execute.d.ts.map +1 -1
  124. package/dist/savings/swap-execute.js +30 -0
  125. package/dist/savings/swaps-client.d.ts +10 -0
  126. package/dist/savings/swaps-client.d.ts.map +1 -1
  127. package/dist/screen/fixtures/probe-corpora.d.ts +23 -0
  128. package/dist/screen/fixtures/probe-corpora.d.ts.map +1 -0
  129. package/dist/screen/fixtures/probe-corpora.js +69 -0
  130. package/dist/screen/index.d.ts +21 -0
  131. package/dist/screen/index.d.ts.map +1 -0
  132. package/dist/screen/index.js +64 -0
  133. package/dist/screen/model-screen.d.ts +111 -0
  134. package/dist/screen/model-screen.d.ts.map +1 -0
  135. package/dist/screen/model-screen.js +178 -0
  136. package/dist/screen/patterns.d.ts +51 -0
  137. package/dist/screen/patterns.d.ts.map +1 -0
  138. package/dist/screen/patterns.js +151 -0
  139. package/dist/screen/phi-gate.d.ts +52 -0
  140. package/dist/screen/phi-gate.d.ts.map +1 -0
  141. package/dist/screen/phi-gate.js +86 -0
  142. package/dist/screen/policy.d.ts +71 -0
  143. package/dist/screen/policy.d.ts.map +1 -0
  144. package/dist/screen/policy.js +334 -0
  145. package/dist/screen/probe.d.ts +118 -0
  146. package/dist/screen/probe.d.ts.map +1 -0
  147. package/dist/screen/probe.js +132 -0
  148. package/dist/screen/screen-cli.d.ts +16 -0
  149. package/dist/screen/screen-cli.d.ts.map +1 -0
  150. package/dist/screen/screen-cli.js +178 -0
  151. package/dist/screen/screen.d.ts +99 -0
  152. package/dist/screen/screen.d.ts.map +1 -0
  153. package/dist/screen/screen.js +0 -0
  154. package/dist/screen/sidecar.d.ts +69 -0
  155. package/dist/screen/sidecar.d.ts.map +1 -0
  156. package/dist/screen/sidecar.js +145 -0
  157. package/dist/screen/types.d.ts +43 -2
  158. package/dist/screen/types.d.ts.map +1 -1
  159. package/dist/settings/api-fetcher.d.ts +14 -3
  160. package/dist/settings/api-fetcher.d.ts.map +1 -1
  161. package/dist/settings/api-fetcher.js +61 -10
  162. package/dist/settings/grading-guide.d.ts +76 -0
  163. package/dist/settings/grading-guide.d.ts.map +1 -0
  164. package/dist/settings/grading-guide.js +23 -0
  165. package/dist/settings/index.d.ts +3 -2
  166. package/dist/settings/index.d.ts.map +1 -1
  167. package/dist/settings/index.js +2 -1
  168. package/dist/settings/task-settings.d.ts +44 -7
  169. package/dist/settings/task-settings.d.ts.map +1 -1
  170. package/dist/settings/task-settings.js +53 -12
  171. package/dist/status.d.ts +26 -20
  172. package/dist/status.d.ts.map +1 -1
  173. package/dist/status.js +47 -29
  174. package/dist/telemetry/artifact-store.d.ts +5 -6
  175. package/dist/telemetry/artifact-store.d.ts.map +1 -1
  176. package/dist/telemetry/artifact-store.js +10 -24
  177. package/dist/telemetry/attempt-meta.d.ts +21 -0
  178. package/dist/telemetry/attempt-meta.d.ts.map +1 -1
  179. package/dist/telemetry/attempt-meta.js +9 -0
  180. package/dist/telemetry/exporter.d.ts +2 -2
  181. package/dist/telemetry/exporter.d.ts.map +1 -1
  182. package/dist/telemetry/exporter.js +22 -41
  183. package/dist/telemetry/grade-mappers.d.ts +22 -0
  184. package/dist/telemetry/grade-mappers.d.ts.map +1 -0
  185. package/dist/telemetry/grade-mappers.js +58 -0
  186. package/dist/telemetry/grades-sql.d.ts +53 -0
  187. package/dist/telemetry/grades-sql.d.ts.map +1 -0
  188. package/dist/telemetry/grades-sql.js +133 -0
  189. package/dist/telemetry/ingest-protocol.d.ts +29 -46
  190. package/dist/telemetry/ingest-protocol.d.ts.map +1 -1
  191. package/dist/telemetry/ingest-protocol.js +16 -54
  192. package/dist/telemetry/store-migrations.d.ts.map +1 -1
  193. package/dist/telemetry/store-migrations.js +51 -0
  194. package/dist/telemetry/store.d.ts +9 -6
  195. package/dist/telemetry/store.d.ts.map +1 -1
  196. package/dist/telemetry/store.js +8 -50
  197. package/dist/tenancy/api-key-format.d.ts +30 -1
  198. package/dist/tenancy/api-key-format.d.ts.map +1 -1
  199. package/dist/tenancy/api-key-format.js +33 -1
  200. package/dist/types/provider.d.ts +3 -0
  201. package/dist/types/provider.d.ts.map +1 -1
  202. package/dist/types/provider.js +25 -0
  203. package/dist/types/route.d.ts +78 -2
  204. package/dist/types/route.d.ts.map +1 -1
  205. package/dist/types/telemetry.d.ts +43 -46
  206. package/dist/types/telemetry.d.ts.map +1 -1
  207. package/dist/validate-cli.d.ts.map +1 -1
  208. package/dist/validate-cli.js +32 -0
  209. package/dist/verify/verify.d.ts +5 -0
  210. package/dist/verify/verify.d.ts.map +1 -1
  211. package/dist/verify/verify.js +2 -0
  212. package/dist/watch/evaluate.d.ts +84 -1
  213. package/dist/watch/evaluate.d.ts.map +1 -1
  214. package/dist/watch/evaluate.js +28 -0
  215. package/dist/watch/monitor.d.ts +8 -2
  216. package/dist/watch/monitor.d.ts.map +1 -1
  217. package/dist/watch/monitor.js +13 -5
  218. package/dist/watch/regret-monitor-cli.d.ts +16 -0
  219. package/dist/watch/regret-monitor-cli.d.ts.map +1 -0
  220. package/dist/watch/regret-monitor-cli.js +137 -0
  221. package/dist/watch/regret-monitor.d.ts +168 -0
  222. package/dist/watch/regret-monitor.d.ts.map +1 -0
  223. package/dist/watch/regret-monitor.js +304 -0
  224. package/dist/watch/upgrade.d.ts +62 -0
  225. package/dist/watch/upgrade.d.ts.map +1 -0
  226. package/dist/watch/upgrade.js +57 -0
  227. package/docs/agent-skill/SKILL.md +109 -5
  228. package/docs/how-it-fits.md +3 -2
  229. package/docs/instrumentation.md +149 -21
  230. package/docs/llms.txt +64 -20
  231. package/docs/mcp-oracle.md +249 -0
  232. package/docs/quickstart.md +95 -7
  233. package/package.json +16 -3
  234. package/registry/leaderboard.json +74 -0
  235. package/registry/registry.json +150 -112
  236. package/screen.d.ts +16 -0
  237. package/templates/call-disposition-qa.json +77 -0
  238. package/templates/catalog-cleansing.json +77 -0
  239. package/templates/compliance-review.json +76 -0
  240. package/templates/cs-next-action.json +76 -0
  241. package/templates/document-extraction.json +78 -0
  242. package/templates/financial-classification.json +75 -0
  243. package/templates/lead-qualification.json +76 -0
  244. package/templates/medical-classification.json +71 -0
  245. package/templates/ticket-triage.json +76 -0
package/dist/status.js CHANGED
@@ -33,46 +33,63 @@ function exportModeOf(config) {
33
33
  return config.export?.mode ?? "local-only";
34
34
  }
35
35
  /**
36
- * The artifact-namespace posture as a boolean + a reason, derivable from config
37
- * ALONE (so both the banner and `/status` agree). The four cases the §2 flip
38
- * creates, each named honestly:
39
- * on + control plane → the default is now on (a sink exists to ship to)
40
- * on + local-only → an explicit MODELRIG_ARTIFACTS opt-in
41
- * off + control plane → an explicit MODELRIG_ARTIFACTS=0 opt-out
42
- * off + local-only → nothing to ship to; off is the local-only default
36
+ * The artifact-namespace posture as a boolean + a reason (P15 CP-3). The on/off
37
+ * SOURCE is the ORG's account posture (`artifact_posture`), resolved from the
38
+ * control plane — never an env var. The cases, each named honestly:
39
+ * control plane, posture off → capture off — your account settings
40
+ * control plane, posture managed/metadata → capture on — your account settings
41
+ * control plane, posture resolving (null) → capture on — account settings (resolving)
42
+ * local-only, dev force-on → MODELRIG_ARTIFACTS=1 (dev-only, local rig)
43
+ * local-only, off → nothing to ship to; off is the local default
44
+ * `posture` is the resolver's current value (null until the first run resolves
45
+ * it, or always null for local-only / hand-built configs).
43
46
  */
44
- function artifactsPosture(config) {
45
- const enabled = config.artifacts?.enabled === true;
47
+ function artifactsPosture(config, posture = null) {
46
48
  const localOnly = exportModeOf(config) === "local-only";
47
- if (enabled) {
49
+ if (localOnly) {
50
+ const enabled = config.artifacts?.enabled === true;
48
51
  return {
49
52
  enabled,
50
- reason: localOnly ? "MODELRIG_ARTIFACTS opt-in (local-only rig)" : "control plane configured",
53
+ reason: enabled
54
+ ? "MODELRIG_ARTIFACTS=1 (dev-only, local rig)"
55
+ : "local-only rig — no control plane to ship to",
51
56
  };
52
57
  }
53
- return {
54
- enabled,
55
- reason: localOnly ? "local-only rig — no control plane to ship to" : "MODELRIG_ARTIFACTS=0 opt-out",
56
- };
58
+ // Control plane configured: the org account posture (P15) governs on/off.
59
+ if (posture === "off") {
60
+ return { enabled: false, reason: "capture off — your account settings (posture: off)" };
61
+ }
62
+ const src = posture === null ? "your account settings (resolving)" : `your account settings (posture: ${posture})`;
63
+ return { enabled: true, reason: `capture on — ${src}` };
64
+ }
65
+ /** Whether content is EFFECTIVELY stored: content transport configured AND the
66
+ * org posture is not one that suppresses content (P15). posture `off`/`metadata`
67
+ * → the server stores no content, so report it off honestly; `managed`/resolving
68
+ * with content configured → on (attempted; the server is the gate). */
69
+ function contentCustodyOn(config, posture) {
70
+ if (config.artifacts?.content === undefined)
71
+ return false;
72
+ return posture !== "off" && posture !== "metadata";
57
73
  }
58
- /** Build the full status snapshot from config + the resolver's per-task cache,
59
- * plus (GS-1) an optional runs-recorded summary read from the local buffer. */
60
- function buildRigStatus(config, tasks = new Map(), runs) {
74
+ /** Build the full status snapshot from config + the resolver's per-task cache and
75
+ * org posture (P15), plus (GS-1) an optional runs-recorded summary from the buffer. */
76
+ function buildRigStatus(config, tasks = new Map(), runs, posture = null) {
61
77
  return {
62
78
  exportMode: exportModeOf(config),
63
- artifacts: artifactsPosture(config),
64
- contentCustody: config.artifacts?.content !== undefined,
79
+ artifacts: artifactsPosture(config, posture),
80
+ contentCustody: contentCustodyOn(config, posture),
65
81
  otlp: config.otlp ? "configured" : "disabled",
66
82
  cache: cachePosture(),
67
83
  tasks: [...tasks].map(([task, s]) => ({ task, ...s })),
68
84
  ...(runs != null ? { runs } : {}),
69
85
  };
70
86
  }
71
- /** The one-line boot banner (§2). Concise on purpose — mode, artifacts (+why),
72
- * content, otlp. */
73
- function formatBootBanner(config) {
74
- const a = artifactsPosture(config);
75
- const content = config.artifacts?.content !== undefined ? "on" : "off";
87
+ /** The one-line boot banner (§2 + P15). Concise on purpose — mode, artifacts
88
+ * (+source), content, otlp. `posture` is null at boot (resolves on the first run),
89
+ * so the banner names the SOURCE (account settings) rather than a stale value. */
90
+ function formatBootBanner(config, posture = null) {
91
+ const a = artifactsPosture(config, posture);
92
+ const content = contentCustodyOn(config, posture) ? "on" : "off";
76
93
  const otlp = config.otlp ? "on" : "off";
77
94
  return (`[modelrig] telemetry: ${exportModeOf(config)} · ` +
78
95
  `artifacts: ${a.enabled ? "on" : "off"} (${a.reason}) · ` +
@@ -80,10 +97,11 @@ function formatBootBanner(config) {
80
97
  }
81
98
  /**
82
99
  * Emit the boot banner to stderr — ONCE at rig construction, and ONLY when a
83
- * control plane is configured (the case where the §2 default flip is in effect
84
- * and the posture is non-obvious). A pure local-only rig with artifacts off is
85
- * the boring, expected default and stays silent (no banner noise in tests or
86
- * embedders). Stderr, so it never pollutes a command's stdout.
100
+ * control plane is configured (the case where capture is on by default and the
101
+ * posture — resolved from account settings — is non-obvious). A pure local-only
102
+ * rig with artifacts off is the boring, expected default and stays silent (no
103
+ * banner noise in tests or embedders). Stderr, so it never pollutes stdout.
104
+ * Posture is null at boot; the banner names its source (account settings).
87
105
  */
88
106
  function emitBootBanner(config) {
89
107
  if (config.export === undefined)
@@ -9,11 +9,14 @@
9
9
  * a sha256 of bytes hashed-then-discarded. Rows are immutable facts: INSERT OR
10
10
  * IGNORE, read past a rowid watermark exactly like inferences.
11
11
  */
12
- import type { ArtifactEdgeRow, ArtifactEvaluationRow, ArtifactRow, EvalCaseRow } from "../types/telemetry";
12
+ import type { ArtifactEdgeRow, ArtifactRow, EvalCaseRow, GradeRow } from "../types/telemetry";
13
13
  export interface ArtifactStore {
14
14
  recordArtifact(row: ArtifactRow): void;
15
15
  recordArtifactEdge(row: ArtifactEdgeRow): void;
16
- recordArtifactEvaluation(row: ArtifactEvaluationRow): void;
16
+ /** Record a unified judgment (grade primitive, R1) — the canonical write path
17
+ * for a grade on an artifact/run subject, which transacts on THIS handle.
18
+ * Writes the shared local `grades` table (read/exported by the telemetry handle). */
19
+ recordGrade(row: GradeRow): void;
17
20
  /** Record a promoted eval case (E4 chunk A) — rides the `:eval_cases` export
18
21
  * stream to the control plane, exactly like the other artifact-graph rows. */
19
22
  recordEvalCase(row: EvalCaseRow): void;
@@ -25,10 +28,6 @@ export interface ArtifactStore {
25
28
  rowid: number;
26
29
  row: ArtifactEdgeRow;
27
30
  }>;
28
- readEvaluationsAfter(afterRowid: number, limit: number): Array<{
29
- rowid: number;
30
- row: ArtifactEvaluationRow;
31
- }>;
32
31
  readEvalCasesAfter(afterRowid: number, limit: number): Array<{
33
32
  rowid: number;
34
33
  row: EvalCaseRow;
@@ -1 +1 @@
1
- {"version":3,"file":"artifact-store.d.ts","sourceRoot":"","sources":["../../src/telemetry/artifact-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EACV,eAAe,EACf,qBAAqB,EACrB,WAAW,EACX,WAAW,EACZ,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,aAAa;IAC5B,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAC;IACvC,kBAAkB,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI,CAAC;IAC/C,wBAAwB,CAAC,GAAG,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC3D;kFAC8E;IAC9E,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAC;IACvC,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;IAClG,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,eAAe,CAAA;KAAE,CAAC,CAAC;IAClG,oBAAoB,CAClB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,qBAAqB,CAAA;KAAE,CAAC,CAAC;IACxD,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;IAClG,gFAAgF;IAChF,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CAAC;IACjD;gEAC4D;IAC5D,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;IAChD;;oFAEgF;IAChF,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,KAAK,IAAI,IAAI,CAAC;CACf;AAwED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAwH/D"}
1
+ {"version":3,"file":"artifact-store.d.ts","sourceRoot":"","sources":["../../src/telemetry/artifact-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EACX,WAAW,EACX,QAAQ,EACT,MAAM,oBAAoB,CAAC;AAQ5B,MAAM,WAAW,aAAa;IAC5B,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAC;IACvC,kBAAkB,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI,CAAC;IAC/C;;yFAEqF;IACrF,WAAW,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CAAC;IACjC;kFAC8E;IAC9E,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAC;IACvC,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;IAClG,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,eAAe,CAAA;KAAE,CAAC,CAAC;IAClG,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;IAClG,gFAAgF;IAChF,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CAAC;IACjD;gEAC4D;IAC5D,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;IAChD;;oFAEgF;IAChF,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,KAAK,IAAI,IAAI,CAAC;CACf;AA2DD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAiH/D"}
@@ -18,6 +18,7 @@ exports.openArtifactStore = openArtifactStore;
18
18
  const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
19
19
  const node_fs_1 = require("node:fs");
20
20
  const node_path_1 = require("node:path");
21
+ const grades_sql_1 = require("./grades-sql");
21
22
  const ARTIFACTS_SQL = `
22
23
  CREATE TABLE IF NOT EXISTS artifacts (
23
24
  id TEXT PRIMARY KEY, run_id TEXT, step_key TEXT, attempt_no INTEGER, task TEXT,
@@ -53,14 +54,6 @@ function toArtifact(r) {
53
54
  function toEdge(r) {
54
55
  return { fromArtifactId: r.from_artifact_id, toArtifactId: r.to_artifact_id, kind: r.kind };
55
56
  }
56
- function toEval(r) {
57
- return {
58
- id: r.id, artifactId: r.artifact_id, runId: r.run_id, evaluator: r.evaluator,
59
- evaluatorKind: r.evaluator_kind,
60
- score: r.score, passed: r.passed === null ? null : r.passed !== 0,
61
- label: r.label, explanation: r.explanation, createdBy: r.created_by,
62
- };
63
- }
64
57
  function toEvalCase(r) {
65
58
  return {
66
59
  id: r.id, task: r.task, sourceArtifactId: r.source_artifact_id,
@@ -78,6 +71,12 @@ function openArtifactStore(dbPath) {
78
71
  // telemetry guarantee; the cloud exporter is the durable copy.
79
72
  db.pragma("synchronous = NORMAL");
80
73
  db.exec(ARTIFACTS_SQL);
74
+ // Grade primitive (R1): the unified `grades` table is shared with the telemetry
75
+ // handle (same file). CREATE IF NOT EXISTS so whichever handle opens first wins;
76
+ // then backfill this store's evaluations into grades (idempotent, INSERT OR
77
+ // IGNORE) so pre-grade evaluations still export as grades. Additive.
78
+ db.exec(grades_sql_1.GRADES_TABLE_SQL);
79
+ (0, grades_sql_1.backfillGradesFromEvaluations)(db);
81
80
  // Additive column for a dev DB that predates E4 (CREATE TABLE IF NOT EXISTS
82
81
  // won't add it to an existing table). SQLite has no ADD COLUMN IF NOT EXISTS;
83
82
  // a duplicate-column error on re-run is expected and swallowed.
@@ -110,14 +109,11 @@ function openArtifactStore(dbPath) {
110
109
  @data_classification, @expires_at, @scrub
111
110
  )`);
112
111
  const insEdge = db.prepare("INSERT OR IGNORE INTO artifact_edges (from_artifact_id, to_artifact_id, kind) VALUES (@from_artifact_id, @to_artifact_id, @kind)");
113
- const insEval = db.prepare(`
114
- INSERT OR IGNORE INTO artifact_evaluations (
115
- id, artifact_id, run_id, evaluator, evaluator_kind, score, passed, label, explanation, created_by
116
- ) VALUES (@id, @artifact_id, @run_id, @evaluator, @evaluator_kind, @score, @passed, @label, @explanation, @created_by)`);
117
112
  const insEvalCase = db.prepare(`
118
113
  INSERT OR IGNORE INTO eval_cases (
119
114
  id, task, source_artifact_id, corrected_artifact_id, origin, note, created_by
120
115
  ) VALUES (@id, @task, @source_artifact_id, @corrected_artifact_id, @origin, @note, @created_by)`);
116
+ const insGrade = (0, grades_sql_1.prepareGradeInsert)(db);
121
117
  return {
122
118
  recordArtifact(row) {
123
119
  insArtifact.run({
@@ -135,13 +131,8 @@ function openArtifactStore(dbPath) {
135
131
  recordArtifactEdge(row) {
136
132
  insEdge.run({ from_artifact_id: row.fromArtifactId, to_artifact_id: row.toArtifactId, kind: row.kind });
137
133
  },
138
- recordArtifactEvaluation(row) {
139
- insEval.run({
140
- id: row.id, artifact_id: row.artifactId, run_id: row.runId, evaluator: row.evaluator,
141
- evaluator_kind: row.evaluatorKind, score: row.score,
142
- passed: row.passed === null ? null : row.passed ? 1 : 0,
143
- label: row.label, explanation: row.explanation, created_by: row.createdBy,
144
- });
134
+ recordGrade(row) {
135
+ insGrade.run((0, grades_sql_1.gradeBindParams)(row));
145
136
  },
146
137
  recordEvalCase(row) {
147
138
  insEvalCase.run({
@@ -160,11 +151,6 @@ function openArtifactStore(dbPath) {
160
151
  .all(afterRowid, limit);
161
152
  return rows.map((r) => ({ rowid: r.__r, row: toEdge(r) }));
162
153
  },
163
- readEvaluationsAfter(afterRowid, limit) {
164
- const rows = db.prepare("SELECT rowid AS __r, * FROM artifact_evaluations WHERE rowid > ? ORDER BY rowid LIMIT ?")
165
- .all(afterRowid, limit);
166
- return rows.map((r) => ({ rowid: r.__r, row: toEval(r) }));
167
- },
168
154
  readEvalCasesAfter(afterRowid, limit) {
169
155
  const rows = db.prepare("SELECT rowid AS __r, * FROM eval_cases WHERE rowid > ? ORDER BY rowid LIMIT ?")
170
156
  .all(afterRowid, limit);
@@ -12,6 +12,7 @@
12
12
  * enum/identifier/hash (length > 128 or containing whitespace).
13
13
  */
14
14
  import type { AdapterUsage, ProviderId } from "../types/provider";
15
+ import type { ScreenReceipt } from "../screen/types";
15
16
  export type FinishReason = "stop" | "length" | "tool_calls" | "content_filter" | "refusal" | "error" | "other";
16
17
  export type ContextBucket = "≤4k" | "≤16k" | "≤64k" | "≤200k" | ">200k";
17
18
  /** D1 egress receipt — shape RESERVED here; populated by the D1 mission. */
@@ -67,6 +68,19 @@ export interface AttemptMetaV1 {
67
68
  readonly output_hash?: string;
68
69
  readonly context_bucket?: ContextBucket;
69
70
  readonly egress?: EgressReceiptV1;
71
+ /** LRE-2: the live A/B experiment arm this call was drawn onto (an identifier —
72
+ * `provider/model` or a variant/arm name), or absent for a non-experiment call.
73
+ * The A/B readout groups `inferences` by `meta.arm`. Meta-safe by construction
74
+ * (an identifier, no whitespace); a non-conforming value is dropped like any. */
75
+ readonly arm?: string;
76
+ /** Screening SC-1a receipt (spec §5) — the counts-only screen summary rides
77
+ * HERE, on `inferences.meta.screen`, so SC-1 adds ZERO migration (§8). Every
78
+ * field is an enum / count / hash (findings are `{detector,type,source,count}`
79
+ * with no-whitespace labels), so the classification rule and the server ingest
80
+ * backstop (`sanitizeMetaForWire`) pass it through intact. Produced by the
81
+ * single producer `summarizeScreen`; NEVER carries a matched value. Reserved &
82
+ * additive. */
83
+ readonly screen?: ScreenReceipt;
70
84
  }
71
85
  export interface RunMetaV1 {
72
86
  readonly v: 1;
@@ -119,6 +133,13 @@ export interface AttemptMetaInputs {
119
133
  readonly streaming?: boolean;
120
134
  /** Repair-rung count carried by the run loop, if any. */
121
135
  readonly repairCount?: number;
136
+ /** LRE-2: the drawn A/B arm name (RunOptions.arm), stamped onto `meta.arm` when
137
+ * meta-safe. Absent ⇒ no `arm` key ⇒ byte-identical to a non-experiment call. */
138
+ readonly arm?: string;
139
+ /** SC-1a: the counts-only screen receipt to ride on `meta.screen`. Passed
140
+ * through verbatim (already counts/enums/hashes — no free text). Absent ⇒ no
141
+ * `screen` key ⇒ byte-identical to a non-screened row. */
142
+ readonly screen?: ScreenReceipt;
122
143
  }
123
144
  /** The classification-rule string test (spec §2, §5 wire backstop): a value is
124
145
  * an ENUM / IDENTIFIER / HASH only if it is at most 128 chars AND contains no
@@ -1 +1 @@
1
- {"version":3,"file":"attempt-meta.d.ts","sourceRoot":"","sources":["../../src/telemetry/attempt-meta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAElE,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,QAAQ,GACR,YAAY,GACZ,gBAAgB,GAChB,SAAS,GACT,OAAO,GACP,OAAO,CAAC;AAEZ,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAExE,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,CAAC,EAAE;QAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnG,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC;IACd,QAAQ,CAAC,aAAa,CAAC,EAAE,YAAY,CAAC;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,8EAA8E;IAC9E,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACnF,QAAQ,CAAC,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxF,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE;QACd,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC;IACF,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,8DAA8D;IAC9D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,cAAc,CAAC,EAAE,aAAa,CAAC;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;CACnC;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC;IACd,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IAClE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IAC9C,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAChD;AAED;;;;uEAIuE;AACvE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,GAAG,MAAM,CAMT;AAED;;uEAEuE;AACvE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IAC9C,4EAA4E;IAC5E,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,8DAA8D;IAC9D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,uEAAuE;IACvE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,CACnB,YAAY,EACZ,UAAU,GAAG,WAAW,GAAG,cAAc,GAAG,kBAAkB,GAAG,oBAAoB,CACtF,CAAC;IACF,mEAAmE;IACnE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,yDAAyD;IACzD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAID;;;;+BAI+B;AAC/B,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,MAAM,CAExD;AAOD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAgCrG;AAID;gEACgE;AAChE,eAAO,MAAM,iBAAiB,mEAAoE,CAAC;AACnG,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AA4BhE;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,cAAc,CAAA;CAAE,EAAE,CAS5G;AAID;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAInE;AAED;;;2CAG2C;AAC3C,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAkBrE;AAwCD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,GAAG,aAAa,GAAG,IAAI,CAgFpF"}
1
+ {"version":3,"file":"attempt-meta.d.ts","sourceRoot":"","sources":["../../src/telemetry/attempt-meta.ts"],"names":[],"mappings":"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"}
@@ -238,6 +238,15 @@ function summarizeAttemptMeta(inputs) {
238
238
  meta.streaming = a.streaming;
239
239
  else if (typeof inputs.streaming === "boolean")
240
240
  meta.streaming = inputs.streaming;
241
+ // LRE-2 A/B arm — an identifier, gated by the classification rule (absent ⇒
242
+ // no key ⇒ byte-identical to a non-experiment row).
243
+ if (isMetaSafeString(inputs.arm))
244
+ meta.arm = inputs.arm;
245
+ // SC-1a screen receipt (spec §5, §8) — the counts-only screen summary rides
246
+ // on meta.screen (ZERO migration). Already counts/enums/hashes; passed
247
+ // through verbatim (absent ⇒ no key ⇒ byte-identical to a non-screened row).
248
+ if (inputs.screen !== undefined)
249
+ meta.screen = inputs.screen;
241
250
  // Externally-sourced identifiers — gated by the classification rule.
242
251
  if (isMetaSafeString(a.model_snapshot))
243
252
  meta.model_snapshot = a.model_snapshot;
@@ -83,8 +83,8 @@ export interface ExporterConfig {
83
83
  readonly artifacts?: boolean;
84
84
  /** The local artifact-metadata buffer (chunk B). A SEPARATE handle from the
85
85
  * telemetry store; present only when the namespace is enabled. Its rows ride
86
- * the `:artifacts`/`:edges`/`:evals` watermark streams (watermarks live in the
87
- * main store's export_state, rows are read from here). */
86
+ * the `:artifacts`/`:edges`/`:eval_cases` watermark streams (watermarks live in
87
+ * the main store's export_state, rows are read from here). */
88
88
  readonly artifactStore?: ArtifactStore;
89
89
  /**
90
90
  * Post-flush hook fired AFTER a confirmed export of the artifacts stream (E4
@@ -1 +1 @@
1
- {"version":3,"file":"exporter.d.ts","sourceRoot":"","sources":["../../src/telemetry/exporter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"exporter.d.ts","sourceRoot":"","sources":["../../src/telemetry/exporter.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,7 @@ exports.createTelemetryExporter = createTelemetryExporter;
24
24
  exports.buildLoadErrorBatch = buildLoadErrorBatch;
25
25
  const resolved_bundle_1 = require("../routes/resolved-bundle");
26
26
  const ingest_protocol_1 = require("./ingest-protocol");
27
+ const grade_mappers_1 = require("./grade-mappers");
27
28
  const sinks_1 = require("./sinks");
28
29
  /**
29
30
  * Build the `routes` mirror payload from loaded bundles (Phase D, spec §13).
@@ -35,6 +36,10 @@ const sinks_1 = require("./sinks");
35
36
  */
36
37
  function buildExportedRouteMirrors(bundles) {
37
38
  return bundles.map((b) => {
39
+ // SC-1b req 1: refuse to mirror a `screen: enforce` route whose enforcement
40
+ // can't be guaranteed to re-resolve on the hosted lane (a T1 classifier) —
41
+ // a teaching failure at sync, never a silent inert enforce at request.
42
+ (0, resolved_bundle_1.assertMirrorSafe)(b);
38
43
  const bundle = (0, resolved_bundle_1.resolveRouteBundle)(b);
39
44
  return {
40
45
  route: b.route,
@@ -104,6 +109,14 @@ function toWireInference(row) {
104
109
  // (pre-WI-1a, or a null envelope) emits nothing, so the payload is
105
110
  // byte-identical to before and the server leaves inferences.meta null.
106
111
  ...(row.meta != null ? { meta: row.meta } : {}),
112
+ // CS-1 Chunk B (spec §6): the counts-only MaskReceipt. spread-iff-present —
113
+ // an unmasked route (no receipt) emits NOTHING, so the payload is
114
+ // byte-identical to before CS-1 and the server leaves inferences.mask null.
115
+ // Requires migration 00062 (inferences.mask jsonb) server-side; apply it
116
+ // BEFORE deploying this build (migrate-first) or the insert 4xx's and the
117
+ // exporter poison-skips the batch. NEVER a matched value (summarizeMask is
118
+ // counts-only; counts-never-values property test covers the wire).
119
+ ...(row.mask != null ? { mask: row.mask } : {}),
107
120
  };
108
121
  }
109
122
  function toWireRun(row) {
@@ -172,37 +185,6 @@ function toWireEvalCase(row) {
172
185
  created_by: row.createdBy,
173
186
  };
174
187
  }
175
- function toWireEvaluation(row) {
176
- return {
177
- id: row.id,
178
- artifact_id: row.artifactId,
179
- run_id: row.runId,
180
- evaluator: row.evaluator,
181
- evaluator_kind: row.evaluatorKind,
182
- score: row.score,
183
- passed: row.passed,
184
- label: row.label,
185
- explanation: row.explanation,
186
- created_by: row.createdBy,
187
- };
188
- }
189
- function toWireFeedback(row) {
190
- return {
191
- id: row.id,
192
- ts: row.ts,
193
- inference_id: row.inferenceId,
194
- episode_key: row.episodeKey,
195
- verdict: row.verdict,
196
- score: row.score,
197
- note: row.note,
198
- source: row.source,
199
- created_by: row.createdBy,
200
- // Present only when the verdict names its own org. Omitted (not null) so
201
- // that `stampBatch` can fall back to the exporter's tenant without having
202
- // to distinguish "no org" from "explicitly no org".
203
- ...(row.orgId !== null ? { org_id: row.orgId } : {}),
204
- };
205
- }
206
188
  function createTelemetryExporter(store, config) {
207
189
  const batchSize = config.batchSize ?? DEFAULT_BATCH_SIZE;
208
190
  const intervalMs = config.intervalMs ?? exports.DEFAULT_INTERVAL_MS;
@@ -330,8 +312,8 @@ function createTelemetryExporter(store, config) {
330
312
  let header = pendingHeader();
331
313
  /**
332
314
  * Drain one watermarked stream to exhaustion, batch by batch, through the
333
- * poison-pill state machine. Every stream (inferences, feedback, runs,
334
- * steps, artifacts, edges, evals) is the SAME at-least-once dance behind its
315
+ * poison-pill state machine. Every stream (inferences, grades, runs,
316
+ * steps, artifacts, edges) is the SAME at-least-once dance behind its
335
317
  * own export_state key — factored here so the watermark/header/poison
336
318
  * bookkeeping lives in exactly one place and no stream can drift from
337
319
  * another. A "skip" advances the watermark past a poison batch WITHOUT
@@ -371,11 +353,13 @@ function createTelemetryExporter(store, config) {
371
353
  inferences: rows.map((row) => toWireInference(row)),
372
354
  watermarkAt: new Date().toISOString(),
373
355
  }));
374
- // Feedback, runs, steps, artifacts, edges, evals: the same dance, each
375
- // behind its own export_state key so no stream ever blocks another — a
376
- // poison in one is skipped past without touching the rest.
377
- await drainStream(`${sourceId}:feedback`, (w, n) => store.readFeedbackAfter(w, n), (rows) => ({
378
- feedback: rows.map((row) => toWireFeedback(row)),
356
+ // Grades (grade primitive, R1) — the unified judgment stream, the SDK's
357
+ // sole write path. Same at-least-once dance behind its own watermark key;
358
+ // a grade lands in `public.grades` (idempotent by id). Runs, steps,
359
+ // artifacts, edges: the same dance, each behind its own export_state key so
360
+ // no stream ever blocks another — a poison in one is skipped past.
361
+ await drainStream(`${sourceId}:grades`, (w, n) => store.readGradesAfter(w, n), (rows) => ({
362
+ grades: rows.map((row) => (0, grade_mappers_1.toWireGrade)(row)),
379
363
  }));
380
364
  // Execution graph (Expansion E2 chunk A) — ONLY when the artifact namespace
381
365
  // is active. When artifacts are off these streams never drain and no
@@ -397,9 +381,6 @@ function createTelemetryExporter(store, config) {
397
381
  await drainStream(`${sourceId}:edges`, (w, n) => artStore.readEdgesAfter(w, n), (rows) => ({
398
382
  artifact_edges: rows.map((row) => toWireEdge(row)),
399
383
  }));
400
- await drainStream(`${sourceId}:evals`, (w, n) => artStore.readEvaluationsAfter(w, n), (rows) => ({
401
- artifact_evaluations: rows.map((row) => toWireEvaluation(row)),
402
- }));
403
384
  // Promoted eval cases (E4 chunk A) — same at-least-once dance behind its
404
385
  // own watermark key.
405
386
  await drainStream(`${sourceId}:eval_cases`, (w, n) => artStore.readEvalCasesAfter(w, n), (rows) => ({
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Wire → `grades` row mappers (grade primitive, 00070). Extracted from
3
+ * ingest-protocol.ts so stampBatch stays under the LOC cap (P1). A `WireGrade`
4
+ * lands in the ONE `grades` table; the pass/fail verdict is DERIVED at read
5
+ * time, never stored. Tenancy is stamped from the principal (T3); a grade may
6
+ * name its OWN org (QA-P6-010), verified by foreignOrgGrades before the write.
7
+ */
8
+ import type { GradeRow } from "../types/telemetry";
9
+ import type { Tenancy } from "./ingest-protocol";
10
+ import type { WireGrade } from "./ingest-protocol";
11
+ /** GradeRow → WireGrade (the exporter's `:grades` stream mapper). org_id is
12
+ * spread-iff-present so stampBatch falls back to the exporter's tenant. */
13
+ export declare function toWireGrade(row: GradeRow): WireGrade;
14
+ /** WireGrade → a grades row (the SDK's sole judgment write path). */
15
+ export declare function gradeToRow({ org_id, ...g }: WireGrade, tenancy: Tenancy): Record<string, unknown>;
16
+ /**
17
+ * Grades naming an org other than the presented key's. The ingest endpoint drops
18
+ * and COUNTS these so a caller cannot file a judgment into another tenant's corpus
19
+ * (QA-P6-010). Returns the offending ids. A service-role exporter needs no such check.
20
+ */
21
+ export declare function foreignOrgGrades(rows: readonly WireGrade[], keyOrgId: string): readonly string[];
22
+ //# sourceMappingURL=grade-mappers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grade-mappers.d.ts","sourceRoot":"","sources":["../../src/telemetry/grade-mappers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD;2EAC2E;AAC3E,wBAAgB,WAAW,CAAC,GAAG,EAAE,QAAQ,GAAG,SAAS,CAgBpD;AAED,qEAAqE;AACrE,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiBjG;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAEhG"}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ /**
3
+ * Wire → `grades` row mappers (grade primitive, 00070). Extracted from
4
+ * ingest-protocol.ts so stampBatch stays under the LOC cap (P1). A `WireGrade`
5
+ * lands in the ONE `grades` table; the pass/fail verdict is DERIVED at read
6
+ * time, never stored. Tenancy is stamped from the principal (T3); a grade may
7
+ * name its OWN org (QA-P6-010), verified by foreignOrgGrades before the write.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.toWireGrade = toWireGrade;
11
+ exports.gradeToRow = gradeToRow;
12
+ exports.foreignOrgGrades = foreignOrgGrades;
13
+ /** GradeRow → WireGrade (the exporter's `:grades` stream mapper). org_id is
14
+ * spread-iff-present so stampBatch falls back to the exporter's tenant. */
15
+ function toWireGrade(row) {
16
+ return {
17
+ id: row.id,
18
+ subject_kind: row.subjectKind,
19
+ subject_id: row.subjectId,
20
+ score: row.score,
21
+ scale_max: row.scaleMax,
22
+ scale_label: row.scaleLabel,
23
+ comment: row.comment,
24
+ kind: row.kind,
25
+ grader: row.grader,
26
+ source: row.source,
27
+ created_by: row.createdBy,
28
+ ts: row.ts,
29
+ ...(row.orgId !== null ? { org_id: row.orgId } : {}),
30
+ };
31
+ }
32
+ /** WireGrade → a grades row (the SDK's sole judgment write path). */
33
+ function gradeToRow({ org_id, ...g }, tenancy) {
34
+ return {
35
+ org_id: org_id ?? tenancy.org_id,
36
+ project_id: tenancy.project_id,
37
+ id: g.id,
38
+ subject_kind: g.subject_kind,
39
+ subject_id: g.subject_id,
40
+ score: g.score,
41
+ scale_max: g.scale_max,
42
+ scale_label: g.scale_label,
43
+ comment: g.comment,
44
+ kind: g.kind,
45
+ grader: g.grader,
46
+ source: g.source,
47
+ created_by: g.created_by,
48
+ ts: g.ts,
49
+ };
50
+ }
51
+ /**
52
+ * Grades naming an org other than the presented key's. The ingest endpoint drops
53
+ * and COUNTS these so a caller cannot file a judgment into another tenant's corpus
54
+ * (QA-P6-010). Returns the offending ids. A service-role exporter needs no such check.
55
+ */
56
+ function foreignOrgGrades(rows, keyOrgId) {
57
+ return rows.filter((r) => r.org_id !== undefined && r.org_id !== keyOrgId).map((r) => r.id);
58
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Shared SQLite DDL + row mapping for the local `grades` table (grade primitive).
3
+ *
4
+ * The unified judgment table is written by TWO better-sqlite3 handles over the
5
+ * same telemetry file — the main telemetry store (`store.ts`, for inference/run
6
+ * grades via `rig.grade`) and the artifact store (`artifact-store.ts`, for
7
+ * artifact-subject grades, which already transact on that handle). Both must
8
+ * agree on the table shape and the bind mapping, so both live here once (DRY,
9
+ * and the two cannot drift). The telemetry handle owns the READ side (the
10
+ * exporter's `:grades` stream).
11
+ *
12
+ * project_id is NOT stored locally: like every telemetry row, it is stamped at
13
+ * export from the principal, never held on the row (one rig = one tenant).
14
+ */
15
+ import type Database from "better-sqlite3";
16
+ import type { GradeRow } from "../types/telemetry";
17
+ /** `CREATE TABLE IF NOT EXISTS grades …` — safe to run on every open. Mirrors
18
+ * `public.grades` minus the export-stamped columns (org handling below). */
19
+ export declare const GRADES_TABLE_SQL = "\nCREATE TABLE IF NOT EXISTS grades (\n id TEXT PRIMARY KEY,\n ts TEXT,\n subject_kind TEXT NOT NULL CHECK (subject_kind IN ('inference','run','artifact')),\n subject_id TEXT NOT NULL,\n score REAL NOT NULL,\n scale_max REAL,\n scale_label TEXT,\n comment TEXT,\n kind TEXT NOT NULL CHECK (kind IN ('human','model-judge','deterministic')),\n grader TEXT,\n source TEXT,\n org_id TEXT,\n created_by TEXT\n);\nCREATE INDEX IF NOT EXISTS idx_grades_subject ON grades (subject_kind, subject_id);\n";
20
+ /** The row shape as it sits in SQLite (snake_case, nullable columns as read back). */
21
+ export interface GradeDbRow {
22
+ id: string;
23
+ ts: string | null;
24
+ subject_kind: string;
25
+ subject_id: string;
26
+ score: number;
27
+ scale_max: number | null;
28
+ scale_label: string | null;
29
+ comment: string | null;
30
+ kind: string;
31
+ grader: string | null;
32
+ source: string | null;
33
+ org_id: string | null;
34
+ created_by: string | null;
35
+ }
36
+ /** Prepare the grade insert statement against an open handle. INSERT OR IGNORE:
37
+ * a grade id is unique, and a re-inserted id (e.g. the backfill racing a live
38
+ * write) is a harmless no-op. */
39
+ export declare function prepareGradeInsert(db: Database.Database): Database.Statement;
40
+ /** Bind a GradeRow to the insert statement's named params. */
41
+ export declare function gradeBindParams(row: GradeRow): Record<string, unknown>;
42
+ /** Read one SQLite grade row back into a GradeRow. */
43
+ export declare function toGradeRow(r: GradeDbRow): GradeRow;
44
+ /** Backfill `grades` from the local `feedback` table, if it exists (grade
45
+ * primitive, GP-1). Same mapping as migration 00070's feedback→grades leg.
46
+ * Idempotent (INSERT OR IGNORE keyed on the source row id). Runs inside the
47
+ * telemetry store's migration ladder. */
48
+ export declare function backfillGradesFromFeedback(db: Database.Database): void;
49
+ /** Backfill `grades` from the local `artifact_evaluations` table, if it exists
50
+ * (grade primitive, GP-1). Same mapping as migration 00070's evaluation leg.
51
+ * Idempotent. Runs when the artifact store opens (it owns that table). */
52
+ export declare function backfillGradesFromEvaluations(db: Database.Database): void;
53
+ //# sourceMappingURL=grades-sql.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grades-sql.d.ts","sourceRoot":"","sources":["../../src/telemetry/grades-sql.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD;4EAC4E;AAC5E,eAAO,MAAM,gBAAgB,ikBAiB5B,CAAC;AAEF,sFAAsF;AACtF,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAWD;;iCAEiC;AACjC,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAE5E;AAED,8DAA8D;AAC9D,wBAAgB,eAAe,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgBtE;AAED,sDAAsD;AACtD,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,GAAG,QAAQ,CAgBlD;AAED;;;yCAGyC;AACzC,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAetE;AAED;;0EAE0E;AAC1E,wBAAgB,6BAA6B,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAgBzE"}