niceeval 0.13.3 → 0.13.4-canary.39

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 (487) hide show
  1. package/INDEX.md +5 -5
  2. package/dist/agents/index.cjs +2 -2
  3. package/dist/agents/index.cjs.map +1 -1
  4. package/dist/agents/project.json +6 -0
  5. package/dist/agents/streaming.cjs.map +1 -1
  6. package/dist/agents/types.cjs.map +1 -1
  7. package/dist/agents/types.d.cts +1 -1
  8. package/dist/agents/types.d.mts +1 -1
  9. package/dist/agents/types.d.ts +1 -1
  10. package/dist/analysis/bindings.d.cts +8 -8
  11. package/dist/analysis/bindings.d.mts +8 -8
  12. package/dist/analysis/bindings.d.ts +8 -8
  13. package/dist/analysis/contracts.cjs.map +1 -1
  14. package/dist/analysis/contracts.d.cts +8 -19
  15. package/dist/analysis/contracts.d.mts +8 -19
  16. package/dist/analysis/contracts.d.ts +8 -19
  17. package/dist/analysis/experiment-groups.cjs +7 -14
  18. package/dist/analysis/experiment-groups.cjs.map +1 -1
  19. package/dist/analysis/index.cjs.map +1 -1
  20. package/dist/analysis/index.d.cts +1 -1
  21. package/dist/analysis/index.d.mts +1 -1
  22. package/dist/analysis/index.d.ts +1 -1
  23. package/dist/cli/application.cjs +4 -13
  24. package/dist/cli/application.cjs.map +1 -1
  25. package/dist/cli/application.d.cts +62 -59
  26. package/dist/cli/application.d.mts +62 -59
  27. package/dist/cli/application.d.ts +62 -59
  28. package/dist/cli/application.js +6 -12
  29. package/dist/cli/bootstrap.cjs +28 -2
  30. package/dist/cli/bootstrap.cjs.map +1 -1
  31. package/dist/cli/contribution.cjs +185 -0
  32. package/dist/cli/contribution.cjs.map +1 -0
  33. package/dist/cli/contribution.d.cts +55 -0
  34. package/dist/cli/contribution.d.mts +55 -0
  35. package/dist/cli/contribution.d.ts +55 -0
  36. package/dist/cli/contribution.js +20 -0
  37. package/dist/cli/contribution.js.map +1 -0
  38. package/dist/cli/node-application.cjs +119 -87
  39. package/dist/cli/node-application.cjs.map +1 -1
  40. package/dist/cli/node-application.d.cts +2 -8
  41. package/dist/cli/node-application.d.mts +2 -8
  42. package/dist/cli/node-application.d.ts +2 -8
  43. package/dist/cli/node-application.js +12 -22
  44. package/dist/cli/program.cjs +87 -2756
  45. package/dist/cli/program.cjs.map +1 -1
  46. package/dist/cli/program.d.cts +11 -332
  47. package/dist/cli/program.d.mts +11 -332
  48. package/dist/cli/program.d.ts +11 -332
  49. package/dist/cli/program.js +4 -28
  50. package/dist/cli.cjs +0 -3
  51. package/dist/cli.cjs.map +1 -1
  52. package/dist/cli.d.cts +0 -1
  53. package/dist/cli.d.mts +0 -1
  54. package/dist/cli.d.ts +0 -1
  55. package/dist/cli.js +6 -14
  56. package/dist/define.cjs +1 -1
  57. package/dist/define.cjs.map +1 -1
  58. package/dist/docker/cache-administration.cjs +8 -0
  59. package/dist/docker/cache-administration.cjs.map +1 -0
  60. package/dist/docker/cache-administration.d.cts +33 -0
  61. package/dist/docker/cache-administration.d.mts +33 -0
  62. package/dist/docker/cache-administration.d.ts +33 -0
  63. package/dist/docker/cache-administration.js +6 -0
  64. package/dist/docker/cache-administration.js.map +1 -0
  65. package/dist/docker/cache-live.cjs +27 -0
  66. package/dist/docker/cache-live.cjs.map +1 -0
  67. package/dist/docker/cache-live.d.cts +3 -0
  68. package/dist/docker/cache-live.d.mts +3 -0
  69. package/dist/docker/cache-live.d.ts +3 -0
  70. package/dist/docker/cache-live.js +6 -0
  71. package/dist/docker/cache-live.js.map +1 -0
  72. package/dist/docker/cli/contribution.cjs +223 -0
  73. package/dist/docker/cli/contribution.cjs.map +1 -0
  74. package/dist/docker/cli/contribution.d.cts +48 -0
  75. package/dist/docker/cli/contribution.d.mts +48 -0
  76. package/dist/docker/cli/contribution.d.ts +48 -0
  77. package/dist/docker/cli/contribution.js +8 -0
  78. package/dist/docker/cli/contribution.js.map +1 -0
  79. package/dist/eval/cli/contribution.cjs +62 -0
  80. package/dist/eval/cli/contribution.cjs.map +1 -0
  81. package/dist/eval/cli/contribution.d.cts +21 -0
  82. package/dist/eval/cli/contribution.d.mts +21 -0
  83. package/dist/eval/cli/contribution.d.ts +21 -0
  84. package/dist/eval/cli/contribution.js +8 -0
  85. package/dist/eval/cli/contribution.js.map +1 -0
  86. package/dist/eval/host/index.cjs +23 -0
  87. package/dist/eval/host/index.cjs.map +1 -0
  88. package/dist/eval/host/index.d.cts +27 -0
  89. package/dist/eval/host/index.d.mts +27 -0
  90. package/dist/eval/host/index.d.ts +27 -0
  91. package/dist/eval/host/index.js +8 -0
  92. package/dist/eval/host/index.js.map +1 -0
  93. package/dist/eval/host/index.mjs +8 -0
  94. package/dist/eval/host/index.mjs.map +1 -0
  95. package/dist/experiment/host/cli/contribution.cjs +835 -0
  96. package/dist/experiment/host/cli/contribution.cjs.map +1 -0
  97. package/dist/experiment/host/cli/contribution.d.cts +329 -0
  98. package/dist/experiment/host/cli/contribution.d.mts +329 -0
  99. package/dist/experiment/host/cli/contribution.d.ts +329 -0
  100. package/dist/experiment/host/cli/contribution.js +22 -0
  101. package/dist/experiment/host/cli/contribution.js.map +1 -0
  102. package/dist/experiment/host/cli/index.cjs +9 -0
  103. package/dist/experiment/host/cli/index.cjs.map +1 -0
  104. package/dist/experiment/host/cli/index.d.cts +2 -0
  105. package/dist/experiment/host/cli/index.d.mts +2 -0
  106. package/dist/experiment/host/cli/index.d.ts +2 -0
  107. package/dist/experiment/host/cli/index.js +10 -0
  108. package/dist/experiment/host/cli/index.js.map +1 -0
  109. package/dist/experiment/host/cli/terminal.cjs +15 -0
  110. package/dist/experiment/host/cli/terminal.cjs.map +1 -0
  111. package/dist/experiment/host/cli/terminal.d.cts +14 -0
  112. package/dist/experiment/host/cli/terminal.d.mts +14 -0
  113. package/dist/experiment/host/cli/terminal.d.ts +14 -0
  114. package/dist/experiment/host/cli/terminal.js +8 -0
  115. package/dist/experiment/host/cli/terminal.js.map +1 -0
  116. package/dist/experiment/host/index.cjs +35 -58
  117. package/dist/experiment/host/index.cjs.map +1 -1
  118. package/dist/experiment/host/index.d.cts +5 -79
  119. package/dist/experiment/host/index.d.mts +5 -79
  120. package/dist/experiment/host/index.d.ts +5 -79
  121. package/dist/experiment/host/index.js +4 -2
  122. package/dist/experiment/host/index.mjs +4 -2
  123. package/dist/experiment/host/operations.cjs +678 -0
  124. package/dist/experiment/host/operations.cjs.map +1 -0
  125. package/dist/experiment/host/operations.d.cts +19 -0
  126. package/dist/experiment/host/operations.d.mts +19 -0
  127. package/dist/experiment/host/operations.d.ts +19 -0
  128. package/dist/experiment/host/operations.js +24 -0
  129. package/dist/experiment/host/operations.js.map +1 -0
  130. package/dist/experiment/host/presentation.cjs +81 -0
  131. package/dist/experiment/host/presentation.cjs.map +1 -0
  132. package/dist/experiment/host/presentation.d.cts +9 -0
  133. package/dist/experiment/host/presentation.d.mts +9 -0
  134. package/dist/experiment/host/presentation.d.ts +9 -0
  135. package/dist/experiment/host/presentation.js +8 -0
  136. package/dist/experiment/host/presentation.js.map +1 -0
  137. package/dist/experiment/host/teardown.cjs +394 -0
  138. package/dist/experiment/host/teardown.cjs.map +1 -0
  139. package/dist/experiment/host/teardown.d.cts +5 -0
  140. package/dist/experiment/host/teardown.d.mts +5 -0
  141. package/dist/experiment/host/teardown.d.ts +5 -0
  142. package/dist/experiment/host/teardown.js +8 -0
  143. package/dist/experiment/host/teardown.js.map +1 -0
  144. package/dist/experiment/host/types.cjs +9 -0
  145. package/dist/experiment/host/types.cjs.map +1 -0
  146. package/dist/experiment/host/types.d.cts +423 -0
  147. package/dist/experiment/host/types.d.mts +423 -0
  148. package/dist/experiment/host/types.d.ts +423 -0
  149. package/dist/experiment/host/types.js +6 -0
  150. package/dist/experiment/host/types.js.map +1 -0
  151. package/dist/i18n/en.cjs +8 -50
  152. package/dist/i18n/en.cjs.map +1 -1
  153. package/dist/i18n/en.d.cts +2 -6
  154. package/dist/i18n/en.d.mts +2 -6
  155. package/dist/i18n/en.d.ts +2 -6
  156. package/dist/o11y/project.json +6 -0
  157. package/dist/project/cli/contribution.cjs +66 -0
  158. package/dist/project/cli/contribution.cjs.map +1 -0
  159. package/dist/project/cli/contribution.d.cts +17 -0
  160. package/dist/project/cli/contribution.d.mts +17 -0
  161. package/dist/project/cli/contribution.d.ts +17 -0
  162. package/dist/project/cli/contribution.js +8 -0
  163. package/dist/project/cli/contribution.js.map +1 -0
  164. package/dist/project/cli/index.cjs +7 -0
  165. package/dist/project/cli/index.cjs.map +1 -0
  166. package/dist/project/cli/index.d.cts +1 -0
  167. package/dist/project/cli/index.d.mts +1 -0
  168. package/dist/project/cli/index.d.ts +1 -0
  169. package/dist/project/cli/index.js +8 -0
  170. package/dist/project/cli/index.js.map +1 -0
  171. package/dist/project/host/index.cjs +11 -0
  172. package/dist/project/host/index.cjs.map +1 -0
  173. package/dist/project/host/index.d.cts +4 -0
  174. package/dist/project/host/index.d.mts +4 -0
  175. package/dist/project/host/index.d.ts +4 -0
  176. package/dist/project/host/index.js +14 -0
  177. package/dist/project/host/index.js.map +1 -0
  178. package/dist/project/host/index.mjs +14 -0
  179. package/dist/project/host/index.mjs.map +1 -0
  180. package/dist/project/host.cjs +59 -0
  181. package/dist/project/host.cjs.map +1 -0
  182. package/dist/project/host.d.cts +17 -0
  183. package/dist/project/host.d.mts +17 -0
  184. package/dist/project/host.d.ts +17 -0
  185. package/dist/project/host.js +6 -0
  186. package/dist/project/host.js.map +1 -0
  187. package/dist/project/index.cjs +11 -0
  188. package/dist/project/index.cjs.map +1 -0
  189. package/dist/project/index.d.cts +4 -0
  190. package/dist/project/index.d.mts +4 -0
  191. package/dist/project/index.d.ts +4 -0
  192. package/dist/project/index.js +14 -0
  193. package/dist/project/index.js.map +1 -0
  194. package/dist/project/node.cjs +91 -0
  195. package/dist/project/node.cjs.map +1 -0
  196. package/dist/project/node.d.cts +6 -0
  197. package/dist/project/node.d.mts +6 -0
  198. package/dist/project/node.d.ts +6 -0
  199. package/dist/project/node.js +12 -0
  200. package/dist/project/node.js.map +1 -0
  201. package/dist/project/services.cjs +17 -0
  202. package/dist/project/services.cjs.map +1 -0
  203. package/dist/project/services.d.cts +47 -0
  204. package/dist/project/services.d.mts +47 -0
  205. package/dist/project/services.d.ts +47 -0
  206. package/dist/project/services.js +12 -0
  207. package/dist/project/services.js.map +1 -0
  208. package/dist/project/templates.cjs +28 -0
  209. package/dist/project/templates.cjs.map +1 -0
  210. package/dist/project/templates.d.cts +4 -0
  211. package/dist/project/templates.d.mts +4 -0
  212. package/dist/project/templates.d.ts +4 -0
  213. package/dist/project/templates.js +12 -0
  214. package/dist/project/templates.js.map +1 -0
  215. package/dist/project.json +6 -0
  216. package/dist/record/family/catalog.d.cts +10 -10
  217. package/dist/record/family/catalog.d.mts +10 -10
  218. package/dist/record/family/catalog.d.ts +10 -10
  219. package/dist/record/family/file-changes.d.cts +8 -8
  220. package/dist/record/family/file-changes.d.mts +8 -8
  221. package/dist/record/family/file-changes.d.ts +8 -8
  222. package/dist/record/host/cli/contribution.cjs +206 -0
  223. package/dist/record/host/cli/contribution.cjs.map +1 -0
  224. package/dist/record/host/cli/contribution.d.cts +32 -0
  225. package/dist/record/host/cli/contribution.d.mts +32 -0
  226. package/dist/record/host/cli/contribution.d.ts +32 -0
  227. package/dist/record/host/cli/contribution.js +10 -0
  228. package/dist/record/host/cli/contribution.js.map +1 -0
  229. package/dist/record/host/cli/index.cjs +8 -0
  230. package/dist/record/host/cli/index.cjs.map +1 -0
  231. package/dist/record/host/cli/index.d.cts +1 -0
  232. package/dist/record/host/cli/index.d.mts +1 -0
  233. package/dist/record/host/cli/index.d.ts +1 -0
  234. package/dist/record/host/cli/index.js +10 -0
  235. package/dist/record/host/cli/index.js.map +1 -0
  236. package/dist/record/host/cli/presentation.cjs +122 -0
  237. package/dist/record/host/cli/presentation.cjs.map +1 -0
  238. package/dist/record/host/cli/presentation.d.cts +7 -0
  239. package/dist/record/host/cli/presentation.d.mts +7 -0
  240. package/dist/record/host/cli/presentation.d.ts +7 -0
  241. package/dist/record/host/cli/presentation.js +12 -0
  242. package/dist/record/host/cli/presentation.js.map +1 -0
  243. package/dist/record/host/index.cjs.map +1 -1
  244. package/dist/record/host/index.d.cts +1 -1
  245. package/dist/record/host/index.d.mts +1 -1
  246. package/dist/record/host/index.d.ts +1 -1
  247. package/dist/record/host/runtime.cjs +184 -1
  248. package/dist/record/host/runtime.cjs.map +1 -1
  249. package/dist/record/host/types.cjs.map +1 -1
  250. package/dist/record/host/types.d.cts +120 -0
  251. package/dist/record/host/types.d.mts +120 -0
  252. package/dist/record/host/types.d.ts +120 -0
  253. package/dist/record/project.json +6 -0
  254. package/dist/report/assets/styles.css +80 -0
  255. package/dist/report/cli/contribution.cjs +325 -0
  256. package/dist/report/cli/contribution.cjs.map +1 -0
  257. package/dist/report/cli/contribution.d.cts +143 -0
  258. package/dist/report/cli/contribution.d.mts +143 -0
  259. package/dist/report/cli/contribution.d.ts +143 -0
  260. package/dist/report/cli/contribution.js +12 -0
  261. package/dist/report/cli/contribution.js.map +1 -0
  262. package/dist/report/client-dist/app.js +9 -9
  263. package/dist/report/components/attempt-detail/content.cjs +1 -1
  264. package/dist/report/components/attempt-detail/content.cjs.map +1 -1
  265. package/dist/report/components/entity-lists/compute.cjs +5 -0
  266. package/dist/report/components/entity-lists/compute.cjs.map +1 -1
  267. package/dist/report/components/entity-lists/compute.d.cts +2 -0
  268. package/dist/report/components/entity-lists/compute.d.mts +2 -0
  269. package/dist/report/components/entity-lists/compute.d.ts +2 -0
  270. package/dist/report/components/entity-lists/content.cjs +35 -12
  271. package/dist/report/components/entity-lists/content.cjs.map +1 -1
  272. package/dist/report/components/entity-lists/index.cjs +0 -3
  273. package/dist/report/components/entity-lists/index.cjs.map +1 -1
  274. package/dist/report/components/summaries/index.cjs +2 -4
  275. package/dist/report/components/summaries/index.cjs.map +1 -1
  276. package/dist/report/definition/cell.cjs +7 -2
  277. package/dist/report/definition/cell.cjs.map +1 -1
  278. package/dist/report/definition/cell.d.cts +2 -0
  279. package/dist/report/definition/cell.d.mts +2 -0
  280. package/dist/report/definition/cell.d.ts +2 -0
  281. package/dist/report/definition/primitives/assertion-evidence.cjs +190 -4
  282. package/dist/report/definition/primitives/assertion-evidence.cjs.map +1 -1
  283. package/dist/report/definition/primitives/assertion-evidence.d.cts +4 -0
  284. package/dist/report/definition/primitives/assertion-evidence.d.mts +4 -0
  285. package/dist/report/definition/primitives/assertion-evidence.d.ts +4 -0
  286. package/dist/report/execution/machine.cjs +2 -3
  287. package/dist/report/execution/machine.cjs.map +1 -1
  288. package/dist/report/execution/machine.d.cts +11 -8
  289. package/dist/report/execution/machine.d.mts +11 -8
  290. package/dist/report/execution/machine.d.ts +11 -8
  291. package/dist/report/host/from-record.cjs +13 -8
  292. package/dist/report/host/from-record.cjs.map +1 -1
  293. package/dist/report/host/index.cjs +5 -1
  294. package/dist/report/host/index.cjs.map +1 -1
  295. package/dist/report/host/index.d.cts +1 -0
  296. package/dist/report/host/index.d.mts +1 -0
  297. package/dist/report/host/index.d.ts +1 -0
  298. package/dist/report/host/index.js +8 -2
  299. package/dist/report/host/index.mjs +8 -2
  300. package/dist/report/host/machine.cjs +23 -22
  301. package/dist/report/host/machine.cjs.map +1 -1
  302. package/dist/report/host/machine.d.cts +1 -1
  303. package/dist/report/host/machine.d.mts +1 -1
  304. package/dist/report/host/machine.d.ts +1 -1
  305. package/dist/report/host/node/loader.cjs +4 -2
  306. package/dist/report/host/node/loader.cjs.map +1 -1
  307. package/dist/report/host/node/loader.d.cts +3 -1
  308. package/dist/report/host/node/loader.d.mts +3 -1
  309. package/dist/report/host/node/loader.d.ts +3 -1
  310. package/dist/report/host/node.cjs +44 -9
  311. package/dist/report/host/node.cjs.map +1 -1
  312. package/dist/report/host/node.d.cts +13 -3
  313. package/dist/report/host/node.d.mts +13 -3
  314. package/dist/report/host/node.d.ts +13 -3
  315. package/dist/report/host/node.js +44 -32
  316. package/dist/report/host/operations.cjs +14 -0
  317. package/dist/report/host/operations.cjs.map +1 -0
  318. package/dist/report/host/operations.d.cts +39 -0
  319. package/dist/report/host/operations.d.mts +39 -0
  320. package/dist/report/host/operations.d.ts +39 -0
  321. package/dist/report/host/operations.js +10 -0
  322. package/dist/report/host/operations.js.map +1 -0
  323. package/dist/report/model/chart/plot.cjs +1 -1
  324. package/dist/report/model/chart/plot.cjs.map +1 -1
  325. package/dist/report/model/locale.cjs +4 -0
  326. package/dist/report/model/locale.cjs.map +1 -1
  327. package/dist/report/model/locale.d.cts +3 -1
  328. package/dist/report/model/locale.d.mts +3 -1
  329. package/dist/report/model/locale.d.ts +3 -1
  330. package/dist/report/react/styles.css +80 -0
  331. package/dist/runner/build-preparation.cjs +5 -5
  332. package/dist/runner/build-preparation.cjs.map +1 -1
  333. package/dist/runner/build-preparation.d.cts +2 -3
  334. package/dist/runner/build-preparation.d.mts +2 -3
  335. package/dist/runner/build-preparation.d.ts +2 -3
  336. package/dist/runner/feedback/coordinator.cjs +18 -15
  337. package/dist/runner/feedback/coordinator.cjs.map +1 -1
  338. package/dist/runner/feedback/coordinator.d.cts +6 -0
  339. package/dist/runner/feedback/coordinator.d.mts +6 -0
  340. package/dist/runner/feedback/coordinator.d.ts +6 -0
  341. package/dist/runner/ledger.cjs +3 -13
  342. package/dist/runner/ledger.cjs.map +1 -1
  343. package/dist/runner/ledger.d.cts +1 -3
  344. package/dist/runner/ledger.d.mts +1 -3
  345. package/dist/runner/ledger.d.ts +1 -3
  346. package/dist/runner/run.cjs +63 -18
  347. package/dist/runner/run.cjs.map +1 -1
  348. package/dist/runner/session.cjs +10 -0
  349. package/dist/runner/session.cjs.map +1 -1
  350. package/dist/runner/session.d.cts +25 -0
  351. package/dist/runner/session.d.mts +25 -0
  352. package/dist/runner/session.d.ts +25 -0
  353. package/dist/runner/types.cjs.map +1 -1
  354. package/dist/runner/types.d.cts +1 -2
  355. package/dist/runner/types.d.mts +1 -2
  356. package/dist/runner/types.d.ts +1 -2
  357. package/dist/sandbox/build-coordinator.cjs +38 -19
  358. package/dist/sandbox/build-coordinator.cjs.map +1 -1
  359. package/dist/sandbox/build-coordinator.d.cts +47 -7
  360. package/dist/sandbox/build-coordinator.d.mts +47 -7
  361. package/dist/sandbox/build-coordinator.d.ts +47 -7
  362. package/dist/sandbox/build-coordinator.js +8 -4
  363. package/dist/sandbox/cli/contribution.cjs +128 -0
  364. package/dist/sandbox/cli/contribution.cjs.map +1 -0
  365. package/dist/sandbox/cli/contribution.d.cts +71 -0
  366. package/dist/sandbox/cli/contribution.d.mts +71 -0
  367. package/dist/sandbox/cli/contribution.d.ts +71 -0
  368. package/dist/sandbox/cli/contribution.js +8 -0
  369. package/dist/sandbox/cli/contribution.js.map +1 -0
  370. package/dist/sandbox/cli-commands.cjs +14 -21
  371. package/dist/sandbox/cli-commands.cjs.map +1 -1
  372. package/dist/sandbox/cli-commands.d.cts +12 -8
  373. package/dist/sandbox/cli-commands.d.mts +12 -8
  374. package/dist/sandbox/cli-commands.d.ts +12 -8
  375. package/dist/sandbox/compose.cjs +22 -2
  376. package/dist/sandbox/compose.cjs.map +1 -1
  377. package/dist/sandbox/compose.d.cts +1 -1
  378. package/dist/sandbox/compose.d.mts +1 -1
  379. package/dist/sandbox/compose.d.ts +1 -1
  380. package/dist/sandbox/docker-profile/cli.cjs +13 -9
  381. package/dist/sandbox/docker-profile/cli.cjs.map +1 -1
  382. package/dist/sandbox/docker-profile/cli.d.cts +2 -0
  383. package/dist/sandbox/docker-profile/cli.d.mts +2 -0
  384. package/dist/sandbox/docker-profile/cli.d.ts +2 -0
  385. package/dist/sandbox/docker-profile/runtime.cjs +68 -7
  386. package/dist/sandbox/docker-profile/runtime.cjs.map +1 -1
  387. package/dist/sandbox/docker-profile/runtime.d.cts +19 -1
  388. package/dist/sandbox/docker-profile/runtime.d.mts +19 -1
  389. package/dist/sandbox/docker-profile/runtime.d.ts +19 -1
  390. package/dist/sandbox/docker-profile/runtime.js +10 -8
  391. package/dist/sandbox/docker-profile/schema.cjs +68 -19
  392. package/dist/sandbox/docker-profile/schema.cjs.map +1 -1
  393. package/dist/sandbox/docker-profile/schema.d.cts +23 -9
  394. package/dist/sandbox/docker-profile/schema.d.mts +23 -9
  395. package/dist/sandbox/docker-profile/schema.d.ts +23 -9
  396. package/dist/sandbox/docker-task-build-cache.cjs +532 -0
  397. package/dist/sandbox/docker-task-build-cache.cjs.map +1 -0
  398. package/dist/sandbox/docker-task-build-cache.d.cts +68 -0
  399. package/dist/sandbox/docker-task-build-cache.d.mts +68 -0
  400. package/dist/sandbox/docker-task-build-cache.d.ts +68 -0
  401. package/dist/sandbox/docker-task-build-cache.js +20 -0
  402. package/dist/sandbox/docker-task-build-cache.js.map +1 -0
  403. package/dist/sandbox/docker.cjs +50 -0
  404. package/dist/sandbox/docker.cjs.map +1 -1
  405. package/dist/sandbox/docker.d.cts +15 -0
  406. package/dist/sandbox/docker.d.mts +15 -0
  407. package/dist/sandbox/docker.d.ts +15 -0
  408. package/dist/sandbox/dockerfile-build.cjs +55 -5
  409. package/dist/sandbox/dockerfile-build.cjs.map +1 -1
  410. package/dist/sandbox/dockerfile-build.d.cts +2 -2
  411. package/dist/sandbox/dockerfile-build.d.mts +2 -2
  412. package/dist/sandbox/dockerfile-build.d.ts +2 -2
  413. package/dist/sandbox/index.cjs +5 -3
  414. package/dist/sandbox/index.cjs.map +1 -1
  415. package/dist/sandbox/index.d.cts +4 -3
  416. package/dist/sandbox/index.d.mts +4 -3
  417. package/dist/sandbox/index.d.ts +4 -3
  418. package/dist/sandbox/index.js +16 -14
  419. package/dist/sandbox/index.mjs +16 -14
  420. package/dist/sandbox/keep.cjs +1 -3
  421. package/dist/sandbox/keep.cjs.map +1 -1
  422. package/dist/sandbox/layer.cjs +70 -79
  423. package/dist/sandbox/layer.cjs.map +1 -1
  424. package/dist/sandbox/layer.d.cts +6 -12
  425. package/dist/sandbox/layer.d.mts +6 -12
  426. package/dist/sandbox/layer.d.ts +6 -12
  427. package/dist/sandbox/layer.js +16 -18
  428. package/dist/sandbox/ledger-paths.cjs +4 -18
  429. package/dist/sandbox/ledger-paths.cjs.map +1 -1
  430. package/dist/sandbox/ledger-paths.d.cts +3 -13
  431. package/dist/sandbox/ledger-paths.d.mts +3 -13
  432. package/dist/sandbox/ledger-paths.d.ts +3 -13
  433. package/dist/sandbox/ledger-paths.js +4 -8
  434. package/dist/sandbox/registry.cjs +1 -1
  435. package/dist/sandbox/registry.cjs.map +1 -1
  436. package/dist/sandbox/runtime.cjs +27 -37
  437. package/dist/sandbox/runtime.cjs.map +1 -1
  438. package/dist/sandbox/runtime.d.cts +1 -2
  439. package/dist/sandbox/runtime.d.mts +1 -2
  440. package/dist/sandbox/runtime.d.ts +1 -2
  441. package/dist/sandbox/runtime.js +6 -8
  442. package/dist/sandbox/types.cjs.map +1 -1
  443. package/dist/sandbox/types.d.cts +3 -3
  444. package/dist/sandbox/types.d.mts +3 -3
  445. package/dist/sandbox/types.d.ts +3 -3
  446. package/dist/sources/project.json +6 -0
  447. package/dist/vendor/remark/remark-gfm.cjs +72 -72
  448. package/dist/vendor/remark/remark-gfm.cjs.map +1 -1
  449. package/dist/vendor/remark/remark-parse.cjs +54 -54
  450. package/dist/vendor/remark/remark-parse.cjs.map +1 -1
  451. package/dist/vendor/remark/remark.cjs +125 -125
  452. package/dist/vendor/remark/remark.cjs.map +2 -2
  453. package/docs-site/zh/README.md +1 -1
  454. package/docs-site/zh/explanation/assert.mdx +4 -0
  455. package/docs-site/zh/explanation/judge.mdx +40 -9
  456. package/docs-site/zh/reference/cli.mdx +67 -43
  457. package/docs-site/zh/reference/define-agent.mdx +2 -2
  458. package/docs-site/zh/reference/report-components.mdx +4 -3
  459. package/docs-site/zh/troubleshooting/debug-sandbox.mdx +6 -0
  460. package/docs-site/zh/troubleshooting/debugging.mdx +28 -1
  461. package/docs-site/zh/tutorials/agent-feedback-loop.mdx +4 -2
  462. package/docs-site/zh/tutorials/concurrency.mdx +2 -2
  463. package/docs-site/zh/tutorials/custom-reports.mdx +175 -9
  464. package/docs-site/zh/tutorials/docker-in-docker.mdx +52 -7
  465. package/docs-site/zh/tutorials/eval-groups.mdx +1 -2
  466. package/docs-site/zh/tutorials/evaluation-kinds.mdx +39 -6
  467. package/docs-site/zh/tutorials/nixos-managed-dind.mdx +14 -5
  468. package/docs-site/zh/tutorials/sandbox-providers.mdx +1 -28
  469. package/docs-site/zh/tutorials/sandbox-reuse.mdx +1 -1
  470. package/docs-site/zh/tutorials/viewing-results.mdx +2 -0
  471. package/package.json +24 -19
  472. package/README.md +0 -176
  473. package/README.zh.md +0 -176
  474. package/dist/cli/record.cjs +0 -246
  475. package/dist/cli/record.cjs.map +0 -1
  476. package/dist/cli/record.d.cts +0 -40
  477. package/dist/cli/record.d.mts +0 -40
  478. package/dist/cli/record.d.ts +0 -40
  479. package/dist/cli/record.js +0 -10
  480. package/dist/cli/record.js.map +0 -1
  481. package/dist/sandbox/local.cjs +0 -361
  482. package/dist/sandbox/local.cjs.map +0 -1
  483. package/dist/sandbox/local.d.cts +0 -80
  484. package/dist/sandbox/local.d.mts +0 -80
  485. package/dist/sandbox/local.d.ts +0 -80
  486. package/dist/sandbox/local.js +0 -6
  487. package/dist/sandbox/local.js.map +0 -1
@@ -0,0 +1,532 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.liveTaskBuildCacheAdminService = void 0;
4
+ exports.observeDockerBuildKitCapacity = observeDockerBuildKitCapacity;
5
+ exports.listDockerCacheDomains = listDockerCacheDomains;
6
+ exports.dockerTaskBuildAuthorityFingerprint = dockerTaskBuildAuthorityFingerprint;
7
+ exports.makeTaskBuildCacheService = makeTaskBuildCacheService;
8
+ exports.inventoryTaskBuildDomain = inventoryTaskBuildDomain;
9
+ exports.planTaskBuildGc = planTaskBuildGc;
10
+ exports.applyTaskBuildGc = applyTaskBuildGc;
11
+ const node_crypto_1 = require("node:crypto");
12
+ const node_child_process_1 = require("node:child_process");
13
+ const node_fs_1 = require("node:fs");
14
+ const node_os_1 = require("node:os");
15
+ const node_path_1 = require("node:path");
16
+ const node_util_1 = require("node:util");
17
+ const node_sqlite_1 = require("node:sqlite");
18
+ const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
19
+ const MINIMUM_AGE_MS = 24 * 60 * 60 * 1000;
20
+ const MAX_TASK_BUILD_AGE_MS = 30 * 24 * 60 * 60 * 1000;
21
+ const PLAN_TTL_MS = 15 * 60 * 1000;
22
+ function domainIdFor(ownerId, daemonId, storageDriver, sentinelId) {
23
+ return (0, node_crypto_1.createHash)("sha256")
24
+ .update(`docker-images\0${ownerId}\0${daemonId}\0${storageDriver}\0${sentinelId}`)
25
+ .digest("hex").slice(0, 24);
26
+ }
27
+ function inventoryState(actual, expected, leases) {
28
+ return actual !== expected ? "unverified" : leases > 0 ? "active-leased" : "cold-reusable";
29
+ }
30
+ function passesGcAgePolicy(row, now) {
31
+ const lastUse = Date.parse(row.last_successful_use_at ?? row.created_at);
32
+ return Date.parse(row.protected_until) <= now && now - lastUse >= MAX_TASK_BUILD_AGE_MS;
33
+ }
34
+ function canonicalDigest(value) {
35
+ return (0, node_crypto_1.createHash)("sha256").update(JSON.stringify(value)).digest("hex");
36
+ }
37
+ function digestPlan(plan) {
38
+ return canonicalDigest(plan);
39
+ }
40
+ function entryEvidence(row) {
41
+ return {
42
+ buildKey: row.build_key,
43
+ imageId: row.image_id,
44
+ manifestDigest: row.manifest_digest,
45
+ generation: row.generation,
46
+ createdAt: row.created_at,
47
+ lastSuccessfulUseAt: row.last_successful_use_at,
48
+ protectedUntil: row.protected_until,
49
+ };
50
+ }
51
+ function stateRoot() {
52
+ const base = process.env.XDG_STATE_HOME ?? (0, node_path_1.join)((0, node_os_1.homedir)(), ".local", "state");
53
+ return (0, node_path_1.join)(base, "niceeval", "cache", "v2", "domains");
54
+ }
55
+ async function docker(args, dockerSocketPath) {
56
+ const connection = dockerSocketPath === undefined ? [] : ["--host", `unix://${dockerSocketPath}`];
57
+ const result = await execFileAsync("docker", [...connection, ...args], { encoding: "utf8", maxBuffer: 4 * 1024 * 1024 });
58
+ return result.stdout.trim();
59
+ }
60
+ function decimalBytes(value) {
61
+ if (typeof value !== "string")
62
+ return null;
63
+ const match = /^([0-9]+(?:\.[0-9]+)?)\s*([kmgtp]?b)$/iu.exec(value.trim());
64
+ if (match === null)
65
+ return null;
66
+ const power = ["b", "kb", "mb", "gb", "tb", "pb"].indexOf(match[2].toLowerCase());
67
+ return power < 0 ? null : Math.round(Number(match[1]) * 1000 ** power);
68
+ }
69
+ async function observeDockerBuildKitCapacity() {
70
+ const output = await docker(["system", "df", "--format", "json"]);
71
+ const rows = output.split(/\r?\n/u).filter(Boolean).map((line) => JSON.parse(line));
72
+ const build = rows.find((row) => row.Type === "Build Cache");
73
+ const reclaimable = typeof build?.Reclaimable === "string" ? build.Reclaimable.trim().split(/\s+/u)[0] : undefined;
74
+ return Object.freeze({
75
+ scope: "provider",
76
+ providerFamily: "docker",
77
+ backendKind: "buildkit",
78
+ state: "unverified",
79
+ observedAt: new Date().toISOString(),
80
+ totalBytes: decimalBytes(build?.Size),
81
+ reclaimableEstimateBytes: decimalBytes(reclaimable),
82
+ reason: "shared-builder-unattributed",
83
+ });
84
+ }
85
+ async function openDomain(dockerSocketPath) {
86
+ if (dockerSocketPath !== undefined)
87
+ throw new Error("managed Docker cache requires the default local Unix socket");
88
+ const root = stateRoot();
89
+ (0, node_fs_1.mkdirSync)(root, { recursive: true, mode: 0o700 });
90
+ const ownerPath = (0, node_path_1.join)(root, "owner-id");
91
+ let ownerId;
92
+ try {
93
+ ownerId = (0, node_fs_1.readFileSync)(ownerPath, "utf8").trim();
94
+ }
95
+ catch {
96
+ ownerId = (0, node_crypto_1.randomUUID)();
97
+ const temporary = `${ownerPath}.${process.pid}.${(0, node_crypto_1.randomUUID)()}.tmp`;
98
+ (0, node_fs_1.writeFileSync)(temporary, `${ownerId}\n`, { encoding: "utf8", mode: 0o600, flag: "wx" });
99
+ try {
100
+ (0, node_fs_1.renameSync)(temporary, ownerPath);
101
+ }
102
+ catch {
103
+ ownerId = (0, node_fs_1.readFileSync)(ownerPath, "utf8").trim();
104
+ }
105
+ }
106
+ const sentinelName = `niceeval-cache-${(0, node_crypto_1.createHash)("sha256").update(ownerId).digest("hex").slice(0, 16)}`;
107
+ const sentinelLabel = "io.niceeval.cache-domain";
108
+ let sentinelId;
109
+ try {
110
+ sentinelId = await docker(["volume", "inspect", "--format", `{{index .Labels \"${sentinelLabel}\"}}`, sentinelName]);
111
+ }
112
+ catch {
113
+ sentinelId = (0, node_crypto_1.randomUUID)();
114
+ await docker(["volume", "create", "--label", `${sentinelLabel}=${sentinelId}`, sentinelName]);
115
+ sentinelId = await docker(["volume", "inspect", "--format", `{{index .Labels \"${sentinelLabel}\"}}`, sentinelName]);
116
+ }
117
+ if (sentinelId.length === 0 || sentinelId === "<no value>")
118
+ throw new Error(`Docker cache sentinel ${sentinelName} has no managed identity`);
119
+ const daemonId = await docker(["info", "--format", "{{.ID}}"], dockerSocketPath);
120
+ const storageDriver = await docker(["info", "--format", "{{.Driver}}"], dockerSocketPath);
121
+ const domainId = domainIdFor(ownerId, daemonId, storageDriver, sentinelId);
122
+ const backendIdentity = (0, node_crypto_1.createHash)("sha256").update(`${daemonId}\0${storageDriver}\0${sentinelId}`).digest("hex");
123
+ const directory = (0, node_path_1.join)(stateRoot(), domainId);
124
+ (0, node_fs_1.mkdirSync)(directory, { recursive: true, mode: 0o700 });
125
+ const db = new node_sqlite_1.DatabaseSync((0, node_path_1.join)(directory, "registry.sqlite"));
126
+ db.exec("PRAGMA journal_mode=WAL; PRAGMA synchronous=FULL; PRAGMA foreign_keys=ON;");
127
+ db.exec(`
128
+ CREATE TABLE IF NOT EXISTS entries (
129
+ build_key TEXT PRIMARY KEY,
130
+ tag TEXT NOT NULL,
131
+ image_id TEXT NOT NULL,
132
+ created_at TEXT NOT NULL,
133
+ last_successful_use_at TEXT,
134
+ protected_until TEXT NOT NULL,
135
+ manifest_digest TEXT NOT NULL,
136
+ generation INTEGER NOT NULL,
137
+ operation_id TEXT NOT NULL,
138
+ state TEXT NOT NULL CHECK(state IN ('indexed','deleting','tombstoned','unverified'))
139
+ );
140
+ CREATE TABLE IF NOT EXISTS metadata (key TEXT PRIMARY KEY, value TEXT NOT NULL);
141
+ CREATE TABLE IF NOT EXISTS leases (
142
+ lease_id TEXT PRIMARY KEY,
143
+ build_key TEXT NOT NULL REFERENCES entries(build_key),
144
+ holder_pid INTEGER NOT NULL,
145
+ holder_boot_id TEXT NOT NULL,
146
+ holder_process_start TEXT NOT NULL,
147
+ generation INTEGER NOT NULL,
148
+ created_at TEXT NOT NULL,
149
+ heartbeat_at TEXT NOT NULL
150
+ );
151
+ CREATE TABLE IF NOT EXISTS roots (
152
+ root_id TEXT PRIMARY KEY,
153
+ build_key TEXT NOT NULL REFERENCES entries(build_key),
154
+ generation INTEGER NOT NULL,
155
+ holder_boot_id TEXT NOT NULL,
156
+ holder_pid INTEGER NOT NULL,
157
+ holder_process_start TEXT NOT NULL,
158
+ state TEXT NOT NULL CHECK(state IN ('prepared','active')),
159
+ created_at TEXT NOT NULL
160
+ );
161
+ CREATE TABLE IF NOT EXISTS gc_plans (
162
+ plan_id TEXT PRIMARY KEY,
163
+ created_at TEXT NOT NULL,
164
+ expires_at TEXT NOT NULL,
165
+ payload TEXT NOT NULL,
166
+ digest TEXT NOT NULL,
167
+ outcome TEXT
168
+ );
169
+ `);
170
+ const epochRow = db.prepare("SELECT value FROM metadata WHERE key = 'authorityEpoch'").get();
171
+ const authorityEpoch = epochRow?.value ?? (0, node_crypto_1.randomUUID)();
172
+ db.prepare("INSERT OR IGNORE INTO metadata(key, value) VALUES ('authorityEpoch', ?)").run(authorityEpoch);
173
+ db.prepare("INSERT OR IGNORE INTO metadata(key, value) VALUES ('safetyRevision', '1')").run();
174
+ const catalog = new node_sqlite_1.DatabaseSync((0, node_path_1.join)(root, "catalog.sqlite"));
175
+ catalog.exec(`
176
+ PRAGMA journal_mode=WAL; PRAGMA synchronous=FULL;
177
+ CREATE TABLE IF NOT EXISTS domains (
178
+ domain_id TEXT PRIMARY KEY,
179
+ provider_family TEXT NOT NULL,
180
+ admin_protocol_version INTEGER NOT NULL,
181
+ backend_kind TEXT NOT NULL,
182
+ first_verified_at TEXT NOT NULL,
183
+ last_verified_at TEXT NOT NULL,
184
+ last_state TEXT NOT NULL
185
+ );
186
+ `);
187
+ const verifiedAt = new Date().toISOString();
188
+ catalog.prepare(`
189
+ INSERT INTO domains(domain_id, provider_family, admin_protocol_version, backend_kind, first_verified_at, last_verified_at, last_state)
190
+ VALUES (?, 'docker', 1, 'docker-images', ?, ?, 'verified-managed')
191
+ ON CONFLICT(domain_id) DO UPDATE SET last_verified_at=excluded.last_verified_at, last_state='verified-managed'
192
+ `).run(domainId, verifiedAt, verifiedAt);
193
+ catalog.close();
194
+ return { domainId, ownerId, authorityEpoch, backendIdentity, db };
195
+ }
196
+ async function listDockerCacheDomains() {
197
+ const current = await openDomain();
198
+ current.db.close();
199
+ const catalog = new node_sqlite_1.DatabaseSync((0, node_path_1.join)(stateRoot(), "catalog.sqlite"), { readOnly: true });
200
+ const rows = catalog.prepare("SELECT domain_id, provider_family, admin_protocol_version, backend_kind FROM domains ORDER BY first_verified_at, domain_id").all();
201
+ catalog.close();
202
+ return rows.map((row) => ({
203
+ providerFamily: "docker",
204
+ adminProtocolVersion: row.admin_protocol_version,
205
+ domainId: row.domain_id,
206
+ backendKind: row.backend_kind,
207
+ state: row.domain_id === current.domainId ? "verified-managed" : "unavailable",
208
+ }));
209
+ }
210
+ async function dockerTaskBuildAuthorityFingerprint() {
211
+ const domain = await openDomain();
212
+ domain.db.close();
213
+ return domain.domainId;
214
+ }
215
+ async function imageId(tag, dockerSocketPath) {
216
+ try {
217
+ return await docker(["image", "inspect", "--format", "{{.Id}}", tag], dockerSocketPath);
218
+ }
219
+ catch {
220
+ return undefined;
221
+ }
222
+ }
223
+ async function hasContainerReference(image, dockerSocketPath) {
224
+ return (await docker(["ps", "-a", "--filter", `ancestor=${image}`, "--quiet"], dockerSocketPath)).length > 0;
225
+ }
226
+ function holderIdentity(pid = process.pid) {
227
+ const bootId = (0, node_fs_1.readFileSync)("/proc/sys/kernel/random/boot_id", "utf8").trim();
228
+ const stat = (0, node_fs_1.readFileSync)(`/proc/${pid}/stat`, "utf8").trim();
229
+ const processStart = stat.slice(stat.lastIndexOf(")") + 2).split(/\s+/u)[19];
230
+ if (bootId.length === 0 || processStart === undefined)
231
+ throw new Error("cannot verify local process identity");
232
+ return { bootId, processStart };
233
+ }
234
+ function processIdentityIsLive(pid, bootId, processStart) {
235
+ try {
236
+ const actual = holderIdentity(pid);
237
+ return actual.bootId === bootId && actual.processStart === processStart;
238
+ }
239
+ catch {
240
+ return false;
241
+ }
242
+ }
243
+ class LiveTaskBuildCacheSession {
244
+ async lookup(buildKey, tag, manifestDigest, dockerSocketPath) {
245
+ const domain = await openDomain(dockerSocketPath);
246
+ const row = domain.db.prepare("SELECT * FROM entries WHERE build_key = ? AND state = 'indexed'").get(buildKey);
247
+ if (row === undefined || row.tag !== tag || row.manifest_digest !== manifestDigest) {
248
+ domain.db.close();
249
+ return false;
250
+ }
251
+ const actual = await imageId(tag, dockerSocketPath);
252
+ if (actual === undefined || actual !== row.image_id) {
253
+ domain.db.prepare("UPDATE entries SET state = 'unverified' WHERE build_key = ?").run(buildKey);
254
+ domain.db.close();
255
+ return false;
256
+ }
257
+ domain.db.close();
258
+ return true;
259
+ }
260
+ async publish(buildKey, tag, manifestDigest, operationId, dockerSocketPath) {
261
+ const actual = await imageId(tag, dockerSocketPath);
262
+ if (actual === undefined)
263
+ throw new Error(`built image ${tag} is absent after build`);
264
+ const domain = await openDomain(dockerSocketPath);
265
+ const now = new Date();
266
+ domain.db.prepare(`
267
+ INSERT INTO entries(build_key, tag, image_id, created_at, last_successful_use_at, protected_until, manifest_digest, generation, operation_id, state)
268
+ VALUES (?, ?, ?, ?, ?, ?, ?, 1, ?, 'indexed')
269
+ ON CONFLICT(build_key) DO UPDATE SET
270
+ tag=excluded.tag, image_id=excluded.image_id, created_at=excluded.created_at,
271
+ last_successful_use_at=excluded.last_successful_use_at,
272
+ protected_until=excluded.protected_until, manifest_digest=excluded.manifest_digest,
273
+ generation=CASE WHEN entries.operation_id = excluded.operation_id THEN entries.generation ELSE entries.generation + 1 END,
274
+ operation_id=excluded.operation_id, state='indexed'
275
+ `).run(buildKey, tag, actual, now.toISOString(), now.toISOString(), new Date(now.getTime() + MINIMUM_AGE_MS).toISOString(), manifestDigest, operationId);
276
+ domain.db.prepare("UPDATE metadata SET value = CAST(value AS INTEGER) + 1 WHERE key = 'safetyRevision'").run();
277
+ domain.db.close();
278
+ }
279
+ async acquireUse(buildKey, tag, manifestDigest, dockerSocketPath) {
280
+ const domain = await openDomain(dockerSocketPath);
281
+ const row = domain.db.prepare("SELECT * FROM entries WHERE build_key = ? AND state = 'indexed'").get(buildKey);
282
+ if (row === undefined || row.tag !== tag || row.manifest_digest !== manifestDigest || await imageId(tag, dockerSocketPath) !== row.image_id) {
283
+ domain.db.close();
284
+ throw new Error(`Docker task-build artifact ${buildKey.slice(0, 12)} is no longer available`);
285
+ }
286
+ const leaseId = (0, node_crypto_1.randomUUID)();
287
+ const rootId = (0, node_crypto_1.randomUUID)();
288
+ const now = new Date().toISOString();
289
+ const holder = holderIdentity();
290
+ domain.db.exec("BEGIN IMMEDIATE");
291
+ try {
292
+ domain.db.prepare("INSERT INTO leases(lease_id, build_key, holder_pid, holder_boot_id, holder_process_start, generation, created_at, heartbeat_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)")
293
+ .run(leaseId, buildKey, process.pid, holder.bootId, holder.processStart, row.generation, now, now);
294
+ domain.db.prepare("INSERT INTO roots(root_id, build_key, generation, holder_boot_id, holder_pid, holder_process_start, state, created_at) VALUES (?, ?, ?, ?, ?, ?, 'prepared', ?)")
295
+ .run(rootId, buildKey, row.generation, holder.bootId, process.pid, holder.processStart, now);
296
+ domain.db.prepare("UPDATE roots SET state = 'active' WHERE root_id = ? AND state = 'prepared'").run(rootId);
297
+ domain.db.prepare("UPDATE entries SET last_successful_use_at = ? WHERE build_key = ?").run(now, buildKey);
298
+ domain.db.exec("COMMIT");
299
+ }
300
+ catch (cause) {
301
+ domain.db.exec("ROLLBACK");
302
+ domain.db.close();
303
+ throw cause;
304
+ }
305
+ let released = false;
306
+ const heartbeat = setInterval(() => {
307
+ if (released)
308
+ return;
309
+ try {
310
+ domain.db.prepare("UPDATE leases SET heartbeat_at = ? WHERE lease_id = ?").run(new Date().toISOString(), leaseId);
311
+ }
312
+ catch {
313
+ // The holder identity and durable root remain authoritative; reconciliation will classify an unreadable registry as unverified.
314
+ }
315
+ }, 30000);
316
+ heartbeat.unref();
317
+ return { release() {
318
+ if (released)
319
+ return;
320
+ released = true;
321
+ clearInterval(heartbeat);
322
+ domain.db.exec("BEGIN IMMEDIATE");
323
+ try {
324
+ domain.db.prepare("DELETE FROM roots WHERE root_id = ?").run(rootId);
325
+ domain.db.prepare("DELETE FROM leases WHERE lease_id = ?").run(leaseId);
326
+ domain.db.exec("COMMIT");
327
+ }
328
+ catch (cause) {
329
+ domain.db.exec("ROLLBACK");
330
+ throw cause;
331
+ }
332
+ domain.db.close();
333
+ } };
334
+ }
335
+ }
336
+ function makeTaskBuildCacheService() {
337
+ return new LiveTaskBuildCacheSession();
338
+ }
339
+ function liveLeaseCount(db, buildKey) {
340
+ const rows = db.prepare("SELECT lease_id, holder_pid, holder_boot_id, holder_process_start FROM leases WHERE build_key = ?").all(buildKey);
341
+ let live = 0;
342
+ for (const row of rows) {
343
+ if (processIdentityIsLive(row.holder_pid, row.holder_boot_id, row.holder_process_start)) {
344
+ live += 1;
345
+ }
346
+ else {
347
+ db.prepare("DELETE FROM leases WHERE lease_id = ?").run(row.lease_id);
348
+ }
349
+ }
350
+ return live;
351
+ }
352
+ function liveRootCount(db, buildKey) {
353
+ const rows = db.prepare("SELECT root_id, holder_pid, holder_boot_id, holder_process_start FROM roots WHERE build_key = ?").all(buildKey);
354
+ let live = 0;
355
+ for (const row of rows) {
356
+ if (processIdentityIsLive(row.holder_pid, row.holder_boot_id, row.holder_process_start))
357
+ live += 1;
358
+ else
359
+ db.prepare("DELETE FROM roots WHERE root_id = ?").run(row.root_id);
360
+ }
361
+ return live;
362
+ }
363
+ async function inventoryTaskBuildDomain(dockerSocketPath) {
364
+ const domain = await openDomain(dockerSocketPath);
365
+ const rows = domain.db.prepare("SELECT * FROM entries ORDER BY COALESCE(last_successful_use_at, created_at), created_at, build_key").all();
366
+ const entries = [];
367
+ for (const row of rows) {
368
+ const actual = await imageId(row.tag, dockerSocketPath);
369
+ const leases = liveLeaseCount(domain.db, row.build_key) + liveRootCount(domain.db, row.build_key);
370
+ entries.push({
371
+ buildKey: row.build_key,
372
+ tag: row.tag,
373
+ imageId: row.image_id,
374
+ createdAt: row.created_at,
375
+ lastSuccessfulUseAt: row.last_successful_use_at,
376
+ protectedUntil: row.protected_until,
377
+ state: inventoryState(actual, row.image_id, leases),
378
+ });
379
+ }
380
+ domain.db.close();
381
+ return { domainId: domain.domainId, providerFamily: "docker", backendKind: "docker-images", state: "verified-managed", entries };
382
+ }
383
+ async function planTaskBuildGc(domainId) {
384
+ const domain = await openDomain();
385
+ if (domain.domainId !== domainId) {
386
+ domain.db.close();
387
+ throw new Error(`unknown Docker image cache domain ${domainId}`);
388
+ }
389
+ const now = new Date();
390
+ const candidates = [];
391
+ const rows = domain.db.prepare("SELECT * FROM entries WHERE state = 'indexed' ORDER BY COALESCE(last_successful_use_at, created_at), created_at, build_key").all();
392
+ for (const row of rows) {
393
+ if (!passesGcAgePolicy(row, now.getTime()))
394
+ continue;
395
+ if (liveLeaseCount(domain.db, row.build_key) > 0)
396
+ continue;
397
+ if (liveRootCount(domain.db, row.build_key) > 0)
398
+ continue;
399
+ if (await imageId(row.tag) !== row.image_id)
400
+ continue;
401
+ if (await hasContainerReference(row.image_id))
402
+ continue;
403
+ const evidence = entryEvidence(row);
404
+ candidates.push({
405
+ buildKey: row.build_key,
406
+ tag: row.tag,
407
+ imageId: row.image_id,
408
+ manifestDigest: row.manifest_digest,
409
+ generation: row.generation,
410
+ evidenceDigest: canonicalDigest(evidence),
411
+ ruleId: "max-age/task-build",
412
+ });
413
+ }
414
+ const revision = Number(domain.db.prepare("SELECT value FROM metadata WHERE key = 'safetyRevision'").get().value);
415
+ const unsigned = {
416
+ schemaVersion: 1,
417
+ planId: (0, node_crypto_1.randomUUID)(),
418
+ domainId,
419
+ ownerId: domain.ownerId,
420
+ backendIdentity: domain.backendIdentity,
421
+ authorityEpoch: domain.authorityEpoch,
422
+ policyVersion: 1,
423
+ registrySafetyRevision: revision,
424
+ observedAt: now.toISOString(),
425
+ expiresAt: new Date(now.getTime() + PLAN_TTL_MS).toISOString(),
426
+ candidates,
427
+ };
428
+ const plan = { ...unsigned, planDigest: digestPlan(unsigned) };
429
+ domain.db.prepare("INSERT INTO gc_plans(plan_id, created_at, expires_at, payload, digest) VALUES (?, ?, ?, ?, ?)")
430
+ .run(plan.planId, plan.observedAt, plan.expiresAt, JSON.stringify(plan), plan.planDigest);
431
+ domain.db.close();
432
+ return plan;
433
+ }
434
+ async function applyTaskBuildGc(domainId, planId) {
435
+ const domain = await openDomain();
436
+ if (domain.domainId !== domainId) {
437
+ domain.db.close();
438
+ throw new Error(`unknown Docker image cache domain ${domainId}`);
439
+ }
440
+ const saved = domain.db.prepare("SELECT expires_at, payload, digest, outcome FROM gc_plans WHERE plan_id = ?").get(planId);
441
+ if (saved === undefined) {
442
+ domain.db.close();
443
+ throw new Error(`unknown GC plan ${planId}`);
444
+ }
445
+ if (saved.outcome !== null) {
446
+ const outcome = JSON.parse(saved.outcome);
447
+ domain.db.close();
448
+ return outcome;
449
+ }
450
+ if (Date.parse(saved.expires_at) < Date.now()) {
451
+ domain.db.close();
452
+ throw new Error(`GC plan ${planId} expired`);
453
+ }
454
+ const plan = JSON.parse(saved.payload);
455
+ const { planDigest: persistedPlanDigest, ...unsigned } = plan;
456
+ if (saved.digest !== persistedPlanDigest || digestPlan(unsigned) !== persistedPlanDigest) {
457
+ domain.db.close();
458
+ throw new Error(`GC plan ${planId} is corrupt`);
459
+ }
460
+ if (plan.domainId !== domain.domainId ||
461
+ plan.ownerId !== domain.ownerId ||
462
+ plan.backendIdentity !== domain.backendIdentity ||
463
+ plan.authorityEpoch !== domain.authorityEpoch ||
464
+ plan.policyVersion !== 1) {
465
+ domain.db.close();
466
+ throw new Error(`GC plan ${planId} authority changed`);
467
+ }
468
+ const outcomes = [];
469
+ for (const candidate of plan.candidates) {
470
+ domain.db.exec("BEGIN IMMEDIATE");
471
+ let row;
472
+ try {
473
+ row = domain.db.prepare("SELECT * FROM entries WHERE build_key = ?").get(candidate.buildKey);
474
+ if (row === undefined || (row.state !== "indexed" && row.state !== "deleting") || row.image_id !== candidate.imageId ||
475
+ row.manifest_digest !== candidate.manifestDigest || row.generation !== candidate.generation ||
476
+ canonicalDigest(entryEvidence(row)) !== candidate.evidenceDigest ||
477
+ liveLeaseCount(domain.db, candidate.buildKey) > 0 || liveRootCount(domain.db, candidate.buildKey) > 0) {
478
+ domain.db.exec("ROLLBACK");
479
+ outcomes.push({ buildKey: candidate.buildKey, status: "skipped", reason: "entry-lease-root-or-generation-changed" });
480
+ continue;
481
+ }
482
+ domain.db.prepare("UPDATE entries SET state = 'deleting' WHERE build_key = ? AND generation = ? AND state IN ('indexed','deleting')")
483
+ .run(candidate.buildKey, candidate.generation);
484
+ domain.db.exec("COMMIT");
485
+ }
486
+ catch (cause) {
487
+ domain.db.exec("ROLLBACK");
488
+ outcomes.push({ buildKey: candidate.buildKey, status: "failed", reason: cause instanceof Error ? cause.message : String(cause) });
489
+ continue;
490
+ }
491
+ const actual = await imageId(row.tag);
492
+ if (actual === undefined) {
493
+ domain.db.prepare("UPDATE entries SET state = 'tombstoned' WHERE build_key = ? AND generation = ? AND state = 'deleting'")
494
+ .run(candidate.buildKey, candidate.generation);
495
+ outcomes.push({ buildKey: candidate.buildKey, status: "already-absent", reason: "provider-confirmed-absent" });
496
+ continue;
497
+ }
498
+ if (actual !== candidate.imageId || await hasContainerReference(candidate.imageId)) {
499
+ domain.db.prepare("UPDATE entries SET state = 'indexed' WHERE build_key = ? AND generation = ? AND state = 'deleting'")
500
+ .run(candidate.buildKey, candidate.generation);
501
+ outcomes.push({ buildKey: candidate.buildKey, status: "skipped", reason: "resource-or-reference-changed" });
502
+ continue;
503
+ }
504
+ try {
505
+ await docker(["image", "rm", candidate.imageId]);
506
+ if (await imageId(row.tag) !== undefined || await hasContainerReference(candidate.imageId)) {
507
+ domain.db.prepare("UPDATE entries SET state = 'unverified' WHERE build_key = ? AND generation = ? AND state = 'deleting'")
508
+ .run(candidate.buildKey, candidate.generation);
509
+ outcomes.push({ buildKey: candidate.buildKey, status: "failed", reason: "image-still-present" });
510
+ continue;
511
+ }
512
+ domain.db.prepare("UPDATE entries SET state = 'tombstoned' WHERE build_key = ? AND generation = ? AND state = 'deleting'")
513
+ .run(candidate.buildKey, candidate.generation);
514
+ outcomes.push({ buildKey: candidate.buildKey, status: "deleted", reason: "max-age/task-build" });
515
+ }
516
+ catch (cause) {
517
+ domain.db.prepare("UPDATE entries SET state = 'unverified' WHERE build_key = ? AND generation = ? AND state = 'deleting'")
518
+ .run(candidate.buildKey, candidate.generation);
519
+ outcomes.push({ buildKey: candidate.buildKey, status: "failed", reason: cause instanceof Error ? cause.message : String(cause) });
520
+ }
521
+ }
522
+ const result = { planId, domainId, outcomes };
523
+ domain.db.prepare("UPDATE gc_plans SET outcome = ? WHERE plan_id = ?").run(JSON.stringify(result), planId);
524
+ domain.db.close();
525
+ return result;
526
+ }
527
+ exports.liveTaskBuildCacheAdminService = Object.freeze({
528
+ inventory: inventoryTaskBuildDomain,
529
+ planGc: planTaskBuildGc,
530
+ applyGc: applyTaskBuildGc,
531
+ });
532
+ //# sourceMappingURL=docker-task-build-cache.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker-task-build-cache.js","sourceRoot":"","sources":["docker-task-build-cache.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { execFile } from \"node:child_process\";\nimport { mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { DatabaseSync } from \"node:sqlite\";\nimport type { DockerCapacityObservation as ProviderCapacityObservation, DockerCacheDomainDescriptor as CacheDomainDescriptor, } from \"../docker/cache-administration.ts\";\nconst execFileAsync = promisify(execFile);\nconst MINIMUM_AGE_MS = 24 * 60 * 60 * 1000;\nconst MAX_TASK_BUILD_AGE_MS = 30 * 24 * 60 * 60 * 1000;\nconst PLAN_TTL_MS = 15 * 60 * 1000;\ninterface EntryRow {\n readonly build_key: string;\n readonly tag: string;\n readonly image_id: string;\n readonly created_at: string;\n readonly last_successful_use_at: string | null;\n readonly protected_until: string;\n readonly manifest_digest: string;\n readonly generation: number;\n readonly operation_id: string;\n readonly state: \"indexed\" | \"deleting\" | \"tombstoned\" | \"unverified\";\n}\nexport interface TaskBuildInventoryEntry {\n readonly buildKey: string;\n readonly tag: string;\n readonly imageId: string;\n readonly createdAt: string;\n readonly lastSuccessfulUseAt: string | null;\n readonly protectedUntil: string;\n readonly state: \"active-leased\" | \"cold-reusable\" | \"unverified\";\n}\nexport interface TaskBuildDomainInventory {\n readonly domainId: string;\n readonly providerFamily: \"docker\";\n readonly backendKind: \"docker-images\";\n readonly state: \"verified-managed\";\n readonly entries: readonly TaskBuildInventoryEntry[];\n}\nexport interface TaskBuildCacheService {\n lookup(buildKey: string, tag: string, manifestDigest: string, dockerSocketPath?: string): Promise<boolean>;\n publish(buildKey: string, tag: string, manifestDigest: string, operationId: string, dockerSocketPath?: string): Promise<void>;\n acquireUse(buildKey: string, tag: string, manifestDigest: string, dockerSocketPath?: string): Promise<{\n release(): void;\n }>;\n}\nexport interface TaskBuildCacheAdminService {\n inventory(): Promise<TaskBuildDomainInventory>;\n planGc(domainId: string): Promise<TaskBuildGcPlan>;\n applyGc(domainId: string, planId: string): Promise<TaskBuildGcOutcome>;\n}\nexport interface TaskBuildGcPlan {\n readonly schemaVersion: 1;\n readonly planId: string;\n readonly domainId: string;\n readonly ownerId: string;\n readonly backendIdentity: string;\n readonly authorityEpoch: string;\n readonly policyVersion: 1;\n readonly registrySafetyRevision: number;\n readonly observedAt: string;\n readonly expiresAt: string;\n readonly planDigest: string;\n readonly candidates: ReadonlyArray<{\n readonly buildKey: string;\n readonly tag: string;\n readonly imageId: string;\n readonly manifestDigest: string;\n readonly generation: number;\n readonly evidenceDigest: string;\n readonly ruleId: \"max-age/task-build\";\n }>;\n}\ninterface DomainHandle {\n readonly domainId: string;\n readonly ownerId: string;\n readonly authorityEpoch: string;\n readonly backendIdentity: string;\n readonly db: DatabaseSync;\n}\nfunction domainIdFor(ownerId: string, daemonId: string, storageDriver: string, sentinelId: string): string {\n return createHash(\"sha256\")\n .update(`docker-images\\0${ownerId}\\0${daemonId}\\0${storageDriver}\\0${sentinelId}`)\n .digest(\"hex\").slice(0, 24);\n}\nfunction inventoryState(actual: string | undefined, expected: string, leases: number): TaskBuildInventoryEntry[\"state\"] {\n return actual !== expected ? \"unverified\" : leases > 0 ? \"active-leased\" : \"cold-reusable\";\n}\nfunction passesGcAgePolicy(row: EntryRow, now: number): boolean {\n const lastUse = Date.parse(row.last_successful_use_at ?? row.created_at);\n return Date.parse(row.protected_until) <= now && now - lastUse >= MAX_TASK_BUILD_AGE_MS;\n}\nfunction canonicalDigest(value: unknown): string {\n return createHash(\"sha256\").update(JSON.stringify(value)).digest(\"hex\");\n}\nfunction digestPlan(plan: Omit<TaskBuildGcPlan, \"planDigest\">): string {\n return canonicalDigest(plan);\n}\nfunction entryEvidence(row: EntryRow): Record<string, unknown> {\n return {\n buildKey: row.build_key,\n imageId: row.image_id,\n manifestDigest: row.manifest_digest,\n generation: row.generation,\n createdAt: row.created_at,\n lastSuccessfulUseAt: row.last_successful_use_at,\n protectedUntil: row.protected_until,\n };\n}\nfunction stateRoot(): string {\n const base = process.env.XDG_STATE_HOME ?? join(homedir(), \".local\", \"state\");\n return join(base, \"niceeval\", \"cache\", \"v2\", \"domains\");\n}\nasync function docker(args: readonly string[], dockerSocketPath?: string): Promise<string> {\n const connection = dockerSocketPath === undefined ? [] : [\"--host\", `unix://${dockerSocketPath}`];\n const result = await execFileAsync(\"docker\", [...connection, ...args], { encoding: \"utf8\", maxBuffer: 4 * 1024 * 1024 });\n return result.stdout.trim();\n}\nfunction decimalBytes(value: unknown): number | null {\n if (typeof value !== \"string\")\n return null;\n const match = /^([0-9]+(?:\\.[0-9]+)?)\\s*([kmgtp]?b)$/iu.exec(value.trim());\n if (match === null)\n return null;\n const power = [\"b\", \"kb\", \"mb\", \"gb\", \"tb\", \"pb\"].indexOf(match[2]!.toLowerCase());\n return power < 0 ? null : Math.round(Number(match[1]) * 1000 ** power);\n}\nexport async function observeDockerBuildKitCapacity(): Promise<ProviderCapacityObservation> {\n const output = await docker([\"system\", \"df\", \"--format\", \"json\"]);\n const rows = output.split(/\\r?\\n/u).filter(Boolean).map((line) => JSON.parse(line) as Record<string, unknown>);\n const build = rows.find((row) => row.Type === \"Build Cache\");\n const reclaimable = typeof build?.Reclaimable === \"string\" ? build.Reclaimable.trim().split(/\\s+/u)[0] : undefined;\n return Object.freeze({\n scope: \"provider\",\n providerFamily: \"docker\",\n backendKind: \"buildkit\",\n state: \"unverified\",\n observedAt: new Date().toISOString(),\n totalBytes: decimalBytes(build?.Size),\n reclaimableEstimateBytes: decimalBytes(reclaimable),\n reason: \"shared-builder-unattributed\",\n });\n}\nasync function openDomain(dockerSocketPath?: string): Promise<DomainHandle> {\n if (dockerSocketPath !== undefined)\n throw new Error(\"managed Docker cache requires the default local Unix socket\");\n const root = stateRoot();\n mkdirSync(root, { recursive: true, mode: 0o700 });\n const ownerPath = join(root, \"owner-id\");\n let ownerId: string;\n try {\n ownerId = readFileSync(ownerPath, \"utf8\").trim();\n }\n catch {\n ownerId = randomUUID();\n const temporary = `${ownerPath}.${process.pid}.${randomUUID()}.tmp`;\n writeFileSync(temporary, `${ownerId}\\n`, { encoding: \"utf8\", mode: 0o600, flag: \"wx\" });\n try {\n renameSync(temporary, ownerPath);\n }\n catch {\n ownerId = readFileSync(ownerPath, \"utf8\").trim();\n }\n }\n const sentinelName = `niceeval-cache-${createHash(\"sha256\").update(ownerId).digest(\"hex\").slice(0, 16)}`;\n const sentinelLabel = \"io.niceeval.cache-domain\";\n let sentinelId: string | undefined;\n try {\n sentinelId = await docker([\"volume\", \"inspect\", \"--format\", `{{index .Labels \\\"${sentinelLabel}\\\"}}`, sentinelName]);\n }\n catch {\n sentinelId = randomUUID();\n await docker([\"volume\", \"create\", \"--label\", `${sentinelLabel}=${sentinelId}`, sentinelName]);\n sentinelId = await docker([\"volume\", \"inspect\", \"--format\", `{{index .Labels \\\"${sentinelLabel}\\\"}}`, sentinelName]);\n }\n if (sentinelId.length === 0 || sentinelId === \"<no value>\")\n throw new Error(`Docker cache sentinel ${sentinelName} has no managed identity`);\n const daemonId = await docker([\"info\", \"--format\", \"{{.ID}}\"], dockerSocketPath);\n const storageDriver = await docker([\"info\", \"--format\", \"{{.Driver}}\"], dockerSocketPath);\n const domainId = domainIdFor(ownerId, daemonId, storageDriver, sentinelId);\n const backendIdentity = createHash(\"sha256\").update(`${daemonId}\\0${storageDriver}\\0${sentinelId}`).digest(\"hex\");\n const directory = join(stateRoot(), domainId);\n mkdirSync(directory, { recursive: true, mode: 0o700 });\n const db = new DatabaseSync(join(directory, \"registry.sqlite\"));\n db.exec(\"PRAGMA journal_mode=WAL; PRAGMA synchronous=FULL; PRAGMA foreign_keys=ON;\");\n db.exec(`\n CREATE TABLE IF NOT EXISTS entries (\n build_key TEXT PRIMARY KEY,\n tag TEXT NOT NULL,\n image_id TEXT NOT NULL,\n created_at TEXT NOT NULL,\n last_successful_use_at TEXT,\n protected_until TEXT NOT NULL,\n manifest_digest TEXT NOT NULL,\n generation INTEGER NOT NULL,\n operation_id TEXT NOT NULL,\n state TEXT NOT NULL CHECK(state IN ('indexed','deleting','tombstoned','unverified'))\n );\n CREATE TABLE IF NOT EXISTS metadata (key TEXT PRIMARY KEY, value TEXT NOT NULL);\n CREATE TABLE IF NOT EXISTS leases (\n lease_id TEXT PRIMARY KEY,\n build_key TEXT NOT NULL REFERENCES entries(build_key),\n holder_pid INTEGER NOT NULL,\n holder_boot_id TEXT NOT NULL,\n holder_process_start TEXT NOT NULL,\n generation INTEGER NOT NULL,\n created_at TEXT NOT NULL,\n heartbeat_at TEXT NOT NULL\n );\n CREATE TABLE IF NOT EXISTS roots (\n root_id TEXT PRIMARY KEY,\n build_key TEXT NOT NULL REFERENCES entries(build_key),\n generation INTEGER NOT NULL,\n holder_boot_id TEXT NOT NULL,\n holder_pid INTEGER NOT NULL,\n holder_process_start TEXT NOT NULL,\n state TEXT NOT NULL CHECK(state IN ('prepared','active')),\n created_at TEXT NOT NULL\n );\n CREATE TABLE IF NOT EXISTS gc_plans (\n plan_id TEXT PRIMARY KEY,\n created_at TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n payload TEXT NOT NULL,\n digest TEXT NOT NULL,\n outcome TEXT\n );\n `);\n const epochRow = db.prepare(\"SELECT value FROM metadata WHERE key = 'authorityEpoch'\").get() as {\n value: string;\n } | undefined;\n const authorityEpoch = epochRow?.value ?? randomUUID();\n db.prepare(\"INSERT OR IGNORE INTO metadata(key, value) VALUES ('authorityEpoch', ?)\").run(authorityEpoch);\n db.prepare(\"INSERT OR IGNORE INTO metadata(key, value) VALUES ('safetyRevision', '1')\").run();\n const catalog = new DatabaseSync(join(root, \"catalog.sqlite\"));\n catalog.exec(`\n PRAGMA journal_mode=WAL; PRAGMA synchronous=FULL;\n CREATE TABLE IF NOT EXISTS domains (\n domain_id TEXT PRIMARY KEY,\n provider_family TEXT NOT NULL,\n admin_protocol_version INTEGER NOT NULL,\n backend_kind TEXT NOT NULL,\n first_verified_at TEXT NOT NULL,\n last_verified_at TEXT NOT NULL,\n last_state TEXT NOT NULL\n );\n `);\n const verifiedAt = new Date().toISOString();\n catalog.prepare(`\n INSERT INTO domains(domain_id, provider_family, admin_protocol_version, backend_kind, first_verified_at, last_verified_at, last_state)\n VALUES (?, 'docker', 1, 'docker-images', ?, ?, 'verified-managed')\n ON CONFLICT(domain_id) DO UPDATE SET last_verified_at=excluded.last_verified_at, last_state='verified-managed'\n `).run(domainId, verifiedAt, verifiedAt);\n catalog.close();\n return { domainId, ownerId, authorityEpoch, backendIdentity, db };\n}\nexport async function listDockerCacheDomains(): Promise<readonly CacheDomainDescriptor[]> {\n const current = await openDomain();\n current.db.close();\n const catalog = new DatabaseSync(join(stateRoot(), \"catalog.sqlite\"), { readOnly: true });\n const rows = catalog.prepare(\"SELECT domain_id, provider_family, admin_protocol_version, backend_kind FROM domains ORDER BY first_verified_at, domain_id\").all() as Array<{\n domain_id: string;\n provider_family: string;\n admin_protocol_version: number;\n backend_kind: string;\n }>;\n catalog.close();\n return rows.map((row) => ({\n providerFamily: \"docker\",\n adminProtocolVersion: row.admin_protocol_version,\n domainId: row.domain_id,\n backendKind: row.backend_kind,\n state: row.domain_id === current.domainId ? \"verified-managed\" : \"unavailable\",\n }));\n}\nexport async function dockerTaskBuildAuthorityFingerprint(): Promise<string> {\n const domain = await openDomain();\n domain.db.close();\n return domain.domainId;\n}\nasync function imageId(tag: string, dockerSocketPath?: string): Promise<string | undefined> {\n try {\n return await docker([\"image\", \"inspect\", \"--format\", \"{{.Id}}\", tag], dockerSocketPath);\n }\n catch {\n return undefined;\n }\n}\nasync function hasContainerReference(image: string, dockerSocketPath?: string): Promise<boolean> {\n return (await docker([\"ps\", \"-a\", \"--filter\", `ancestor=${image}`, \"--quiet\"], dockerSocketPath)).length > 0;\n}\nfunction holderIdentity(pid = process.pid): {\n bootId: string;\n processStart: string;\n} {\n const bootId = readFileSync(\"/proc/sys/kernel/random/boot_id\", \"utf8\").trim();\n const stat = readFileSync(`/proc/${pid}/stat`, \"utf8\").trim();\n const processStart = stat.slice(stat.lastIndexOf(\")\") + 2).split(/\\s+/u)[19];\n if (bootId.length === 0 || processStart === undefined)\n throw new Error(\"cannot verify local process identity\");\n return { bootId, processStart };\n}\nfunction processIdentityIsLive(pid: number, bootId: string, processStart: string): boolean {\n try {\n const actual = holderIdentity(pid);\n return actual.bootId === bootId && actual.processStart === processStart;\n }\n catch {\n return false;\n }\n}\nclass LiveTaskBuildCacheSession implements TaskBuildCacheService {\n async lookup(buildKey: string, tag: string, manifestDigest: string, dockerSocketPath?: string): Promise<boolean> {\n const domain = await openDomain(dockerSocketPath);\n const row = domain.db.prepare(\"SELECT * FROM entries WHERE build_key = ? AND state = 'indexed'\").get(buildKey) as EntryRow | undefined;\n if (row === undefined || row.tag !== tag || row.manifest_digest !== manifestDigest) {\n domain.db.close();\n return false;\n }\n const actual = await imageId(tag, dockerSocketPath);\n if (actual === undefined || actual !== row.image_id) {\n domain.db.prepare(\"UPDATE entries SET state = 'unverified' WHERE build_key = ?\").run(buildKey);\n domain.db.close();\n return false;\n }\n domain.db.close();\n return true;\n }\n async publish(buildKey: string, tag: string, manifestDigest: string, operationId: string, dockerSocketPath?: string): Promise<void> {\n const actual = await imageId(tag, dockerSocketPath);\n if (actual === undefined)\n throw new Error(`built image ${tag} is absent after build`);\n const domain = await openDomain(dockerSocketPath);\n const now = new Date();\n domain.db.prepare(`\n INSERT INTO entries(build_key, tag, image_id, created_at, last_successful_use_at, protected_until, manifest_digest, generation, operation_id, state)\n VALUES (?, ?, ?, ?, ?, ?, ?, 1, ?, 'indexed')\n ON CONFLICT(build_key) DO UPDATE SET\n tag=excluded.tag, image_id=excluded.image_id, created_at=excluded.created_at,\n last_successful_use_at=excluded.last_successful_use_at,\n protected_until=excluded.protected_until, manifest_digest=excluded.manifest_digest,\n generation=CASE WHEN entries.operation_id = excluded.operation_id THEN entries.generation ELSE entries.generation + 1 END,\n operation_id=excluded.operation_id, state='indexed'\n `).run(buildKey, tag, actual, now.toISOString(), now.toISOString(), new Date(now.getTime() + MINIMUM_AGE_MS).toISOString(), manifestDigest, operationId);\n domain.db.prepare(\"UPDATE metadata SET value = CAST(value AS INTEGER) + 1 WHERE key = 'safetyRevision'\").run();\n domain.db.close();\n }\n async acquireUse(buildKey: string, tag: string, manifestDigest: string, dockerSocketPath?: string): Promise<{\n release(): void;\n }> {\n const domain = await openDomain(dockerSocketPath);\n const row = domain.db.prepare(\"SELECT * FROM entries WHERE build_key = ? AND state = 'indexed'\").get(buildKey) as EntryRow | undefined;\n if (row === undefined || row.tag !== tag || row.manifest_digest !== manifestDigest || await imageId(tag, dockerSocketPath) !== row.image_id) {\n domain.db.close();\n throw new Error(`Docker task-build artifact ${buildKey.slice(0, 12)} is no longer available`);\n }\n const leaseId = randomUUID();\n const rootId = randomUUID();\n const now = new Date().toISOString();\n const holder = holderIdentity();\n domain.db.exec(\"BEGIN IMMEDIATE\");\n try {\n domain.db.prepare(\"INSERT INTO leases(lease_id, build_key, holder_pid, holder_boot_id, holder_process_start, generation, created_at, heartbeat_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)\")\n .run(leaseId, buildKey, process.pid, holder.bootId, holder.processStart, row.generation, now, now);\n domain.db.prepare(\"INSERT INTO roots(root_id, build_key, generation, holder_boot_id, holder_pid, holder_process_start, state, created_at) VALUES (?, ?, ?, ?, ?, ?, 'prepared', ?)\")\n .run(rootId, buildKey, row.generation, holder.bootId, process.pid, holder.processStart, now);\n domain.db.prepare(\"UPDATE roots SET state = 'active' WHERE root_id = ? AND state = 'prepared'\").run(rootId);\n domain.db.prepare(\"UPDATE entries SET last_successful_use_at = ? WHERE build_key = ?\").run(now, buildKey);\n domain.db.exec(\"COMMIT\");\n }\n catch (cause) {\n domain.db.exec(\"ROLLBACK\");\n domain.db.close();\n throw cause;\n }\n let released = false;\n const heartbeat = setInterval(() => {\n if (released)\n return;\n try {\n domain.db.prepare(\"UPDATE leases SET heartbeat_at = ? WHERE lease_id = ?\").run(new Date().toISOString(), leaseId);\n }\n catch {\n // The holder identity and durable root remain authoritative; reconciliation will classify an unreadable registry as unverified.\n }\n }, 30000);\n heartbeat.unref();\n return { release() {\n if (released)\n return;\n released = true;\n clearInterval(heartbeat);\n domain.db.exec(\"BEGIN IMMEDIATE\");\n try {\n domain.db.prepare(\"DELETE FROM roots WHERE root_id = ?\").run(rootId);\n domain.db.prepare(\"DELETE FROM leases WHERE lease_id = ?\").run(leaseId);\n domain.db.exec(\"COMMIT\");\n }\n catch (cause) {\n domain.db.exec(\"ROLLBACK\");\n throw cause;\n }\n domain.db.close();\n } };\n }\n}\nexport function makeTaskBuildCacheService(): TaskBuildCacheService {\n return new LiveTaskBuildCacheSession();\n}\nfunction liveLeaseCount(db: DatabaseSync, buildKey: string): number {\n const rows = db.prepare(\"SELECT lease_id, holder_pid, holder_boot_id, holder_process_start FROM leases WHERE build_key = ?\").all(buildKey) as Array<{\n lease_id: string;\n holder_pid: number;\n holder_boot_id: string;\n holder_process_start: string;\n }>;\n let live = 0;\n for (const row of rows) {\n if (processIdentityIsLive(row.holder_pid, row.holder_boot_id, row.holder_process_start)) {\n live += 1;\n }\n else {\n db.prepare(\"DELETE FROM leases WHERE lease_id = ?\").run(row.lease_id);\n }\n }\n return live;\n}\nfunction liveRootCount(db: DatabaseSync, buildKey: string): number {\n const rows = db.prepare(\"SELECT root_id, holder_pid, holder_boot_id, holder_process_start FROM roots WHERE build_key = ?\").all(buildKey) as Array<{\n root_id: string;\n holder_pid: number;\n holder_boot_id: string;\n holder_process_start: string;\n }>;\n let live = 0;\n for (const row of rows) {\n if (processIdentityIsLive(row.holder_pid, row.holder_boot_id, row.holder_process_start))\n live += 1;\n else\n db.prepare(\"DELETE FROM roots WHERE root_id = ?\").run(row.root_id);\n }\n return live;\n}\nexport async function inventoryTaskBuildDomain(dockerSocketPath?: string): Promise<TaskBuildDomainInventory> {\n const domain = await openDomain(dockerSocketPath);\n const rows = domain.db.prepare(\"SELECT * FROM entries ORDER BY COALESCE(last_successful_use_at, created_at), created_at, build_key\").all() as unknown as EntryRow[];\n const entries: TaskBuildInventoryEntry[] = [];\n for (const row of rows) {\n const actual = await imageId(row.tag, dockerSocketPath);\n const leases = liveLeaseCount(domain.db, row.build_key) + liveRootCount(domain.db, row.build_key);\n entries.push({\n buildKey: row.build_key,\n tag: row.tag,\n imageId: row.image_id,\n createdAt: row.created_at,\n lastSuccessfulUseAt: row.last_successful_use_at,\n protectedUntil: row.protected_until,\n state: inventoryState(actual, row.image_id, leases),\n });\n }\n domain.db.close();\n return { domainId: domain.domainId, providerFamily: \"docker\", backendKind: \"docker-images\", state: \"verified-managed\", entries };\n}\nexport async function planTaskBuildGc(domainId: string): Promise<TaskBuildGcPlan> {\n const domain = await openDomain();\n if (domain.domainId !== domainId) {\n domain.db.close();\n throw new Error(`unknown Docker image cache domain ${domainId}`);\n }\n const now = new Date();\n const candidates: TaskBuildGcPlan[\"candidates\"][number][] = [];\n const rows = domain.db.prepare(\"SELECT * FROM entries WHERE state = 'indexed' ORDER BY COALESCE(last_successful_use_at, created_at), created_at, build_key\").all() as unknown as EntryRow[];\n for (const row of rows) {\n if (!passesGcAgePolicy(row, now.getTime()))\n continue;\n if (liveLeaseCount(domain.db, row.build_key) > 0)\n continue;\n if (liveRootCount(domain.db, row.build_key) > 0)\n continue;\n if (await imageId(row.tag) !== row.image_id)\n continue;\n if (await hasContainerReference(row.image_id))\n continue;\n const evidence = entryEvidence(row);\n candidates.push({\n buildKey: row.build_key,\n tag: row.tag,\n imageId: row.image_id,\n manifestDigest: row.manifest_digest,\n generation: row.generation,\n evidenceDigest: canonicalDigest(evidence),\n ruleId: \"max-age/task-build\",\n });\n }\n const revision = Number((domain.db.prepare(\"SELECT value FROM metadata WHERE key = 'safetyRevision'\").get() as {\n value: string;\n }).value);\n const unsigned: Omit<TaskBuildGcPlan, \"planDigest\"> = {\n schemaVersion: 1,\n planId: randomUUID(),\n domainId,\n ownerId: domain.ownerId,\n backendIdentity: domain.backendIdentity,\n authorityEpoch: domain.authorityEpoch,\n policyVersion: 1,\n registrySafetyRevision: revision,\n observedAt: now.toISOString(),\n expiresAt: new Date(now.getTime() + PLAN_TTL_MS).toISOString(),\n candidates,\n };\n const plan: TaskBuildGcPlan = { ...unsigned, planDigest: digestPlan(unsigned) };\n domain.db.prepare(\"INSERT INTO gc_plans(plan_id, created_at, expires_at, payload, digest) VALUES (?, ?, ?, ?, ?)\")\n .run(plan.planId, plan.observedAt, plan.expiresAt, JSON.stringify(plan), plan.planDigest);\n domain.db.close();\n return plan;\n}\nexport interface TaskBuildGcOutcome {\n readonly planId: string;\n readonly domainId: string;\n readonly outcomes: ReadonlyArray<{\n readonly buildKey: string;\n readonly status: \"deleted\" | \"already-absent\" | \"skipped\" | \"failed\";\n readonly reason: string;\n }>;\n}\nexport async function applyTaskBuildGc(domainId: string, planId: string): Promise<TaskBuildGcOutcome> {\n const domain = await openDomain();\n if (domain.domainId !== domainId) {\n domain.db.close();\n throw new Error(`unknown Docker image cache domain ${domainId}`);\n }\n const saved = domain.db.prepare(\"SELECT expires_at, payload, digest, outcome FROM gc_plans WHERE plan_id = ?\").get(planId) as {\n expires_at: string;\n payload: string;\n digest: string;\n outcome: string | null;\n } | undefined;\n if (saved === undefined) {\n domain.db.close();\n throw new Error(`unknown GC plan ${planId}`);\n }\n if (saved.outcome !== null) {\n const outcome = JSON.parse(saved.outcome);\n domain.db.close();\n return outcome;\n }\n if (Date.parse(saved.expires_at) < Date.now()) {\n domain.db.close();\n throw new Error(`GC plan ${planId} expired`);\n }\n const plan = JSON.parse(saved.payload) as TaskBuildGcPlan;\n const { planDigest: persistedPlanDigest, ...unsigned } = plan;\n if (saved.digest !== persistedPlanDigest || digestPlan(unsigned) !== persistedPlanDigest) {\n domain.db.close();\n throw new Error(`GC plan ${planId} is corrupt`);\n }\n if (plan.domainId !== domain.domainId ||\n plan.ownerId !== domain.ownerId ||\n plan.backendIdentity !== domain.backendIdentity ||\n plan.authorityEpoch !== domain.authorityEpoch ||\n plan.policyVersion !== 1) {\n domain.db.close();\n throw new Error(`GC plan ${planId} authority changed`);\n }\n const outcomes: Array<{\n buildKey: string;\n status: \"deleted\" | \"already-absent\" | \"skipped\" | \"failed\";\n reason: string;\n }> = [];\n for (const candidate of plan.candidates) {\n domain.db.exec(\"BEGIN IMMEDIATE\");\n let row: EntryRow | undefined;\n try {\n row = domain.db.prepare(\"SELECT * FROM entries WHERE build_key = ?\").get(candidate.buildKey) as EntryRow | undefined;\n if (row === undefined || (row.state !== \"indexed\" && row.state !== \"deleting\") || row.image_id !== candidate.imageId ||\n row.manifest_digest !== candidate.manifestDigest || row.generation !== candidate.generation ||\n canonicalDigest(entryEvidence(row)) !== candidate.evidenceDigest ||\n liveLeaseCount(domain.db, candidate.buildKey) > 0 || liveRootCount(domain.db, candidate.buildKey) > 0) {\n domain.db.exec(\"ROLLBACK\");\n outcomes.push({ buildKey: candidate.buildKey, status: \"skipped\", reason: \"entry-lease-root-or-generation-changed\" });\n continue;\n }\n domain.db.prepare(\"UPDATE entries SET state = 'deleting' WHERE build_key = ? AND generation = ? AND state IN ('indexed','deleting')\")\n .run(candidate.buildKey, candidate.generation);\n domain.db.exec(\"COMMIT\");\n }\n catch (cause) {\n domain.db.exec(\"ROLLBACK\");\n outcomes.push({ buildKey: candidate.buildKey, status: \"failed\", reason: cause instanceof Error ? cause.message : String(cause) });\n continue;\n }\n const actual = await imageId(row.tag);\n if (actual === undefined) {\n domain.db.prepare(\"UPDATE entries SET state = 'tombstoned' WHERE build_key = ? AND generation = ? AND state = 'deleting'\")\n .run(candidate.buildKey, candidate.generation);\n outcomes.push({ buildKey: candidate.buildKey, status: \"already-absent\", reason: \"provider-confirmed-absent\" });\n continue;\n }\n if (actual !== candidate.imageId || await hasContainerReference(candidate.imageId)) {\n domain.db.prepare(\"UPDATE entries SET state = 'indexed' WHERE build_key = ? AND generation = ? AND state = 'deleting'\")\n .run(candidate.buildKey, candidate.generation);\n outcomes.push({ buildKey: candidate.buildKey, status: \"skipped\", reason: \"resource-or-reference-changed\" });\n continue;\n }\n try {\n await docker([\"image\", \"rm\", candidate.imageId]);\n if (await imageId(row.tag) !== undefined || await hasContainerReference(candidate.imageId)) {\n domain.db.prepare(\"UPDATE entries SET state = 'unverified' WHERE build_key = ? AND generation = ? AND state = 'deleting'\")\n .run(candidate.buildKey, candidate.generation);\n outcomes.push({ buildKey: candidate.buildKey, status: \"failed\", reason: \"image-still-present\" });\n continue;\n }\n domain.db.prepare(\"UPDATE entries SET state = 'tombstoned' WHERE build_key = ? AND generation = ? AND state = 'deleting'\")\n .run(candidate.buildKey, candidate.generation);\n outcomes.push({ buildKey: candidate.buildKey, status: \"deleted\", reason: \"max-age/task-build\" });\n }\n catch (cause) {\n domain.db.prepare(\"UPDATE entries SET state = 'unverified' WHERE build_key = ? AND generation = ? AND state = 'deleting'\")\n .run(candidate.buildKey, candidate.generation);\n outcomes.push({ buildKey: candidate.buildKey, status: \"failed\", reason: cause instanceof Error ? cause.message : String(cause) });\n }\n }\n const result = { planId, domainId, outcomes } as const;\n domain.db.prepare(\"UPDATE gc_plans SET outcome = ? WHERE plan_id = ?\").run(JSON.stringify(result), planId);\n domain.db.close();\n return result;\n}\nexport const liveTaskBuildCacheAdminService: TaskBuildCacheAdminService = Object.freeze({\n inventory: inventoryTaskBuildDomain,\n planGc: planTaskBuildGc,\n applyGc: applyTaskBuildGc,\n});\n"]}