modelrig 0.0.1 → 0.2.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 (420) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/LICENSE +201 -0
  3. package/README.md +145 -8
  4. package/data/PROVENANCE.md +19 -0
  5. package/data/pricing-manual.json +22 -0
  6. package/data/pricing-map.json +46362 -0
  7. package/data/pricing-overlay.json +419 -0
  8. package/dist/adapters/anthropic.d.ts +90 -0
  9. package/dist/adapters/anthropic.d.ts.map +1 -0
  10. package/dist/adapters/anthropic.js +296 -0
  11. package/dist/adapters/build-adapters.d.ts +11 -0
  12. package/dist/adapters/build-adapters.d.ts.map +1 -0
  13. package/dist/adapters/build-adapters.js +45 -0
  14. package/dist/adapters/deepseek.d.ts +47 -0
  15. package/dist/adapters/deepseek.d.ts.map +1 -0
  16. package/dist/adapters/deepseek.js +216 -0
  17. package/dist/adapters/gemini.d.ts +44 -0
  18. package/dist/adapters/gemini.d.ts.map +1 -0
  19. package/dist/adapters/gemini.js +262 -0
  20. package/dist/adapters/grok.d.ts +53 -0
  21. package/dist/adapters/grok.d.ts.map +1 -0
  22. package/dist/adapters/grok.js +232 -0
  23. package/dist/adapters/openai-compat.d.ts +80 -0
  24. package/dist/adapters/openai-compat.d.ts.map +1 -0
  25. package/dist/adapters/openai-compat.js +244 -0
  26. package/dist/adapters/openai-stream.d.ts +58 -0
  27. package/dist/adapters/openai-stream.d.ts.map +1 -0
  28. package/dist/adapters/openai-stream.js +120 -0
  29. package/dist/adapters/openai.d.ts +55 -0
  30. package/dist/adapters/openai.d.ts.map +1 -0
  31. package/dist/adapters/openai.js +281 -0
  32. package/dist/adapters/sampling.d.ts +28 -0
  33. package/dist/adapters/sampling.d.ts.map +1 -0
  34. package/dist/adapters/sampling.js +34 -0
  35. package/dist/adapters/tool-mapping.d.ts +92 -0
  36. package/dist/adapters/tool-mapping.d.ts.map +1 -0
  37. package/dist/adapters/tool-mapping.js +143 -0
  38. package/dist/artifacts/artifact.d.ts +137 -0
  39. package/dist/artifacts/artifact.d.ts.map +1 -0
  40. package/dist/artifacts/artifact.js +377 -0
  41. package/dist/artifacts/content-uploader.d.ts +87 -0
  42. package/dist/artifacts/content-uploader.d.ts.map +1 -0
  43. package/dist/artifacts/content-uploader.js +124 -0
  44. package/dist/artifacts/index.d.ts +63 -0
  45. package/dist/artifacts/index.d.ts.map +1 -0
  46. package/dist/artifacts/index.js +80 -0
  47. package/dist/artifacts/run-context.d.ts +129 -0
  48. package/dist/artifacts/run-context.d.ts.map +1 -0
  49. package/dist/artifacts/run-context.js +208 -0
  50. package/dist/artifacts/scrub.d.ts +60 -0
  51. package/dist/artifacts/scrub.d.ts.map +1 -0
  52. package/dist/artifacts/scrub.js +139 -0
  53. package/dist/artifacts/step.d.ts +26 -0
  54. package/dist/artifacts/step.d.ts.map +1 -0
  55. package/dist/artifacts/step.js +37 -0
  56. package/dist/artifacts/taint.d.ts +63 -0
  57. package/dist/artifacts/taint.d.ts.map +1 -0
  58. package/dist/artifacts/taint.js +76 -0
  59. package/dist/bakeoff/cache-sim.d.ts +99 -0
  60. package/dist/bakeoff/cache-sim.d.ts.map +1 -0
  61. package/dist/bakeoff/cache-sim.js +126 -0
  62. package/dist/bakeoff/engine.d.ts +52 -0
  63. package/dist/bakeoff/engine.d.ts.map +1 -0
  64. package/dist/bakeoff/engine.js +163 -0
  65. package/dist/bakeoff/eval-cases.d.ts +96 -0
  66. package/dist/bakeoff/eval-cases.d.ts.map +1 -0
  67. package/dist/bakeoff/eval-cases.js +105 -0
  68. package/dist/bakeoff/replay.d.ts +52 -0
  69. package/dist/bakeoff/replay.d.ts.map +1 -0
  70. package/dist/bakeoff/replay.js +94 -0
  71. package/dist/bakeoff/report.d.ts +41 -0
  72. package/dist/bakeoff/report.d.ts.map +1 -0
  73. package/dist/bakeoff/report.js +142 -0
  74. package/dist/bakeoff/samples.d.ts +77 -0
  75. package/dist/bakeoff/samples.d.ts.map +1 -0
  76. package/dist/bakeoff/samples.js +148 -0
  77. package/dist/bakeoff/stats.d.ts +13 -0
  78. package/dist/bakeoff/stats.d.ts.map +1 -0
  79. package/dist/bakeoff/stats.js +48 -0
  80. package/dist/bakeoff/types.d.ts +37 -0
  81. package/dist/bakeoff/types.d.ts.map +1 -0
  82. package/dist/bakeoff/types.js +10 -0
  83. package/dist/cli.d.ts +25 -0
  84. package/dist/cli.d.ts.map +1 -0
  85. package/dist/cli.js +590 -0
  86. package/dist/config.d.ts +204 -0
  87. package/dist/config.d.ts.map +1 -0
  88. package/dist/config.js +252 -0
  89. package/dist/deprecations.d.ts +32 -0
  90. package/dist/deprecations.d.ts.map +1 -0
  91. package/dist/deprecations.js +59 -0
  92. package/dist/feedback/coverage.d.ts +32 -0
  93. package/dist/feedback/coverage.d.ts.map +1 -0
  94. package/dist/feedback/coverage.js +95 -0
  95. package/dist/feedback/feedback.d.ts +35 -0
  96. package/dist/feedback/feedback.d.ts.map +1 -0
  97. package/dist/feedback/feedback.js +39 -0
  98. package/dist/gateway/http-protocol.d.ts +175 -0
  99. package/dist/gateway/http-protocol.d.ts.map +1 -0
  100. package/dist/gateway/http-protocol.js +105 -0
  101. package/dist/index.d.ts +242 -0
  102. package/dist/index.d.ts.map +1 -0
  103. package/dist/index.js +576 -0
  104. package/dist/init/finder.d.ts +94 -0
  105. package/dist/init/finder.d.ts.map +1 -0
  106. package/dist/init/finder.js +343 -0
  107. package/dist/init/init-cli.d.ts +10 -0
  108. package/dist/init/init-cli.d.ts.map +1 -0
  109. package/dist/init/init-cli.js +86 -0
  110. package/dist/init/observe-cli.d.ts +19 -0
  111. package/dist/init/observe-cli.d.ts.map +1 -0
  112. package/dist/init/observe-cli.js +73 -0
  113. package/dist/init/observe.d.ts +81 -0
  114. package/dist/init/observe.d.ts.map +1 -0
  115. package/dist/init/observe.js +245 -0
  116. package/dist/init/run.d.ts +99 -0
  117. package/dist/init/run.d.ts.map +1 -0
  118. package/dist/init/run.js +281 -0
  119. package/dist/init/signatures.d.ts +39 -0
  120. package/dist/init/signatures.d.ts.map +1 -0
  121. package/dist/init/signatures.js +116 -0
  122. package/dist/matrix/aggregate.d.ts +89 -0
  123. package/dist/matrix/aggregate.d.ts.map +1 -0
  124. package/dist/matrix/aggregate.js +186 -0
  125. package/dist/query/grammar.d.ts +35 -0
  126. package/dist/query/grammar.d.ts.map +1 -0
  127. package/dist/query/grammar.js +279 -0
  128. package/dist/query/run.d.ts +8 -0
  129. package/dist/query/run.d.ts.map +1 -0
  130. package/dist/query/run.js +21 -0
  131. package/dist/registry/build.d.ts +219 -0
  132. package/dist/registry/build.d.ts.map +1 -0
  133. package/dist/registry/build.js +313 -0
  134. package/dist/registry/cache-policy.d.ts +94 -0
  135. package/dist/registry/cache-policy.d.ts.map +1 -0
  136. package/dist/registry/cache-policy.js +238 -0
  137. package/dist/registry/call-notes.d.ts +11 -0
  138. package/dist/registry/call-notes.d.ts.map +1 -0
  139. package/dist/registry/call-notes.js +110 -0
  140. package/dist/registry/claims.d.ts +63 -0
  141. package/dist/registry/claims.d.ts.map +1 -0
  142. package/dist/registry/claims.js +107 -0
  143. package/dist/registry/effective-rate.d.ts +151 -0
  144. package/dist/registry/effective-rate.d.ts.map +1 -0
  145. package/dist/registry/effective-rate.js +156 -0
  146. package/dist/registry/facts.d.ts +32 -0
  147. package/dist/registry/facts.d.ts.map +1 -0
  148. package/dist/registry/facts.js +136 -0
  149. package/dist/registry/fingerprint.d.ts +20 -0
  150. package/dist/registry/fingerprint.d.ts.map +1 -0
  151. package/dist/registry/fingerprint.js +150 -0
  152. package/dist/registry/parity.d.ts +52 -0
  153. package/dist/registry/parity.d.ts.map +1 -0
  154. package/dist/registry/parity.js +82 -0
  155. package/dist/registry/pricing-shape.d.ts +113 -0
  156. package/dist/registry/pricing-shape.d.ts.map +1 -0
  157. package/dist/registry/pricing-shape.js +123 -0
  158. package/dist/registry/pricing.d.ts +43 -0
  159. package/dist/registry/pricing.d.ts.map +1 -0
  160. package/dist/registry/pricing.js +127 -0
  161. package/dist/registry/rows.d.ts +16 -0
  162. package/dist/registry/rows.d.ts.map +1 -0
  163. package/dist/registry/rows.js +57 -0
  164. package/dist/registry/seed.d.ts +43 -0
  165. package/dist/registry/seed.d.ts.map +1 -0
  166. package/dist/registry/seed.js +97 -0
  167. package/dist/registry/select.d.ts +68 -0
  168. package/dist/registry/select.d.ts.map +1 -0
  169. package/dist/registry/select.js +141 -0
  170. package/dist/registry/staleness.d.ts +18 -0
  171. package/dist/registry/staleness.d.ts.map +1 -0
  172. package/dist/registry/staleness.js +39 -0
  173. package/dist/rigindex/bootstrap.d.ts +36 -0
  174. package/dist/rigindex/bootstrap.d.ts.map +1 -0
  175. package/dist/rigindex/bootstrap.js +97 -0
  176. package/dist/rigindex/fit.d.ts +24 -0
  177. package/dist/rigindex/fit.d.ts.map +1 -0
  178. package/dist/rigindex/fit.js +76 -0
  179. package/dist/rigindex/gates.d.ts +52 -0
  180. package/dist/rigindex/gates.d.ts.map +1 -0
  181. package/dist/rigindex/gates.js +109 -0
  182. package/dist/rigindex/graph.d.ts +31 -0
  183. package/dist/rigindex/graph.d.ts.map +1 -0
  184. package/dist/rigindex/graph.js +120 -0
  185. package/dist/rigindex/index.d.ts +23 -0
  186. package/dist/rigindex/index.d.ts.map +1 -0
  187. package/dist/rigindex/index.js +112 -0
  188. package/dist/rigindex/types.d.ts +76 -0
  189. package/dist/rigindex/types.d.ts.map +1 -0
  190. package/dist/rigindex/types.js +8 -0
  191. package/dist/routes/cache-lint.d.ts +41 -0
  192. package/dist/routes/cache-lint.d.ts.map +1 -0
  193. package/dist/routes/cache-lint.js +81 -0
  194. package/dist/routes/draft.d.ts +83 -0
  195. package/dist/routes/draft.d.ts.map +1 -0
  196. package/dist/routes/draft.js +135 -0
  197. package/dist/routes/loader.d.ts +63 -0
  198. package/dist/routes/loader.d.ts.map +1 -0
  199. package/dist/routes/loader.js +574 -0
  200. package/dist/routes/manifest.d.ts +24 -0
  201. package/dist/routes/manifest.d.ts.map +1 -0
  202. package/dist/routes/manifest.js +118 -0
  203. package/dist/routes/resolved-bundle.d.ts +79 -0
  204. package/dist/routes/resolved-bundle.d.ts.map +1 -0
  205. package/dist/routes/resolved-bundle.js +148 -0
  206. package/dist/routes/sampling-config.d.ts +32 -0
  207. package/dist/routes/sampling-config.d.ts.map +1 -0
  208. package/dist/routes/sampling-config.js +91 -0
  209. package/dist/routes/serveability.d.ts +52 -0
  210. package/dist/routes/serveability.d.ts.map +1 -0
  211. package/dist/routes/serveability.js +73 -0
  212. package/dist/routes/template.d.ts +18 -0
  213. package/dist/routes/template.d.ts.map +1 -0
  214. package/dist/routes/template.js +94 -0
  215. package/dist/run/ajv.d.ts +22 -0
  216. package/dist/run/ajv.d.ts.map +1 -0
  217. package/dist/run/ajv.js +32 -0
  218. package/dist/run/cache-handle.d.ts +58 -0
  219. package/dist/run/cache-handle.d.ts.map +1 -0
  220. package/dist/run/cache-handle.js +54 -0
  221. package/dist/run/cache-stamp.d.ts +65 -0
  222. package/dist/run/cache-stamp.d.ts.map +1 -0
  223. package/dist/run/cache-stamp.js +0 -0
  224. package/dist/run/capture-write.d.ts +33 -0
  225. package/dist/run/capture-write.d.ts.map +1 -0
  226. package/dist/run/capture-write.js +55 -0
  227. package/dist/run/cost.d.ts +26 -0
  228. package/dist/run/cost.d.ts.map +1 -0
  229. package/dist/run/cost.js +41 -0
  230. package/dist/run/dispatch.d.ts +99 -0
  231. package/dist/run/dispatch.d.ts.map +1 -0
  232. package/dist/run/dispatch.js +191 -0
  233. package/dist/run/envelope.d.ts +21 -0
  234. package/dist/run/envelope.d.ts.map +1 -0
  235. package/dist/run/envelope.js +45 -0
  236. package/dist/run/grounding.d.ts +56 -0
  237. package/dist/run/grounding.d.ts.map +1 -0
  238. package/dist/run/grounding.js +89 -0
  239. package/dist/run/raw.d.ts +88 -0
  240. package/dist/run/raw.d.ts.map +1 -0
  241. package/dist/run/raw.js +286 -0
  242. package/dist/run/record-attempt.d.ts +40 -0
  243. package/dist/run/record-attempt.d.ts.map +1 -0
  244. package/dist/run/record-attempt.js +99 -0
  245. package/dist/run/repair.d.ts +36 -0
  246. package/dist/run/repair.d.ts.map +1 -0
  247. package/dist/run/repair.js +61 -0
  248. package/dist/run/resolve.d.ts +99 -0
  249. package/dist/run/resolve.d.ts.map +1 -0
  250. package/dist/run/resolve.js +203 -0
  251. package/dist/run/retry.d.ts +19 -0
  252. package/dist/run/retry.d.ts.map +1 -0
  253. package/dist/run/retry.js +50 -0
  254. package/dist/run/run.d.ts +55 -0
  255. package/dist/run/run.d.ts.map +1 -0
  256. package/dist/run/run.js +540 -0
  257. package/dist/run/stream.d.ts +49 -0
  258. package/dist/run/stream.d.ts.map +1 -0
  259. package/dist/run/stream.js +87 -0
  260. package/dist/run/validate.d.ts +15 -0
  261. package/dist/run/validate.d.ts.map +1 -0
  262. package/dist/run/validate.js +55 -0
  263. package/dist/savings/cache-ledger.d.ts +108 -0
  264. package/dist/savings/cache-ledger.d.ts.map +1 -0
  265. package/dist/savings/cache-ledger.js +174 -0
  266. package/dist/savings/cache-reconcile.d.ts +64 -0
  267. package/dist/savings/cache-reconcile.d.ts.map +1 -0
  268. package/dist/savings/cache-reconcile.js +59 -0
  269. package/dist/savings/cache-stats.d.ts +63 -0
  270. package/dist/savings/cache-stats.d.ts.map +1 -0
  271. package/dist/savings/cache-stats.js +108 -0
  272. package/dist/savings/emit.d.ts +38 -0
  273. package/dist/savings/emit.d.ts.map +1 -0
  274. package/dist/savings/emit.js +100 -0
  275. package/dist/savings/odometer.d.ts +32 -0
  276. package/dist/savings/odometer.d.ts.map +1 -0
  277. package/dist/savings/odometer.js +70 -0
  278. package/dist/savings/swap-execute.d.ts +58 -0
  279. package/dist/savings/swap-execute.d.ts.map +1 -0
  280. package/dist/savings/swap-execute.js +130 -0
  281. package/dist/savings/swaps-client.d.ts +55 -0
  282. package/dist/savings/swaps-client.d.ts.map +1 -0
  283. package/dist/savings/swaps-client.js +95 -0
  284. package/dist/settings/api-fetcher.d.ts +39 -0
  285. package/dist/settings/api-fetcher.d.ts.map +1 -0
  286. package/dist/settings/api-fetcher.js +92 -0
  287. package/dist/settings/index.d.ts +10 -0
  288. package/dist/settings/index.d.ts.map +1 -0
  289. package/dist/settings/index.js +15 -0
  290. package/dist/settings/task-settings.d.ts +91 -0
  291. package/dist/settings/task-settings.d.ts.map +1 -0
  292. package/dist/settings/task-settings.js +116 -0
  293. package/dist/status.d.ts +77 -0
  294. package/dist/status.d.ts.map +1 -0
  295. package/dist/status.js +113 -0
  296. package/dist/telemetry/artifact-store.d.ts +48 -0
  297. package/dist/telemetry/artifact-store.d.ts.map +1 -0
  298. package/dist/telemetry/artifact-store.js +189 -0
  299. package/dist/telemetry/cache-miss-streak.d.ts +79 -0
  300. package/dist/telemetry/cache-miss-streak.d.ts.map +1 -0
  301. package/dist/telemetry/cache-miss-streak.js +99 -0
  302. package/dist/telemetry/capture.d.ts +31 -0
  303. package/dist/telemetry/capture.d.ts.map +1 -0
  304. package/dist/telemetry/capture.js +81 -0
  305. package/dist/telemetry/exporter-setup.d.ts +28 -0
  306. package/dist/telemetry/exporter-setup.d.ts.map +1 -0
  307. package/dist/telemetry/exporter-setup.js +34 -0
  308. package/dist/telemetry/exporter.d.ts +137 -0
  309. package/dist/telemetry/exporter.d.ts.map +1 -0
  310. package/dist/telemetry/exporter.js +510 -0
  311. package/dist/telemetry/health.d.ts +76 -0
  312. package/dist/telemetry/health.d.ts.map +1 -0
  313. package/dist/telemetry/health.js +92 -0
  314. package/dist/telemetry/ingest-protocol.d.ts +310 -0
  315. package/dist/telemetry/ingest-protocol.d.ts.map +1 -0
  316. package/dist/telemetry/ingest-protocol.js +363 -0
  317. package/dist/telemetry/load-error-report.d.ts +24 -0
  318. package/dist/telemetry/load-error-report.d.ts.map +1 -0
  319. package/dist/telemetry/load-error-report.js +50 -0
  320. package/dist/telemetry/otel-map.d.ts +121 -0
  321. package/dist/telemetry/otel-map.d.ts.map +1 -0
  322. package/dist/telemetry/otel-map.js +224 -0
  323. package/dist/telemetry/otel-normalize.d.ts +104 -0
  324. package/dist/telemetry/otel-normalize.d.ts.map +1 -0
  325. package/dist/telemetry/otel-normalize.js +530 -0
  326. package/dist/telemetry/otlp-emitter.d.ts +52 -0
  327. package/dist/telemetry/otlp-emitter.d.ts.map +1 -0
  328. package/dist/telemetry/otlp-emitter.js +144 -0
  329. package/dist/telemetry/otlp-proto.d.ts +29 -0
  330. package/dist/telemetry/otlp-proto.d.ts.map +1 -0
  331. package/dist/telemetry/otlp-proto.js +266 -0
  332. package/dist/telemetry/sinks.d.ts +90 -0
  333. package/dist/telemetry/sinks.d.ts.map +1 -0
  334. package/dist/telemetry/sinks.js +180 -0
  335. package/dist/telemetry/store.d.ts +65 -0
  336. package/dist/telemetry/store.d.ts.map +1 -0
  337. package/dist/telemetry/store.js +547 -0
  338. package/dist/tenancy/api-key-format.d.ts +77 -0
  339. package/dist/tenancy/api-key-format.d.ts.map +1 -0
  340. package/dist/tenancy/api-key-format.js +110 -0
  341. package/dist/tenancy/constants.d.ts +23 -0
  342. package/dist/tenancy/constants.d.ts.map +1 -0
  343. package/dist/tenancy/constants.js +25 -0
  344. package/dist/tenancy/scrub.d.ts +47 -0
  345. package/dist/tenancy/scrub.d.ts.map +1 -0
  346. package/dist/tenancy/scrub.js +85 -0
  347. package/dist/types/config-teaching.d.ts +62 -0
  348. package/dist/types/config-teaching.d.ts.map +1 -0
  349. package/dist/types/config-teaching.js +183 -0
  350. package/dist/types/failures-teaching.d.ts +56 -0
  351. package/dist/types/failures-teaching.d.ts.map +1 -0
  352. package/dist/types/failures-teaching.js +177 -0
  353. package/dist/types/failures.d.ts +27 -0
  354. package/dist/types/failures.d.ts.map +1 -0
  355. package/dist/types/failures.js +41 -0
  356. package/dist/types/provider.d.ts +200 -0
  357. package/dist/types/provider.d.ts.map +1 -0
  358. package/dist/types/provider.js +40 -0
  359. package/dist/types/route.d.ts +205 -0
  360. package/dist/types/route.d.ts.map +1 -0
  361. package/dist/types/route.js +6 -0
  362. package/dist/types/telemetry.d.ts +206 -0
  363. package/dist/types/telemetry.d.ts.map +1 -0
  364. package/dist/types/telemetry.js +6 -0
  365. package/dist/validate-cli.d.ts +12 -0
  366. package/dist/validate-cli.d.ts.map +1 -0
  367. package/dist/validate-cli.js +57 -0
  368. package/dist/verify/capture.d.ts +66 -0
  369. package/dist/verify/capture.d.ts.map +1 -0
  370. package/dist/verify/capture.js +180 -0
  371. package/dist/verify/cli-run.d.ts +23 -0
  372. package/dist/verify/cli-run.d.ts.map +1 -0
  373. package/dist/verify/cli-run.js +57 -0
  374. package/dist/verify/diff.d.ts +48 -0
  375. package/dist/verify/diff.d.ts.map +1 -0
  376. package/dist/verify/diff.js +157 -0
  377. package/dist/verify/index.d.ts +17 -0
  378. package/dist/verify/index.d.ts.map +1 -0
  379. package/dist/verify/index.js +24 -0
  380. package/dist/verify/report.d.ts +14 -0
  381. package/dist/verify/report.d.ts.map +1 -0
  382. package/dist/verify/report.js +88 -0
  383. package/dist/verify/types.d.ts +101 -0
  384. package/dist/verify/types.d.ts.map +1 -0
  385. package/dist/verify/types.js +17 -0
  386. package/dist/verify/verify.d.ts +29 -0
  387. package/dist/verify/verify.d.ts.map +1 -0
  388. package/dist/verify/verify.js +148 -0
  389. package/dist/watch/budget.d.ts +19 -0
  390. package/dist/watch/budget.d.ts.map +1 -0
  391. package/dist/watch/budget.js +35 -0
  392. package/dist/watch/evaluate.d.ts +225 -0
  393. package/dist/watch/evaluate.d.ts.map +1 -0
  394. package/dist/watch/evaluate.js +155 -0
  395. package/dist/watch/monitor.d.ts +116 -0
  396. package/dist/watch/monitor.d.ts.map +1 -0
  397. package/dist/watch/monitor.js +199 -0
  398. package/dist/watch/proposals.d.ts +89 -0
  399. package/dist/watch/proposals.d.ts.map +1 -0
  400. package/dist/watch/proposals.js +197 -0
  401. package/dist/watch/run-record.d.ts +64 -0
  402. package/dist/watch/run-record.d.ts.map +1 -0
  403. package/dist/watch/run-record.js +86 -0
  404. package/dist/watch/run-reported.d.ts +20 -0
  405. package/dist/watch/run-reported.d.ts.map +1 -0
  406. package/dist/watch/run-reported.js +53 -0
  407. package/dist/watch/run.d.ts +73 -0
  408. package/dist/watch/run.d.ts.map +1 -0
  409. package/dist/watch/run.js +83 -0
  410. package/dist/watch/state-store.d.ts +48 -0
  411. package/dist/watch/state-store.d.ts.map +1 -0
  412. package/dist/watch/state-store.js +86 -0
  413. package/dist/watch/state.d.ts +21 -0
  414. package/dist/watch/state.d.ts.map +1 -0
  415. package/dist/watch/state.js +93 -0
  416. package/package.json +56 -14
  417. package/registry/LICENSE +20 -0
  418. package/registry/leaderboard.json +3639 -0
  419. package/registry/registry.json +7263 -0
  420. package/index.js +0 -3
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ /**
3
+ * Watch diff-evaluators — Phase 4 WS1 (plan §4). Pure: no store, no
4
+ * network, no clock beyond the expiry stamp. Two event classes:
5
+ *
6
+ * price_change — a candidate's pricing moved; when the blended cost shift
7
+ * clears the threshold (default ±10%), every route declaring that
8
+ * candidate gets a suggested bake-off proposal.
9
+ * new_model — a new pricing-map entry on a provider a route already
10
+ * uses → suggested bake-off (the re-probe/bake-off run IS the evidence
11
+ * step; the proposal never claims conformance it hasn't measured).
12
+ *
13
+ * Proposals NEVER execute anything. Idempotency: the trigger hash is a
14
+ * stable digest of (route, trigger content) — re-running a watch cycle over
15
+ * the same facts produces the same hashes, and the control-plane unique
16
+ * index (route, trigger_hash) makes duplicates a no-op.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.PROPOSAL_TTL_DAYS = void 0;
20
+ exports.triggerHash = triggerHash;
21
+ exports.evaluateEvents = evaluateEvents;
22
+ exports.buildCacheContext = buildCacheContext;
23
+ exports.explainCacheContext = explainCacheContext;
24
+ const node_crypto_1 = require("node:crypto");
25
+ const effective_rate_1 = require("../registry/effective-rate");
26
+ exports.PROPOSAL_TTL_DAYS = 30;
27
+ /** Reference token mix for blending input/output rates into one comparable
28
+ * number: 3 input tokens per output token — a conservative, route-agnostic
29
+ * default (schema-bound analysis routes run input-heavy). */
30
+ const BLEND_IN = 3;
31
+ const BLEND_OUT = 1;
32
+ function blended(rates) {
33
+ return rates.inputUsdPerTok * BLEND_IN + rates.outputUsdPerTok * BLEND_OUT;
34
+ }
35
+ function triggerHash(route, trigger) {
36
+ return (0, node_crypto_1.createHash)("sha256").update(`${route}\n${JSON.stringify(trigger)}`).digest("hex").slice(0, 32);
37
+ }
38
+ function expiryStamp() {
39
+ return new Date(Date.now() + exports.PROPOSAL_TTL_DAYS * 24 * 3600 * 1000).toISOString();
40
+ }
41
+ function evaluateEvents(routes, events, config) {
42
+ const drafts = [];
43
+ for (const event of events) {
44
+ if (event.type === "price_change") {
45
+ const before = blended(event.old);
46
+ if (before <= 0)
47
+ continue; // nothing sane to compare against
48
+ const deltaPct = ((blended(event.new) - before) / before) * 100;
49
+ if (Math.abs(deltaPct) < config.thresholdPct)
50
+ continue;
51
+ const trigger = {
52
+ type: "price_change",
53
+ provider: event.provider,
54
+ model: event.model,
55
+ deltaPct,
56
+ oldRates: event.old,
57
+ newRates: event.new,
58
+ };
59
+ for (const route of routes) {
60
+ if (!route.candidates.some((c) => c.provider === event.provider && c.model === event.model)) {
61
+ continue;
62
+ }
63
+ drafts.push({
64
+ route: route.route,
65
+ kind: "bakeoff",
66
+ trigger,
67
+ triggerHash: triggerHash(route.route, trigger),
68
+ expiresAt: expiryStamp(),
69
+ });
70
+ }
71
+ }
72
+ else {
73
+ const trigger = {
74
+ type: "new_model",
75
+ provider: event.provider,
76
+ model: event.model,
77
+ pricing: event.pricing,
78
+ };
79
+ for (const route of routes) {
80
+ if (!route.candidates.some((c) => c.provider === event.provider))
81
+ continue;
82
+ // A model the route already declares is not "new" for it.
83
+ if (route.candidates.some((c) => c.provider === event.provider && c.model === event.model)) {
84
+ continue;
85
+ }
86
+ drafts.push({
87
+ route: route.route,
88
+ kind: "bakeoff",
89
+ trigger,
90
+ triggerHash: triggerHash(route.route, trigger),
91
+ expiresAt: expiryStamp(),
92
+ });
93
+ }
94
+ }
95
+ }
96
+ return drafts;
97
+ }
98
+ const PER_MTOK = 1e6;
99
+ /**
100
+ * Assemble the `cache_context` evidence block + verdict for a proposal (spec
101
+ * §5.5), pure. The verdict compares the incumbent's cache-ADJUSTED effective
102
+ * input rate against the challenger's COLD list rate, amortized over the switch
103
+ * cost, and gates on the hysteresis config. The advantage is measured PER
104
+ * CACHED PREFIX (the tokens the decision actually turns on), so a per-call
105
+ * dollar figure is directly comparable to the floor.
106
+ */
107
+ function buildCacheContext(input, config = effective_rate_1.DEFAULT_CACHE_HYSTERESIS) {
108
+ const incumbentEff = (0, effective_rate_1.effectiveInputRate)(input.observed, input.incumbentRates);
109
+ const challengerCold = input.challengerRates.input;
110
+ // Switch cost of leaving the warm incumbent for the cold challenger, and the
111
+ // per-call saving the incumbent's warmth is worth (spec §4.2–4.3).
112
+ const switch_cost_usd = (0, effective_rate_1.switchCostUsd)(input.incumbentPrefixTokens, input.challengerRates, input.incumbentRates);
113
+ const perCallSaving = (0, effective_rate_1.perCallCacheSavingsUsd)(input.incumbentPrefixTokens, input.observed.h, input.incumbentRates);
114
+ const cache_option_value_usd = (0, effective_rate_1.cacheOptionValueUsd)(input.remainingCalls, perCallSaving);
115
+ const breakeven_conformant_calls = (0, effective_rate_1.breakevenCalls)(switch_cost_usd, perCallSaving);
116
+ // The cache-adjusted per-call advantage of the challenger over the incumbent,
117
+ // on the cached prefix: (incumbent effective − challenger cold) per prefix
118
+ // token, times the prefix. Positive ⇒ the cold challenger is still cheaper.
119
+ const perCallAdvantageUsd = (incumbentEff - challengerCold) * input.incumbentPrefixTokens;
120
+ const totalAdvantageUsd = perCallAdvantageUsd * Math.max(input.remainingCalls, 0);
121
+ const verdict = (0, effective_rate_1.classifyCacheVerdict)({
122
+ hasCacheSignal: input.hasCacheSignal,
123
+ perCallAdvantageUsd,
124
+ totalAdvantageUsd,
125
+ windowSpendUsd: input.windowSpendUsd,
126
+ }, config);
127
+ return {
128
+ observed_hit_rate: input.observed.h,
129
+ observed_write_rate: input.observed.w,
130
+ window_days: input.windowDays,
131
+ incumbent_effective_in_per_mtok: incumbentEff * PER_MTOK,
132
+ challenger_cold_in_per_mtok: challengerCold * PER_MTOK,
133
+ switch_cost_usd,
134
+ cache_option_value_usd,
135
+ breakeven_conformant_calls,
136
+ verdict,
137
+ };
138
+ }
139
+ /**
140
+ * The [Briefing §30] rendered explanation — one prose line a human reads on the
141
+ * console and the `swap execute` approval prompt. Single-sourced here so the
142
+ * console, the CLI, and the OTLP span never phrase the same decision three ways.
143
+ */
144
+ function explainCacheContext(ctx, incumbentLabel, challengerLabel) {
145
+ const warmMtok = ctx.incumbent_effective_in_per_mtok.toFixed(2);
146
+ const coldMtok = ctx.challenger_cold_in_per_mtok.toFixed(2);
147
+ const hit = `${(ctx.observed_hit_rate * 100).toFixed(0)}%`;
148
+ const breakeven = Number.isFinite(ctx.breakeven_conformant_calls)
149
+ ? `breaks even after ${Math.ceil(ctx.breakeven_conformant_calls)} calls`
150
+ : "never breaks even";
151
+ return (`${incumbentLabel} is warm (${hit} hit rate, effective $${warmMtok}/Mtok in); ` +
152
+ `${challengerLabel} is nominally cheaper but cold ($${coldMtok}/Mtok in). ` +
153
+ `Switching costs $${ctx.switch_cost_usd.toFixed(4)} and ${breakeven}. ` +
154
+ `Verdict: ${ctx.verdict}.`);
155
+ }
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Monitor v1 — conform-rate degradation → bake-off proposal (Expansion E4 chunk B).
3
+ *
4
+ * The watch loop reacts to PRICE moves; the Monitor reacts to QUALITY moves. It
5
+ * rolls up the deterministic-eval conform rate per (org, task) into a daily
6
+ * series, and when a recent window falls below the trailing baseline by a ruled
7
+ * margin — with enough evaluations on BOTH sides to trust the number — it emits
8
+ * ONE `proposals` row (kind='bakeoff') asking for a re-evaluation. It reuses the
9
+ * ENTIRE existing proposals machinery: same table, same kind, same
10
+ * (route, trigger_hash) idempotency, same human-approval gate. No new proposal
11
+ * kind, no auto-actuation — the swap gate is untouched (spec §3.2).
12
+ *
13
+ * ── MEASURED-ONLY DOCTRINE ────────────────────────────────────────────────
14
+ * A degradation is proposed only from DETERMINISTIC evaluations (evaluator_kind
15
+ * = 'deterministic' — no model-judge softness), and only when BOTH windows clear
16
+ * `MONITOR_MIN_N`. Below that the rate is too noisy to act on: two failures can
17
+ * swing a small sample past the margin, and the house rule is to refuse rather
18
+ * than propose on thin data.
19
+ */
20
+ import type { ProposalDraft } from "./evaluate";
21
+ /** The recent window whose conformance we judge. A week smooths daily noise
22
+ * while staying responsive to a regression that just landed. */
23
+ export declare const MONITOR_WINDOW_DAYS = 7;
24
+ /** The trailing baseline the window is compared against — the 28 days
25
+ * immediately BEFORE the window (non-overlapping). Four weeks is a stable
26
+ * reference that predates a week-old regression; it matches the proposal TTL
27
+ * cadence, so a baseline never silently includes an unresolved degradation. */
28
+ export declare const MONITOR_BASELINE_DAYS = 28;
29
+ /** The drop, in percentage POINTS of conform rate, that flags a degradation.
30
+ * Mirrors the watch loop's ±10% material-shift threshold — one house number for
31
+ * "materially worse" — so the two loops speak the same language. */
32
+ export declare const MONITOR_MARGIN_PTS = 10;
33
+ /** Minimum deterministic evaluations required in EACH window before the rate is
34
+ * trustworthy enough to propose on (measured-only). */
35
+ export declare const MONITOR_MIN_N = 20;
36
+ export interface MonitorConfig {
37
+ readonly windowDays: number;
38
+ readonly baselineDays: number;
39
+ readonly marginPts: number;
40
+ readonly minN: number;
41
+ }
42
+ export declare const DEFAULT_MONITOR_CONFIG: MonitorConfig;
43
+ /** One day's deterministic-eval counts for a task. `conformN` ≤ `n`. */
44
+ export interface ConformDay {
45
+ readonly date: string;
46
+ readonly n: number;
47
+ readonly conformN: number;
48
+ }
49
+ export interface TaskConformSeries {
50
+ readonly task: string;
51
+ readonly days: readonly ConformDay[];
52
+ }
53
+ /** A single deterministic evaluation row for the rollup (server read shape). */
54
+ export interface EvalRollupRow {
55
+ readonly artifactId: string;
56
+ readonly passed: boolean | null;
57
+ readonly createdAt: string;
58
+ }
59
+ /**
60
+ * Roll deterministic-eval rows up into per-(task) daily conform counts. The
61
+ * task comes from `taskByArtifact` (the caller joins artifacts→task locally,
62
+ * since artifact_evaluations carries only artifact_id). Rows whose artifact has
63
+ * no known task, or whose `passed` is null (not a pass/fail eval), are dropped.
64
+ */
65
+ export declare function rollupConformRate(rows: readonly EvalRollupRow[], taskByArtifact: ReadonlyMap<string, string>): TaskConformSeries[];
66
+ /**
67
+ * The degradation rule (measured-only). For each task, compare the recent
68
+ * window to the trailing baseline; emit a bake-off draft when the drop clears
69
+ * the margin AND both windows clear min-n. Deterministic over `now` (passed in,
70
+ * never read from the clock) so the fixture test is reproducible. The
71
+ * trigger_hash keys on the task + both window bounds, so re-running the SAME
72
+ * day is a no-op (the (route, trigger_hash) unique index dedupes it).
73
+ */
74
+ export declare function evaluateConformDegradation(series: readonly TaskConformSeries[], now: Date, config?: MonitorConfig): ProposalDraft[];
75
+ /**
76
+ * The reads a Monitor cycle needs, injected so the orchestrator is testable
77
+ * without a database. BOTH must be scoped to ONE org (the rollup groups by task
78
+ * within that scope — cross-org tasks sharing a name must never merge): a
79
+ * hosted cron iterates orgs, a self-host has exactly one.
80
+ */
81
+ export interface MonitorReads {
82
+ /** Deterministic artifact evaluations created at/after `sinceIso`. */
83
+ readonly recentDeterministicEvals: (sinceIso: string) => Promise<readonly EvalRollupRow[]>;
84
+ /** task for each of the given artifact ids (the rollup join — artifact_evaluations
85
+ * carries only artifact_id). Only the ids that actually have evals are asked
86
+ * for, so the read stays bounded regardless of total artifact count. */
87
+ readonly taskFor: (artifactIds: readonly string[]) => Promise<ReadonlyMap<string, string>>;
88
+ }
89
+ export interface MonitorCycleResult {
90
+ readonly series: TaskConformSeries[];
91
+ readonly drafts: ProposalDraft[];
92
+ /** How many proposals the control plane actually created (0 when duplicates). */
93
+ readonly inserted: number;
94
+ }
95
+ /**
96
+ * One Monitor cycle: read the recent deterministic evals + task map, roll up,
97
+ * apply the degradation rule, and submit any drafts through the EXISTING
98
+ * proposals client (idempotent on (route, trigger_hash)). Returns the series +
99
+ * drafts + inserted count so a caller/CLI can report without a second query.
100
+ * Never actuates — submitting a proposal is the whole of its authority (§3.2).
101
+ */
102
+ export declare function runMonitorCycle(reads: MonitorReads, submitDrafts: (drafts: readonly ProposalDraft[]) => Promise<number>, now: Date, config?: MonitorConfig): Promise<MonitorCycleResult>;
103
+ export interface MonitorReadsConfig {
104
+ readonly supabaseUrl: string;
105
+ readonly serviceRoleKey: string;
106
+ /** The org this cycle runs for — reads are org-scoped so tasks never merge
107
+ * across tenants. A hosted cron iterates orgs; a self-host has exactly one. */
108
+ readonly orgId: string;
109
+ readonly fetchFn?: typeof fetch;
110
+ }
111
+ /** PostgREST reads for a Monitor cycle (service role; mirrors the proposals
112
+ * client). Two org-scoped queries, joined in-SDK by `runMonitorCycle` — no DDL,
113
+ * no view (spec §3.1). `taskFor` batches ids ≤100 (T9 — PostgREST URLs fail
114
+ * silently around 8KB). */
115
+ export declare function createMonitorReads(config: MonitorReadsConfig): MonitorReads;
116
+ //# sourceMappingURL=monitor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitor.d.ts","sourceRoot":"","sources":["../../src/watch/monitor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAA4C,aAAa,EAAE,MAAM,YAAY,CAAC;AAG1F;gEACgE;AAChE,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC;;;+EAG+E;AAC/E,eAAO,MAAM,qBAAqB,KAAK,CAAC;AACxC;;oEAEoE;AACpE,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC;uDACuD;AACvD,eAAO,MAAM,aAAa,KAAK,CAAC;AAEhC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,sBAAsB,EAAE,aAKpC,CAAC;AAEF,wEAAwE;AACxE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,UAAU,EAAE,CAAC;CACtC;AAED,gFAAgF;AAChF,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAYD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,SAAS,aAAa,EAAE,EAC9B,cAAc,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAC1C,iBAAiB,EAAE,CA0BrB;AAeD;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,SAAS,iBAAiB,EAAE,EACpC,GAAG,EAAE,IAAI,EACT,MAAM,GAAE,aAAsC,GAC7C,aAAa,EAAE,CAgCjB;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,sEAAsE;IACtE,QAAQ,CAAC,wBAAwB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,aAAa,EAAE,CAAC,CAAC;IAC3F;;4EAEwE;IACxE,QAAQ,CAAC,OAAO,EAAE,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC5F;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC;IACjC,iFAAiF;IACjF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,YAAY,EACnB,YAAY,EAAE,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,EACnE,GAAG,EAAE,IAAI,EACT,MAAM,GAAE,aAAsC,GAC7C,OAAO,CAAC,kBAAkB,CAAC,CAU7B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC;mFAC+E;IAC/E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACjC;AAYD;;;2BAG2B;AAC3B,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,YAAY,CA6B3E"}
@@ -0,0 +1,199 @@
1
+ "use strict";
2
+ /**
3
+ * Monitor v1 — conform-rate degradation → bake-off proposal (Expansion E4 chunk B).
4
+ *
5
+ * The watch loop reacts to PRICE moves; the Monitor reacts to QUALITY moves. It
6
+ * rolls up the deterministic-eval conform rate per (org, task) into a daily
7
+ * series, and when a recent window falls below the trailing baseline by a ruled
8
+ * margin — with enough evaluations on BOTH sides to trust the number — it emits
9
+ * ONE `proposals` row (kind='bakeoff') asking for a re-evaluation. It reuses the
10
+ * ENTIRE existing proposals machinery: same table, same kind, same
11
+ * (route, trigger_hash) idempotency, same human-approval gate. No new proposal
12
+ * kind, no auto-actuation — the swap gate is untouched (spec §3.2).
13
+ *
14
+ * ── MEASURED-ONLY DOCTRINE ────────────────────────────────────────────────
15
+ * A degradation is proposed only from DETERMINISTIC evaluations (evaluator_kind
16
+ * = 'deterministic' — no model-judge softness), and only when BOTH windows clear
17
+ * `MONITOR_MIN_N`. Below that the rate is too noisy to act on: two failures can
18
+ * swing a small sample past the margin, and the house rule is to refuse rather
19
+ * than propose on thin data.
20
+ */
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.DEFAULT_MONITOR_CONFIG = exports.MONITOR_MIN_N = exports.MONITOR_MARGIN_PTS = exports.MONITOR_BASELINE_DAYS = exports.MONITOR_WINDOW_DAYS = void 0;
23
+ exports.rollupConformRate = rollupConformRate;
24
+ exports.evaluateConformDegradation = evaluateConformDegradation;
25
+ exports.runMonitorCycle = runMonitorCycle;
26
+ exports.createMonitorReads = createMonitorReads;
27
+ const evaluate_1 = require("./evaluate");
28
+ /** The recent window whose conformance we judge. A week smooths daily noise
29
+ * while staying responsive to a regression that just landed. */
30
+ exports.MONITOR_WINDOW_DAYS = 7;
31
+ /** The trailing baseline the window is compared against — the 28 days
32
+ * immediately BEFORE the window (non-overlapping). Four weeks is a stable
33
+ * reference that predates a week-old regression; it matches the proposal TTL
34
+ * cadence, so a baseline never silently includes an unresolved degradation. */
35
+ exports.MONITOR_BASELINE_DAYS = 28;
36
+ /** The drop, in percentage POINTS of conform rate, that flags a degradation.
37
+ * Mirrors the watch loop's ±10% material-shift threshold — one house number for
38
+ * "materially worse" — so the two loops speak the same language. */
39
+ exports.MONITOR_MARGIN_PTS = 10;
40
+ /** Minimum deterministic evaluations required in EACH window before the rate is
41
+ * trustworthy enough to propose on (measured-only). */
42
+ exports.MONITOR_MIN_N = 20;
43
+ exports.DEFAULT_MONITOR_CONFIG = {
44
+ windowDays: exports.MONITOR_WINDOW_DAYS,
45
+ baselineDays: exports.MONITOR_BASELINE_DAYS,
46
+ marginPts: exports.MONITOR_MARGIN_PTS,
47
+ minN: exports.MONITOR_MIN_N,
48
+ };
49
+ /** ISO day (YYYY-MM-DD) of a timestamp. */
50
+ function dayOf(iso) {
51
+ return iso.slice(0, 10);
52
+ }
53
+ /** N days before `d`, as a YYYY-MM-DD day string. */
54
+ function dayMinus(d, days) {
55
+ return new Date(d.getTime() - days * 86400000).toISOString().slice(0, 10);
56
+ }
57
+ /**
58
+ * Roll deterministic-eval rows up into per-(task) daily conform counts. The
59
+ * task comes from `taskByArtifact` (the caller joins artifacts→task locally,
60
+ * since artifact_evaluations carries only artifact_id). Rows whose artifact has
61
+ * no known task, or whose `passed` is null (not a pass/fail eval), are dropped.
62
+ */
63
+ function rollupConformRate(rows, taskByArtifact) {
64
+ // task → day → {n, conformN}
65
+ const byTask = new Map();
66
+ for (const r of rows) {
67
+ if (r.passed === null)
68
+ continue;
69
+ const task = taskByArtifact.get(r.artifactId);
70
+ if (task === undefined)
71
+ continue;
72
+ const day = dayOf(r.createdAt);
73
+ let days = byTask.get(task);
74
+ if (days === undefined) {
75
+ days = new Map();
76
+ byTask.set(task, days);
77
+ }
78
+ const cell = days.get(day) ?? { n: 0, conformN: 0 };
79
+ cell.n += 1;
80
+ if (r.passed)
81
+ cell.conformN += 1;
82
+ days.set(day, cell);
83
+ }
84
+ return [...byTask.entries()]
85
+ .map(([task, days]) => ({
86
+ task,
87
+ days: [...days.entries()]
88
+ .map(([date, c]) => ({ date, n: c.n, conformN: c.conformN }))
89
+ .sort((a, b) => (a.date < b.date ? -1 : a.date > b.date ? 1 : 0)),
90
+ }))
91
+ .sort((a, b) => (a.task < b.task ? -1 : a.task > b.task ? 1 : 0));
92
+ }
93
+ /** Aggregate the days whose date is in [from, to) into one window. */
94
+ function windowOf(days, from, to) {
95
+ let n = 0;
96
+ let conformN = 0;
97
+ for (const d of days) {
98
+ if (d.date >= from && d.date < to) {
99
+ n += d.n;
100
+ conformN += d.conformN;
101
+ }
102
+ }
103
+ return { from, to, n, conformRate: n > 0 ? conformN / n : 0 };
104
+ }
105
+ /**
106
+ * The degradation rule (measured-only). For each task, compare the recent
107
+ * window to the trailing baseline; emit a bake-off draft when the drop clears
108
+ * the margin AND both windows clear min-n. Deterministic over `now` (passed in,
109
+ * never read from the clock) so the fixture test is reproducible. The
110
+ * trigger_hash keys on the task + both window bounds, so re-running the SAME
111
+ * day is a no-op (the (route, trigger_hash) unique index dedupes it).
112
+ */
113
+ function evaluateConformDegradation(series, now, config = exports.DEFAULT_MONITOR_CONFIG) {
114
+ const windowFrom = dayMinus(now, config.windowDays);
115
+ const windowTo = dayMinus(now, 0);
116
+ const baselineFrom = dayMinus(now, config.windowDays + config.baselineDays);
117
+ const baselineTo = windowFrom;
118
+ const expiresAt = new Date(now.getTime() + evaluate_1.PROPOSAL_TTL_DAYS * 86400000).toISOString();
119
+ const drafts = [];
120
+ for (const s of series) {
121
+ const window = windowOf(s.days, windowFrom, windowTo);
122
+ const baseline = windowOf(s.days, baselineFrom, baselineTo);
123
+ if (window.n < config.minN || baseline.n < config.minN)
124
+ continue; // thin data → refuse
125
+ const dropPts = (baseline.conformRate - window.conformRate) * 100;
126
+ if (dropPts < config.marginPts)
127
+ continue; // not materially worse
128
+ const trigger = {
129
+ type: "conform_degradation",
130
+ task: s.task,
131
+ window,
132
+ baseline,
133
+ dropPts,
134
+ marginPts: config.marginPts,
135
+ minN: config.minN,
136
+ };
137
+ drafts.push({
138
+ route: s.task,
139
+ kind: "bakeoff",
140
+ trigger,
141
+ triggerHash: (0, evaluate_1.triggerHash)(s.task, trigger),
142
+ expiresAt,
143
+ });
144
+ }
145
+ return drafts;
146
+ }
147
+ /**
148
+ * One Monitor cycle: read the recent deterministic evals + task map, roll up,
149
+ * apply the degradation rule, and submit any drafts through the EXISTING
150
+ * proposals client (idempotent on (route, trigger_hash)). Returns the series +
151
+ * drafts + inserted count so a caller/CLI can report without a second query.
152
+ * Never actuates — submitting a proposal is the whole of its authority (§3.2).
153
+ */
154
+ async function runMonitorCycle(reads, submitDrafts, now, config = exports.DEFAULT_MONITOR_CONFIG) {
155
+ const sinceMs = now.getTime() - (config.windowDays + config.baselineDays) * 86400000;
156
+ const sinceIso = new Date(sinceMs).toISOString();
157
+ const rows = await reads.recentDeterministicEvals(sinceIso);
158
+ const ids = [...new Set(rows.map((r) => r.artifactId))];
159
+ const tasks = ids.length > 0 ? await reads.taskFor(ids) : new Map();
160
+ const series = rollupConformRate(rows, tasks);
161
+ const drafts = evaluateConformDegradation(series, now, config);
162
+ const inserted = drafts.length > 0 ? await submitDrafts(drafts) : 0;
163
+ return { series, drafts, inserted };
164
+ }
165
+ /** PostgREST reads for a Monitor cycle (service role; mirrors the proposals
166
+ * client). Two org-scoped queries, joined in-SDK by `runMonitorCycle` — no DDL,
167
+ * no view (spec §3.1). `taskFor` batches ids ≤100 (T9 — PostgREST URLs fail
168
+ * silently around 8KB). */
169
+ function createMonitorReads(config) {
170
+ const base = config.supabaseUrl.replace(/\/$/, "");
171
+ const fetchFn = config.fetchFn ?? fetch;
172
+ const org = encodeURIComponent(config.orgId);
173
+ async function get(path) {
174
+ const res = await fetchFn(`${base}/rest/v1/${path}`, {
175
+ headers: { apikey: config.serviceRoleKey, authorization: `Bearer ${config.serviceRoleKey}` },
176
+ });
177
+ if (!res.ok)
178
+ throw new Error(`monitor read ${path} → ${res.status} ${await res.text().catch(() => "")}`);
179
+ return (await res.json().catch(() => []));
180
+ }
181
+ return {
182
+ async recentDeterministicEvals(sinceIso) {
183
+ const rows = await get(`artifact_evaluations?select=artifact_id,passed,created_at&org_id=eq.${org}` +
184
+ `&evaluator_kind=eq.deterministic&created_at=gte.${encodeURIComponent(sinceIso)}`);
185
+ return rows.map((r) => ({ artifactId: r.artifact_id, passed: r.passed, createdAt: r.created_at }));
186
+ },
187
+ async taskFor(artifactIds) {
188
+ const out = new Map();
189
+ for (let i = 0; i < artifactIds.length; i += 100) {
190
+ const batch = artifactIds.slice(i, i + 100).map(encodeURIComponent).join(",");
191
+ const rows = await get(`artifacts?select=id,task&org_id=eq.${org}&id=in.(${batch})`);
192
+ for (const r of rows)
193
+ if (r.task !== null)
194
+ out.set(r.id, r.task);
195
+ }
196
+ return out;
197
+ },
198
+ };
199
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Proposal lifecycle + control-plane client — Phase 4 WS1 (plan §4).
3
+ *
4
+ * suggested → evidenced (bake-off attached)
5
+ * → approved (human, recorded) → executed (swap machinery)
6
+ * suggested|evidenced → rejected | expired
7
+ *
8
+ * Proposals NEVER auto-execute: "executed" is only reachable through
9
+ * "approved", and approval is a human CLI action (`swap execute --approve`).
10
+ * Transport is PostgREST with the service-role key — proposals are
11
+ * control-plane-only state (cross-run truth, not per-inference telemetry).
12
+ */
13
+ import type { ProposalDraft, ProposalKind, ProposalTrigger } from "./evaluate";
14
+ export type ProposalStatus = "suggested" | "evidenced" | "approved" | "rejected" | "executed" | "expired";
15
+ export declare function assertTransition(from: ProposalStatus, to: ProposalStatus): void;
16
+ export interface ProposalRecord {
17
+ readonly id: string;
18
+ readonly route: string;
19
+ readonly kind: ProposalKind;
20
+ readonly trigger: ProposalTrigger;
21
+ readonly triggerHash: string;
22
+ readonly evidence: Record<string, unknown> | null;
23
+ readonly status: ProposalStatus;
24
+ readonly createdAt: string;
25
+ readonly updatedAt: string;
26
+ readonly expiresAt: string;
27
+ /** Who approved or rejected (A1.2). Null while undecided. */
28
+ readonly approvedBy: string | null;
29
+ /** When the decision was recorded — NOT when a swap executed. */
30
+ readonly decidedAt: string | null;
31
+ }
32
+ export interface ProposalsClientConfig {
33
+ readonly supabaseUrl: string;
34
+ readonly serviceRoleKey: string;
35
+ /**
36
+ * The tenant this client writes for. When set (the multi-tenant hosted cron —
37
+ * managed-loop §2), `submitDrafts` STAMPS every row with this org and dedupes
38
+ * against the real `(org_id, route, trigger_hash)` unique index, and
39
+ * `expireOverdue` sweeps only THIS org's rows. When omitted (the CLI /
40
+ * self-host lane) behaviour is unchanged: `org_id` falls to its house-org
41
+ * column default and one deployment sweeps its own single tenant. Omitting it
42
+ * on a hosted cron would file every org's proposals under the house org — the
43
+ * whole reason this field exists. Reads keyed by id (`get`/`orgOf`/`decide`)
44
+ * are org-agnostic and unaffected; `list` already takes its org as a param.
45
+ */
46
+ readonly orgId?: string;
47
+ readonly fetchFn?: typeof fetch;
48
+ }
49
+ export interface ProposalsClient {
50
+ /** Insert drafts; duplicates on (route, trigger_hash) are silent no-ops.
51
+ * Returns how many rows the control plane actually created. */
52
+ submitDrafts(drafts: readonly ProposalDraft[]): Promise<number>;
53
+ /**
54
+ * List proposals for ONE org, or across all of them.
55
+ *
56
+ * `orgId` is required and `null` is the explicit "every org" case, used by
57
+ * the CLI and by self-host deployments where there is exactly one. An
58
+ * OPTIONAL parameter would have been the same code with a worse failure
59
+ * mode: the unscoped read this replaces was unscoped because nobody passed
60
+ * anything, and an omitted argument reads as an oversight while an explicit
61
+ * null reads as a decision (C6 review ruling §7.2).
62
+ */
63
+ list(orgId: string | null, status?: ProposalStatus): Promise<ProposalRecord[]>;
64
+ get(id: string): Promise<ProposalRecord | null>;
65
+ /** Bake-off evidence + the suggested→evidenced flip, one status-scoped PATCH.
66
+ * Only a proposal still OPEN to evidence (suggested, or evidenced being
67
+ * re-run) matches — a terminal proposal (approved/executed/rejected/expired)
68
+ * matches zero rows, so evidence can never resurrect it. Returns false when
69
+ * nothing matched (already moved on), like `decide`. */
70
+ attachEvidence(id: string, evidence: Record<string, unknown>): Promise<boolean>;
71
+ /** Validated status change (assertTransition is the caller's guard for
72
+ * reads-before-writes; the PATCH is still status-scoped server-side). */
73
+ setStatus(id: string, from: ProposalStatus, to: ProposalStatus): Promise<void>;
74
+ /** A HUMAN decision on a proposal — addendum A1.2. Records who decided and
75
+ * when alongside the status flip, in one status-scoped PATCH.
76
+ *
77
+ * Approving is NOT executing: this writes a decision, never a swap_event.
78
+ * The swap still happens at a CLI (`modelrig swap execute --approve`) and
79
+ * the YAML it emits is still applied by git. Returns false when the row had
80
+ * already moved on (a concurrent decision), so the caller can say so
81
+ * instead of reporting a success that did not happen. */
82
+ /** The org that owns this proposal — the tenant a write must be authorized against. */
83
+ orgOf(id: string): Promise<string | null>;
84
+ decide(id: string, from: ProposalStatus, to: "approved" | "rejected", decidedBy: string, decidedByUserId?: string | null, orgId?: string): Promise<boolean>;
85
+ /** One sweep: overdue suggested/evidenced → expired. */
86
+ expireOverdue(now: Date): Promise<void>;
87
+ }
88
+ export declare function createProposalsClient(config: ProposalsClientConfig): ProposalsClient;
89
+ //# sourceMappingURL=proposals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proposals.d.ts","sourceRoot":"","sources":["../../src/watch/proposals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE/E,MAAM,MAAM,cAAc,GACtB,WAAW,GACX,WAAW,GACX,UAAU,GACV,UAAU,GACV,UAAU,GACV,SAAS,CAAC;AAWd,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,cAAc,GAAG,IAAI,CAO/E;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAClD,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,6DAA6D;IAC7D,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,iEAAiE;IACjE,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAkCD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACjC;AAED,MAAM,WAAW,eAAe;IAC9B;mEAC+D;IAC/D,YAAY,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChE;;;;;;;;;OASG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAC/E,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAChD;;;;4DAIwD;IACxD,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAChF;6EACyE;IACzE,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E;;;;;;;6DAOyD;IACzD,uFAAuF;IACvF,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC1C,MAAM,CACJ,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,cAAc,EACpB,EAAE,EAAE,UAAU,GAAG,UAAU,EAC3B,SAAS,EAAE,MAAM,EACjB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,EAC/B,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,wDAAwD;IACxD,aAAa,CAAC,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzC;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,eAAe,CAuLpF"}