reeval 0.10.0 → 0.12.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 (295) hide show
  1. package/README.md +64 -39
  2. package/THIRD_PARTY_NOTICES.md +75 -106
  3. package/bin/mcp-timer.cjs +224 -0
  4. package/dist/{adapter-DWlpOtRn.js → adapter-DigeVFWC.js} +3 -3
  5. package/dist/{adapter-DWlpOtRn.js.map → adapter-DigeVFWC.js.map} +1 -1
  6. package/dist/{agent-CaS_2Sce.js → agent-CatUEo5h.js} +21 -6
  7. package/dist/{agent-CaS_2Sce.js.map → agent-CatUEo5h.js.map} +1 -1
  8. package/dist/{assemble-B9Alds-z.js → assemble-CF063ms6.js} +19 -17
  9. package/dist/assemble-CF063ms6.js.map +1 -0
  10. package/dist/assemble-CJoD_Rzr.js +1 -0
  11. package/dist/bridge/index.mjs +15 -7
  12. package/dist/{capture-CNb9SuU5.js → capture-BiD7lVaM.js} +26 -18
  13. package/dist/{capture-CNb9SuU5.js.map → capture-BiD7lVaM.js.map} +1 -1
  14. package/dist/capture-Dp3q7K7Y.js +1 -0
  15. package/dist/{cli-D303Vj5N.js → cli-B5zQCR2r.js} +266 -547
  16. package/dist/cli-B5zQCR2r.js.map +1 -0
  17. package/dist/{cli-spec-BPZbQG2p.js → cli-spec-BXIBUlaK.js} +46 -18
  18. package/dist/cli-spec-BXIBUlaK.js.map +1 -0
  19. package/dist/cli.js +2 -2
  20. package/dist/{command-BT9a37ZR.js → command-BMHXHqMT.js} +17 -14
  21. package/dist/command-BMHXHqMT.js.map +1 -0
  22. package/dist/command-C94CQNh8.js +91 -0
  23. package/dist/command-C94CQNh8.js.map +1 -0
  24. package/dist/command-CVtgyqlM.js +335 -0
  25. package/dist/command-CVtgyqlM.js.map +1 -0
  26. package/dist/{command-BLfT7vnQ.js → command-CaZgCTIw.js} +13 -17
  27. package/dist/command-CaZgCTIw.js.map +1 -0
  28. package/dist/{command-CMJtHKRa.js → command-DTgBZR0k.js} +6 -6
  29. package/dist/{command-CMJtHKRa.js.map → command-DTgBZR0k.js.map} +1 -1
  30. package/dist/{commands-1p-bIWhN.js → commands-BXzIDB3X.js} +1 -1
  31. package/dist/commands-CjpGBUWr.js +666 -0
  32. package/dist/commands-CjpGBUWr.js.map +1 -0
  33. package/dist/{config-DEgnUiU-.js → config-Dv5MG7Rp.js} +31 -34
  34. package/dist/config-Dv5MG7Rp.js.map +1 -0
  35. package/dist/{context-C1mxXh80.js → context-Dgn48BqT.js} +13 -2
  36. package/dist/context-Dgn48BqT.js.map +1 -0
  37. package/dist/contrasts-CcoMLC_y.js +101 -0
  38. package/dist/contrasts-CcoMLC_y.js.map +1 -0
  39. package/dist/db-BeqRiWLl.js +602 -0
  40. package/dist/db-BeqRiWLl.js.map +1 -0
  41. package/dist/db-CJDRVQal.js +2 -0
  42. package/dist/{dist-B8hJImYt.js → dist-CMjp3qqF.js} +81 -14
  43. package/dist/dist-CMjp3qqF.js.map +1 -0
  44. package/dist/{docker-sZrNrr82.js → docker-BbTlMmYi.js} +2 -2
  45. package/dist/{docker-sZrNrr82.js.map → docker-BbTlMmYi.js.map} +1 -1
  46. package/dist/{docker-7b_2SaH7.js → docker-CCXdbREk.js} +20 -4
  47. package/dist/{docker-7b_2SaH7.js.map → docker-CCXdbREk.js.map} +1 -1
  48. package/dist/{docker-yauK-9X8.js → docker-DC69dKxB.js} +1 -1
  49. package/dist/{doctor-BYNok4UO.js → doctor-CqttrZcs.js} +56 -22
  50. package/dist/doctor-CqttrZcs.js.map +1 -0
  51. package/dist/{egress-C4PZTSSe.js → egress-BfK_O9ce.js} +435 -31
  52. package/dist/egress-BfK_O9ce.js.map +1 -0
  53. package/dist/{environment-DNjRk0nU.js → environment-BBz1Yes9.js} +225 -12
  54. package/dist/environment-BBz1Yes9.js.map +1 -0
  55. package/dist/{evaluate-D4zeRGBF.js → evaluate-CXQ1o-pd.js} +539 -562
  56. package/dist/evaluate-CXQ1o-pd.js.map +1 -0
  57. package/dist/{evaluate-C1UVL21l.d.ts → evaluate-yjZKUexW.d.ts} +2 -2
  58. package/dist/facts-DtENlf9s.js +898 -0
  59. package/dist/facts-DtENlf9s.js.map +1 -0
  60. package/dist/{files-BXUdY8tr.js → files-B-eUpCZ1.js} +30 -7
  61. package/dist/files-B-eUpCZ1.js.map +1 -0
  62. package/dist/files-BsQbYz2i.js +65 -0
  63. package/dist/files-BsQbYz2i.js.map +1 -0
  64. package/dist/{files-DQmHE7pb.js → files-COHQLEHE.js} +6 -17
  65. package/dist/files-COHQLEHE.js.map +1 -0
  66. package/dist/files-DqCBW7i8.js +1 -0
  67. package/dist/files-Ha-jsQXf.js +1 -0
  68. package/dist/generate-Cs2TMH_k.js +1647 -0
  69. package/dist/generate-Cs2TMH_k.js.map +1 -0
  70. package/dist/{git-DfG-YJ1u.js → git-DhykwgKF.js} +2 -2
  71. package/dist/{git-DfG-YJ1u.js.map → git-DhykwgKF.js.map} +1 -1
  72. package/dist/{harness-B8QC9u0O.js → harness-BAjw1fcr.js} +3 -3
  73. package/dist/{harness-B8QC9u0O.js.map → harness-BAjw1fcr.js.map} +1 -1
  74. package/dist/harness.d.ts +1 -1
  75. package/dist/harness.js +1 -1
  76. package/dist/{header-hK-Z_Po9.js → header-kSmWatcO.js} +10 -3
  77. package/dist/{header-hK-Z_Po9.js.map → header-kSmWatcO.js.map} +1 -1
  78. package/dist/{images-0On0cztu.js → images-BmJRuTpm.js} +61 -13
  79. package/dist/images-BmJRuTpm.js.map +1 -0
  80. package/dist/index.d.ts +3 -3
  81. package/dist/index.js +4 -4
  82. package/dist/init-Bwc9byQr.js +543 -0
  83. package/dist/init-Bwc9byQr.js.map +1 -0
  84. package/dist/init-D7Y1ny1z.js +1 -0
  85. package/dist/insights-B2Xmhz9o.js +64 -0
  86. package/dist/insights-B2Xmhz9o.js.map +1 -0
  87. package/dist/{invocations-DbGfBAA_.js → invocations-CQTbP092.js} +3 -3
  88. package/dist/{invocations-DbGfBAA_.js.map → invocations-CQTbP092.js.map} +1 -1
  89. package/dist/{judge-DW_GDOmB.js → judge-Dt6KW6_O.js} +5 -3
  90. package/dist/judge-Dt6KW6_O.js.map +1 -0
  91. package/dist/judge.d.ts +7 -6
  92. package/dist/judge.js +8 -7
  93. package/dist/judge.js.map +1 -1
  94. package/dist/{live-jlfszAbb.js → live-DYd2QEyR.js} +2 -2
  95. package/dist/{live-jlfszAbb.js.map → live-DYd2QEyR.js.map} +1 -1
  96. package/dist/{model-h_cDtcRr.js → model-B-mel-Gv.js} +46 -20
  97. package/dist/model-B-mel-Gv.js.map +1 -0
  98. package/dist/model-BGKYVpoj.js +1 -0
  99. package/dist/{model-DaVCY3rb.js → model-C7tSwT7f.js} +2 -2
  100. package/dist/{model-DaVCY3rb.js.map → model-C7tSwT7f.js.map} +1 -1
  101. package/dist/{model-oqcDplJG.js → model-CWlAqmbU.js} +150 -46
  102. package/dist/model-CWlAqmbU.js.map +1 -0
  103. package/dist/model-DHY-dfoO.js +1 -0
  104. package/dist/{node-B3ydHo6t.js → node-D0mtjRAO.js} +3 -3
  105. package/dist/{node-B3ydHo6t.js.map → node-D0mtjRAO.js.map} +1 -1
  106. package/dist/{options-Bh2W63dK.js → options-CPUW97_7.js} +9 -12
  107. package/dist/options-CPUW97_7.js.map +1 -0
  108. package/dist/{pairs-CnInRu-G.js → pairs-DP6XOJby.js} +2 -2
  109. package/dist/{pairs-CnInRu-G.js.map → pairs-DP6XOJby.js.map} +1 -1
  110. package/dist/{patch-Zac5aIRM.js → patch-D4oluWzH.js} +2 -2
  111. package/dist/{patch-Zac5aIRM.js.map → patch-D4oluWzH.js.map} +1 -1
  112. package/dist/{plan-C9Cy27Ay.js → plan-OkwUcJQ9.js} +31 -12
  113. package/dist/plan-OkwUcJQ9.js.map +1 -0
  114. package/dist/plugins-CUWMnSNb.js +654 -0
  115. package/dist/plugins-CUWMnSNb.js.map +1 -0
  116. package/dist/{preflight-CPWpQeBI.js → preflight-B6pY89bF.js} +1 -1
  117. package/dist/{preflight-D7iFPKeK.js → preflight-Bjm7_ylE.js} +14 -10
  118. package/dist/preflight-Bjm7_ylE.js.map +1 -0
  119. package/dist/{prepare-doGxaAGR.js → prepare-CQmK3SBn.js} +71 -24
  120. package/dist/prepare-CQmK3SBn.js.map +1 -0
  121. package/dist/prepare-DbdgtZKe.js +2 -0
  122. package/dist/{provenance-DmE9uPVt.js → provenance-B3Y17oCC.js} +2 -2
  123. package/dist/{provenance-DmE9uPVt.js.map → provenance-B3Y17oCC.js.map} +1 -1
  124. package/dist/providers-CXN2RFz-.js +1 -0
  125. package/dist/{providers-tAOD1NQN.js → providers-eoniqK6w.js} +24 -10
  126. package/dist/providers-eoniqK6w.js.map +1 -0
  127. package/dist/query-CLRZmWBT.js +139 -0
  128. package/dist/query-CLRZmWBT.js.map +1 -0
  129. package/dist/query-CmBDYt0_.js +1 -0
  130. package/dist/{questions-DjAwMxZ3.js → questions-1XOulevV.js} +6 -6
  131. package/dist/{questions-DjAwMxZ3.js.map → questions-1XOulevV.js.map} +1 -1
  132. package/dist/{record-BKmMvZ6O.js → record-kk9M1hj-.js} +8 -4
  133. package/dist/record-kk9M1hj-.js.map +1 -0
  134. package/dist/remarks-1521zwfW.js +38 -0
  135. package/dist/remarks-1521zwfW.js.map +1 -0
  136. package/dist/remarks-BhAV1H4V.js +1 -0
  137. package/dist/remarks-DlJCqWRs.js +278 -0
  138. package/dist/remarks-DlJCqWRs.js.map +1 -0
  139. package/dist/{remote-HDRt16ew.js → remote-cE2VWfkJ.js} +3 -3
  140. package/dist/{remote-HDRt16ew.js.map → remote-cE2VWfkJ.js.map} +1 -1
  141. package/dist/resolve-C4zeccCH.js +724 -0
  142. package/dist/resolve-C4zeccCH.js.map +1 -0
  143. package/dist/resolve-D30yZYmB.js +1 -0
  144. package/dist/{results-DuauQI3Z.js → results-Drtt0uFl.js} +33 -7
  145. package/dist/results-Drtt0uFl.js.map +1 -0
  146. package/dist/{resume-BRfa8E_s.js → resume-BEFazUfy.js} +4 -4
  147. package/dist/{resume-BRfa8E_s.js.map → resume-BEFazUfy.js.map} +1 -1
  148. package/dist/rules-BFzQqPIm.js +317 -0
  149. package/dist/rules-BFzQqPIm.js.map +1 -0
  150. package/dist/run-BeMy92Us.js +88 -0
  151. package/dist/run-BeMy92Us.js.map +1 -0
  152. package/dist/{sandbox-D3A8oUb7.js → sandbox-CQaJj7n9.js} +2 -2
  153. package/dist/{sandbox-D3A8oUb7.js.map → sandbox-CQaJj7n9.js.map} +1 -1
  154. package/dist/sandbox.d.ts +1 -1
  155. package/dist/sandbox.js +1 -1
  156. package/dist/server-V4-2w0l8.js +1 -0
  157. package/dist/{server-XDleKaF_.js → server-xK0les4f.js} +8 -8
  158. package/dist/{server-XDleKaF_.js.map → server-xK0les4f.js.map} +1 -1
  159. package/dist/{shared-DYpIb1BI.js → shared-CA61BuPJ.js} +25 -3
  160. package/dist/shared-CA61BuPJ.js.map +1 -0
  161. package/dist/source-BDow_oW8.js +1 -0
  162. package/dist/{source-C8xumIWj.js → source-Q1hEKbCs.js} +2 -2
  163. package/dist/{source-C8xumIWj.js.map → source-Q1hEKbCs.js.map} +1 -1
  164. package/dist/src-B9L9yGKI.js +1 -0
  165. package/dist/{src-ofUaYbuY.js → src-Bcah6ZkT.js} +1 -1
  166. package/dist/{src-DvCg0NBs.js → src-BhmaorOU.js} +28 -6
  167. package/dist/{src-DvCg0NBs.js.map → src-BhmaorOU.js.map} +1 -1
  168. package/dist/{src-CF17Ug08.js → src-C0CeKiLU.js} +19 -4
  169. package/dist/{src-CF17Ug08.js.map → src-C0CeKiLU.js.map} +1 -1
  170. package/dist/src-C0xowZ3C.js +2 -0
  171. package/dist/src-CHIfIKUu.js +2 -0
  172. package/dist/src-DLtyz4w5.js +2 -0
  173. package/dist/src-DPIjmReZ.js +2 -0
  174. package/dist/{src-C_lPtowT.js → src-DXNh5mTr.js} +1 -1
  175. package/dist/{src-FGXhkEkH.js → src-DiLMkIr9.js} +142 -13
  176. package/dist/src-DiLMkIr9.js.map +1 -0
  177. package/dist/{src-B7treWa8.js → src-LekQrr_S.js} +324 -32
  178. package/dist/src-LekQrr_S.js.map +1 -0
  179. package/dist/src-bCnsA6Vp.js +2 -0
  180. package/dist/{src-u8_ixn_F.js → src-cbCb-MPy.js} +20 -4
  181. package/dist/src-cbCb-MPy.js.map +1 -0
  182. package/dist/{src-DvK0EIZx.js → src-qGoFkuJF.js} +55 -6
  183. package/dist/{src-DvK0EIZx.js.map → src-qGoFkuJF.js.map} +1 -1
  184. package/dist/{src-jzagbuqH.js → src-ynBVosfX.js} +1 -1
  185. package/dist/state-BQR_BCm4.js +1 -0
  186. package/dist/{state-C__9swoG.js → state-BmZ8QVZ8.js} +12 -12
  187. package/dist/{state-C__9swoG.js.map → state-BmZ8QVZ8.js.map} +1 -1
  188. package/dist/studio-app/assets/index-CnYJijyI.js +58 -0
  189. package/dist/studio-app/index.html +1 -1
  190. package/dist/suite-BaHPmAGy.js +1 -0
  191. package/dist/suite-C8sw2pox.js +481 -0
  192. package/dist/suite-C8sw2pox.js.map +1 -0
  193. package/dist/summary-0oQNGskv.js +837 -0
  194. package/dist/summary-0oQNGskv.js.map +1 -0
  195. package/dist/testing.d.ts +2 -2
  196. package/dist/testing.js +2 -2
  197. package/dist/{text-gEcKjAyp.js → text-CrVy5ioL.js} +18 -2
  198. package/dist/text-CrVy5ioL.js.map +1 -0
  199. package/dist/{transcript-BNNANU8A.js → transcript-BTxJpW4R.js} +2 -2
  200. package/dist/{transcript-BNNANU8A.js.map → transcript-BTxJpW4R.js.map} +1 -1
  201. package/dist/types-C5vI3g1C.js.map +1 -1
  202. package/dist/{types-g17bRAzt.d.ts → types-GraZtfHN.d.ts} +858 -39
  203. package/dist/usage-BDo2q_yu.js +1 -0
  204. package/dist/{command-Bge8F7Ko.js → validate-BdoXUuL_.js} +35 -383
  205. package/dist/validate-BdoXUuL_.js.map +1 -0
  206. package/dist/view/index.d.ts +20 -9
  207. package/dist/view/index.js +7 -6
  208. package/dist/views-BoUoX4_A.js +125 -0
  209. package/dist/views-BoUoX4_A.js.map +1 -0
  210. package/dist/views-noVQNCUP.js +2 -0
  211. package/dist/{worker-entry-yOchGYYv.js → worker-entry-D0-GErmU.js} +2 -2
  212. package/dist/{worker-entry-yOchGYYv.js.map → worker-entry-D0-GErmU.js.map} +1 -1
  213. package/dist/{workspace-D8sSgpiy.js → workspace-B90YDU_a.js} +1 -1
  214. package/dist/{workspace-CgyHEM0l.js → workspace-tjZFkjxC.js} +4 -4
  215. package/dist/{workspace-CgyHEM0l.js.map → workspace-tjZFkjxC.js.map} +1 -1
  216. package/package.json +10 -8
  217. package/skills/eval-rubric/SKILL.md +130 -0
  218. package/dist/agent-CURAwx_q.js +0 -334
  219. package/dist/agent-CURAwx_q.js.map +0 -1
  220. package/dist/assemble-B9Alds-z.js.map +0 -1
  221. package/dist/assemble-J5MukZFY.js +0 -1
  222. package/dist/capture-jquXZBKK.js +0 -1
  223. package/dist/cli-D303Vj5N.js.map +0 -1
  224. package/dist/cli-spec-BPZbQG2p.js.map +0 -1
  225. package/dist/command-BLfT7vnQ.js.map +0 -1
  226. package/dist/command-BT9a37ZR.js.map +0 -1
  227. package/dist/command-Bge8F7Ko.js.map +0 -1
  228. package/dist/command-BkFjijN2.js +0 -1
  229. package/dist/commands-BFx16WB8.js +0 -225
  230. package/dist/commands-BFx16WB8.js.map +0 -1
  231. package/dist/config-DEgnUiU-.js.map +0 -1
  232. package/dist/context-C1mxXh80.js.map +0 -1
  233. package/dist/db-CdHizc4_.js +0 -1406
  234. package/dist/db-CdHizc4_.js.map +0 -1
  235. package/dist/db-Dm1cRJJP.js +0 -2
  236. package/dist/dist-B8hJImYt.js.map +0 -1
  237. package/dist/doctor-BYNok4UO.js.map +0 -1
  238. package/dist/duration-CEOQww97.js +0 -26
  239. package/dist/duration-CEOQww97.js.map +0 -1
  240. package/dist/egress-C4PZTSSe.js.map +0 -1
  241. package/dist/environment-DNjRk0nU.js.map +0 -1
  242. package/dist/evaluate-D4zeRGBF.js.map +0 -1
  243. package/dist/family-D2b7WD10.js +0 -67
  244. package/dist/family-D2b7WD10.js.map +0 -1
  245. package/dist/files-BXUdY8tr.js.map +0 -1
  246. package/dist/files-BhyltlDB.js +0 -1
  247. package/dist/files-DQmHE7pb.js.map +0 -1
  248. package/dist/files-ZZPqfAo6.js +0 -1
  249. package/dist/images-0On0cztu.js.map +0 -1
  250. package/dist/init-B77Rpcqc.js +0 -360
  251. package/dist/init-B77Rpcqc.js.map +0 -1
  252. package/dist/init-BrOWin3W.js +0 -1
  253. package/dist/judge-DW_GDOmB.js.map +0 -1
  254. package/dist/model-NM3ID0uR.js +0 -1
  255. package/dist/model-h_cDtcRr.js.map +0 -1
  256. package/dist/model-nwWJvaUR.js +0 -1
  257. package/dist/model-oqcDplJG.js.map +0 -1
  258. package/dist/options-Bh2W63dK.js.map +0 -1
  259. package/dist/plan-C9Cy27Ay.js.map +0 -1
  260. package/dist/preflight-D7iFPKeK.js.map +0 -1
  261. package/dist/prepare-BGjePFQl.js +0 -2
  262. package/dist/prepare-doGxaAGR.js.map +0 -1
  263. package/dist/process-CSVO_jsc.js +0 -119
  264. package/dist/process-CSVO_jsc.js.map +0 -1
  265. package/dist/providers-gDMko8fl.js +0 -1
  266. package/dist/providers-tAOD1NQN.js.map +0 -1
  267. package/dist/query-Bes9Kh6Y.js +0 -91
  268. package/dist/query-Bes9Kh6Y.js.map +0 -1
  269. package/dist/query-C_G_svLU.js +0 -1
  270. package/dist/record-BKmMvZ6O.js.map +0 -1
  271. package/dist/results-DuauQI3Z.js.map +0 -1
  272. package/dist/server-C7sg1ndo.js +0 -1
  273. package/dist/shared-DYpIb1BI.js.map +0 -1
  274. package/dist/source-fGd0SaKP.js +0 -1
  275. package/dist/src-B7treWa8.js.map +0 -1
  276. package/dist/src-DNnG4e4R.js +0 -2
  277. package/dist/src-DTbrY1hi.js +0 -2
  278. package/dist/src-DdyJEh2v.js +0 -2
  279. package/dist/src-Dj9PAroc.js +0 -2
  280. package/dist/src-Du8H85Qq.js +0 -2
  281. package/dist/src-FGXhkEkH.js.map +0 -1
  282. package/dist/src-pJZOrYR9.js +0 -1
  283. package/dist/src-u8_ixn_F.js.map +0 -1
  284. package/dist/state-CgjQo29K.js +0 -1
  285. package/dist/studio-app/assets/index-DrQc2Yxd.js +0 -58
  286. package/dist/summary-BLAVLySU.js +0 -385
  287. package/dist/summary-BLAVLySU.js.map +0 -1
  288. package/dist/summary-DgyjUh_l.js +0 -192
  289. package/dist/summary-DgyjUh_l.js.map +0 -1
  290. package/dist/text-gEcKjAyp.js.map +0 -1
  291. package/dist/tools-GCyNYSc1.js +0 -249
  292. package/dist/tools-GCyNYSc1.js.map +0 -1
  293. package/dist/views-BW6oCDUQ.js +0 -2
  294. package/dist/views-BmQF4UCI.js +0 -225
  295. package/dist/views-BmQF4UCI.js.map +0 -1
@@ -1,8 +1,7 @@
1
1
  import { u as ownFileURL } from "./root-DICDHCtp.js";
2
- import { n as shellQuote, t as run } from "./process-CSVO_jsc.js";
3
2
  import { existsSync, lstatSync, readFileSync, readdirSync, readlinkSync, renameSync, writeFileSync } from "node:fs";
4
3
  import { tmpdir } from "node:os";
5
- import { basename, dirname, join, posix, relative } from "node:path";
4
+ import { basename, dirname, join, posix, relative, win32 } from "node:path";
6
5
  import net, { BlockList, isIP } from "node:net";
7
6
  import { createHash, generateKeyPairSync, randomBytes, randomInt, sign } from "node:crypto";
8
7
  import { fileURLToPath } from "node:url";
@@ -1177,6 +1176,119 @@ function outputTail(text, max = 8) {
1177
1176
  return stripAnsi(text).split(/\r?\n/).map((l) => l.trimEnd()).filter((l) => l.trim()).slice(-max);
1178
1177
  }
1179
1178
  //#endregion
1179
+ //#region ../sandbox-docker/src/process.ts
1180
+ const CMD_META = /([()\][%!^"`<>&|;, *?])/g;
1181
+ const cmdEscape = (arg, twice) => {
1182
+ const quoted = `"${arg.replace(/(\\*)"/g, "$1$1\\\"").replace(/(\\*)$/, "$1$1")}"`.replace(CMD_META, "^$1");
1183
+ return twice ? quoted.replace(CMD_META, "^$1") : quoted;
1184
+ };
1185
+ /**
1186
+ * How to spawn `cmd` on Windows, where npm, npx and pnpm are `.cmd` scripts that only cmd.exe
1187
+ * runs: the program PATH and PATHEXT find, and for a script, cmd.exe with every argument escaped.
1188
+ */
1189
+ function windowsSpawn(cmd, args, env = process.env, exists = existsSync) {
1190
+ const exts = (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean);
1191
+ const file = (/[\\/]/.test(cmd) ? [""] : (env.PATH ?? env.Path ?? "").split(";").filter(Boolean)).flatMap((dir) => {
1192
+ const base = dir ? win32.join(dir, cmd) : cmd;
1193
+ return [...win32.extname(cmd) ? [base] : [], ...exts.map((ext) => base + ext.toLowerCase())];
1194
+ }).find(exists) ?? cmd;
1195
+ if (!/\.(cmd|bat)$/i.test(file)) return {
1196
+ file,
1197
+ args,
1198
+ verbatim: false
1199
+ };
1200
+ const twice = /node_modules[\\/]\.bin[\\/][^\\/]+\.cmd$/i.test(file);
1201
+ const line = [win32.normalize(file).replace(CMD_META, "^$1"), ...args.map((a) => cmdEscape(a, twice))].join(" ");
1202
+ return {
1203
+ file: env.ComSpec ?? "cmd.exe",
1204
+ args: [
1205
+ "/d",
1206
+ "/s",
1207
+ "/c",
1208
+ `"${line}"`
1209
+ ],
1210
+ verbatim: true
1211
+ };
1212
+ }
1213
+ /**
1214
+ * Kills a process and everything it started: its process group on POSIX (a detached child leads
1215
+ * one), its process tree with `taskkill` on Windows, which has neither groups nor signals.
1216
+ */
1217
+ function killTree(pid) {
1218
+ if (process.platform === "win32") {
1219
+ spawn("taskkill", [
1220
+ "/pid",
1221
+ String(pid),
1222
+ "/t",
1223
+ "/f"
1224
+ ], {
1225
+ stdio: "ignore",
1226
+ windowsHide: true
1227
+ }).on("error", () => {});
1228
+ return;
1229
+ }
1230
+ try {
1231
+ process.kill(-pid, "SIGKILL");
1232
+ } catch {
1233
+ try {
1234
+ process.kill(pid, "SIGKILL");
1235
+ } catch {}
1236
+ }
1237
+ }
1238
+ /** `s` as one single-quoted POSIX shell word. */
1239
+ const shellQuote = (s) => `'${s.replaceAll("'", `'\\''`)}'`;
1240
+ function run(cmd, args, options = {}) {
1241
+ const { signal } = options;
1242
+ return new Promise((resolve, reject) => {
1243
+ if (signal?.aborted) return reject(signal.reason);
1244
+ const detached = options.detached ?? true;
1245
+ const target = process.platform === "win32" ? windowsSpawn(cmd, args, options.env ? {
1246
+ ...process.env,
1247
+ ...options.env
1248
+ } : process.env) : {
1249
+ file: cmd,
1250
+ args,
1251
+ verbatim: false
1252
+ };
1253
+ const child = spawn(target.file, target.args, {
1254
+ cwd: options.cwd,
1255
+ stdio: "pipe",
1256
+ detached: detached && !target.verbatim,
1257
+ windowsHide: true,
1258
+ windowsVerbatimArguments: target.verbatim,
1259
+ env: options.env ? {
1260
+ ...process.env,
1261
+ ...options.env
1262
+ } : process.env
1263
+ });
1264
+ const out = [];
1265
+ let stderr = "";
1266
+ child.stdout.on("data", (d) => out.push(d));
1267
+ child.stderr.on("data", (d) => {
1268
+ stderr += d;
1269
+ });
1270
+ const onAbort = () => {
1271
+ if ((detached || process.platform === "win32") && child.pid) killTree(child.pid);
1272
+ else child.kill("SIGKILL");
1273
+ };
1274
+ signal?.addEventListener("abort", onAbort, { once: true });
1275
+ child.on("error", reject);
1276
+ child.on("close", (code) => {
1277
+ signal?.removeEventListener("abort", onAbort);
1278
+ if (signal?.aborted) return reject(signal.reason);
1279
+ const stdout = Buffer.concat(out);
1280
+ resolve({
1281
+ exitCode: code ?? 1,
1282
+ stdout: options.binary ? stdout : stdout.toString(),
1283
+ stderr
1284
+ });
1285
+ });
1286
+ if (child.pid) options.onSpawn?.(child.pid);
1287
+ child.stdin.on("error", () => {});
1288
+ child.stdin.end(options.input ?? "");
1289
+ });
1290
+ }
1291
+ //#endregion
1180
1292
  //#region ../sandbox-docker/src/trace.ts
1181
1293
  /** Most of each stream a trace keeps; the rest is counted. */
1182
1294
  const MAX_STREAM = 4096;
@@ -1396,12 +1508,22 @@ for (let i = 0; i < Number(seconds); i++) {
1396
1508
  child.on("error", () => {});
1397
1509
  child.unref();
1398
1510
  }
1399
- async function dockerState(engine) {
1511
+ async function dockerState(engine, signal) {
1512
+ let missing = false;
1513
+ const format = engineSpec(engine).stateFormat;
1400
1514
  const r = await docker([
1401
1515
  "info",
1402
1516
  "--format",
1403
- engineSpec(engine).stateFormat
1404
- ], { engine }).catch(() => null);
1517
+ format
1518
+ ], {
1519
+ engine,
1520
+ signal
1521
+ }).catch((error) => {
1522
+ if (signal?.aborted) throw signal.reason;
1523
+ missing = error?.code === "ENOENT";
1524
+ return null;
1525
+ });
1526
+ if (missing) return "missing";
1405
1527
  const [version, os] = r?.exitCode === 0 ? r.stdout.toString("utf8").trim().split(/\s+/) : [];
1406
1528
  if (!version) return "down";
1407
1529
  return os === "windows" ? "windows-containers" : "running";
@@ -1489,16 +1611,16 @@ async function imageInfo(image, engine) {
1489
1611
  const HARNESS_PACKAGES = {
1490
1612
  cursor: {
1491
1613
  name: "@reeval/harness-cursor-sdk",
1492
- version: "0.1.5"
1614
+ version: "0.1.6"
1493
1615
  },
1494
1616
  "claude-code": {
1495
1617
  name: "@ai-sdk/harness-claude-code",
1496
- version: "1.0.158",
1497
- patch: "6c1cff12"
1618
+ version: "1.0.160",
1619
+ patch: "b17cde50"
1498
1620
  },
1499
1621
  antigravity: {
1500
1622
  name: "@reeval/harness-antigravity",
1501
- version: "0.1.8"
1623
+ version: "0.1.9"
1502
1624
  },
1503
1625
  opencode: {
1504
1626
  name: "@reeval/harness-opencode",
@@ -1522,7 +1644,7 @@ const HARNESS_PACKAGES = {
1522
1644
  },
1523
1645
  "grok-build": {
1524
1646
  name: "@reeval/harness-grok-build",
1525
- version: "0.1.0"
1647
+ version: "0.1.1"
1526
1648
  }
1527
1649
  };
1528
1650
  /** Every harness with an image, in {@link HARNESS_PACKAGES} order. */
@@ -1563,6 +1685,11 @@ const SANDBOX_HOME = `/home/${SANDBOX_USER}`;
1563
1685
  const SANDBOX_ROOT = "/reeval";
1564
1686
  /** The agent's working directory, relative to {@link SANDBOX_ROOT}. */
1565
1687
  const WORKSPACE_DIR = "workspace";
1688
+ /**
1689
+ * reeval's own state in the container, root's and mode 0700: outside {@link SANDBOX_ROOT}, which
1690
+ * {@link SANDBOX_USER} owns and so could rename it away and put its own in its place.
1691
+ */
1692
+ const SANDBOX_STATE = "/var/lib/reeval";
1566
1693
  const BRIDGE_PORT = 43210;
1567
1694
  //#endregion
1568
1695
  //#region ../sandbox-docker/src/egress/cert.ts
@@ -3251,9 +3378,18 @@ async function confinementArgs(options) {
3251
3378
  }
3252
3379
  /** Runtime `npm i -g` goes to the sandbox user's own prefix, whose `bin` the images put on PATH. */
3253
3380
  const userEnv = (options) => options.root ? {} : { NPM_CONFIG_PREFIX: `${SANDBOX_HOME}/.local` };
3381
+ /** Root's PATH in a privileged exec: none of the sandbox user's own `bin` directories. */
3382
+ const SYSTEM_PATH = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
3254
3383
  /** Set on every exec, so a kill can find the command's whole process tree in the container. */
3255
3384
  const EXEC_MARKER = "REEVAL_EXEC_ID";
3256
3385
  /**
3386
+ * Every exec that can create a file starts with this. An exec'd process inherits the umask of the
3387
+ * engine's shim, not the container's: since Docker 29.6 that's 0000 wherever dockerd starts
3388
+ * containerd itself (Docker-in-Docker, rootless, OrbStack), which makes homes, the workspace and
3389
+ * everything an agent writes world-writable, and tools such as fx and OpenSSH refuse them.
3390
+ */
3391
+ const EXEC_UMASK = "umask 022";
3392
+ /**
3257
3393
  * The container's cgroup counts every process the kernel killed at its memory limit: cgroup v2's
3258
3394
  * `memory.events` and v1's `memory.oom_control` both have an `oom_kill` line. Without either,
3259
3395
  * Docker's `OOMKilled` says only whether there was one.
@@ -3363,9 +3499,9 @@ async function createDockerSession(options) {
3363
3499
  "--user",
3364
3500
  "0:0",
3365
3501
  id,
3366
- "mkdir",
3367
- "-p",
3368
- SANDBOX_ROOT
3502
+ "sh",
3503
+ "-c",
3504
+ `${EXEC_UMASK} && mkdir -p ${SANDBOX_ROOT}`
3369
3505
  ], {
3370
3506
  engine,
3371
3507
  signal
@@ -3441,7 +3577,7 @@ async function createDockerSession(options) {
3441
3577
  id,
3442
3578
  "bash",
3443
3579
  "-c",
3444
- command
3580
+ `${EXEC_UMASK}; ${command}`
3445
3581
  ];
3446
3582
  const nextMarker = () => `${id.slice(0, 12)}-${++execs}`;
3447
3583
  /**
@@ -3474,6 +3610,39 @@ async function createDockerSession(options) {
3474
3610
  throw error;
3475
3611
  }
3476
3612
  };
3613
+ const runPrivileged = async (o) => {
3614
+ const marker = nextMarker();
3615
+ const args = [
3616
+ "exec",
3617
+ "--privileged",
3618
+ "--user",
3619
+ "0:0",
3620
+ "--workdir",
3621
+ o.workingDirectory ? posix.resolve(SANDBOX_ROOT, o.workingDirectory) : SANDBOX_ROOT,
3622
+ "--env",
3623
+ `${EXEC_MARKER}=${marker}`,
3624
+ "--env",
3625
+ `PATH=${SYSTEM_PATH}`,
3626
+ id,
3627
+ "/bin/sh",
3628
+ "-c",
3629
+ `${EXEC_UMASK}; ${o.command}`
3630
+ ];
3631
+ try {
3632
+ const r = await docker(args, {
3633
+ signal: o.abortSignal,
3634
+ engine
3635
+ });
3636
+ return {
3637
+ exitCode: r.exitCode,
3638
+ stdout: r.stdout.toString("utf8"),
3639
+ stderr: r.stderr
3640
+ };
3641
+ } catch (error) {
3642
+ if (o.abortSignal?.aborted) await killExec(marker);
3643
+ throw error;
3644
+ }
3645
+ };
3477
3646
  const readBinaryFile = async (o) => {
3478
3647
  const r = await docker([
3479
3648
  "exec",
@@ -3495,7 +3664,7 @@ async function createDockerSession(options) {
3495
3664
  id,
3496
3665
  "sh",
3497
3666
  "-c",
3498
- `mkdir -p ${shellQuote(posix.dirname(path))} && cat > ${shellQuote(path)}`
3667
+ `${EXEC_UMASK} && mkdir -p ${shellQuote(posix.dirname(path))} && cat > ${shellQuote(path)}`
3499
3668
  ], {
3500
3669
  input: Buffer.from(o.content),
3501
3670
  signal: o.abortSignal,
@@ -3536,6 +3705,7 @@ async function createDockerSession(options) {
3536
3705
  ...substituting,
3537
3706
  oomKills: () => oomKills(id, engine),
3538
3707
  run,
3708
+ runPrivileged,
3539
3709
  async spawn(o) {
3540
3710
  const env = envFor(o.env);
3541
3711
  const marker = nextMarker();
@@ -3661,10 +3831,16 @@ const slugify = (text, max) => text.toLowerCase().replace(/[^a-z0-9]+/g, "-").re
3661
3831
  /** The build context of reeval's base image, shipped in the package. */
3662
3832
  const DOCKER_CONTEXT = fileURLToPath(ownFileURL("docker"));
3663
3833
  /**
3834
+ * How reeval bakes a harness into an image, beyond the build context and the adapter: bump it when
3835
+ * that changes what a baked image holds, so every image baked before rebuilds on its next use.
3836
+ */
3837
+ const BAKE_REVISION = 2;
3838
+ /**
3664
3839
  * The image `docker({ from })` evals run in: `from` plus Node, git and the harness's CLI. The hash
3665
- * covers the toolchain layer too, so a change to the sandbox user or paths builds anew.
3840
+ * covers the toolchain layer and {@link BAKE_REVISION} too, so a change to the sandbox user, paths
3841
+ * or how the harness is baked builds anew.
3666
3842
  */
3667
- const harnessImageFor = (harness, from) => `${imageFor(harness)}-${slugify(from, 40) || "image"}-${sha256(toolchainDockerfile(from)).slice(0, 8)}`;
3843
+ const harnessImageFor = (harness, from) => `${imageFor(harness)}-${slugify(from, 40) || "image"}-${sha256(`${BAKE_REVISION}\0${toolchainDockerfile(from)}`).slice(0, 8)}`;
3668
3844
  /**
3669
3845
  * How each harness's CLI gets into an image: its adapter's bootstrap, and the binary it leaves
3670
3846
  * (or, for an adapter without one, a command that prints what it installed).
@@ -3674,22 +3850,22 @@ const BOOTSTRAPS = {
3674
3850
  name: "Cursor",
3675
3851
  cli: "@cursor/sdk",
3676
3852
  version: `node -p "'@cursor/sdk ' + require(process.env.HOME + '/.ai-sdk-harness/.harness-bootstrap/cursor-sdk/node_modules/@cursor/sdk/package.json').version"`,
3677
- adapter: async () => (await import("./src-DTbrY1hi.js")).createCursorSdk()
3853
+ adapter: async () => (await import("./src-C0xowZ3C.js")).createCursorSdk()
3678
3854
  },
3679
3855
  "claude-code": {
3680
3856
  name: "Claude Code",
3681
3857
  cli: "claude",
3682
- adapter: async () => (await import("./dist-B8hJImYt.js")).createClaudeCode()
3858
+ adapter: async () => (await import("./dist-CMjp3qqF.js")).createClaudeCode()
3683
3859
  },
3684
3860
  antigravity: {
3685
3861
  name: "Antigravity",
3686
3862
  cli: "agy",
3687
- adapter: async () => (await import("./src-DNnG4e4R.js")).createAntigravity()
3863
+ adapter: async () => (await import("./src-bCnsA6Vp.js")).createAntigravity()
3688
3864
  },
3689
3865
  opencode: {
3690
3866
  name: "OpenCode",
3691
3867
  cli: "opencode",
3692
- adapter: async () => (await import("./src-ofUaYbuY.js")).createOpenCode({
3868
+ adapter: async () => (await import("./src-Bcah6ZkT.js")).createOpenCode({
3693
3869
  auth: { GOOGLE_GENERATIVE_AI_API_KEY: "unused" },
3694
3870
  model: "google/unused"
3695
3871
  })
@@ -3697,7 +3873,7 @@ const BOOTSTRAPS = {
3697
3873
  goose: {
3698
3874
  name: "Goose",
3699
3875
  cli: "goose",
3700
- adapter: async () => (await import("./src-DdyJEh2v.js")).createGoose({
3876
+ adapter: async () => (await import("./src-DPIjmReZ.js")).createGoose({
3701
3877
  auth: { GOOGLE_API_KEY: "unused" },
3702
3878
  model: "unused"
3703
3879
  })
@@ -3705,17 +3881,17 @@ const BOOTSTRAPS = {
3705
3881
  pi: {
3706
3882
  name: "pi",
3707
3883
  cli: "pi",
3708
- adapter: async () => (await import("./src-jzagbuqH.js")).createPi({ auth: { GEMINI_API_KEY: "unused" } })
3884
+ adapter: async () => (await import("./src-ynBVosfX.js")).createPi({ auth: { GEMINI_API_KEY: "unused" } })
3709
3885
  },
3710
3886
  codex: {
3711
3887
  name: "Codex",
3712
3888
  cli: "codex",
3713
- adapter: async () => (await import("./src-Dj9PAroc.js")).createCodex({ auth: { OPENAI_API_KEY: "unused" } })
3889
+ adapter: async () => (await import("./src-DLtyz4w5.js")).createCodex({ auth: { OPENAI_API_KEY: "unused" } })
3714
3890
  },
3715
3891
  fx: {
3716
3892
  name: "fx",
3717
3893
  cli: "fx",
3718
- adapter: async () => (await import("./src-C_lPtowT.js")).createFx({
3894
+ adapter: async () => (await import("./src-DXNh5mTr.js")).createFx({
3719
3895
  auth: { AI_GATEWAY_API_KEY: "unused" },
3720
3896
  model: "unused/unused"
3721
3897
  })
@@ -3723,7 +3899,7 @@ const BOOTSTRAPS = {
3723
3899
  "grok-build": {
3724
3900
  name: "Grok Build",
3725
3901
  cli: "grok",
3726
- adapter: async () => (await import("./src-Du8H85Qq.js")).createGrokBuild({
3902
+ adapter: async () => (await import("./src-CHIfIKUu.js")).createGrokBuild({
3727
3903
  auth: { XAI_API_KEY: "unused" },
3728
3904
  model: "unused"
3729
3905
  })
@@ -3911,9 +4087,13 @@ const removeQuietly = async (ref, engine) => {
3911
4087
  ref
3912
4088
  ], { engine }).catch(() => {});
3913
4089
  };
3914
- /** The hash of reeval's base image build context, which its images carry as a label. */
4090
+ /**
4091
+ * The hash of reeval's base image build context and {@link BAKE_REVISION}, which its images carry
4092
+ * as a label.
4093
+ */
3915
4094
  function contextHash() {
3916
4095
  const hash = createHash("sha256");
4096
+ hash.update(`bake ${BAKE_REVISION}\0`);
3917
4097
  for (const path of contextFiles(DOCKER_CONTEXT, join(DOCKER_CONTEXT, "Dockerfile"))) {
3918
4098
  hash.update(`${path}\0`);
3919
4099
  hash.update(readFileSync(join(DOCKER_CONTEXT, path)));
@@ -4119,6 +4299,108 @@ async function buildInstallLayer(parent, steps, options = {}) {
4119
4299
  }
4120
4300
  return tag;
4121
4301
  }
4302
+ /** Where a plugin layer leaves each built plugin, by its build's hash. */
4303
+ const PLUGIN_BUILDS_DIR = `${SANDBOX_ROOT}/plugin-builds`;
4304
+ /**
4305
+ * The sha256 of a plugin build's source as the layer gets it: every file `docker build` sends from
4306
+ * `context` (less `.dockerignore` and `.git`), with its executable bit or symlink target.
4307
+ */
4308
+ function sourceTreeHash(context) {
4309
+ const hash = createHash("sha256");
4310
+ for (const path of contextFiles(context, null)) {
4311
+ if (path === ".git" || path.startsWith(".git/")) continue;
4312
+ const full = join(context, path);
4313
+ const stat = lstatSync(full);
4314
+ hash.update(`${path}\0${stat.mode & 73 ? "x" : "-"}\0`);
4315
+ hash.update(stat.isSymbolicLink() ? readlinkSync(full) : readFileSync(full));
4316
+ hash.update("\0");
4317
+ }
4318
+ return hash.digest("hex");
4319
+ }
4320
+ /** The hash a plugin layer's tag and directory carry: commit, tree and build. */
4321
+ const pluginBuildKey = (b) => sha256(JSON.stringify({
4322
+ commit: b.commit,
4323
+ tree: b.tree,
4324
+ path: b.path,
4325
+ cwd: b.cwd,
4326
+ run: b.steps
4327
+ }));
4328
+ /** The image a plugin build makes on `parent`: the parent's id, then the build's hash. */
4329
+ const pluginLayerTag = (parent, b) => `reeval-plugin:${parent.id.replace(/^sha256:/, "").slice(0, 12)}-${pluginBuildKey(b).slice(0, 16)}`;
4330
+ /** Where a plugin layer leaves the plugin's directory. */
4331
+ const pluginBuildDir = (b) => `${PLUGIN_BUILDS_DIR}/${pluginBuildKey(b).slice(0, 16)}`;
4332
+ /** The line a plugin build's script fails with when its `cwd` isn't in the source. */
4333
+ const noCwd = (cwd) => `reeval: build cwd ${cwd} isn't a directory in the source`;
4334
+ /**
4335
+ * A plugin build's commands as one script, run from `cwd` under `src` (the source's root), stopping
4336
+ * at the first failure as an install script does, or before any when `cwd` isn't there.
4337
+ */
4338
+ const pluginBuildScript = (b, src) => installScript(b.steps).replaceAll("reeval: install ", "reeval: build ").replace(/^cd \/\n/, `cd ${shellQuote(`${src}/${b.cwd}`)} || { echo ${shellQuote(noCwd(b.cwd))} >&2; exit 1; }\n`);
4339
+ /**
4340
+ * Builds a plugin's layer on `parent` if it's missing: the whole source, then its commands from
4341
+ * `cwd` as root with the sandbox user's home as HOME (as an install layer runs), keeping only the
4342
+ * plugin's directory at {@link pluginBuildDir}. Secrets and the workspace never exist here.
4343
+ */
4344
+ async function buildPluginLayer(parent, b, options) {
4345
+ const { signal, engine } = options;
4346
+ const tag = pluginLayerTag(parent, b);
4347
+ if ((await docker([
4348
+ "image",
4349
+ "inspect",
4350
+ "--format",
4351
+ "{{.Created}}",
4352
+ tag
4353
+ ], {
4354
+ signal,
4355
+ engine
4356
+ })).exitCode === 0) return tag;
4357
+ const src = "/tmp/reeval-plugin-src";
4358
+ const script = pluginBuildScript(b, src);
4359
+ const encoded = Buffer.from(script).toString("base64");
4360
+ const home = `$(getent passwd ${SANDBOX_USER} | cut -d: -f6)`;
4361
+ const dir = pluginBuildDir(b);
4362
+ const dockerfile = [
4363
+ `FROM ${parent.ref}`,
4364
+ "USER root",
4365
+ `COPY . ${src}`,
4366
+ `RUN rm -rf ${src}/.git && echo ${encoded} | base64 -d > /tmp/reeval-plugin-build.sh \\`,
4367
+ ` && if id -u ${SANDBOX_USER} >/dev/null 2>&1; then export HOME="${home}"; fi \\`,
4368
+ " && bash /tmp/reeval-plugin-build.sh && rm /tmp/reeval-plugin-build.sh \\",
4369
+ ` && mkdir -p ${dir} && cp -a ${shellQuote(`${src}/${b.path}`)}/. ${dir}/ && rm -rf ${src} ${dir}/.git \\`,
4370
+ ` && chmod -R a+rX ${dir} \\`,
4371
+ ` && { ! id -u ${SANDBOX_USER} >/dev/null 2>&1 || find "$HOME" -xdev ! -user ${SANDBOX_USER} -exec chown -h ${SANDBOX_USER}: {} +; }`,
4372
+ `WORKDIR ${SANDBOX_ROOT}`
4373
+ ].join("\n");
4374
+ const build = await docker([
4375
+ "build",
4376
+ "--progress",
4377
+ "plain",
4378
+ ...BUILT_BY,
4379
+ "--tag",
4380
+ tag,
4381
+ "-f",
4382
+ "-",
4383
+ b.context
4384
+ ], {
4385
+ input: dockerfile,
4386
+ signal,
4387
+ engine
4388
+ });
4389
+ const output = `${build.stdout.toString("utf8")}${build.stderr}`;
4390
+ options.output?.write(`${script}\n${dockerfile}\n\n${output}`);
4391
+ if (build.exitCode !== 0) {
4392
+ const failed = /reeval: build (\d+\/\d+) exited (\d+): (.*)/.exec(output);
4393
+ const missing = output.includes(noCwd(b.cwd));
4394
+ throw buildError(output, {
4395
+ stage: "plugin",
4396
+ ref: tag,
4397
+ headline: `Building ${options.name}`,
4398
+ log: options.output?.path ?? null,
4399
+ engine
4400
+ }, () => missing ? noCwd(b.cwd).slice(8) : failed ? `build ${failed[1]} exited ${failed[2]}: ${clipLine(failed[3] ?? "")}` : null, (line) => !line.startsWith("reeval: build "));
4401
+ }
4402
+ return tag;
4403
+ }
4122
4404
  /** The build arg a Dockerfile can start `FROM` to layer on reeval's sandbox image. */
4123
4405
  const REEVAL_BASE_ARG = "REEVAL_BASE";
4124
4406
  /**
@@ -4156,11 +4438,14 @@ function dockerignoreMatcher(text) {
4156
4438
  return excluded;
4157
4439
  };
4158
4440
  }
4159
- /** Files in the build context that `docker build` would send, sorted, relative to `context`. */
4441
+ /**
4442
+ * Files in the build context that `docker build` would send, sorted, relative to `context`. A
4443
+ * Dockerfile read from stdin (`dockerfile` null) has no `<Dockerfile>.dockerignore` of its own.
4444
+ */
4160
4445
  function contextFiles(context, dockerfile) {
4161
- const own = [`${dockerfile}.dockerignore`, join(context, ".dockerignore")].find(existsSync);
4446
+ const own = [...dockerfile ? [`${dockerfile}.dockerignore`] : [], join(context, ".dockerignore")].find(existsSync);
4162
4447
  const ignored = dockerignoreMatcher(own ? readFileSync(own, "utf8") : "");
4163
- const always = /* @__PURE__ */ new Set([relative(context, dockerfile), ".dockerignore"]);
4448
+ const always = /* @__PURE__ */ new Set([...dockerfile ? [relative(context, dockerfile)] : [], ".dockerignore"]);
4164
4449
  const files = [];
4165
4450
  const walk = (rel) => {
4166
4451
  for (const entry of readdirSync(join(context, rel), { withFileTypes: true })) {
@@ -4240,6 +4525,13 @@ async function buildDockerfile(dockerfile, options) {
4240
4525
  return tag;
4241
4526
  }
4242
4527
  //#endregion
4243
- export { removeContainerDetached as $, hostAllowed as A, WORKSPACE_DIR as B, applyTransformations as C, HARNESS_HOSTS as D, DOCKER_EGRESS as E, HARNESS_PACKAGES as F, docker as G, harnessLabel as H, LABEL as I, dockerOk as J, dockerAvailable as K, SANDBOX_HOME as L, BASE_IMAGE as M, BRIDGE_PORT as N, PACKAGE_HOSTS as O, DEFAULT_IMAGE as P, isRegistryDigest as Q, SANDBOX_ROOT as R, placeholder as S, onEndpoint as T, imageFor as U, adapterVersion as V, isBakedHarness as W, imageInfo as X, dockerState as Y, imageTags as Z, ROOT_CAPABILITIES as _, buildInstallLayer as a, isTransient as at, CA_PATH as b, dockerfileTag as c, ENGINES as ct, installLayerTag as d, normalizeImageId as dt, onDockerCommand as et, installScript as f, DEFAULT_LIMITS as g, usesReevalBase as h, buildImage as i, failureCause as it, BAKED_HARNESSES as j, defaultAllowedHosts as k, dockerignoreMatcher as l, dockerSeccompFile as lt, resolveFrom as m, REEVAL_BASE_ARG as n, RETRY_DELAYS as nt, contextFiles as o, parseBuildOutput as ot, pruneImages as p, dockerCapacity as q, buildDockerfile as r, causeLine as rt, contextHash as s, retryTransient as st, DOCKER_CONTEXT as t, ImageBuildError as tt, harnessImageFor as u, engineSpec as ut, createDockerSession as v, matches as w, PROXY_PORT as x, dockerSandboxProvider as y, SANDBOX_USER as z };
4528
+ //#region ../sandbox-docker/src/mcp-timer.ts
4529
+ /**
4530
+ * reeval's MCP start-up timer, shipped in the package: a Node script that runs a stdio MCP server
4531
+ * and logs when it answers `initialize` (see its header). It runs in any sandbox with `node`.
4532
+ */
4533
+ const MCP_TIMER = fileURLToPath(ownFileURL("bin/mcp-timer.cjs"));
4534
+ //#endregion
4535
+ export { docker as $, applyTransformations as A, BRIDGE_PORT as B, DEFAULT_LIMITS as C, CA_PATH as D, dockerSandboxProvider as E, PACKAGE_HOSTS as F, SANDBOX_ROOT as G, HARNESS_PACKAGES as H, defaultAllowedHosts as I, WORKSPACE_DIR as J, SANDBOX_STATE as K, hostAllowed as L, onEndpoint as M, DOCKER_EGRESS as N, PROXY_PORT as O, HARNESS_HOSTS as P, isBakedHarness as Q, BAKED_HARNESSES as R, usesReevalBase as S, createDockerSession as T, LABEL as U, DEFAULT_IMAGE as V, SANDBOX_HOME as W, harnessLabel as X, adapterVersion as Y, imageFor as Z, pluginBuildKey as _, retryTransient as _t, buildDockerfile as a, imageTags as at, resolveFrom as b, engineSpec as bt, buildPluginLayer as c, onDockerCommand as ct, dockerfileTag as d, ImageBuildError as dt, dockerAvailable as et, dockerignoreMatcher as f, RETRY_DELAYS as ft, pluginBuildDir as g, parseBuildOutput as gt, installScript as h, isTransient as ht, REEVAL_BASE_ARG as i, imageInfo as it, matches as j, placeholder as k, contextFiles as l, run as lt, installLayerTag as m, failureCause as mt, DOCKER_CONTEXT as n, dockerOk as nt, buildImage as o, isRegistryDigest as ot, harnessImageFor as p, causeLine as pt, SANDBOX_USER as q, PLUGIN_BUILDS_DIR as r, dockerState as rt, buildInstallLayer as s, removeContainerDetached as st, MCP_TIMER as t, dockerCapacity as tt, contextHash as u, shellQuote as ut, pluginLayerTag as v, ENGINES as vt, ROOT_CAPABILITIES as w, sourceTreeHash as x, normalizeImageId as xt, pruneImages as y, dockerSeccompFile as yt, BASE_IMAGE as z };
4244
4536
 
4245
- //# sourceMappingURL=src-B7treWa8.js.map
4537
+ //# sourceMappingURL=src-LekQrr_S.js.map