elanous 0.2.38 → 0.2.41

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 (712) hide show
  1. package/README.md +7 -7
  2. package/apps/pwa/out/404/index.html +1 -1
  3. package/apps/pwa/out/404.html +1 -1
  4. package/apps/pwa/out/_next/static/{RrjXTwz-urRAbChP1bX02 → GiOLWmt4MqDZePubBjA4Q}/_buildManifest.js +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1115.434ae2ecb0ad986d.js +149 -0
  6. package/apps/pwa/out/_next/static/chunks/1121.667cec0bcdbb3fdb.js +36 -0
  7. package/apps/pwa/out/_next/static/chunks/1178.1aa9cad0e7695427.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1197-54da59d250a6e476.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/{5203.51e5d8b5f1dcfe53.js → 1219.7e17964e0e7cd8e5.js} +3 -3
  10. package/apps/pwa/out/_next/static/chunks/1245.1cfd13b26dbd71d6.js +287 -0
  11. package/apps/pwa/out/_next/static/chunks/1494-f93046ff5c5a124d.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/1609.2b312797599b8e45.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1661.0dd330f3d89f73f3.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/167-0c121e4b47e0f9da.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1700.cdc2bf8cc685e221.js +90 -0
  16. package/apps/pwa/out/_next/static/chunks/1703-78e46acad29f3cfc.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/{7573.2376e13c9c21f1f8.js → 1765.679b29625c8e88d4.js} +2 -2
  18. package/apps/pwa/out/_next/static/chunks/{3528.e4b8ab70d339f965.js → 1800.f7ff51dc4978a958.js} +1 -1
  19. package/apps/pwa/out/_next/static/chunks/1971-7efb628c471dc5a0.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/1999-8de7b7bb36801913.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2073.689dcb2680113d76.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2198-557d49184104d165.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/221-440ce67fa9f5c839.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/{8879.ac06755bcf3e44a1.js → 2263.e09b6edea33bad2d.js} +1 -1
  25. package/apps/pwa/out/_next/static/chunks/2427-8ed8e98624cbd664.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2457-725c5827bc003795.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2491-2718b15a5ccb75a5.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2527-5c636a43c7cc5dde.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2692-1027cb16fe4ccf49.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/2743.5d3f76948be32b34.js +41 -0
  31. package/apps/pwa/out/_next/static/chunks/2773.0e80b9d325fb5635.js +32 -0
  32. package/apps/pwa/out/_next/static/chunks/2873-0f3cb56c8e3528ea.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/{9fe1b809.738da85c8b17e3fb.js → 2fdf2931.b431eee4fb468bc3.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/{eaad0cba.771200940c529df7.js → 2fe2c302.41b517f88d6fe502.js} +1 -1
  35. package/apps/pwa/out/_next/static/chunks/3097.864e92bdaa2f4d15.js +79 -0
  36. package/apps/pwa/out/_next/static/chunks/3136-d6870ba63300a93e.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3173-0289113d434e83b7.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3230-49298c3b73ef2268.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/325-dd9208a1a0ab7ce4.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3283.528f430dd043fb4e.js +74 -0
  41. package/apps/pwa/out/_next/static/chunks/3295.cc8cb13b8f0dae1a.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/3688-86e3b88abf18cb3b.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/3804-7220467a5473a8df.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/3808.3e1e247ce7bdf889.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/{b7478fef.5917716286213fcc.js → 385e4574.e9886ab32759eda3.js} +3 -3
  46. package/apps/pwa/out/_next/static/chunks/3927.b5473ad109da44c5.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/3934-98ea94832e194796.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4133.2056bb4d78f621af.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/4156.ba4de4a3664f04b4.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4297-239ca82f293faab0.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/4320-dcc5a7734126f4c9.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4434.94b4c552a2d91e69.js +148 -0
  53. package/apps/pwa/out/_next/static/chunks/{8911.bf5e712acb25fb6c.js → 4527.a69f2894d1bc9f4a.js} +1 -1
  54. package/apps/pwa/out/_next/static/chunks/4579.03e4092f73950965.js +226 -0
  55. package/apps/pwa/out/_next/static/chunks/{5307.d7328020227880c2.js → 4667.97e31aa38c95c475.js} +4 -4
  56. package/apps/pwa/out/_next/static/chunks/{6142.913b44e260a3f925.js → 4702.4a4adc1f16d7c93b.js} +1 -1
  57. package/apps/pwa/out/_next/static/chunks/4815.481501c57b3568d9.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/487-d16e698ef14662d9.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/4888-7a38bf522c9cc6fe.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/5034-30e429d6bb086881.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5040-35c494e60dadd97d.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/50c6ab1e.81a96e419350909d.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/5154.4b6a836179356f30.js +94 -0
  64. package/apps/pwa/out/_next/static/chunks/{8487.291666583bebe640.js → 5159.115f1c2ca471386c.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/5228-a8200df486278f2d.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/530.d26346e18089640a.js +115 -0
  67. package/apps/pwa/out/_next/static/chunks/5379.97af106d09566f69.js +8 -0
  68. package/apps/pwa/out/_next/static/chunks/{89d6c04f-6b8ab341748e468a.js → 53aeb4ee-51c92f8d683f5220.js} +1 -1
  69. package/apps/pwa/out/_next/static/chunks/{3291.f6c1005387d514bd.js → 5471.1e611302ed3a7c53.js} +2 -2
  70. package/apps/pwa/out/_next/static/chunks/5479-b6372e762719f92f.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/5534-699c5cbcbc96c5d7.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/{3086.fb14b60ce98b53d3.js → 5574.f35accf4f132b29d.js} +1 -1
  73. package/apps/pwa/out/_next/static/chunks/5701.9c4e8f250312eeee.js +24 -0
  74. package/apps/pwa/out/_next/static/chunks/{1632.7d87f998e714bede.js → 5744.b9415e18ad623100.js} +1 -1
  75. package/apps/pwa/out/_next/static/chunks/{5300.677c97e0393742e6.js → 5892.2526d962339662d8.js} +1 -1
  76. package/apps/pwa/out/_next/static/chunks/5937.c2df9e3447e1f667.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/5941.8210cc93c9202c0a.js +286 -0
  78. package/apps/pwa/out/_next/static/chunks/{7161-8f22db3ec5ed005e.js → 5947-135e26537d80a6b9.js} +3 -3
  79. package/apps/pwa/out/_next/static/chunks/{3124-561f7f037943cde2.js → 5964-7e21164a8f2cf0ce.js} +1 -1
  80. package/apps/pwa/out/_next/static/chunks/5975.4004f820ae3cecd5.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6142-7ccd48795d7abd55.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6160.bf9177b8c1bfb243.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6398.71ba0690c8027555.js +27 -0
  84. package/apps/pwa/out/_next/static/chunks/6492.2bd5c10edc1a064e.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/6552.a3840aa7da35ad68.js +62 -0
  86. package/apps/pwa/out/_next/static/chunks/6736.1e36d3ac5fa5e41d.js +24 -0
  87. package/apps/pwa/out/_next/static/chunks/6874.d5cf7eb8edb2cabe.js +2 -0
  88. package/apps/pwa/out/_next/static/chunks/6900.3ccbe069bdd4556a.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/71327eb4.add50b365f94bf3a.js +122 -0
  90. package/apps/pwa/out/_next/static/chunks/7136.deca3e3a2ddaa374.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7139-ee9f8ed2677a40b3.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{2415.738b777642a02233.js → 7191.fdc955f7d96064a4.js} +1 -1
  93. package/apps/pwa/out/_next/static/chunks/7423-e0aa5d9e2962120e.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7453.afc1ea7e05d56a8c.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/7503-5e6a3d7fe67e4a0c.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/7761-476fd7bf768abd34.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/7975.eafb12097a0a9e62.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/{1026-44010f405704050c.js → 8050-9b364bdef8f71927.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/8152.64e253c35cccfaae.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/8190.620f0231b3924bcb.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/83184dcd-0ee6247ff41eb3f2.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8448.45b6b1f1a99eeb35.js +104 -0
  103. package/apps/pwa/out/_next/static/chunks/8464-e24f10451b658aac.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8477.e4c944bb3aa5d2f3.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8710.ca385257d5ca422e.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8830.627ccf294ec2465c.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8880.64c445592f04acaf.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8981.c706964c8ba27aff.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{5638.107314dc479e2f37.js → 9048.212083de42d25be3.js} +2 -2
  110. package/apps/pwa/out/_next/static/chunks/9053.bd0fffaff8d3f836.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/9161-c66e723d7ec9d682.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/9185.1ecdf9b65c0bb684.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/9356.fccd5f58086b4ff5.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/9446.dc0406109371d329.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9506.dcf25d467a42627e.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/{8019.21ca554a821dad01.js → 9507.7026657a2f47eb64.js} +16 -16
  117. package/apps/pwa/out/_next/static/chunks/9541.eb8e2f8480c7feca.js +93 -0
  118. package/apps/pwa/out/_next/static/chunks/9577.ed7582186efa5482.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9579.4a8169600fff2058.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9642-ff2e039eb62e3b92.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9659-8f2323348113ad80.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9724.4c5623af2db43153.js +34 -0
  123. package/apps/pwa/out/_next/static/chunks/{6493.27ad77de7aac7966.js → 9834.63ab2bbc3153172e.js} +1 -1
  124. package/apps/pwa/out/_next/static/chunks/{3389.012c70767a872f9b.js → 9869.81a1e24ca682d5a0.js} +1 -1
  125. package/apps/pwa/out/_next/static/chunks/{8994d93e.33ba491f95345fc2.js → a0a01613.6d1cca322238d7fe.js} +1 -1
  126. package/apps/pwa/out/_next/static/chunks/{de8b930d.d94c0f42acf807fc.js → addc2b32.8c4ff8f0aefe987d.js} +1 -1
  127. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-8d9d76ea322d855c.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed2c4e59f9f1fe21.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-2dc99e03c5d76ca0.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/board/page-b5a3a788330e920f.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-866aac5ff226a7f3.js → page-14949db884bfa672.js} +1 -1
  132. package/apps/pwa/out/_next/static/chunks/app/bots/page-ea76c85b36388a97.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/ceo/page-01716d20af62d325.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/chat/page-62baf6881a64b1e9.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/consult/page-f89ba590c2af8afa.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/control/page-22f8b0f78d9637e5.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/decisions/page-817f9d7e6820be80.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/design-check/page-ffb9bc0d2650249a.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/editor/page-f6d0e64873c0f629.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/exec/page-8bfa0d4ba23a209d.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/field/page-f5060462249e32c7.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/healthz/route-8d9d76ea322d855c.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/inside/page-b2049f8b1ef79117.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/intake/page-1446c5fa93907f11.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/layout-b48a7a07c5204156.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/live/page-e974b8c4ca47614c.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/live-run/page-8a919b869bd28594.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/loops/page-d31b8de6bfcd72ed.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/market/page-64765f817909db29.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-d128c8569a36ee9b.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/morning/page-b2679d357e9b9270.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/not-found-6fabec98a9e7b269.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/observatory/page-048f30149dcf1349.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-9113181d6b5a2725.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-40f9e19149024298.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-1e7a755a13227611.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3c8f8b67a203cf07.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/page-18032f5437215062.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/reflection/page-da3b739192fd0ee3.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d332545571bd6fd1.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/sessions/page-5237aa5b3f3b8ec5.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a142dfb0331a05f5.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/settings/page-d16e56c3989c147e.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6b6593600869e2cd.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/setup/layout-8d9d76ea322d855c.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/setup/page-29e8b8a8396b55cb.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/share/page-b3414d856a1a7e2f.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c3affa52b7ce961b.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f21dddf9f95b6fab.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/term/page-f5a30a24745bf088.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/today/page-8c8569a09b4d4e34.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/trace/page-2ce32722c0243483.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/vault/page-4767b0d9c0a98c6c.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-116ee1339c387a75.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/app/workflows/page-35e8c50ca4ef7ffc.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/app/workspace/page-52e17113356bb891.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7458ae05ed2ac1a0.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/b2271e54.c1de3347976e90b0.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/{b7459770.6539b11860eb8a9c.js → c0c1a699.0ba79f97005965d4.js} +7 -7
  180. package/apps/pwa/out/_next/static/chunks/framework-ad6c9dd524ad6ef8.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/main-app-2ddd1f2b44d6aa59.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/main-e3d82bdc358d20c5.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/pages/_app-71d5aa3896e1655f.js +1 -0
  184. package/apps/pwa/out/_next/static/chunks/pages/_error-03ffc54e00438546.js +1 -0
  185. package/apps/pwa/out/_next/static/chunks/webpack-56bb89af5a611d0b.js +1 -0
  186. package/apps/pwa/out/approvals/index.html +1 -1
  187. package/apps/pwa/out/approvals/index.txt +22 -22
  188. package/apps/pwa/out/autopilot/index.html +1 -1
  189. package/apps/pwa/out/autopilot/index.txt +22 -22
  190. package/apps/pwa/out/board/index.html +1 -1
  191. package/apps/pwa/out/board/index.txt +22 -22
  192. package/apps/pwa/out/botlab/index.html +1 -1
  193. package/apps/pwa/out/botlab/index.txt +21 -21
  194. package/apps/pwa/out/bots/index.html +1 -1
  195. package/apps/pwa/out/bots/index.txt +21 -21
  196. package/apps/pwa/out/ceo/index.html +1 -1
  197. package/apps/pwa/out/ceo/index.txt +22 -22
  198. package/apps/pwa/out/chat/index.html +1 -1
  199. package/apps/pwa/out/chat/index.txt +21 -21
  200. package/apps/pwa/out/consult/index.html +1 -1
  201. package/apps/pwa/out/consult/index.txt +22 -22
  202. package/apps/pwa/out/control/index.html +1 -1
  203. package/apps/pwa/out/control/index.txt +22 -22
  204. package/apps/pwa/out/decisions/index.html +1 -1
  205. package/apps/pwa/out/decisions/index.txt +21 -21
  206. package/apps/pwa/out/design-check/index.html +1 -1
  207. package/apps/pwa/out/design-check/index.txt +22 -22
  208. package/apps/pwa/out/editor/index.html +1 -1
  209. package/apps/pwa/out/editor/index.txt +22 -22
  210. package/apps/pwa/out/exec/index.html +1 -1
  211. package/apps/pwa/out/exec/index.txt +22 -22
  212. package/apps/pwa/out/field/index.html +1 -1
  213. package/apps/pwa/out/field/index.txt +22 -22
  214. package/apps/pwa/out/healthz +1 -1
  215. package/apps/pwa/out/index.html +1 -1
  216. package/apps/pwa/out/index.txt +21 -21
  217. package/apps/pwa/out/inside/index.html +1 -1
  218. package/apps/pwa/out/inside/index.txt +21 -21
  219. package/apps/pwa/out/intake/index.html +1 -1
  220. package/apps/pwa/out/intake/index.txt +22 -22
  221. package/apps/pwa/out/live/index.html +1 -1
  222. package/apps/pwa/out/live/index.txt +22 -22
  223. package/apps/pwa/out/live-run/index.html +1 -1
  224. package/apps/pwa/out/live-run/index.txt +22 -22
  225. package/apps/pwa/out/loops/index.html +1 -1
  226. package/apps/pwa/out/loops/index.txt +21 -21
  227. package/apps/pwa/out/market/index.html +1 -1
  228. package/apps/pwa/out/market/index.txt +21 -21
  229. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  230. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  231. package/apps/pwa/out/morning/index.html +1 -1
  232. package/apps/pwa/out/morning/index.txt +22 -22
  233. package/apps/pwa/out/observatory/index.html +1 -1
  234. package/apps/pwa/out/observatory/index.txt +22 -22
  235. package/apps/pwa/out/ops/checklist/index.html +1 -1
  236. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  237. package/apps/pwa/out/ops/release/index.html +1 -1
  238. package/apps/pwa/out/ops/release/index.txt +21 -21
  239. package/apps/pwa/out/ops/seats/index.html +1 -1
  240. package/apps/pwa/out/ops/seats/index.txt +21 -21
  241. package/apps/pwa/out/outputs/index.html +1 -1
  242. package/apps/pwa/out/outputs/index.txt +21 -21
  243. package/apps/pwa/out/reflection/index.html +1 -1
  244. package/apps/pwa/out/reflection/index.txt +22 -22
  245. package/apps/pwa/out/scheduler/index.html +1 -1
  246. package/apps/pwa/out/scheduler/index.txt +22 -22
  247. package/apps/pwa/out/sessions/index.html +1 -1
  248. package/apps/pwa/out/sessions/index.txt +21 -21
  249. package/apps/pwa/out/settings/devices/index.html +1 -1
  250. package/apps/pwa/out/settings/devices/index.txt +22 -22
  251. package/apps/pwa/out/settings/index.html +1 -1
  252. package/apps/pwa/out/settings/index.txt +22 -22
  253. package/apps/pwa/out/setup/done/index.html +1 -1
  254. package/apps/pwa/out/setup/done/index.txt +22 -22
  255. package/apps/pwa/out/setup/index.html +1 -1
  256. package/apps/pwa/out/setup/index.txt +22 -22
  257. package/apps/pwa/out/share/index.html +1 -1
  258. package/apps/pwa/out/share/index.txt +22 -22
  259. package/apps/pwa/out/showroom/index.html +1 -1
  260. package/apps/pwa/out/showroom/index.txt +21 -21
  261. package/apps/pwa/out/tasks/index.html +1 -1
  262. package/apps/pwa/out/tasks/index.txt +22 -22
  263. package/apps/pwa/out/term/index.html +1 -1
  264. package/apps/pwa/out/term/index.txt +22 -22
  265. package/apps/pwa/out/today/index.html +1 -1
  266. package/apps/pwa/out/today/index.txt +22 -22
  267. package/apps/pwa/out/trace/index.html +1 -1
  268. package/apps/pwa/out/trace/index.txt +22 -22
  269. package/apps/pwa/out/vault/index.html +1 -1
  270. package/apps/pwa/out/vault/index.txt +22 -22
  271. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  272. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  273. package/apps/pwa/out/workflows/index.html +1 -1
  274. package/apps/pwa/out/workflows/index.txt +22 -22
  275. package/apps/pwa/out/workspace/index.html +1 -1
  276. package/apps/pwa/out/workspace/index.txt +22 -22
  277. package/apps/pwa/out/worktrees/index.html +1 -1
  278. package/apps/pwa/out/worktrees/index.txt +22 -22
  279. package/bin/elanous.mjs +6 -1
  280. package/catalog/models/openai/gpt-6.1-sol.yaml +16 -0
  281. package/catalog/models/openai/gpt-6.1-terra.yaml +16 -0
  282. package/graphs/demo/persona-marketer/fixtures/marketer-scenario.yaml +10 -0
  283. package/graphs/demo/persona-marketer/persona-marketer.yaml +25 -0
  284. package/graphs/demo/persona-marketer/recipes.yaml +19 -0
  285. package/graphs/demo/persona-teacher/lesson-pack.yaml +16 -0
  286. package/graphs/demo/persona-teacher/recipes.yaml +17 -0
  287. package/graphs/demo/persona-teacher/weekly-lesson.yaml +36 -0
  288. package/graphs/overlays/stop-heal-ladder.yaml +23 -2
  289. package/graphs/release/release-loop.yaml +3 -1
  290. package/graphs/units/gate/gate.yaml +20 -0
  291. package/graphs/units/git/git.yaml +26 -0
  292. package/graphs/units/implement/implement.yaml +19 -0
  293. package/graphs/units/landing/landing.yaml +18 -0
  294. package/graphs/units/review/review.yaml +20 -0
  295. package/graphs/units/verbs/recipes.yaml +3 -0
  296. package/graphs/units/verbs/research.yaml +20 -0
  297. package/graphs/video/explainer-line.yaml +4 -1
  298. package/graphs/work/research-report.yaml +11 -1
  299. package/package.json +1 -1
  300. package/scripts/dead-code/report.ts +169 -0
  301. package/scripts/disk-steward.ts +46 -0
  302. package/scripts/fleet/node-setup.sh +50 -0
  303. package/scripts/graph-units/verbs/research.ts +55 -0
  304. package/scripts/lib/morning-report-options.ts +3 -4
  305. package/scripts/lib/tui-regress-evidence.ts +56 -0
  306. package/scripts/llm-cost-ledger.ts +179 -8
  307. package/scripts/measure-nl-routing-corpus.ts +10 -2
  308. package/scripts/morning-report.ts +5 -1
  309. package/scripts/persona-teacher/weekly-lesson-node.ts +172 -0
  310. package/scripts/public-copy-lint.ts +163 -19
  311. package/scripts/public-export.ts +15 -7
  312. package/scripts/ratchets/train-side-invariants.sh +0 -1
  313. package/scripts/release-loop/export-check-node.ts +21 -3
  314. package/scripts/release-loop/gate-autoheal.ts +117 -0
  315. package/scripts/release-loop/gate-baseline-receipt.ts +8 -1
  316. package/scripts/release-loop/gate-diff.ts +22 -3
  317. package/scripts/release-loop/gate-node.ts +583 -64
  318. package/scripts/release-loop/gate-shard-dispatch.ts +128 -0
  319. package/scripts/release-loop/gate-shard-load-flaky.ts +256 -0
  320. package/scripts/release-loop/gate-shard-receipts.ts +89 -0
  321. package/scripts/release-loop/gate-triage-node.ts +70 -10
  322. package/scripts/release-loop/gate-wall.ts +5 -5
  323. package/scripts/release-loop/preflight.ts +6 -2
  324. package/scripts/release-loop/resume-release.ts +267 -20
  325. package/scripts/release-loop/resume.ts +48 -0
  326. package/scripts/release-loop/traffic-node.ts +6 -3
  327. package/scripts/release-loop/unattended-release.ts +4 -2
  328. package/scripts/release-loop/version-node.ts +7 -2
  329. package/scripts/release-story/draft.ts +1 -1
  330. package/scripts/research-bench/README.md +53 -0
  331. package/scripts/research-bench/questions.json +66 -0
  332. package/scripts/research-bench/rubric.md +33 -0
  333. package/scripts/research-bench/run.ts +523 -0
  334. package/scripts/shadow-authoring-probe.ts +20 -0
  335. package/scripts/tui-regress.ts +85 -10
  336. package/scripts/ux-sim.ts +19 -2
  337. package/src/acp/core-turn-bridge.ts +94 -4
  338. package/src/agent/autonomous-tools.ts +10 -3
  339. package/src/agent/monad-agent-turn.ts +4 -1
  340. package/src/agent/registry.ts +26 -2
  341. package/src/agent/shared-app-tools.ts +1 -1
  342. package/src/agent/surface-ux/build.ts +12 -3
  343. package/src/agent/surface-ux/types.ts +1 -1
  344. package/src/agent/task-notification.ts +75 -6
  345. package/src/agent/types.ts +3 -0
  346. package/src/agent-mission/driver.ts +29 -3
  347. package/src/agent-mission/mission-cli.ts +2 -1
  348. package/src/agent-substrate/review-context-pack.ts +365 -0
  349. package/src/agent-substrate/self-review-cli.ts +291 -20
  350. package/src/ask-user-question/index.ts +6 -0
  351. package/src/ask-user-question/inline-resolver.ts +49 -0
  352. package/src/auto-research/question-ladder-contract.ts +22 -3
  353. package/src/auto-research/research-turn.ts +359 -17
  354. package/src/autopilot/agent-loop.ts +1 -1
  355. package/src/autopilot/discovery/wiki-claim-proposer.ts +22 -1
  356. package/src/autopilot/pty-control-loop.ts +8 -1
  357. package/src/boot/daemon-tools/index.ts +4 -3
  358. package/src/boot/daemon-tools/self-implement.ts +312 -7
  359. package/src/boot/daemon-tools/types.ts +2 -0
  360. package/src/budget/llm-cost.ts +44 -5
  361. package/src/budget/shadow-arms.ts +52 -0
  362. package/src/budget/unified-usage.ts +17 -1
  363. package/src/capture/tui-self-report.ts +14 -0
  364. package/src/chat/index.ts +33 -7
  365. package/src/chat/pickers/state.ts +7 -1
  366. package/src/cli/agent-cli.ts +43 -8
  367. package/src/cli/intake-cli.ts +22 -1
  368. package/src/cli/lesson-cli.ts +19 -3
  369. package/src/cli/log-event-names.ts +6 -0
  370. package/src/cli/mcp-login.ts +8 -18
  371. package/src/cli/msg-cli.ts +57 -1
  372. package/src/cli/pod-cli.ts +17 -2
  373. package/src/cli/pr-land-heavy-remote.ts +15 -9
  374. package/src/cli/pty-takeover-cli.ts +67 -7
  375. package/src/cli/release-cli.ts +79 -7
  376. package/src/cli/repo-cli.ts +2 -1
  377. package/src/cli/sim-cli.ts +7 -1
  378. package/src/cli/tasks-cli.ts +41 -13
  379. package/src/codex/models.ts +30 -15
  380. package/src/control-plane/ledger.ts +21 -4
  381. package/src/core-turn/run-core-turn.ts +47 -3
  382. package/src/core-turn/run-goal-loop.ts +240 -10
  383. package/src/core-turn/types.ts +9 -0
  384. package/src/dashboard/acp-boot.ts +72 -3
  385. package/src/dashboard/chat/acp-chat.ts +2 -2
  386. package/src/dashboard/classic-sigquit.ts +16 -0
  387. package/src/dashboard/index.ts +327 -27
  388. package/src/dashboard/input/chat-main-interaction-opts.ts +3 -0
  389. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +7 -2
  390. package/src/dashboard/input/chat-main-slash-command.ts +7 -0
  391. package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
  392. package/src/dashboard/input/dashboard-priority-key-route.ts +21 -5
  393. package/src/dashboard/input/external-input-host.ts +2 -0
  394. package/src/dashboard/sidetab-runtime.ts +228 -0
  395. package/src/dashboard/slash-runtime/ask-clarification.ts +7 -1
  396. package/src/dashboard/slash-runtime/dashboard-handlers.ts +20 -8
  397. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -2
  398. package/src/dashboard/term-slash-runtime.ts +16 -18
  399. package/src/dashboard/turn-preamble.ts +14 -1
  400. package/src/disk-steward/judge.ts +73 -0
  401. package/src/disk-steward/ledger.ts +122 -0
  402. package/src/disk-steward/steward.ts +373 -0
  403. package/src/domains/guardian-tick.ts +191 -2
  404. package/src/domains/knowledge.ts +1 -1
  405. package/src/esc-abort-gate.ts +33 -1
  406. package/src/execution-loop/launch-gate.ts +206 -1
  407. package/src/graph-runner/graph-cli.ts +27 -4
  408. package/src/graph-runner/in-process-registry.ts +37 -0
  409. package/src/graph-runner/runner.ts +63 -11
  410. package/src/graph-wizard/generate.ts +16 -7
  411. package/src/graph-wizard/mission-compose.ts +201 -0
  412. package/src/grok/agent-search.ts +8 -2
  413. package/src/grok/credential.ts +5 -0
  414. package/src/grounding/ref-index.ts +30 -0
  415. package/src/grounding/ref-vector.ts +61 -0
  416. package/src/grounding/sources-cli.ts +11 -3
  417. package/src/grounding/sources.ts +15 -1
  418. package/src/harness/harness-cli-command.ts +305 -23
  419. package/src/harness/harness-incidents.ts +312 -7
  420. package/src/harness/harness-pod-dispatch.ts +7 -1
  421. package/src/harness/harness-space.ts +15 -1
  422. package/src/harness/progress-worker-entry.ts +59 -0
  423. package/src/harness/progress-worker-runtime.ts +11 -0
  424. package/src/index.ts +35 -5
  425. package/src/input/external-input-queue.ts +10 -0
  426. package/src/instance/dev-project.ts +25 -0
  427. package/src/intake-plane/collect-telegram-saved.ts +36 -1
  428. package/src/intake-plane/intake-to-tasks.ts +246 -3
  429. package/src/intelligence-map/model-alias.ts +6 -5
  430. package/src/intelligence-map/model-catalog.ts +59 -2
  431. package/src/lessons/friction-ledger.ts +154 -0
  432. package/src/live-supply/collector.ts +149 -0
  433. package/src/live-supply/probes.ts +52 -0
  434. package/src/live-supply/snapshot.ts +40 -0
  435. package/src/llm/model-defaults.ts +4 -4
  436. package/src/llm.ts +473 -87
  437. package/src/loops/orchestrator/tick.ts +56 -0
  438. package/src/mcp/mcp-oauth.ts +3 -1
  439. package/src/model-tier/llm-tier-map.ts +9 -9
  440. package/src/model-tier/turn-tier.ts +1 -1
  441. package/src/msg/msg-mirror-github.ts +80 -0
  442. package/src/msg/msg-mirror-policy.ts +61 -0
  443. package/src/msg/msg-mirror-runner.ts +219 -0
  444. package/src/msg/msg-mirror-state.ts +33 -0
  445. package/src/msg/msg-store.ts +11 -0
  446. package/src/nexus/api/harness-api.ts +2 -1
  447. package/src/output-truncation.ts +41 -12
  448. package/src/project/project-store.ts +48 -1
  449. package/src/pty/snapshot.py +132 -0
  450. package/src/pty-shell/pty-control-ipc.ts +29 -2
  451. package/src/pty-shell/pty-manifest.ts +59 -3
  452. package/src/pty-shell/registry.ts +2 -0
  453. package/src/pty-shell/tui-run-state.ts +80 -3
  454. package/src/release-loop/gate-host-reservation.ts +157 -4
  455. package/src/release-loop/gate-shard-ledger.ts +68 -0
  456. package/src/release-loop/merged-pr-checklist.ts +25 -2
  457. package/src/release-loop/rehearsal-shard-plan.ts +6 -1
  458. package/src/release-loop/rehearsal.ts +27 -0
  459. package/src/release-loop/release-schedule.ts +90 -1
  460. package/src/research/bloom-exemplars.ts +135 -0
  461. package/src/research/edge-decision.ts +124 -15
  462. package/src/research/gap-followup.ts +249 -0
  463. package/src/research/lenses/counter-evidence.ts +100 -0
  464. package/src/research/lenses/working-backwards.ts +89 -0
  465. package/src/research/plugin-discovery.ts +242 -0
  466. package/src/research-bridge/invoke.ts +4 -2
  467. package/src/research-bridge/types.ts +2 -0
  468. package/src/self-dev/ask-launch-flow.ts +73 -131
  469. package/src/self-dev/dev-cli.ts +19 -17
  470. package/src/self-dev/dev-pipeline.ts +8 -4
  471. package/src/self-dev/graph-front-nodes.ts +23 -0
  472. package/src/self-dev/graph-journey-route.ts +10 -2
  473. package/src/self-dev/launch-preflight-text.ts +2 -2
  474. package/src/self-dev/launch-preflight.ts +47 -11
  475. package/src/self-dev/orchestrate-cli.ts +1 -0
  476. package/src/self-dev/orchestrate.ts +15 -0
  477. package/src/self-dev/run-supervisor.ts +204 -3
  478. package/src/self-dev/run-types.ts +3 -0
  479. package/src/self-implement/device-first.ts +8 -2
  480. package/src/self-implement/doctor-visit.ts +76 -58
  481. package/src/self-implement/gate-artifacts.ts +16 -0
  482. package/src/self-implement/gate-baseline.ts +75 -4
  483. package/src/self-implement/gate-cli.ts +368 -30
  484. package/src/self-implement/gate-receipt-registry.ts +180 -0
  485. package/src/self-implement/gate-remote.ts +165 -24
  486. package/src/self-implement/goal-author-clarification.ts +205 -32
  487. package/src/self-implement/goal-author-decompose.ts +24 -15
  488. package/src/self-implement/goal-author.ts +86 -10
  489. package/src/self-implement/graph-stage-units.ts +172 -0
  490. package/src/self-implement/graph-templates.ts +162 -1
  491. package/src/self-implement/graph-variant.ts +37 -4
  492. package/src/self-implement/host-regate.ts +124 -49
  493. package/src/self-implement/impl-findings-feedback.ts +188 -0
  494. package/src/self-implement/knowhow-pack.ts +227 -10
  495. package/src/self-implement/off-diff-evidence.ts +124 -0
  496. package/src/self-implement/orchestrator.ts +320 -28
  497. package/src/self-implement/run-ledger.ts +110 -14
  498. package/src/self-implement/run-stop.ts +33 -2
  499. package/src/self-implement/running-runs.ts +35 -12
  500. package/src/self-implement/seams.ts +6 -3
  501. package/src/self-implement/self-implement-cli.ts +40 -6
  502. package/src/self-implement/stop-autoheal-operational.ts +43 -0
  503. package/src/self-implement/stop-autoheal.ts +15 -6
  504. package/src/session/chat.ts +66 -15
  505. package/src/session/request-size-guard.ts +123 -0
  506. package/src/session-runtime/provider-circuit.ts +140 -0
  507. package/src/shell-runner/file-engine.ts +1 -0
  508. package/src/shell-runner/types.ts +4 -0
  509. package/src/sidetab-core/model.ts +312 -0
  510. package/src/skills/tools/schedule-wakeup.ts +23 -1
  511. package/src/skills/tools/shell.ts +51 -5
  512. package/src/steward/directive-audit.ts +354 -0
  513. package/src/surface/child-process.ts +31 -0
  514. package/src/surface/tui-stderr-owner.ts +48 -0
  515. package/src/task-agent/cover.ts +30 -12
  516. package/src/task-agent/judge.ts +56 -0
  517. package/src/task-agent/parent-host.ts +14 -1
  518. package/src/task-agent/postland-card.ts +35 -2
  519. package/src/task-agent/rejudge-on-head.ts +46 -2
  520. package/src/task-agent/repair-cycle.ts +1 -1
  521. package/src/task-agent/task-hand.ts +133 -25
  522. package/src/task-agent/tier-split.ts +105 -21
  523. package/src/task-orchestrator/surfaces/pod-command-job.ts +330 -2
  524. package/src/task-orchestrator/surfaces/pod-config-snapshot.ts +123 -0
  525. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +70 -2
  526. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +29 -4
  527. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +11 -8
  528. package/src/task-orchestrator/surfaces/pod-si-warm-protocol.ts +1 -1
  529. package/src/task-orchestrator/surfaces/pod-source-receive.ts +74 -6
  530. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +2 -1
  531. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +56 -15
  532. package/src/task-orchestrator/surfaces/self-implement-pod.ts +298 -45
  533. package/src/task-orchestrator/surfaces/self-implement.ts +18 -0
  534. package/src/tool-runtime/skill-exec-runtime.ts +95 -5
  535. package/src/tui/entry.ts +25 -5
  536. package/src/tui/inline-choice.ts +188 -0
  537. package/src/tui/sidetab/list.ts +36 -165
  538. package/src/tui/sidetab/nl-tool.ts +2 -136
  539. package/src/tui/sidetab/peek.ts +52 -0
  540. package/src/tui/slash/term.ts +12 -1
  541. package/src/tui-client/dashboard-session.ts +10 -1
  542. package/src/user-config.ts +45 -9
  543. package/src/ux-sim/classic-tui-seat-scenarios.ts +1 -7
  544. package/src/ux-sim/fake-land-queue.ts +88 -0
  545. package/src/ux-sim/fault-needs-human-reason-repair.ts +107 -0
  546. package/src/ux-sim/fault-pod-child-result.ts +42 -0
  547. package/src/ux-sim/gate-shard-host-reroute.ts +82 -0
  548. package/src/ux-sim/goal-interim-trace.ts +24 -0
  549. package/src/ux-sim/next-tui-seat-scenarios.ts +8 -13
  550. package/src/ux-sim/release-sim-rig.ts +262 -0
  551. package/src/ux-sim/seminar-rehearsal.ts +109 -0
  552. package/src/ux-sim/subagent-tools-device.ts +2 -2
  553. package/src/ux-sim/task-orchestrator-surfaces-self-implement-pod-device.ts +4 -1
  554. package/src/version/packed-revision.json +1 -1
  555. package/src/video-pipeline/recipes/explainer.ts +54 -2
  556. package/src/web-search/grok.ts +32 -6
  557. package/src/web-search/index.ts +8 -7
  558. package/src/workflow-runtime/node-catalog.ts +53 -4
  559. package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +0 -27
  560. package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/1923-5c1695332240246a.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/1938.0e6c60ee91c4d7f5.js +0 -148
  567. package/apps/pwa/out/_next/static/chunks/2104.70e086d5174a4736.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/214.186a430da28338f1.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +0 -93
  571. package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +0 -104
  572. package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +0 -24
  581. package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +0 -36
  583. package/apps/pwa/out/_next/static/chunks/3341-f09b9efbd7a82f70.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +0 -287
  586. package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +0 -94
  592. package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/3f0de3de-2340c532c00395db.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/4199-f7c6eb40cd0322f8.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +0 -32
  604. package/apps/pwa/out/_next/static/chunks/4804.6012b5cd33c22792.js +0 -90
  605. package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +0 -79
  607. package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +0 -74
  610. package/apps/pwa/out/_next/static/chunks/5041-5aada92ca215ffdd.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/5255-1b60d50eabe9f057.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +0 -286
  614. package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +0 -8
  617. package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/7000.28157393caaf5343.js +0 -62
  629. package/apps/pwa/out/_next/static/chunks/7311-60a7ea80d23c7521.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/7488.966b116789f3d41a.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/7524.ce973525d30b3d52.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/7628.6b16863ac3972333.js +0 -34
  636. package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/7954.4f7a8832663ee979.js +0 -115
  639. package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/8509.3a54d4e61893d7cb.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +0 -149
  647. package/apps/pwa/out/_next/static/chunks/9223.cbcc88e0e9950426.js +0 -41
  648. package/apps/pwa/out/_next/static/chunks/9299.24e2a7d9b6d1f91b.js +0 -226
  649. package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +0 -24
  650. package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/9581.da63ddf41acfad46.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +0 -2
  654. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/intake/page-c348a3959c5b5fc6.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d1d1210f99f620ae.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/outputs/page-291ab19fe2acb173.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/page-7f569e533ddeecba.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/app/share/page-a9d9a3e66459c1e0.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/term/page-6b140f77593576eb.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/bb6987f9.3647e1a23b0e3217.js +0 -122
  705. package/apps/pwa/out/_next/static/chunks/framework-4b12a946f352cee2.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.js +0 -1
  711. package/scripts/ratchets/next-tui-entry-budget.ts +0 -124
  712. /package/apps/pwa/out/_next/static/{RrjXTwz-urRAbChP1bX02 → GiOLWmt4MqDZePubBjA4Q}/_ssgManifest.js +0 -0
@@ -1,3 +1,4 @@
1
+ import { createHash } from 'node:crypto';
1
2
  import { mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
2
3
  import { join } from 'node:path';
3
4
 
@@ -39,6 +40,29 @@ export function captureFailedPodJobs(input: {
39
40
  }
40
41
  const location = { host: first.host, context: first.context, namespace: first.namespace, childRunId: first.childRunId, jobUid: first.jobUid };
41
42
  const evidenceDir = join(artifactDir, 'pod-failure-capture', runId, job, first.childRunId as string);
43
+ // A failed kubectl/SSH read is itself the missing diagnostic. Keep its stderr in
44
+ // the private artifact directory and put only the path and exit status in the ledger.
45
+ const readFailure = (reason: string, result: { status: number | null; stderr: string }, extra: Record<string, unknown> = {}): void => {
46
+ let stderrEvidence: string | null = null;
47
+ let stderrCaptureStatus: 'saved' | 'redacted' | 'empty' | 'write-failed' = result.stderr ? 'saved' : 'empty';
48
+ if (result.stderr) {
49
+ try {
50
+ mkdirSync(evidenceDir, { recursive: true });
51
+ const tail = result.stderr.slice(-8192).split(/\r?\n/).map(line => {
52
+ if (!SECRET_VALUE.test(line)) return line;
53
+ stderrCaptureStatus = 'redacted';
54
+ return '[redacted credential line]';
55
+ }).join('\n');
56
+ const digest = createHash('sha256').update(tail).digest('hex').slice(0, 16);
57
+ stderrEvidence = join(evidenceDir, `${reason}-${digest}.stderr.log`);
58
+ try { writeFileSync(stderrEvidence, tail, { flag: 'wx', mode: 0o600 }); }
59
+ catch (error) {
60
+ if ((error as NodeJS.ErrnoException).code !== 'EEXIST' || readFileSync(stderrEvidence, 'utf8') !== tail) throw error;
61
+ }
62
+ } catch { stderrEvidence = null; stderrCaptureStatus = 'write-failed'; }
63
+ }
64
+ finish('failed', reason, { ...location, ...extra, kubectlStatus: result.status, stderrEvidence, stderrCaptureStatus });
65
+ };
42
66
  const previous = rows.find(row => row.event === 'pod-failure-capture' && row.data?.job === job && row.data?.outcome === 'collected'
43
67
  && row.data.childRunId === first.childRunId && row.data.jobUid === first.jobUid
44
68
  && row.data.host === first.host && row.data.context === first.context && row.data.namespace === first.namespace);
@@ -54,8 +78,8 @@ export function captureFailedPodJobs(input: {
54
78
  try {
55
79
  const jobResult = kubectl(first.host as string, [...args, 'get', 'job', job, '-o', 'json']);
56
80
  if (jobResult.status !== 0) {
57
- finish(/\bNotFound\b|not found/i.test(jobResult.stderr) ? 'vanished' : 'failed',
58
- /\bNotFound\b|not found/i.test(jobResult.stderr) ? 'job-not-found' : 'job-read-failed', location);
81
+ if (/\bNotFound\b|not found/i.test(jobResult.stderr)) finish('vanished', 'job-not-found', { ...location, kubectlStatus: jobResult.status });
82
+ else readFailure('job-read-failed', jobResult);
59
83
  return;
60
84
  }
61
85
  const jobBody = JSON.parse(jobResult.stdout) as { metadata?: { name?: string; uid?: string } };
@@ -78,7 +102,7 @@ export function captureFailedPodJobs(input: {
78
102
  } catch { return false; }
79
103
  });
80
104
  const podResult = kubectl(first.host as string, [...args, 'get', 'pods', '-l', `job-name=${job}`, '-o', 'json']);
81
- if (podResult.status !== 0) { finish('failed', 'pods-read-failed', { ...location, jobEvidence }); return; }
105
+ if (podResult.status !== 0) { readFailure('pods-read-failed', podResult, { jobEvidence }); return; }
82
106
  const pods = JSON.parse(podResult.stdout) as { items?: Array<{ metadata?: { name?: string; ownerReferences?: Array<{ uid?: string }> } }> };
83
107
  if (!pods.items?.length || pods.items.some(p => !p.metadata?.ownerReferences?.some(owner => owner.uid === jobBody.metadata?.uid))) {
84
108
  finish('failed', 'pod-owner-mismatch', { ...location, jobEvidence }); return;
@@ -89,7 +113,8 @@ export function captureFailedPodJobs(input: {
89
113
  finish('failed', 'pod-ambiguous', { ...location, jobEvidence, podEvidence }); return;
90
114
  }
91
115
  const logs = kubectl(first.host as string, [...args, 'logs', `pod/${podName}`, '-c', 'child']);
92
- if (logs.status !== 0) { finish('failed', 'logs-read-failed', { ...location, jobEvidence, podEvidence }); return; }
116
+ if (logs.status !== 0) { readFailure('logs-read-failed', logs, { jobEvidence, podEvidence }); return; }
117
+ if (!logs.stdout.trim()) { finish('failed', 'logs-empty', { ...location, jobEvidence, podEvidence }); return; }
93
118
  const logEvidence = save('child.log', logs.stdout);
94
119
  finish('collected', 'job-failed', { ...location, jobEvidence, podEvidence, logEvidence });
95
120
  } catch { finish('failed', 'capture-error', location); }
@@ -78,24 +78,27 @@ export function seedMirrorOnce(o: { host: string; commit: string; cwd: string; p
78
78
  * one sha when it does not — objects only, no ref is moved). Never throws: a miss returns `reason` and the caller skips
79
79
  * the seed (best effort — the Job keeps its GitHub path).
80
80
  */
81
- export async function resolveDefaultSourceHead(o: { repoUrl: string; base?: string; cwd: string; git?: Push; limitMs?: number }): Promise<{ sha?: string; reason?: string }> {
81
+ export async function resolveDefaultSourceHead(o: { repoUrl: string; base?: string; cwd: string; git?: Push; limitMs?: number }): Promise<{ sha?: string; reason?: string; originCalls?: number }> {
82
82
  const git = o.git ?? gitWithin;
83
83
  const limitMs = o.limitMs ?? 30_000;
84
84
  const base = o.base || 'main';
85
- if (base.startsWith('-') || !/^[\w./-]+$/.test(base) || o.repoUrl.startsWith('-')) return { reason: 'invalid-ref' };
85
+ if (base.startsWith('-') || !/^[\w./-]+$/.test(base) || o.repoUrl.startsWith('-')) return { reason: 'invalid-ref', originCalls: 0 };
86
+ let originCalls = 0;
86
87
  try {
88
+ originCalls += 1;
87
89
  const listed = await git(['ls-remote', '--', o.repoUrl, `refs/heads/${base}`], o.cwd, limitMs);
88
- if (listed.rc !== 0) return { reason: 'ls-remote-failed' };
90
+ if (listed.rc !== 0) return { reason: 'ls-remote-failed', originCalls };
89
91
  // Only the exact ref asked for — never the first `refs/heads/*` line (a branch named `a/refs/heads/main` must not pass).
90
92
  const want = `refs/heads/${base}`;
91
93
  const sha = listed.output.split(/\r?\n/).map((line) => line.split('\t')).find(([hash, ref]) => ref === want && /^[0-9a-f]{40}$/.test(hash ?? ''))?.[0];
92
- if (!sha) return { reason: 'ls-remote-no-sha' };
93
- if ((await git(['cat-file', '-e', `${sha}^{commit}`], o.cwd, limitMs)).rc === 0) return { sha };
94
+ if (!sha) return { reason: 'ls-remote-no-sha', originCalls };
95
+ if ((await git(['cat-file', '-e', `${sha}^{commit}`], o.cwd, limitMs)).rc === 0) return { sha, originCalls };
96
+ originCalls += 1;
94
97
  const fetched = await git(['fetch', '--quiet', '--no-write-fetch-head', '--', o.repoUrl, sha], o.cwd, GATE_MIRROR_SEED_LIMIT_MS);
95
- if (fetched.rc !== 0) return { reason: 'commit-fetch-failed' };
96
- return (await git(['cat-file', '-e', `${sha}^{commit}`], o.cwd, limitMs)).rc === 0 ? { sha } : { reason: 'commit-not-local' };
98
+ if (fetched.rc !== 0) return { reason: 'commit-fetch-failed', originCalls };
99
+ return (await git(['cat-file', '-e', `${sha}^{commit}`], o.cwd, limitMs)).rc === 0 ? { sha, originCalls } : { reason: 'commit-not-local', originCalls };
97
100
  } catch {
98
- return { reason: 'resolve-threw' };
101
+ return { reason: 'resolve-threw', originCalls };
99
102
  }
100
103
  }
101
104
 
@@ -103,7 +103,7 @@ export function parseSiWarmCommand(raw: unknown): SiWarmCommand | null {
103
103
  || !digest(row.executionKey) || !str(row.sourceSha) || !SHA.test(row.sourceSha)
104
104
  || !token(row.podUid) || !integer(row.generation) || row.generation < 1
105
105
  || !validKey(row.key) || row.envProfile !== 'si-standard-v1'
106
- || !finite(row.deadlineAt) || !digest(row.payloadSha256)
106
+ || !finite(row.deadlineAt) || row.deadlineAt <= 0 || !digest(row.payloadSha256)
107
107
  || !digest(row.credentialBundleSha256)) return null;
108
108
  return raw as SiWarmCommand;
109
109
  }
@@ -5,7 +5,7 @@ import { execFileSync } from 'node:child_process';
5
5
  import { siTaskPodStageShell } from './pod-lifecycle-stages.js';
6
6
 
7
7
  export type PodSource =
8
- | { kind: 'default'; base?: string }
8
+ | { kind: 'default'; base?: string; baseSha?: string }
9
9
  | { kind: 'commit'; sha: string }
10
10
  | { kind: 'pr'; number: number }
11
11
  | { kind: 'bundle'; bundlePath: string; sha256: string; sizeBytes: number; headCommit: string };
@@ -64,6 +64,24 @@ export function podSourceScript(source: PodSource, repoUrl: string, mirrorPath =
64
64
  const quotedCommitFile = `'${(options.imageCommitFile ?? '/opt/elanous-source-commit').replace(/'/g, `'\\''`)}'`;
65
65
  const quotedImageGitDir = `'${(options.imageGitDir ?? '/opt/elanous-pin.git').replace(/'/g, `'\\''`)}'`;
66
66
  const clone = `git clone -q --depth 50 ${quotedUrl} repo`;
67
+ // First observation slice: count source checkout work without changing its routing.
68
+ const ioStart = [
69
+ // Count calls performed by this Pod source stage. Branch validation via
70
+ // assertRemoteBase runs on the host before Job creation and is outside it.
71
+ 'pod_source_io_origin_calls=0',
72
+ 'pod_source_io_started=$(date +%s)',
73
+ 'pod_source_io_reported=0',
74
+ 'pod_source_io_measured=0',
75
+ 'pod_source_io_measure() { pod_source_io_files=$(git ls-files -z | tr -cd "\\000" | wc -c | tr -d " "); pod_source_io_seconds=$(( $(date +%s) - pod_source_io_started )); pod_source_io_measured=1; }',
76
+ 'pod_source_io_emit() {',
77
+ ' [ "$pod_source_io_reported" -eq 0 ] || return 0; pod_source_io_reported=1',
78
+ ' [ -n "${pod_source_io_seconds:-}" ] || pod_source_io_seconds=$(( $(date +%s) - pod_source_io_started ))',
79
+ ' [ -n "${pod_source_io_files:-}" ] || pod_source_io_files=null',
80
+ ' pod_source_io_status=incomplete; if [ "$pod_source_io_measured" -eq 1 ]; then pod_source_io_status=complete; fi',
81
+ ' printf \'ELANOUS_POD_SOURCE_IO {"originCalls":%s,"checkoutFiles":%s,"sourceVia":"%s","sourceSeconds":%s,"sourceStatus":"%s","pushCalls":null,"installRan":null,"installSeconds":null}\\n\' "$pod_source_io_origin_calls" "$pod_source_io_files" "${source_via:-unknown}" "$pod_source_io_seconds" "$pod_source_io_status"',
82
+ '}',
83
+ 'trap pod_source_io_emit EXIT',
84
+ ];
67
85
  const start = [
68
86
  'if [ -e repo ]; then exit 5; fi',
69
87
  // POD-MIRROR-IO: the image's pinned tree is a shared read-only lower layer.
@@ -113,7 +131,11 @@ export function podSourceScript(source: PodSource, repoUrl: string, mirrorPath =
113
131
  'else',
114
132
  " printf 'ELANOUS_POD_SOURCE_MIRROR_SKIP %s\\n' \"$mirror_skip\"",
115
133
  ' if [ -e repo ]; then rm -r -- repo || exit 5; fi',
116
- ` ${clone} || exit 5`,
134
+ ...(source.kind === 'default' && source.baseSha ? [] : [' pod_source_io_origin_calls=$((pod_source_io_origin_calls + 1))']),
135
+ ...(source.kind === 'default' && source.baseSha ? [
136
+ ` printf 'ELANOUS_POD_SOURCE_BASE_SHA_UNAVAILABLE %s\\n' '${source.baseSha}'`,
137
+ ' exit 5',
138
+ ] : [` ${clone} || exit 5`]),
117
139
  ' source_via=github',
118
140
  'fi',
119
141
  'fi',
@@ -121,22 +143,50 @@ export function podSourceScript(source: PodSource, repoUrl: string, mirrorPath =
121
143
  'cd repo || exit 5',
122
144
  ];
123
145
  if (source.kind === 'default') {
146
+ if (source.baseSha) {
147
+ const sha = assertSha(source.baseSha, 'base sha');
148
+ const base = source.base ?? 'main';
149
+ if (base.startsWith('-') || !/^[\w./-]+$/.test(base)) throw new Error(`invalid Pod base ref: ${base}`);
150
+ const quote = (value: string) => `'${value.replace(/'/g, `'\\''`)}'`;
151
+ const quotedBase = quote(base);
152
+ const quotedTrackingRef = quote(`refs/remotes/origin/${base}`);
153
+ const quotedUpstream = quote(`origin/${base}`);
154
+ return [
155
+ ...ioStart,
156
+ ...start,
157
+ `if ! git cat-file -e '${sha}^{commit}' 2>/dev/null; then git fetch --quiet --no-write-fetch-head ${quotedMirror} '${sha}' || { printf 'ELANOUS_POD_SOURCE_BASE_SHA_UNAVAILABLE %s\\n' '${sha}'; exit 5; }; fi`,
158
+ `git checkout -q -B ${quotedBase} '${sha}' || exit 5`,
159
+ `git update-ref ${quotedTrackingRef} '${sha}' || exit 5`,
160
+ `git symbolic-ref refs/remotes/origin/HEAD ${quotedTrackingRef} || exit 5`,
161
+ `git branch --set-upstream-to=${quotedUpstream} ${quotedBase} >/dev/null || exit 5`,
162
+ 'head=$(git rev-parse HEAD)',
163
+ 'pod_source_io_measure',
164
+ "printf 'ELANOUS_POD_SOURCE default %s\\n' \"$head\"",
165
+ 'pod_source_io_emit',
166
+ ].join('\n');
167
+ }
124
168
  if (source.base && source.base !== 'main') {
125
169
  assertRemoteBase(repoUrl, source.base);
126
170
  const base = source.base;
127
171
  const quote = (value: string) => `'${value.replace(/'/g, `'\\''`)}'`;
128
172
  const quotedTrackingRef = quote(`refs/remotes/origin/${base}`);
129
173
  return [
174
+ ...ioStart,
130
175
  ...start,
176
+ 'pod_source_io_origin_calls=$((pod_source_io_origin_calls + 1))',
131
177
  `git fetch --depth 50 origin ${quote(`+refs/heads/${base}:refs/remotes/origin/${base}`)} || exit 5`,
132
178
  `git checkout -q -B ${quote(base)} ${quotedTrackingRef} || exit 5`,
133
179
  'head=$(git rev-parse HEAD)',
180
+ 'pod_source_io_measure',
134
181
  "printf 'ELANOUS_POD_SOURCE default %s\\n' \"$head\"",
182
+ 'pod_source_io_emit',
135
183
  ].join('\n');
136
184
  }
137
185
  return [
186
+ ...ioStart,
138
187
  ...start,
139
188
  'if [ "$source_via" != github ]; then',
189
+ ' pod_source_io_origin_calls=$((pod_source_io_origin_calls + 1))',
140
190
  ' remote_info=$(git ls-remote --symref origin HEAD) || exit 5',
141
191
  ` remote_head=$(printf '%s\\n' "$remote_info" | awk '$2=="HEAD" && $1!="ref:" {print $1}')`,
142
192
  ` remote_branch=$(printf '%s\\n' "$remote_info" | awk '$1=="ref:" && $3=="HEAD" && $2 ~ /^refs\\/heads\\// {sub(/^refs\\/heads\\//, "", $2); print $2}')`,
@@ -146,6 +196,7 @@ export function podSourceScript(source: PodSource, repoUrl: string, mirrorPath =
146
196
  ' git reset --hard "$remote_head" || exit 5',
147
197
  " printf 'ELANOUS_POD_SOURCE_DELTA mirror\\n'",
148
198
  ' else',
199
+ ' pod_source_io_origin_calls=$((pod_source_io_origin_calls + 1))',
149
200
  ' git fetch --depth 50 origin HEAD && git reset --hard FETCH_HEAD || exit 5',
150
201
  " printf 'ELANOUS_POD_SOURCE_DELTA origin\\n'",
151
202
  ' fi',
@@ -158,53 +209,68 @@ export function podSourceScript(source: PodSource, repoUrl: string, mirrorPath =
158
209
  ' git branch --set-upstream-to="origin/$remote_branch" "$remote_branch" >/dev/null || exit 5',
159
210
  'fi',
160
211
  'head=$(git rev-parse HEAD)',
212
+ 'pod_source_io_measure',
161
213
  "printf 'ELANOUS_POD_SOURCE default %s\\n' \"$head\"",
214
+ 'pod_source_io_emit',
162
215
  ].join('\n');
163
216
  }
164
217
  if (source.kind === 'commit') {
165
218
  const sha = assertSha(source.sha, 'sha');
166
219
  return [
220
+ ...ioStart,
167
221
  ...start,
168
- `if ! git cat-file -e '${sha}^{commit}' 2>/dev/null; then git fetch --depth 1 origin ${sha} || exit 5; fi`,
222
+ `if ! git cat-file -e '${sha}^{commit}' 2>/dev/null; then pod_source_io_origin_calls=$((pod_source_io_origin_calls + 1)); git fetch --depth 1 origin ${sha} || exit 5; fi`,
169
223
  `git checkout --detach ${sha} || exit 5`,
170
224
  'head=$(git rev-parse HEAD)',
225
+ 'pod_source_io_measure',
171
226
  "printf 'ELANOUS_POD_SOURCE commit %s\\n' \"$head\"",
227
+ 'pod_source_io_emit',
172
228
  ].join('\n');
173
229
  }
174
230
  if (source.kind === 'pr') {
175
231
  const n = assertPositiveInt(source.number);
176
232
  return [
233
+ ...ioStart,
177
234
  ...start,
235
+ 'pod_source_io_origin_calls=$((pod_source_io_origin_calls + 1))',
178
236
  `pr_sha=$(git ls-remote origin refs/pull/${n}/head | cut -f1) || exit 5`,
179
237
  'if ! [[ "$pr_sha" =~ ^[0-9a-f]{40}$ ]]; then exit 5; fi',
180
- `if ! git cat-file -e "$pr_sha^{commit}" 2>/dev/null; then git fetch --depth 50 origin pull/${n}/head || exit 5; fi`,
238
+ `if ! git cat-file -e "$pr_sha^{commit}" 2>/dev/null; then pod_source_io_origin_calls=$((pod_source_io_origin_calls + 1)); git fetch --depth 50 origin pull/${n}/head || exit 5; fi`,
181
239
  `git checkout -B pr-${n} "$pr_sha" || exit 5`,
182
240
  // A pinned image starts at one shallow main commit. Fetching a PR tip at
183
241
  // depth 50 can leave that pin and the PR in disconnected shallow spans.
184
242
  // Deepen only after merge-base fails; the gate still reports unavailable
185
243
  // if ancestry cannot be obtained.
244
+ 'pod_source_io_origin_calls=$((pod_source_io_origin_calls + 1))',
186
245
  'remote_info=$(git ls-remote --symref origin HEAD 2>/dev/null) || { printf \'ELANOUS_POD_COMPARISON_BASE unavailable\\n\'; exit 5; }',
187
246
  `base_branch=$(printf '%s\\n' "$remote_info" | awk '$1=="ref:" && $3=="HEAD" && $2 ~ /^refs\\/heads\\// {sub(/^refs\\/heads\\//, "", $2); print $2}')`,
188
247
  'if [ -n "$base_branch" ] && git check-ref-format --branch "$base_branch" >/dev/null 2>&1; then',
189
248
  ' base_ref="refs/remotes/origin/$base_branch"',
249
+ ' pod_source_io_origin_calls=$((pod_source_io_origin_calls + 1))',
190
250
  ' git fetch --depth 50 origin "+refs/heads/$base_branch:$base_ref" || { printf \'ELANOUS_POD_COMPARISON_BASE unavailable\\n\'; exit 5; }',
191
251
  ' git symbolic-ref refs/remotes/origin/HEAD "$base_ref" || exit 5',
192
252
  ' if ! git merge-base HEAD "$base_ref" >/dev/null 2>&1 && [ "$(git rev-parse --is-shallow-repository)" = true ]; then',
253
+ ' pod_source_io_origin_calls=$((pod_source_io_origin_calls + 1))',
193
254
  ` git fetch --deepen=100 origin "+refs/heads/$base_branch:$base_ref" +refs/pull/${n}/head:refs/remotes/origin/pr-${n}-head || printf 'ELANOUS_POD_COMPARISON_BASE deepen-failed\\n'`,
194
255
  ' fi',
195
256
  ' if ! git merge-base HEAD "$base_ref" >/dev/null 2>&1 && [ "$(git rev-parse --is-shallow-repository)" = true ]; then',
257
+ ' pod_source_io_origin_calls=$((pod_source_io_origin_calls + 1))',
196
258
  ` git fetch --unshallow origin "+refs/heads/$base_branch:$base_ref" +refs/pull/${n}/head:refs/remotes/origin/pr-${n}-head || { printf 'ELANOUS_POD_COMPARISON_BASE unavailable\\n'; exit 5; }`,
197
259
  ' fi',
198
260
  " if ! git merge-base HEAD \"$base_ref\" >/dev/null 2>&1; then printf 'ELANOUS_POD_COMPARISON_BASE unavailable\\n'; fi",
199
261
  "else printf 'ELANOUS_POD_COMPARISON_BASE unavailable\\n'; exit 5; fi",
200
262
  'head=$(git rev-parse HEAD)',
263
+ 'pod_source_io_measure',
201
264
  "printf 'ELANOUS_POD_SOURCE pr %s\\n' \"$head\"",
265
+ 'pod_source_io_emit',
202
266
  ].join('\n');
203
267
  }
204
268
  const sha256 = assertSha256(source.sha256);
205
269
  const sizeBytes = assertSize(source.sizeBytes);
206
270
  const headCommit = assertSha(source.headCommit, 'headCommit');
207
271
  return [
272
+ ...ioStart,
273
+ 'source_via=bundle',
208
274
  'ready=0',
209
275
  'for i in $(seq 1 300); do',
210
276
  ' if [ -f /tmp/source.ready ]; then ready=1; break; fi',
@@ -242,8 +308,10 @@ export function podSourceScript(source: PodSource, repoUrl: string, mirrorPath =
242
308
  ' git -C repo fetch /tmp/source.bundle "refs/elanous/pod-source/*:refs/remotes/bundle/*" || exit 5',
243
309
  'fi',
244
310
  `git -C repo checkout --detach ${headCommit} || exit 5`,
245
- 'head=$(git -C repo rev-parse HEAD) || exit 5',
246
- "printf 'ELANOUS_POD_SOURCE bundle %s\\n' \"$head\"",
247
311
  'cd repo || exit 5',
312
+ 'head=$(git rev-parse HEAD) || exit 5',
313
+ 'pod_source_io_measure',
314
+ "printf 'ELANOUS_POD_SOURCE bundle %s\\n' \"$head\"",
315
+ 'pod_source_io_emit',
248
316
  ].join('\n');
249
317
  }
@@ -389,6 +389,7 @@ export class WarmPodTransport {
389
389
  || command.workerId !== this.spec.workerId || command.cutSha !== this.spec.cutSha
390
390
  || !equalKey(command.key, this.spec.key)
391
391
  || ![command.runId, command.attemptId, command.leaseId, command.workerId].every(value => TOKEN.test(value))
392
+ || typeof command.podUid !== 'string' || !command.podUid
392
393
  || !Number.isSafeInteger(command.generation) || command.generation < 1) return fallback('key-drift');
393
394
  const prefix = ['--context', this.spec.kubectlContext, '-n', this.spec.namespace];
394
395
  const observed = this.kubectl([...prefix, 'get', 'pod', this.spec.name, '-o', 'json']);
@@ -425,7 +426,7 @@ export class WarmPodTransport {
425
426
  try { nodeArch = node.status === 0 ? JSON.parse(node.stdout)?.metadata?.labels?.['kubernetes.io/arch'] : null; }
426
427
  catch { nodeArch = null; }
427
428
  if (nodeArch !== this.spec.key.architecture) return fallback('pod-unready');
428
- if ((command.podUid && uid !== command.podUid) || (this.podUid && uid !== this.podUid)) {
429
+ if (uid !== command.podUid || (this.podUid !== null && uid !== this.podUid)) {
429
430
  this.quarantined = true; return fallback('pod-replaced');
430
431
  }
431
432
  this.podUid = uid;
@@ -44,6 +44,8 @@ function waitForPrepareRetry(signal?: AbortSignal): Promise<void> {
44
44
  export type WarmReplayInput = Omit<WarmWorkerCommand, 'leaseId' | 'generation' | 'workerId' | 'key'>;
45
45
  export interface WarmReplayResult { command: WarmWorkerCommand | null; transport: WarmPodTransportResult }
46
46
  export interface WarmWorkerCandidate { host: string; tier: WarmPoolTier; spec: WarmPodSpec }
47
+ /** The OS `flock(fd, operation)` binding the prepare lease waits on. */
48
+ export type WarmPrepareFlock = (fd: number, operation: number) => number;
47
49
  export interface WarmPodProviderOptions {
48
50
  candidates: readonly WarmWorkerCandidate[];
49
51
  /** One pinned template per host/tier. Each expands to the measured profile quota. */
@@ -64,6 +66,8 @@ export interface WarmPodProviderOptions {
64
66
  prepareLockDirectory?: string;
65
67
  /** Cancels a prepare waiting for another process to finish the same host/worker slot. */
66
68
  prepareAbortSignal?: AbortSignal;
69
+ /** Injects the prepare-lease flock binding. Omitted keeps this platform's binding; null/false declares it unsupported. */
70
+ prepareFlock?: WarmPrepareFlock | null | false;
67
71
  /** Gate file this pool serves, used to bind cold prepare legs to their 1-file gate measurement key. */
68
72
  pairingGateFile?: string;
69
73
  }
@@ -164,7 +168,7 @@ const prepareLockLib = process.platform === 'linux' || process.platform === 'dar
164
168
  flock: { args: ['int', 'int'], returns: 'int' },
165
169
  [process.platform === 'linux' ? '__errno_location' : '__error']: { args: [], returns: 'ptr' },
166
170
  }) : null;
167
- const prepareFlock = prepareLockLib?.symbols.flock ?? null;
171
+ const prepareFlock: WarmPrepareFlock | null = prepareLockLib?.symbols.flock ?? null;
168
172
  const prepareErrnoLocation = prepareLockLib?.symbols[process.platform === 'linux' ? '__errno_location' : '__error'];
169
173
  const readPrepareErrno = (): number => (prepareErrnoLocation ? read.i32(prepareErrnoLocation() as Pointer) : -1);
170
174
  const LOCK_EX = 2;
@@ -173,7 +177,7 @@ const LOCK_UN = 8;
173
177
  const PREPARE_LOCK_WAIT_MS = (POD_READY_WAIT_SECONDS * 1_000) + 30_000;
174
178
 
175
179
  async function withPrepareLease<T>(candidate: WarmWorkerCandidate, directory: string | undefined,
176
- work: () => Promise<T>, signal?: AbortSignal): Promise<T | null> {
180
+ work: () => Promise<T>, signal?: AbortSignal, flock?: WarmPrepareFlock | null): Promise<T | null> {
177
181
  const uid = typeof process.getuid === 'function' ? process.getuid() : userInfo().uid;
178
182
  const root = directory ?? join(tmpdir(), `elanous-warm-prepare-${uid}`);
179
183
  const identity = createHash('sha256').update(`${candidate.host}/${candidate.spec.workerId}`).digest('hex');
@@ -186,11 +190,11 @@ async function withPrepareLease<T>(candidate: WarmWorkerCandidate, directory: st
186
190
  const info = lstatSync(lock);
187
191
  if (!info.isFile() || info.isSymbolicLink() || info.uid !== uid || (info.mode & 0o077) !== 0)
188
192
  throw new Error('unsafe warm prepare lock file');
189
- if (!prepareFlock) throw new Error('warm prepare OS locks are unavailable on this platform');
193
+ if (!flock) throw new Error('warm prepare OS locks are unavailable on this platform');
190
194
  const lockDeadline = performance.now() + PREPARE_LOCK_WAIT_MS;
191
195
  while (!acquired) {
192
196
  if (signal?.aborted) throw new Error('warm prepare lock wait cancelled');
193
- if (prepareFlock(fd, LOCK_EX | LOCK_NB) === 0) { acquired = true; break; }
197
+ if (flock(fd, LOCK_EX | LOCK_NB) === 0) { acquired = true; break; }
194
198
  const errno = readPrepareErrno();
195
199
  // EWOULDBLOCK/EAGAIN: Linux 11, Darwin 35. EINTR is safe to retry.
196
200
  if (errno !== 11 && errno !== 35 && errno !== 4)
@@ -209,7 +213,7 @@ async function withPrepareLease<T>(candidate: WarmWorkerCandidate, directory: st
209
213
  workerId: candidate.spec.workerId, reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' });
210
214
  throw error;
211
215
  } finally {
212
- if (acquired && fd !== undefined) prepareFlock?.(fd, LOCK_UN);
216
+ if (acquired && fd !== undefined) flock?.(fd, LOCK_UN);
213
217
  if (fd !== undefined) closeSync(fd);
214
218
  }
215
219
  }
@@ -223,7 +227,14 @@ export class WarmPodProvider {
223
227
  private readonly legs: WarmReuseTimeLegRow[] = [];
224
228
  /** One terminal transition per fenced lease, including concurrent callers. Failed transitions remain retryable. */
225
229
  private readonly terminalLeases = new Map<string, Promise<'sanitized' | 'quarantined'>>();
230
+ /** A gate fallback supersedes an in-flight sanitize even if its control reply is late. */
231
+ private readonly quarantineRequested = new Set<string>();
232
+ private readonly terminalEndLogged = new Set<string>();
233
+ /** While quarantine is settling, reject only that Pod incarnation after acquisition. */
234
+ private readonly quarantiningPods = new Set<string>();
226
235
  private readonly standingWorkers = new Map<string, Promise<boolean>>();
236
+ /** This instance's prepare-lease flock binding; null means the platform cannot lock and every slot fails. */
237
+ private readonly prepareFlock: WarmPrepareFlock | null;
227
238
  constructor(private readonly options: WarmPodProviderOptions) {
228
239
  const url = new URL(options.controlUrl);
229
240
  if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password || url.search || url.hash
@@ -266,6 +277,9 @@ export class WarmPodProvider {
266
277
  }
267
278
  this.fetcher = options.fetch ?? fetch;
268
279
  this.now = options.now ?? Date.now;
280
+ // An omitted option keeps the platform binding; an explicit false/null declares flock unsupported.
281
+ this.prepareFlock = options.prepareFlock === undefined ? prepareFlock
282
+ : options.prepareFlock === false ? null : options.prepareFlock;
269
283
  }
270
284
 
271
285
  private async control(path: string, credential: string, body?: Record<string, unknown>): Promise<{ status: number; value: any }> {
@@ -347,7 +361,8 @@ export class WarmPodProvider {
347
361
  const inFlight = this.standingWorkers.get(key);
348
362
  if (inFlight) return inFlight;
349
363
  const preparation = withPrepareLease(configured, this.options.prepareLockDirectory,
350
- () => this.prepareStandingWorker(configured, this.options.prepareAbortSignal), this.options.prepareAbortSignal)
364
+ () => this.prepareStandingWorker(configured, this.options.prepareAbortSignal), this.options.prepareAbortSignal,
365
+ this.prepareFlock)
351
366
  .then(result => result === true);
352
367
  this.standingWorkers.set(key, preparation);
353
368
  try { return await preparation; }
@@ -626,6 +641,12 @@ export class WarmPodProvider {
626
641
  podName: leasedCandidate.spec.name, podContext: leasedCandidate.spec.kubectlContext, image: leasedCandidate.spec.image,
627
642
  requestedAt: new Date(this.now()).toISOString(),
628
643
  workerId: row.name, key: leasedCandidate.spec.key };
644
+ // Acquisition is by pool key. A healthy sibling or replacement Pod must remain eligible.
645
+ // Never run transport on the old Pod while its previous lease is being quarantined.
646
+ if (this.quarantiningPods.has(JSON.stringify([command.workerId, command.podUid]))) {
647
+ await this.quarantine(command, 'prior-lease-quarantine-pending', false);
648
+ return fallback('lease-unavailable');
649
+ }
629
650
  const admitted = patchWarmLeaseMetadata(leasedCandidate.spec, command, 'leased', this.options.kubectl);
630
651
  if (!admitted.ok) {
631
652
  debug.log('pod.provenance', 'lease-patch-refused', { pod: leasedCandidate.spec.name,
@@ -685,7 +706,7 @@ export class WarmPodProvider {
685
706
  let outcome: 'sanitized' | 'quarantined';
686
707
  try { outcome = await terminal; }
687
708
  catch (error) { if (this.terminalLeases.get(key) === terminal) this.terminalLeases.delete(key); throw error; }
688
- if (outcome === 'quarantined') throw new Error('warm sanitize unavailable');
709
+ if (outcome === 'quarantined' || this.quarantineRequested.has(key)) throw new Error('warm sanitize unavailable');
689
710
  }
690
711
 
691
712
  private async finalizeOnce(command: WarmWorkerCommand): Promise<'sanitized' | 'quarantined'> {
@@ -702,25 +723,39 @@ export class WarmPodProvider {
702
723
  await this.quarantineOnce(command, 'sanitize-unavailable', true);
703
724
  return 'quarantined';
704
725
  }
705
- debug.log('pod.provenance', 'lease-end', { pod: candidate.spec.name, podUid: command.podUid,
706
- leaseId: command.leaseId, runId: command.runId, attemptId: command.attemptId,
707
- releasedAt: new Date(this.now()).toISOString(), result: 'sanitized' });
726
+ const key = JSON.stringify([command.workerId, command.leaseId, command.generation, command.podUid]);
727
+ if (!this.quarantineRequested.has(key)) {
728
+ debug.log('pod.provenance', 'lease-end', { pod: candidate.spec.name, podUid: command.podUid,
729
+ leaseId: command.leaseId, runId: command.runId, attemptId: command.attemptId,
730
+ releasedAt: new Date(this.now()).toISOString(), result: 'sanitized' });
731
+ this.terminalEndLogged.add(key);
732
+ }
708
733
  return 'sanitized';
709
734
  }
710
735
 
711
736
  /** `leaseStarted=false` marks a refusal before `lease-start`, so start/end history stays paired. */
712
737
  async quarantine(command: WarmWorkerCommand, reason: string, leaseStarted = true): Promise<void> {
713
738
  const key = JSON.stringify([command.workerId, command.leaseId, command.generation, command.podUid]);
739
+ const podKey = JSON.stringify([command.workerId, command.podUid]);
740
+ this.quarantiningPods.add(podKey);
714
741
  const prior = this.terminalLeases.get(key);
715
742
  if (prior) {
716
- const outcome = await prior;
717
- debug.log('pod.provenance', 'lease-terminal-suppressed', { workerId: command.workerId,
718
- leaseId: command.leaseId, generation: command.generation, requested: 'quarantine', outcome });
743
+ this.quarantineRequested.add(key);
744
+ const terminal = prior.then(async outcome => {
745
+ if (outcome === 'sanitized') {
746
+ await this.quarantineOnce(command, reason, leaseStarted);
747
+ return 'quarantined' as const;
748
+ }
749
+ return outcome;
750
+ });
751
+ this.terminalLeases.set(key, terminal);
752
+ try { await terminal; this.quarantiningPods.delete(podKey); }
753
+ catch (error) { if (this.terminalLeases.get(key) === terminal) this.terminalLeases.delete(key); throw error; }
719
754
  return;
720
755
  }
721
756
  const terminal = this.quarantineOnce(command, reason, leaseStarted).then(() => 'quarantined' as const);
722
757
  this.terminalLeases.set(key, terminal);
723
- try { await terminal; }
758
+ try { await terminal; this.quarantiningPods.delete(podKey); }
724
759
  catch (error) { if (this.terminalLeases.get(key) === terminal) this.terminalLeases.delete(key); throw error; }
725
760
  }
726
761
 
@@ -734,9 +769,11 @@ export class WarmPodProvider {
734
769
  if (!cleared.ok && reason !== 'provenance-unavailable') debug.log('pod.provenance', 'lease-patch-refused', { pod: candidate.spec.name,
735
770
  podUid: command.podUid, leaseId: command.leaseId, reason: cleared.reason }, { level: 'warn' });
736
771
  }
737
- debug.log('pod.provenance', leaseStarted ? 'lease-end' : 'lease-refused', { podUid: command.podUid,
772
+ const key = JSON.stringify([command.workerId, command.leaseId, command.generation, command.podUid]);
773
+ debug.log('pod.provenance', this.terminalEndLogged.has(key) ? 'lease-late-quarantine' : leaseStarted ? 'lease-end' : 'lease-refused', { podUid: command.podUid,
738
774
  leaseId: command.leaseId, runId: command.runId, attemptId: command.attemptId, leaseStarted,
739
775
  releasedAt: new Date(this.now()).toISOString(), result: 'quarantined', reason });
776
+ this.terminalEndLogged.add(key);
740
777
  }
741
778
 
742
779
 
@@ -751,6 +788,10 @@ export function loadWarmPodProvider(path: string, pairingGateFile?: string): War
751
788
  const parsed: unknown = JSON.parse(readFileSync(path, 'utf8'));
752
789
  if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) throw new Error('invalid warm provider config');
753
790
  const options = parsed as WarmPodProviderOptions;
791
+ // JSON cannot carry a real OS binding: only the unsupported-platform declaration is meaningful here.
792
+ // Omitting the field keeps this platform's dlopen binding (undefined), so the default path is unchanged.
793
+ if (options.prepareFlock !== undefined && options.prepareFlock !== null && options.prepareFlock !== false)
794
+ throw new Error('invalid warm provider prepare flock');
754
795
  // The production entry points (--prepare/--reconcile/--serve) bind the 1-file gate key here.
755
796
  if (pairingGateFile !== undefined) {
756
797
  if (!pairingGateFile.trim()) throw new Error('warm provider pairing gate file must not be empty');