elanous 0.2.40 → 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 (558) 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/{HjeK7zONHfR7op1hKXp4k → 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/{9184.45afbf44fec87574.js → 1178.1aa9cad0e7695427.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/{2829-734fe8bf2eee7347.js → 1197-54da59d250a6e476.js} +1 -1
  9. package/apps/pwa/out/_next/static/chunks/{6749.0744ce6eb08d40e9.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/1765.679b29625c8e88d4.js +77 -0
  18. package/apps/pwa/out/_next/static/chunks/{2226.2cf61ec781827219.js → 1800.f7ff51dc4978a958.js} +2 -2
  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/{9175.2de5209a5ce6f68a.js → 2073.689dcb2680113d76.js} +1 -1
  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/{5383.bdfa5d886e39a826.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/{9069.657590a84afb8fac.js → 2743.5d3f76948be32b34.js} +2 -2
  31. package/apps/pwa/out/_next/static/chunks/{6624.981ef7caeb680560.js → 2773.0e80b9d325fb5635.js} +2 -2
  32. package/apps/pwa/out/_next/static/chunks/2873-0f3cb56c8e3528ea.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/{4864a2ca.1c1c280a7772c5e5.js → 2fdf2931.b431eee4fb468bc3.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/{9189505a.980427ac048c8c60.js → 2fe2c302.41b517f88d6fe502.js} +1 -1
  35. package/apps/pwa/out/_next/static/chunks/{9992.07ce73c10bd5e6a1.js → 3097.864e92bdaa2f4d15.js} +2 -2
  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/{b84cad00.594027ebe0531fe2.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/{8086.1ab9103c41be884f.js → 4156.ba4de4a3664f04b4.js} +1 -1
  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/{1281.d81877e35b9068f4.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/{8357.1aaa713b052a78b1.js → 4667.97e31aa38c95c475.js} +4 -4
  56. package/apps/pwa/out/_next/static/chunks/{5436.fdf6fa8ae3e9588d.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/{4769.9fd582071301f382.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/{d8de0de2-dd0f4ac8e5ab1832.js → 53aeb4ee-51c92f8d683f5220.js} +1 -1
  69. package/apps/pwa/out/_next/static/chunks/{6257.c0037b8949239f5e.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/{2566.beaffc3a5e1fcd2e.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/{2066.a77257c8c350770a.js → 5744.b9415e18ad623100.js} +1 -1
  75. package/apps/pwa/out/_next/static/chunks/5892.2526d962339662d8.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/{4351.0f37a6db2b34d50b.js → 5937.c2df9e3447e1f667.js} +1 -1
  77. package/apps/pwa/out/_next/static/chunks/5941.8210cc93c9202c0a.js +286 -0
  78. package/apps/pwa/out/_next/static/chunks/{6051-0ae955eedb10adb9.js → 5947-135e26537d80a6b9.js} +3 -3
  79. package/apps/pwa/out/_next/static/chunks/{3746-f80a78f220bf37b5.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/{2047.8f23e210995d4548.js → 6874.d5cf7eb8edb2cabe.js} +2 -2
  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/7191.fdc955f7d96064a4.js +1 -0
  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/{8272-025653884f9645d2.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/{2281-b8cede695c6c650e.js → 8464-e24f10451b658aac.js} +1 -1
  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/{5622.94893f5aea7185d0.js → 8880.64c445592f04acaf.js} +1 -1
  108. package/apps/pwa/out/_next/static/chunks/{1452.162bb2d9d699e82a.js → 8981.c706964c8ba27aff.js} +1 -1
  109. package/apps/pwa/out/_next/static/chunks/{470.51a72a2348306455.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/{2177.df8547f9d7215c4e.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/{7515.1ad6efe157fa4448.js → 9579.4a8169600fff2058.js} +1 -1
  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/{2499.02fbfd18126c10c0.js → 9834.63ab2bbc3153172e.js} +1 -1
  124. package/apps/pwa/out/_next/static/chunks/9869.81a1e24ca682d5a0.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/{409c787b.e48c5bec8ec10456.js → a0a01613.6d1cca322238d7fe.js} +1 -1
  126. package/apps/pwa/out/_next/static/chunks/{6cc1d1d6.9a98dd4622f1afc6.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-ba957ff875a026a0.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/{c696986b.5dc8bb1143af16d1.js → b2271e54.c1de3347976e90b0.js} +1 -1
  179. package/apps/pwa/out/_next/static/chunks/{ca3702f8.2913182e73889fa2.js → c0c1a699.0ba79f97005965d4.js} +1 -1
  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-teacher/lesson-pack.yaml +16 -0
  283. package/graphs/demo/persona-teacher/recipes.yaml +17 -0
  284. package/graphs/demo/persona-teacher/weekly-lesson.yaml +36 -0
  285. package/graphs/overlays/stop-heal-ladder.yaml +23 -2
  286. package/graphs/release/release-loop.yaml +3 -1
  287. package/graphs/units/gate/gate.yaml +20 -0
  288. package/graphs/units/git/git.yaml +26 -0
  289. package/graphs/units/implement/implement.yaml +19 -0
  290. package/graphs/units/landing/landing.yaml +18 -0
  291. package/graphs/units/review/review.yaml +20 -0
  292. package/graphs/units/verbs/recipes.yaml +3 -0
  293. package/graphs/units/verbs/research.yaml +20 -0
  294. package/graphs/work/research-report.yaml +11 -1
  295. package/package.json +1 -1
  296. package/scripts/disk-steward.ts +46 -0
  297. package/scripts/fleet/node-setup.sh +50 -0
  298. package/scripts/graph-units/verbs/research.ts +55 -0
  299. package/scripts/llm-cost-ledger.ts +179 -8
  300. package/scripts/measure-nl-routing-corpus.ts +10 -2
  301. package/scripts/persona-teacher/weekly-lesson-node.ts +172 -0
  302. package/scripts/public-copy-lint.ts +163 -19
  303. package/scripts/ratchets/train-side-invariants.sh +0 -1
  304. package/scripts/release-loop/gate-autoheal.ts +117 -0
  305. package/scripts/release-loop/gate-baseline-receipt.ts +8 -1
  306. package/scripts/release-loop/gate-diff.ts +22 -3
  307. package/scripts/release-loop/gate-node.ts +205 -17
  308. package/scripts/release-loop/gate-shard-load-flaky.ts +256 -0
  309. package/scripts/release-loop/gate-triage-node.ts +70 -10
  310. package/scripts/release-loop/resume-release.ts +247 -15
  311. package/scripts/release-loop/traffic-node.ts +6 -3
  312. package/scripts/release-loop/unattended-release.ts +4 -2
  313. package/scripts/shadow-authoring-probe.ts +20 -0
  314. package/scripts/ux-sim.ts +19 -2
  315. package/src/acp/core-turn-bridge.ts +86 -4
  316. package/src/agent-substrate/self-review-cli.ts +91 -29
  317. package/src/auto-research/research-turn.ts +10 -1
  318. package/src/autopilot/discovery/wiki-claim-proposer.ts +22 -1
  319. package/src/boot/daemon-tools/self-implement.ts +46 -9
  320. package/src/budget/shadow-arms.ts +52 -0
  321. package/src/chat/pickers/state.ts +7 -1
  322. package/src/cli/log-event-names.ts +5 -0
  323. package/src/cli/mcp-login.ts +8 -18
  324. package/src/cli/msg-cli.ts +57 -1
  325. package/src/cli/pr-land-heavy-remote.ts +15 -9
  326. package/src/cli/release-cli.ts +27 -1
  327. package/src/cli/sim-cli.ts +7 -1
  328. package/src/cli/tasks-cli.ts +5 -4
  329. package/src/codex/models.ts +30 -15
  330. package/src/core-turn/run-core-turn.ts +3 -0
  331. package/src/core-turn/run-goal-loop.ts +88 -2
  332. package/src/dashboard/acp-boot.ts +72 -3
  333. package/src/dashboard/index.ts +6 -0
  334. package/src/dashboard/turn-preamble.ts +12 -1
  335. package/src/disk-steward/judge.ts +73 -0
  336. package/src/disk-steward/ledger.ts +122 -0
  337. package/src/disk-steward/steward.ts +373 -0
  338. package/src/domains/guardian-tick.ts +191 -2
  339. package/src/graph-runner/graph-cli.ts +21 -0
  340. package/src/graph-runner/in-process-registry.ts +37 -0
  341. package/src/graph-runner/runner.ts +33 -3
  342. package/src/grounding/ref-index.ts +19 -0
  343. package/src/grounding/sources-cli.ts +9 -1
  344. package/src/harness/harness-cli-command.ts +267 -14
  345. package/src/harness/harness-incidents.ts +312 -7
  346. package/src/harness/harness-space.ts +15 -1
  347. package/src/harness/progress-worker-entry.ts +59 -0
  348. package/src/harness/progress-worker-runtime.ts +11 -0
  349. package/src/index.ts +18 -2
  350. package/src/instance/dev-project.ts +25 -0
  351. package/src/intelligence-map/model-alias.ts +6 -5
  352. package/src/intelligence-map/model-catalog.ts +59 -2
  353. package/src/llm/model-defaults.ts +4 -4
  354. package/src/llm.ts +42 -11
  355. package/src/loops/orchestrator/tick.ts +48 -0
  356. package/src/mcp/mcp-oauth.ts +3 -1
  357. package/src/model-tier/llm-tier-map.ts +9 -9
  358. package/src/model-tier/turn-tier.ts +1 -1
  359. package/src/msg/msg-mirror-github.ts +80 -0
  360. package/src/msg/msg-mirror-policy.ts +61 -0
  361. package/src/msg/msg-mirror-runner.ts +219 -0
  362. package/src/msg/msg-mirror-state.ts +33 -0
  363. package/src/msg/msg-store.ts +11 -0
  364. package/src/output-truncation.ts +41 -12
  365. package/src/project/project-store.ts +48 -1
  366. package/src/release-loop/gate-host-reservation.ts +144 -0
  367. package/src/release-loop/release-schedule.ts +90 -1
  368. package/src/research/bloom-exemplars.ts +135 -0
  369. package/src/self-dev/ask-launch-flow.ts +39 -25
  370. package/src/self-dev/dev-cli.ts +17 -17
  371. package/src/self-dev/graph-front-nodes.ts +23 -0
  372. package/src/self-dev/launch-preflight.ts +9 -4
  373. package/src/self-dev/orchestrate.ts +15 -0
  374. package/src/self-dev/run-supervisor.ts +185 -3
  375. package/src/self-dev/run-types.ts +3 -0
  376. package/src/self-implement/gate-artifacts.ts +13 -0
  377. package/src/self-implement/gate-cli.ts +54 -24
  378. package/src/self-implement/gate-remote.ts +23 -5
  379. package/src/self-implement/goal-author-clarification.ts +31 -12
  380. package/src/self-implement/goal-author.ts +77 -5
  381. package/src/self-implement/graph-stage-units.ts +172 -0
  382. package/src/self-implement/graph-templates.ts +162 -1
  383. package/src/self-implement/graph-variant.ts +37 -4
  384. package/src/self-implement/host-regate.ts +4 -4
  385. package/src/self-implement/knowhow-pack.ts +38 -0
  386. package/src/self-implement/orchestrator.ts +235 -21
  387. package/src/self-implement/run-ledger.ts +64 -6
  388. package/src/self-implement/run-stop.ts +21 -2
  389. package/src/self-implement/running-runs.ts +35 -12
  390. package/src/self-implement/self-implement-cli.ts +36 -4
  391. package/src/self-implement/stop-autoheal-operational.ts +43 -0
  392. package/src/self-implement/stop-autoheal.ts +15 -6
  393. package/src/session/chat.ts +31 -54
  394. package/src/session/request-size-guard.ts +123 -0
  395. package/src/sidetab-core/model.ts +136 -0
  396. package/src/task-agent/parent-host.ts +14 -1
  397. package/src/task-agent/task-hand.ts +4 -1
  398. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +43 -0
  399. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +29 -4
  400. package/src/task-orchestrator/surfaces/self-implement-pod.ts +116 -16
  401. package/src/task-orchestrator/surfaces/self-implement.ts +18 -0
  402. package/src/tui/entry.ts +10 -3
  403. package/src/tui/sidetab/list.ts +45 -0
  404. package/src/tui/sidetab/nl-tool.ts +2 -136
  405. package/src/tui/sidetab/peek.ts +52 -0
  406. package/src/tui-client/dashboard-session.ts +3 -0
  407. package/src/user-config.ts +11 -5
  408. package/src/ux-sim/fault-needs-human-reason-repair.ts +107 -0
  409. package/src/ux-sim/fault-pod-child-result.ts +42 -0
  410. package/src/ux-sim/release-sim-rig.ts +262 -0
  411. package/src/ux-sim/seminar-rehearsal.ts +109 -0
  412. package/src/ux-sim/subagent-tools-device.ts +2 -2
  413. package/src/version/packed-revision.json +1 -1
  414. package/apps/pwa/out/_next/static/chunks/1060.014f1f01a17aec26.js +0 -115
  415. package/apps/pwa/out/_next/static/chunks/1350.59f40e39e02d91b1.js +0 -1
  416. package/apps/pwa/out/_next/static/chunks/1415.79821ec7ae99acdb.js +0 -1
  417. package/apps/pwa/out/_next/static/chunks/147.f92f63bbc5e85fa5.js +0 -286
  418. package/apps/pwa/out/_next/static/chunks/1537-6bb97b5214928ea9.js +0 -1
  419. package/apps/pwa/out/_next/static/chunks/1661.fb425a1d8a065b72.js +0 -149
  420. package/apps/pwa/out/_next/static/chunks/1671-1c22b40b50b208f2.js +0 -1
  421. package/apps/pwa/out/_next/static/chunks/1758.0204d3f48783c49d.js +0 -90
  422. package/apps/pwa/out/_next/static/chunks/1806.027bf78b6a94d340.js +0 -104
  423. package/apps/pwa/out/_next/static/chunks/2061-7f2bbc53ae96c88b.js +0 -1
  424. package/apps/pwa/out/_next/static/chunks/2096-a938496bc996dcbd.js +0 -1
  425. package/apps/pwa/out/_next/static/chunks/2200-9a453b8f99687d49.js +0 -1
  426. package/apps/pwa/out/_next/static/chunks/2522.f2766b76d22c8bdf.js +0 -34
  427. package/apps/pwa/out/_next/static/chunks/261.0d471e8aded799f3.js +0 -226
  428. package/apps/pwa/out/_next/static/chunks/2615.3c9738153de3ef3f.js +0 -1
  429. package/apps/pwa/out/_next/static/chunks/2727.e703d99ac414916d.js +0 -1
  430. package/apps/pwa/out/_next/static/chunks/2752.7904b8df0254d0ae.js +0 -27
  431. package/apps/pwa/out/_next/static/chunks/2762-5051a862dfa40e99.js +0 -1
  432. package/apps/pwa/out/_next/static/chunks/2767-31784bfedf8e245d.js +0 -1
  433. package/apps/pwa/out/_next/static/chunks/2774-719820e3f5b2a3eb.js +0 -1
  434. package/apps/pwa/out/_next/static/chunks/2812-f016aa0dda149287.js +0 -1
  435. package/apps/pwa/out/_next/static/chunks/311-32dcac79970985e8.js +0 -1
  436. package/apps/pwa/out/_next/static/chunks/3175-f93f7495cd28253c.js +0 -1
  437. package/apps/pwa/out/_next/static/chunks/3184.8da993f5502d2140.js +0 -1
  438. package/apps/pwa/out/_next/static/chunks/3231-d7c981db0ff8bdcc.js +0 -1
  439. package/apps/pwa/out/_next/static/chunks/3250.151309c5176d6b4b.js +0 -1
  440. package/apps/pwa/out/_next/static/chunks/3330.7443183b7e6fdbdf.js +0 -1
  441. package/apps/pwa/out/_next/static/chunks/3517.a5aa1797a9dbf2ee.js +0 -1
  442. package/apps/pwa/out/_next/static/chunks/3567-45f676877ed9e8a5.js +0 -1
  443. package/apps/pwa/out/_next/static/chunks/3819.8a1de79b2e8c7298.js +0 -24
  444. package/apps/pwa/out/_next/static/chunks/39.9b37b0be4c128a83.js +0 -77
  445. package/apps/pwa/out/_next/static/chunks/3b355b3d.6f73c98bf6f9c749.js +0 -122
  446. package/apps/pwa/out/_next/static/chunks/4023.a19045970a9ce16a.js +0 -36
  447. package/apps/pwa/out/_next/static/chunks/413-24c8284bda08241d.js +0 -1
  448. package/apps/pwa/out/_next/static/chunks/4135.e45d6ebc29e20647.js +0 -1
  449. package/apps/pwa/out/_next/static/chunks/4283.65502f5d0e6ff6c0.js +0 -287
  450. package/apps/pwa/out/_next/static/chunks/4305-4e28fa92a7b34a5b.js +0 -1
  451. package/apps/pwa/out/_next/static/chunks/4335-50efa61fd7613142.js +0 -1
  452. package/apps/pwa/out/_next/static/chunks/4720.ecbd1693fa151068.js +0 -1
  453. package/apps/pwa/out/_next/static/chunks/483.725e4a61be922788.js +0 -1
  454. package/apps/pwa/out/_next/static/chunks/4969-4b209d7307410c00.js +0 -1
  455. package/apps/pwa/out/_next/static/chunks/5068-c7f53862f83c0917.js +0 -1
  456. package/apps/pwa/out/_next/static/chunks/5315.bc96711c24dfefe2.js +0 -74
  457. package/apps/pwa/out/_next/static/chunks/5542.efbf14f16baed4dd.js +0 -1
  458. package/apps/pwa/out/_next/static/chunks/5644.8f401a25601d05fc.js +0 -1
  459. package/apps/pwa/out/_next/static/chunks/5658.35f70eb9871a54bf.js +0 -1
  460. package/apps/pwa/out/_next/static/chunks/5721.7bdc0e904c76ab51.js +0 -8
  461. package/apps/pwa/out/_next/static/chunks/5790-eef0ca20884a6bdf.js +0 -1
  462. package/apps/pwa/out/_next/static/chunks/5802.ef0d8598ca68fe84.js +0 -62
  463. package/apps/pwa/out/_next/static/chunks/5890.fb974729788dcb71.js +0 -1
  464. package/apps/pwa/out/_next/static/chunks/5924.5ef25cddd36d5dbf.js +0 -1
  465. package/apps/pwa/out/_next/static/chunks/5979-e59c099ebf8d1f35.js +0 -1
  466. package/apps/pwa/out/_next/static/chunks/6020.714cfeada2315e2e.js +0 -94
  467. package/apps/pwa/out/_next/static/chunks/6027-dfe0349d8c50f698.js +0 -1
  468. package/apps/pwa/out/_next/static/chunks/6178.bc4730c86cf74536.js +0 -1
  469. package/apps/pwa/out/_next/static/chunks/6273.d808b0dcb3c2b155.js +0 -1
  470. package/apps/pwa/out/_next/static/chunks/6292.6ef1df64fa6a4c8a.js +0 -1
  471. package/apps/pwa/out/_next/static/chunks/647-af8dd920ba46533c.js +0 -1
  472. package/apps/pwa/out/_next/static/chunks/6541-170dc5c59e135c0c.js +0 -1
  473. package/apps/pwa/out/_next/static/chunks/6742-a1ad4a94ba7bc37a.js +0 -1
  474. package/apps/pwa/out/_next/static/chunks/6836-493dc55c39187949.js +0 -1
  475. package/apps/pwa/out/_next/static/chunks/6856-53ac421c06039a18.js +0 -1
  476. package/apps/pwa/out/_next/static/chunks/6908.06008c67f6380ea9.js +0 -148
  477. package/apps/pwa/out/_next/static/chunks/6915.096931864206f522.js +0 -1
  478. package/apps/pwa/out/_next/static/chunks/6925.5e181fb7dcf90193.js +0 -1
  479. package/apps/pwa/out/_next/static/chunks/7203-800e11037adc41eb.js +0 -1
  480. package/apps/pwa/out/_next/static/chunks/7219-15bdd9a80661af8e.js +0 -1
  481. package/apps/pwa/out/_next/static/chunks/7279.6170f591105936bb.js +0 -93
  482. package/apps/pwa/out/_next/static/chunks/7349-373165c7fbdcc3df.js +0 -1
  483. package/apps/pwa/out/_next/static/chunks/7514-a533ba0ca1cae4f4.js +0 -1
  484. package/apps/pwa/out/_next/static/chunks/7521.d919cc1fab80c1d9.js +0 -24
  485. package/apps/pwa/out/_next/static/chunks/7538.90e97bbdf9178cff.js +0 -1
  486. package/apps/pwa/out/_next/static/chunks/7611.85f045bf232053ac.js +0 -1
  487. package/apps/pwa/out/_next/static/chunks/7825-39203196a12579b2.js +0 -1
  488. package/apps/pwa/out/_next/static/chunks/7869.5e1a9a12fd70d6c7.js +0 -1
  489. package/apps/pwa/out/_next/static/chunks/8099.1cccf31c1baa7e1c.js +0 -1
  490. package/apps/pwa/out/_next/static/chunks/8179-e61fffbdb70f1152.js +0 -1
  491. package/apps/pwa/out/_next/static/chunks/8265.bdeb991b34db6a06.js +0 -1
  492. package/apps/pwa/out/_next/static/chunks/8638-e42615f2166165b5.js +0 -1
  493. package/apps/pwa/out/_next/static/chunks/8639-92c11d069792429e.js +0 -1
  494. package/apps/pwa/out/_next/static/chunks/8691.54e22831d5e8ccf8.js +0 -1
  495. package/apps/pwa/out/_next/static/chunks/8d173e38.18a2f7b4e1848bdb.js +0 -1
  496. package/apps/pwa/out/_next/static/chunks/9125-ae588d88a0293b93.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/9311.f9f641a46a508611.js +0 -1
  498. package/apps/pwa/out/_next/static/chunks/9371-a6fee8378ebfa3ee.js +0 -1
  499. package/apps/pwa/out/_next/static/chunks/9421-3aa9ff4fa7f63d8a.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76394dc618d322c8.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/app/approvals/page-1b948637c37b3abd.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-c63400f1bcf3e47c.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/app/board/page-95d0957267819586.js +0 -1
  504. package/apps/pwa/out/_next/static/chunks/app/bots/page-bb6fd0714879cb87.js +0 -1
  505. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8f9038520d2acbef.js +0 -1
  506. package/apps/pwa/out/_next/static/chunks/app/chat/page-d4b48397e05fce2c.js +0 -1
  507. package/apps/pwa/out/_next/static/chunks/app/consult/page-72d5744245dc0c27.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/app/control/page-37625dc8300fa43a.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/app/decisions/page-fbef9d160272dbc1.js +0 -1
  510. package/apps/pwa/out/_next/static/chunks/app/design-check/page-58424168df84928e.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/app/editor/page-72c12ba430ac57c0.js +0 -1
  512. package/apps/pwa/out/_next/static/chunks/app/exec/page-d53f3e9ed806d7e0.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/app/field/page-4d2fbd45feee0829.js +0 -1
  514. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76394dc618d322c8.js +0 -1
  515. package/apps/pwa/out/_next/static/chunks/app/inside/page-8783dc0ed7590a2c.js +0 -1
  516. package/apps/pwa/out/_next/static/chunks/app/intake/page-3706cb390606e930.js +0 -1
  517. package/apps/pwa/out/_next/static/chunks/app/layout-9b0a86598e0111fd.js +0 -1
  518. package/apps/pwa/out/_next/static/chunks/app/live/page-4edb8df90f4537ce.js +0 -1
  519. package/apps/pwa/out/_next/static/chunks/app/live-run/page-83d27757e2b8060a.js +0 -1
  520. package/apps/pwa/out/_next/static/chunks/app/loops/page-47398b9ba1cc5e1b.js +0 -1
  521. package/apps/pwa/out/_next/static/chunks/app/market/page-fb86f55cfe2e681d.js +0 -1
  522. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e22345fc8fd47b1b.js +0 -1
  523. package/apps/pwa/out/_next/static/chunks/app/morning/page-fca2e59a81744d9e.js +0 -1
  524. package/apps/pwa/out/_next/static/chunks/app/not-found-6e96bda63100b31e.js +0 -1
  525. package/apps/pwa/out/_next/static/chunks/app/observatory/page-4d17ad8e0db8cea4.js +0 -1
  526. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-121f92766c33beaa.js +0 -1
  527. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-43f14212c545f92d.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ccec2023e7a974ec.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/app/outputs/page-b04f33f548b89a94.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/app/page-c8792823c0917021.js +0 -1
  531. package/apps/pwa/out/_next/static/chunks/app/reflection/page-8c0e32782ceef4cb.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-94bd3922eb230ce8.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/app/sessions/page-bca565887bafa03c.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-ac1dffafe649fc6c.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/app/settings/page-52374edb5e23e455.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ad4ebca120d43ca7.js +0 -1
  537. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76394dc618d322c8.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/app/setup/page-718b89ce4b4ae4e4.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/app/share/page-204eca33eeeaddec.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/app/showroom/page-e58ba9bcdb9ac0f9.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/app/tasks/page-98f6dd50bafd7734.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/app/term/page-139d722de1dcd6c1.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/app/today/page-5a4bdd72bff27057.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/app/trace/page-6f6ab17d44f984ce.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/app/vault/page-aabb7bd15fb72da9.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-e4322319164a4436.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/app/workflows/page-e9efc0c8f32e2371.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/app/workspace/page-ccde99f07aaf71f7.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-80464aced9614390.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/d5d3cefc-373c4eb722ed848b.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/framework-002b472a66935d31.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/main-49b88d47292c0476.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/main-app-fff2549cb10a133f.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/pages/_app-32abbbba3f3b76b7.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/pages/_error-9d9cfef60c60dd7a.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/webpack-cc7f483fa294034a.js +0 -1
  557. package/scripts/ratchets/next-tui-entry-budget.ts +0 -124
  558. /package/apps/pwa/out/_next/static/{HjeK7zONHfR7op1hKXp4k → GiOLWmt4MqDZePubBjA4Q}/_ssgManifest.js +0 -0
@@ -43,6 +43,11 @@ export interface SupervisorRound {
43
43
  mainSyncRelaunchFeatures?: string[];
44
44
  /** PR 없는 미분류 실패에 대해 실제 분해 실행기로 수복한 원래 골. 새 taskId에도 한 번 상한을 지킨다. */
45
45
  selfHealDecomposeFeatures?: string[];
46
+ /**
47
+ * NEEDS-HUMAN-REASON-REPAIR — 사유별 자가 수복 1회의 소진 기억(사유 → 그때 수복한 골 전문).
48
+ * 사유가 다르면 다른 시도다. 옛 원장엔 이 칸이 없다 = 「안 쟀다」이지 「시도했다」가 아니다.
49
+ */
50
+ selfHealRepairFeatures?: Partial<Record<NeedsHumanRepairReason, string[]>>;
46
51
  /**
47
52
  * Tasks of this round that ended `status=failed` without a PR. Omitted when there are none — and on older
48
53
  * history, which never measured it, so the no-PR streak guard reads it as «not measured» and stays off.
@@ -137,7 +142,96 @@ export interface SupervisorDecision {
137
142
  };
138
143
  oscillation?: { taskIds: string[]; helper: 'review-oscillation'; signature: string; repairGoals?: Record<string, string>; heldTaskIds?: string[] };
139
144
  pendingDecision?: 'attempt-care-escalation';
140
- selfHeal?: { reason: 'supervisor-unclassified-decompose'; attempt: 1; taskIds: string[] };
145
+ selfHeal?: { reason: SelfHealReason; attempt: 1; taskIds: string[]; repairGoals?: Record<string, string> };
146
+ }
147
+
148
+ /**
149
+ * NEEDS-HUMAN-REASON-REPAIR — needs-human 으로 접히기 «전»에 한 번 수복해 볼 사유.
150
+ * 각 사유의 수복은 다르다: 없는 경로 → 재접지 · 범위 확장 → 좁히기 · 시간 초과 → 좁은 시험 · 조각 없음 → 조각 재걸기.
151
+ */
152
+ export type NeedsHumanRepairReason = 'missing-path' | 'scope-expansion' | 'step-timeout' | 'no-piece';
153
+
154
+ /** 선행 0.2.38 의 분해 수복 사유까지 포함한 자가 수복 사유 전체. */
155
+ export type SelfHealReason = 'supervisor-unclassified-decompose' | `supervisor-${NeedsHumanRepairReason}`;
156
+
157
+ const NEEDS_HUMAN_REPAIR_REASONS: readonly NeedsHumanRepairReason[] = ['missing-path', 'scope-expansion', 'step-timeout', 'no-piece'];
158
+
159
+ /** 파일 부재의 두 코드 — 없는 경로(ENOENT)와 중간 성분이 파일인 경로(ENOTDIR). */
160
+ const MISSING_PATH_ERROR_CODES: ReadonlySet<string> = new Set(['ENOENT', 'ENOTDIR']);
161
+
162
+ const NEEDS_HUMAN_REPAIR_INSTRUCTION: Record<NeedsHumanRepairReason, string> = {
163
+ 'missing-path': '없는 경로를 다시 접지한다 — 저장소에 있는 파일이나 골에 명시된 대상 경로만 고르고, 새 파일은 골이 신설을 요구할 때만 만든다',
164
+ 'scope-expansion': '범위 확장을 좁힌다 — 대상 경로 밖으로 나간 변경을 되돌리고 골의 대상·완료 경계 안에서만 구현한다',
165
+ 'step-timeout': '단계 예산을 넘겼다 — 좁은 시험 하나로 판정선을 먼저 세우고 나머지 실행은 그 뒤로 미룬다',
166
+ 'no-piece': '조각 없이 실패했다 — 같은 골을 다시 걸되 완료 경계를 한 조각 분량으로 잘라 건다',
167
+ };
168
+
169
+ function normalizedRepairPath(path: string): string {
170
+ return path.replace(/^\.\//u, '').replace(/[),.;:]+$/u, '');
171
+ }
172
+
173
+ /** 경로가 범위 집합 안인가 — 정확 일치 · 디렉터리 접두 · (언급이 파일 이름뿐이면) 파일 이름 일치. */
174
+ function pathWithinScope(path: string, scope: readonly string[]): boolean {
175
+ const p = normalizedRepairPath(path);
176
+ return scope.some((raw) => {
177
+ const s = normalizedRepairPath(raw);
178
+ if (s === p) return true;
179
+ if (s.endsWith('/') ? p.startsWith(s) : p.startsWith(`${s}/`)) return true;
180
+ return !p.includes('/') && s.split('/').at(-1) === p;
181
+ });
182
+ }
183
+
184
+ /**
185
+ * 범위 확장 — «밖»이라고 잰 변경 전부.
186
+ * ⛔ 대상 경로를 모르면 `changedFiles` 로는 «밖»을 단정하지 않는다(둘 다 쟀을 때만).
187
+ * 다만 실행 범위 가드가 «대상 밖»으로 직접 잰 값(`outsideTargetFiles`)은 그 자체가 측정이다.
188
+ */
189
+ function expandedBeyondTargetPaths(result: SupervisorJobResult): string[] {
190
+ const measured = result.outsideTargetFiles ?? [];
191
+ const changed = result.changedFiles;
192
+ const targets = result.targetPaths;
193
+ const byScope = changed !== undefined && targets !== undefined && targets.length > 0
194
+ ? changed.filter((file) => !pathWithinScope(file, targets))
195
+ : [];
196
+ return [...new Set([...measured, ...byScope])];
197
+ }
198
+
199
+ /**
200
+ * needs-human 앞의 수복 사유 discriminator — 결과에 이미 실리는 판정 재료만 본다:
201
+ * 단계(`timed-out`) · 오류 코드(ENOENT/ENOTDIR) · 변경 파일 vs 골 대상 경로 · 분해 제안 조각 수.
202
+ * PR 이 있는 결과(사람이 볼 PR)와 재시도 재료가 있는 결과는 여기 대상이 아니다(undefined).
203
+ */
204
+ export function needsHumanRepairReason(result: SupervisorJobResult): NeedsHumanRepairReason | undefined {
205
+ if (result.status !== 'failed' || result.prNumber !== undefined || result.prUrl) return undefined;
206
+ if (result.stage === 'timed-out') return 'step-timeout';
207
+ if (result.error?.code !== undefined && MISSING_PATH_ERROR_CODES.has(result.error.code)) return 'missing-path';
208
+ if (expandedBeyondTargetPaths(result).length > 0) return 'scope-expansion';
209
+ if ((result.decomposeProposal?.pieces.length ?? 0) < 2) return 'no-piece';
210
+ return undefined;
211
+ }
212
+
213
+ /** 사유별 수복 골 원문 — 사유의 수복 지시 + 골의 대상 경로 + 관측된 원인 + 원래 골. */
214
+ export function needsHumanRepairGoal(result: SupervisorJobResult, reason: NeedsHumanRepairReason): string {
215
+ const outside = expandedBeyondTargetPaths(result);
216
+ const repairTargets = result.targetPaths?.length ? result.targetPaths : undefined;
217
+ return [
218
+ `[supervisor-needs-human-repair:${reason}] ${NEEDS_HUMAN_REPAIR_INSTRUCTION[reason]}`,
219
+ ...(repairTargets?.length ? [`대상 경로: ${repairTargets.join(', ')}`] : []),
220
+ ...(outside.length ? [`대상 경로 밖 변경: ${outside.join(', ')}`] : []),
221
+ ...(result.error?.message ? [`이전 실패: ${result.error.message.slice(0, 200)}`] : []),
222
+ result.feature,
223
+ ].join('\n');
224
+ }
225
+
226
+ /** 수복 사유가 붙은 자가 수복인가 — 선행 분해 수복('supervisor-unclassified-decompose')과 갈라낸다. */
227
+ function needsHumanRepairDecisionReason(reason: SelfHealReason): NeedsHumanRepairReason | undefined {
228
+ return NEEDS_HUMAN_REPAIR_REASONS.find((candidate) => reason === `supervisor-${candidate}`);
229
+ }
230
+
231
+ /** 사유별 소진 기억에 이 조각이 이미 있는가 — 새 taskId 여도 골 전문으로 짝을 맞춘다. */
232
+ function needsHumanRepairSpent(history: readonly SupervisorRound[], reason: NeedsHumanRepairReason, feature: string): boolean {
233
+ const key = resumeKey(feature);
234
+ return history.some((entry) => (entry.selfHealRepairFeatures?.[reason] ?? []).some((spent) => resumeKey(spent) === key));
141
235
  }
142
236
 
143
237
  export interface SupervisorLimits {
@@ -245,6 +339,11 @@ export type SupervisorJobResult = SelfDevJobResult & {
245
339
  reviewReason?: string;
246
340
  salvage?: 'launched' | 'parked';
247
341
  next?: SupervisorNext;
342
+ /**
343
+ * NEEDS-HUMAN-REASON-REPAIR — 실행 범위 가드가 «대상 경로 밖»으로 직접 잰 변경.
344
+ * 골이 대상 경로를 안 선언했어도 이 값은 측정이다 — `changedFiles` 와 달리 «밖»을 단정할 수 있다.
345
+ */
346
+ outsideTargetFiles?: readonly string[];
248
347
  };
249
348
 
250
349
  export function aggregateReviewTrend(results: readonly SelfDevJobResult[]): ReviewRework['trend'] | undefined {
@@ -360,6 +459,8 @@ export function decideNextRun(input: {
360
459
  reviewMustFixTrend?: ReviewRework['trend'];
361
460
  /** True: the rerun consumes the authored goal. False: it cannot, so oscillation stops for a human. Undefined: pure decision. */
362
461
  repairGoalExecution?: boolean;
462
+ /** Separate opt-in for needs-human reason repairs; omitted keeps the new repair execution disabled. */
463
+ needsHumanReasonRepairExecution?: boolean;
363
464
  /** 분해 제안을 실제 조각 실행으로 승격할 수 있는 supervisor 경로에만 true. */
364
465
  decompositionExecution?: boolean;
365
466
  }): SupervisorDecision {
@@ -550,7 +651,52 @@ export function decideNextRun(input: {
550
651
  why: `supervisor-unclassified-decompose (attempt: 1/1) — PR 없는 미분류 조각 ${taskIds.length}개를 실증된 분해 제안으로 한 번 재걸기`,
551
652
  };
552
653
  }
654
+ // NEEDS-HUMAN-REASON-REPAIR — 사람에게 접기 «전»에 사유별로 한 번 수복한다. 수복 골은 rerun 이 그대로 실행한다.
655
+ // ⛔ 실행기가 선언되지 않았으면(repairGoalExecution !== true) 수복 대신 지금처럼 사람에게 간다.
656
+ if (input.repairGoalExecution === true && input.needsHumanReasonRepairExecution === true && round + 1 <= maxRounds) {
657
+ const repairable = activeResults.flatMap((result) => {
658
+ if (!t.needsHuman.includes(result.taskId)) return [];
659
+ if (!t.classifications.some((classification) => classification.taskId === result.taskId && classification.kind === 'unclassified')) return [];
660
+ const reason = needsHumanRepairReason(result);
661
+ if (reason === undefined || (result.targetPaths?.length ?? 0) === 0) return [];
662
+ return needsHumanRepairSpent(history, reason, result.feature) ? [] : [{ result, reason }];
663
+ });
664
+ const first = repairable[0];
665
+ const single = first !== undefined && repairable.length === 1 && t.needsHuman.every((id) => id === first.result.taskId)
666
+ ? first : undefined;
667
+ if (single) {
668
+ const taskIds = [single.result.taskId];
669
+ return {
670
+ ...base,
671
+ action: 'relaunch',
672
+ needsHuman: t.needsHuman.filter((id) => !taskIds.includes(id)),
673
+ selfHeal: {
674
+ reason: `supervisor-${single.reason}`,
675
+ attempt: 1,
676
+ taskIds,
677
+ repairGoals: { [single.result.taskId]: needsHumanRepairGoal(single.result, single.reason) },
678
+ },
679
+ why: `supervisor-${single.reason} (attempt: 1/1) — ${NEEDS_HUMAN_REPAIR_INSTRUCTION[single.reason]}`,
680
+ };
681
+ }
682
+ }
553
683
  if (t.needsHuman.length > 0) {
684
+ // 이미 한 번 수복했는데 같은 사유로 다시 섰다 — 사유·시도를 원문으로 남기고 사람에게 넘긴다.
685
+ const exhausted = activeResults.flatMap((result) => {
686
+ if (!t.needsHuman.includes(result.taskId)) return [];
687
+ const reason = needsHumanRepairReason(result);
688
+ if (reason === undefined || !needsHumanRepairSpent(history, reason, result.feature)) return [];
689
+ return [{ result, reason }];
690
+ });
691
+ if (exhausted.length > 0) {
692
+ return {
693
+ ...base,
694
+ action: 'stop',
695
+ stopReason: 'needs-human',
696
+ why: withGoalPlanRevisionObservation(`${exhausted.map(({ result, reason }) =>
697
+ `supervisor-${reason} (attempt: 1/1) — ${NEEDS_HUMAN_REPAIR_INSTRUCTION[reason]} 을 한 번 시도했으나 같은 조각이 다시 실패했다(${result.taskId})`).join(' · ')} · 사람이 볼 것 ${t.needsHuman.length}`),
698
+ };
699
+ }
554
700
  return {
555
701
  ...base,
556
702
  action: 'stop',
@@ -802,6 +948,9 @@ export function appendRound(
802
948
  if (result.durationMs === undefined) { unknownTimeTaskIds.add(result.taskId); continue; }
803
949
  lostTimeMsByTask[result.taskId] = (lostTimeMsByTask[result.taskId] ?? 0) + result.durationMs;
804
950
  }
951
+ const selfHealRepairReason = decision?.action !== 'stop' && decision?.selfHeal
952
+ ? needsHumanRepairDecisionReason(decision.selfHeal.reason)
953
+ : undefined;
805
954
  return [...history, {
806
955
  round: history.length,
807
956
  landed: countLanded(results),
@@ -826,6 +975,15 @@ export function appendRound(
826
975
  return feature === undefined ? [] : [feature];
827
976
  }),
828
977
  } : {}),
978
+ // NEEDS-HUMAN-REASON-REPAIR — 사유별 수복 1회 소진을 회차 원장에 남긴다(사유가 다르면 다른 시도).
979
+ ...(selfHealRepairReason !== undefined && decision?.selfHeal ? {
980
+ selfHealRepairFeatures: {
981
+ [selfHealRepairReason]: decision.selfHeal.taskIds.flatMap((id) => {
982
+ const feature = results.find((result) => result.taskId === id)?.feature;
983
+ return feature === undefined ? [] : [feature];
984
+ }),
985
+ },
986
+ } : {}),
829
987
  ...(decision?.action === 'add-repair-task' && decision.oscillation ? (() => {
830
988
  // Each repaired task is recorded under its original goal feature and, when a rerun runs the authored goal as
831
989
  // the piece's new feature (orchestrate), under that repair text too — so the repair's own oscillation stops.
@@ -1048,6 +1206,7 @@ export interface SuperviseRunOptions {
1048
1206
  sweepPendingMerges?: typeof sweepFrozenMerges;
1049
1207
  /** True only when rerun consumes `invocation.repairGoals`; omitted or false → a review oscillation stops for a human. */
1050
1208
  repairGoalExecution?: boolean;
1209
+ needsHumanReasonRepairExecution?: boolean;
1051
1210
  /**
1052
1211
  * TASK-AGENT-SHADOW — 멈춤이 확정되면 판단부를 그림자로 부른다(기본 `recordTaskAgentShadowMove`).
1053
1212
  * `false` 면 끈다. 던져도 런의 결말은 바뀌지 않는다(fail-soft).
@@ -1097,6 +1256,7 @@ export async function rejudgeTerminalTaskCard(runId: string | null, deps: {
1097
1256
  export async function superviseRun(opts: SuperviseRunOptions): Promise<SupervisorJobResult[]> {
1098
1257
  let results = [...opts.initial];
1099
1258
  let history: SupervisorRound[] = [];
1259
+ const maxRounds = opts.limits?.maxRounds ?? DEFAULT_MAX_ROUNDS;
1100
1260
 
1101
1261
  for (;;) {
1102
1262
  try {
@@ -1144,6 +1304,7 @@ export async function superviseRun(opts: SuperviseRunOptions): Promise<Superviso
1144
1304
  decompositionExecution: opts.promoteDecomposition !== undefined,
1145
1305
  // Undeclared = cannot run the repair goal: an add-repair-task would otherwise be a same-strategy relaunch.
1146
1306
  repairGoalExecution: opts.repairGoalExecution === true,
1307
+ ...(opts.needsHumanReasonRepairExecution === undefined ? {} : { needsHumanReasonRepairExecution: opts.needsHumanReasonRepairExecution }),
1147
1308
  ...(aggregateReviewTrend(results) ? { reviewMustFixTrend: aggregateReviewTrend(results) } : {}),
1148
1309
  ...(opts.limits ? { limits: opts.limits } : {}),
1149
1310
  ...(observed.deployFindings ? { deployFindings: observed.deployFindings } : {}),
@@ -1154,6 +1315,21 @@ export async function superviseRun(opts: SuperviseRunOptions): Promise<Superviso
1154
1315
  } : {}),
1155
1316
  });
1156
1317
 
1318
+ const reasonRepairSkipped = decision.action !== 'stop' || decision.stopReason !== 'needs-human' || history.length + 1 > maxRounds
1319
+ ? [] : results.flatMap((result) => {
1320
+ if (!decision.needsHuman.includes(result.taskId) || needsHumanRepairReason(result) === undefined) return [];
1321
+ if (!decision.classifications.some((classification) => classification.taskId === result.taskId && classification.kind === 'unclassified')) return [];
1322
+ const repairReason = needsHumanRepairReason(result)!;
1323
+ if (needsHumanRepairSpent(history, repairReason, result.feature)) return [];
1324
+ const reason = opts.repairGoalExecution !== true || opts.needsHumanReasonRepairExecution !== true
1325
+ ? 'disabled' : 'no-target-paths';
1326
+ if (reason === 'no-target-paths' && (result.targetPaths?.length ?? 0) > 0) return [];
1327
+ return [{ taskId: result.taskId, reason }];
1328
+ });
1329
+ for (const skipped of reasonRepairSkipped) {
1330
+ try { opts.observe?.('supervisor.reason-repair-skipped', skipped); } catch { /* fail-soft */ }
1331
+ }
1332
+
1157
1333
  // The supervisor consumes knowhow when it judges a failed piece. Keep the child prompt untouched.
1158
1334
  const failedPiece = results.find((result) => result.status === 'failed' && result.feature.trim());
1159
1335
  if (failedPiece) {
@@ -1188,7 +1364,13 @@ export async function superviseRun(opts: SuperviseRunOptions): Promise<Superviso
1188
1364
  decomposePromotion = { attempted: true, reason: `shim-failed: ${String(error)}` };
1189
1365
  }
1190
1366
  }
1191
- if (decision.selfHeal) {
1367
+ if (decision.selfHeal && needsHumanRepairDecisionReason(decision.selfHeal.reason) !== undefined) {
1368
+ // NEEDS-HUMAN-REASON-REPAIR — 수복 시도는 rerun 이 사유별 수복 골로 실행한다(아래 repairGoals).
1369
+ // 여기서는 «한 번 시도했다»를 관측하고 relaunch 를 유지한다 — 실패는 다음 라운드 판정이 사유·시도 원문으로 접는다.
1370
+ try { opts.observe?.('supervisor-self-heal', { runId, reason: decision.selfHeal.reason,
1371
+ attempt: decision.selfHeal.attempt, taskIds: decision.selfHeal.taskIds,
1372
+ outcome: 'relaunching', repairGoalTasks: Object.keys(decision.selfHeal.repairGoals ?? {}) }); } catch { /* fail-open */ }
1373
+ } else if (decision.selfHeal) {
1192
1374
  const promoted = decomposePromotion.attempted && (decomposePromotion.pieceCount ?? 0) >= 2;
1193
1375
  try { opts.observe?.('supervisor-self-heal', { runId, reason: decision.selfHeal.reason,
1194
1376
  attempt: decision.selfHeal.attempt, taskIds: decision.selfHeal.taskIds,
@@ -1309,7 +1491,7 @@ export async function superviseRun(opts: SuperviseRunOptions): Promise<Superviso
1309
1491
  // but their results stay in the round so the human hand-off (and the final review-oscillating stop) keeps them.
1310
1492
  const held = decision.oscillation?.heldTaskIds ?? [];
1311
1493
  const heldResults = results.filter((result) => held.includes(result.taskId));
1312
- const repairGoals = { ...decision.relaunchGoals, ...decision.oscillation?.repairGoals };
1494
+ const repairGoals = { ...decision.relaunchGoals, ...decision.selfHeal?.repairGoals, ...decision.oscillation?.repairGoals };
1313
1495
  const rerunResults = await opts.rerun(held.length ? results.filter((result) => !held.includes(result.taskId)) : results,
1314
1496
  { relaunch: true, ...(Object.keys(repairGoals).length > 0 ? { repairGoals } : {}) });
1315
1497
  results = [...rerunResults, ...heldResults.filter((heldResult) => !rerunResults.some((result) => result.taskId === heldResult.taskId))];
@@ -114,6 +114,9 @@ export interface SelfDevJobResult {
114
114
  completionDisposition?: string;
115
115
  /** Abandoned-run classification from the child. Independent of completionDisposition. */
116
116
  failureClassification?: AbandonedClassification;
117
+ /** Basis and explicit terminal reason are kept separate from the classification label. */
118
+ classificationBasis?: string;
119
+ terminationReason?: string;
117
120
  /** Provider failure evidence from the child result; absent when unobserved. */
118
121
  providerErrors?: { count: number; provider: string; category: 'quota' | 'credential' | 'request' | 'other' };
119
122
  /** Stable child run identity used to join its run-ledger proposal. */
@@ -78,6 +78,8 @@ export interface GateArtifactSummary extends GateArtifactCounts {
78
78
  head40: string | null;
79
79
  base40: string | null;
80
80
  envKey: string;
81
+ /** Seat self-gate marker observed at process entry (true only for ELANOUS_TRAIN_GATE=1). */
82
+ trainGate?: boolean;
81
83
  shards: number;
82
84
  cohort: string[];
83
85
  shardsDetail: GateArtifactShard[];
@@ -128,6 +130,7 @@ export interface GateArtifactInput {
128
130
  head40: string | null;
129
131
  base40: string | null;
130
132
  envKey: string;
133
+ trainGate?: boolean;
131
134
  testFiles: readonly string[];
132
135
  verdict: string | null;
133
136
  verdictLine?: string;
@@ -218,6 +221,7 @@ export function writeGateArtifacts(input: GateArtifactInput): { summaryPath: str
218
221
  head40: input.head40,
219
222
  base40: input.base40,
220
223
  envKey: input.envKey,
224
+ ...(input.trainGate !== undefined ? { trainGate: input.trainGate } : {}),
221
225
  shards: input.sharded ? input.sharded.shards.length : 0,
222
226
  cohort: sorted(input.testFiles),
223
227
  shardsDetail,
@@ -251,12 +255,14 @@ export function writeRemoteUnavailableGateArtifacts(
251
255
  reason: 'remote-unsupported' | 'remote-fetch-failed',
252
256
  resolveRev: RevResolver = defaultRevResolver(cwd),
253
257
  envKey: () => string = defaultGateEnvKey,
258
+ trainGate?: boolean,
254
259
  ): { summaryPath: string; junitFiles: string[] } {
255
260
  return writeGateArtifacts({
256
261
  dir: resolveArtifactDir(dir, cwd),
257
262
  head40: resolveRev('HEAD'),
258
263
  base40: baseRef ? resolveRev(baseRef) : null,
259
264
  envKey: envKey(),
265
+ trainGate,
260
266
  testFiles: [],
261
267
  verdict: null,
262
268
  exitCode,
@@ -266,6 +272,13 @@ export function writeRemoteUnavailableGateArtifacts(
266
272
  });
267
273
  }
268
274
 
275
+ /** The local train wrapper owns the receipt marker, including when artifacts came from a remote host. */
276
+ export function recordGateTrainMarker(summaryPath: string, trainGate: boolean): void {
277
+ const summary = JSON.parse(readFileSync(summaryPath, 'utf8')) as Record<string, unknown>;
278
+ summary.trainGate = trainGate;
279
+ writeFileSync(summaryPath, `${JSON.stringify(summary, null, 2)}\n`);
280
+ }
281
+
269
282
  // ── 원격 산출 회수 (SIDE-VERIFY-GATE-SHARDS ②) ──────────────────────────────
270
283
  // 원격 run 은 `$W` 임시 트리에서 돌고 끝나면 trap 이 `$W` 를 지운다(gate-remote.ts remoteScript). 그래서 원격 쪽
271
284
  // `--artifact-dir` 는 `$W` «밖»의 호스트 디스크 경로(/var/tmp/elanous-gate-artifacts-<nonce>)로 준다 — run 이 끝나도 남고, 회수
@@ -4,7 +4,6 @@ import { tmpdir } from 'node:os';
4
4
  import { spawnSync } from 'node:child_process';
5
5
  import { basename, join, resolve } from 'node:path/posix';
6
6
  import { prepareDeterministicChildEnvironment } from '../../scripts/lib/deterministic-env.js';
7
- import { audit as auditEntryBudget, entryBudgetAffected } from '../../scripts/ratchets/next-tui-entry-budget.js';
8
7
  import { withGateTestEnv } from '../../scripts/lib/gate-test-env.js';
9
8
  import { runIsolationHardcodeGate } from '../../scripts/ci-isolation-hardcode-gate.js';
10
9
  import { runModelHardcodeGate } from '../../scripts/ci-model-hardcode-gate.js';
@@ -58,6 +57,49 @@ export interface SelfGateCliOptions {
58
57
  scenarioFile?: string;
59
58
  /** SIDE-VERIFY — 조각별 지금/기준 JUnit ⊕ summary.json 을 이 디렉토리에 «쓰기만» 한다(판정·exit·기존 줄 불변). */
60
59
  artifactDir?: string;
60
+ /** Marker captured by the process entry point; keeps receipts stable if the environment changes during dispatch. */
61
+ trainGate?: boolean;
62
+ }
63
+
64
+ const SELF_GATE_SEAT_TRACKS = new Set(['OP', 'OPC', 'OPT', 'TC', 'UX', 'MK']);
65
+
66
+ interface SelfGateTrainMarker {
67
+ track: string | null;
68
+ received: boolean;
69
+ }
70
+
71
+ /** Capture and log the marker exactly as the self-gate process received it. */
72
+ export function observeSelfGateTrainMarker(): SelfGateTrainMarker {
73
+ const track = process.env.ELANOUS_TRACK?.trim() || null;
74
+ const received = process.env.ELANOUS_TRAIN_GATE === '1';
75
+ try { debug.log('self-gate', 'train-gate-marker', { track, received }); } catch { /* evidence logging must not change gate behavior */ }
76
+ return { track, received };
77
+ }
78
+
79
+ /** Seat invocations may only measure the pinned tree after the landing train has admitted the gate. */
80
+ export function refuseSeatSelfGateWithoutTrainMarker(marker = observeSelfGateTrainMarker()): { track: string; message: string } | undefined {
81
+ const { track, received } = marker;
82
+ if (!track || !SELF_GATE_SEAT_TRACKS.has(track) || received) return undefined;
83
+ try { debug.log('self-gate', 'seat-refused', { track, requiredMarker: 'ELANOUS_TRAIN_GATE=1' }); } catch { /* refusal must survive an unavailable observer */ }
84
+ return { track, message: 'gate 는 열차가 착지 때 1회 — land-enqueue.sh 로 줄에 올려라' };
85
+ }
86
+
87
+ /** A refused admission still writes the observed marker when an artifact directory was requested. */
88
+ export function writeSeatSelfGateRefusalArtifact(cwd: string, artifactDir: string, marker: SelfGateTrainMarker): string | undefined {
89
+ if (!artifactDir.trim()) return undefined;
90
+ const dir = resolveArtifactDir(artifactDir, cwd);
91
+ const written = writeGateArtifacts({
92
+ dir,
93
+ head40: defaultRevResolver(cwd)('HEAD'),
94
+ base40: null,
95
+ envKey: defaultGateEnvKey(),
96
+ trainGate: marker.received,
97
+ testFiles: [],
98
+ verdict: 'seat-refused',
99
+ verdictLine: `seat gate refused before dispatch (track=${marker.track ?? 'none'}; trainGate=${marker.received})`,
100
+ exitCode: 2,
101
+ });
102
+ return written.summaryPath;
61
103
  }
62
104
 
63
105
  interface ProcessResult {
@@ -125,7 +167,6 @@ interface SelfGateCliDeps {
125
167
  /** iOS 순수-로직 시험 게이트 심(시험 주입용). */
126
168
  runIosGate?: (out: GateOutput) => number;
127
169
  runPwaGate?: (out: GateOutput) => number;
128
- runEntryBudgetGate?: (cwd: string, changedFiles: readonly string[]) => { affected: boolean; errors: string[] };
129
170
  listPrWorktrees?: (cwd: string) => PrWorktreeListEntry[] | { lookupFailed: string };
130
171
  inspectWorktreeDirtiness?: (path: string) => { dirty: boolean } | { lookupFailed: string };
131
172
  /** `--artifact-dir` 전용 심 — 커밋 sha 해석(실패 = null) · 환경 키. */
@@ -809,23 +850,25 @@ export function selectGateTestFiles(cwd: string, options: GateSelectionOptions =
809
850
 
810
851
  export function runSelfGateCli(cwd: string, options: SelfGateCliOptions = {}, deps: SelfGateCliDeps = {}): SelfGateCliResult {
811
852
  const capture: GateArtifactCapture = {};
853
+ const trainGate = options.trainGate ?? process.env.ELANOUS_TRAIN_GATE === '1';
812
854
  const result = runSelfGateCliCore(cwd, options, deps, capture, false) as SelfGateCliResult;
813
855
  persistGateReceipt(cwd, capture, deps);
814
- if (options.artifactDir !== undefined) emitGateArtifacts(cwd, options.artifactDir, result, capture, deps);
856
+ if (options.artifactDir !== undefined) emitGateArtifacts(cwd, options.artifactDir, result, capture, deps, trainGate);
815
857
  return result;
816
858
  }
817
859
 
818
860
  /** Production path: shard bundles use async Bun children; all non-shard policy and timeout logic is shared. */
819
861
  export async function runSelfGateCliAsync(cwd: string, options: SelfGateCliOptions = {}, deps: SelfGateCliDeps = {}): Promise<SelfGateCliResult> {
820
862
  const capture: GateArtifactCapture = {};
863
+ const trainGate = options.trainGate ?? process.env.ELANOUS_TRAIN_GATE === '1';
821
864
  const result = await runSelfGateCliCore(cwd, options, deps, capture, true);
822
865
  persistGateReceipt(cwd, capture, deps);
823
- if (options.artifactDir !== undefined) emitGateArtifacts(cwd, options.artifactDir, result, capture, deps);
866
+ if (options.artifactDir !== undefined) emitGateArtifacts(cwd, options.artifactDir, result, capture, deps, trainGate);
824
867
  return result;
825
868
  }
826
869
 
827
870
  /** 쓰기 실패는 «경고 한 줄»로만 접는다 — 판정·exit 코드는 그대로다. */
828
- function emitGateArtifacts(cwd: string, artifactDir: string, result: SelfGateCliResult, capture: GateArtifactCapture, deps: SelfGateCliDeps): void {
871
+ function emitGateArtifacts(cwd: string, artifactDir: string, result: SelfGateCliResult, capture: GateArtifactCapture, deps: SelfGateCliDeps, trainGate: boolean): void {
829
872
  if (!artifactDir.trim()) {
830
873
  result.lines.push('⚠ artifacts: --artifact-dir 가 빈 경로라 안 썼다 (판정은 그대로다)');
831
874
  return;
@@ -839,6 +882,7 @@ function emitGateArtifacts(cwd: string, artifactDir: string, result: SelfGateCli
839
882
  head40: resolveRev('HEAD'),
840
883
  base40: capture.baseRef ? resolveRev(capture.baseRef) : null,
841
884
  envKey: (deps.envKey ?? defaultGateEnvKey)(),
885
+ trainGate,
842
886
  testFiles: capture.testFiles ?? result.testFiles,
843
887
  verdict: capture.verdict ?? null,
844
888
  ...(capture.verdictLine !== undefined ? { verdictLine: capture.verdictLine } : {}),
@@ -1210,20 +1254,6 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
1210
1254
  // 🍎 iOS 축 — 안드로이드와 «같은 자리»에 둔다(skipTestStep 앞). Swift 만 바뀐 PR 도 여기서 조기 리턴한다.
1211
1255
  const iosPassed = runAdditionalGate('ios-gate', deps.runIosGate ?? runIosUnitTestGate, selection.files, cwd, lines);
1212
1256
  const pwaPassed = runAdditionalGate('pwa-gate', deps.runPwaGate ?? runPwaBuildGate, selection.files, cwd, lines);
1213
- let entryBudgetPassed = false;
1214
- try {
1215
- const budget = (deps.runEntryBudgetGate ?? ((dir, files) => {
1216
- const affected = entryBudgetAffected(files);
1217
- return { affected, errors: affected ? auditEntryBudget(dir).errors : [] };
1218
- }))(cwd, selection.files);
1219
- entryBudgetPassed = budget.errors.length === 0;
1220
- lines.push(budget.affected
1221
- ? `next-tui-entry-budget: ${entryBudgetPassed ? 'pass' : `FAIL ${budget.errors.join('; ')}`}`
1222
- : 'next-tui-entry-budget: skip (unrelated changes)');
1223
- } catch (error) {
1224
- lines.push(`next-tui-entry-budget: UNMEASURED ${error instanceof Error ? error.message : String(error)}`);
1225
- }
1226
-
1227
1257
  if (receiptDecision?.mode === 'inherit' && testFiles.length === 0 && fullTestFiles.length > 0) {
1228
1258
  capture.testReceiptMeasured = true;
1229
1259
  capture.failedTestFiles = [];
@@ -1235,7 +1265,7 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
1235
1265
  const policyPassed = runPolicyGates(selection.files, cwd, lines, deps);
1236
1266
  logGateCliBaseline(cwd, { ...ZERO_GATE_BASELINE, unrunImporterTotal, lookupFailed: importerLookupFailed });
1237
1267
  return {
1238
- exitCode: policyPassed && androidPassed && iosPassed && pwaPassed && entryBudgetPassed && expose.passed ? 0 : 1,
1268
+ exitCode: policyPassed && androidPassed && iosPassed && pwaPassed && expose.passed ? 0 : 1,
1239
1269
  lines, changedFiles: selection.files, testFiles, unverified: scope.unverified,
1240
1270
  documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests,
1241
1271
  alwaysIncludeMissing, importerTestsAdded,
@@ -1249,7 +1279,7 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
1249
1279
  capture.failedTestFiles = [];
1250
1280
  logGateCliBaseline(cwd, { ...ZERO_GATE_BASELINE, unrunImporterTotal, lookupFailed: importerLookupFailed });
1251
1281
  Object.assign(capture, { verdict: 'skipped', artifactsUnavailable: 'no-tests' } satisfies GateArtifactCapture);
1252
- return { exitCode: androidPassed && iosPassed && pwaPassed && entryBudgetPassed && policyPassed && expose.passed ? 0 : 1, lines, changedFiles: selection.files, testFiles: [], unverified: scope.unverified, documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests, alwaysIncludeMissing, importerTestsAdded, baseline: { introduced: 0, preexisting: 0, unknown: 0, preconditionUnmet: 0 } };
1282
+ return { exitCode: androidPassed && iosPassed && pwaPassed && policyPassed && expose.passed ? 0 : 1, lines, changedFiles: selection.files, testFiles: [], unverified: scope.unverified, documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests, alwaysIncludeMissing, importerTestsAdded, baseline: { introduced: 0, preexisting: 0, unknown: 0, preconditionUnmet: 0 } };
1253
1283
  }
1254
1284
 
1255
1285
  // The default direct Bun path has one process and one 300s limit. Route real child/PTY tests through
@@ -1339,7 +1369,7 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
1339
1369
  capture.verdictLine = lines[lines.length - 1];
1340
1370
  const policyPassed = runPolicyGates(selection.files, cwd, lines, deps);
1341
1371
  return {
1342
- exitCode: capture.verdict !== 'passed' || !policyPassed || !androidPassed || !iosPassed || !pwaPassed || !entryBudgetPassed || !expose.passed ? 1 : 0,
1372
+ exitCode: capture.verdict !== 'passed' || !policyPassed || !androidPassed || !iosPassed || !pwaPassed || !expose.passed ? 1 : 0,
1343
1373
  lines, changedFiles: selection.files, testFiles, unverified: scope.unverified,
1344
1374
  documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests,
1345
1375
  alwaysIncludeMissing, importerTestsAdded, ...(shardBaseline ? { baseline: shardBaseline } : {}),
@@ -1359,7 +1389,7 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
1359
1389
  Object.assign(capture, { verdict: 'passed', verdictLine: lines[lines.length - 1] } satisfies GateArtifactCapture);
1360
1390
  const policyPassed = runPolicyGates(selection.files, cwd, lines, deps);
1361
1391
  logGateCliBaseline(cwd, { ...ZERO_GATE_BASELINE, unrunImporterTotal, lookupFailed: importerLookupFailed });
1362
- return { exitCode: policyPassed && androidPassed && iosPassed && pwaPassed && entryBudgetPassed && expose.passed ? 0 : 1, lines, changedFiles: selection.files, testFiles, unverified: scope.unverified, documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests, alwaysIncludeMissing, importerTestsAdded, baseline: { introduced: 0, preexisting: 0, unknown: 0, preconditionUnmet: 0 } };
1392
+ return { exitCode: policyPassed && androidPassed && iosPassed && pwaPassed && expose.passed ? 0 : 1, lines, changedFiles: selection.files, testFiles, unverified: scope.unverified, documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests, alwaysIncludeMissing, importerTestsAdded, baseline: { introduced: 0, preexisting: 0, unknown: 0, preconditionUnmet: 0 } };
1363
1393
  }
1364
1394
 
1365
1395
  if (worktreeLog.includes('deterministic environment setup failed')) lines.push(worktreeLog);
@@ -1394,7 +1424,7 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
1394
1424
  verdictLine: lines[lines.length - 1],
1395
1425
  } satisfies GateArtifactCapture);
1396
1426
  const policyPassed = runPolicyGates(selection.files, cwd, lines, deps);
1397
- const exitCode = !androidPassed || !iosPassed || !pwaPassed || !entryBudgetPassed || !policyPassed || !expose.passed || report.introduced > 0 || report.unknown > 0 || report.preconditionUnmet > 0 ? 1 : 0;
1427
+ const exitCode = !androidPassed || !iosPassed || !pwaPassed || !policyPassed || !expose.passed || report.introduced > 0 || report.unknown > 0 || report.preconditionUnmet > 0 ? 1 : 0;
1398
1428
  return { exitCode, lines, changedFiles: selection.files, testFiles, unverified: scope.unverified, documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests, alwaysIncludeMissing, importerTestsAdded, baseline: { introduced: report.introduced, preexisting: report.preexisting, unknown: report.unknown, preconditionUnmet: report.preconditionUnmet } };
1399
1429
  }
1400
1430
 
@@ -7,7 +7,7 @@ import { existsSync, lstatSync, realpathSync } from 'node:fs';
7
7
  import { loadavg } from 'node:os';
8
8
  import { isAbsolute, join, relative, resolve, sep } from 'node:path';
9
9
  import { debug } from '../debug/log.js';
10
- import { gateHostReservationRoot, inspectReleaseGateHost } from '../release-loop/gate-host-reservation.js';
10
+ import { gateHostReservationRoot, inspectReleaseGateHost, readGateHostResourcesForHost, type GateHostResourceReading } from '../release-loop/gate-host-reservation.js';
11
11
  import type { GateRemoteConfig } from '../user-config.js';
12
12
 
13
13
  export type GateRemoteTool = 'self-gate' | 'ci-typecheck-changed' | 'public-export-test-run';
@@ -538,6 +538,8 @@ export interface DispatchDeps {
538
538
  now?: () => number;
539
539
  /** Test seam for gate.remote events; production defaults to the structured debug log. */
540
540
  log?: (event: string, data: Record<string, unknown>) => void;
541
+ /** Read-only host-resource probe; production reads Pod pool ledgers, tests inject the same measured snapshot. */
542
+ readHostResources?: (host: string) => GateHostResourceReading;
541
543
  write?: { out: (data: string | Uint8Array) => void; err: (data: string | Uint8Array) => void };
542
544
  }
543
545
 
@@ -595,8 +597,24 @@ export async function dispatchHeavyCheck(opts: DispatchOptions, deps: DispatchDe
595
597
  const reservationRoot = opts.tool === 'self-gate' || opts.tool === 'ci-typecheck-changed'
596
598
  ? opts.reservationRoot ?? (deps.runner ? undefined : gateHostReservationRoot()) : undefined;
597
599
  if (reservationRoot) {
600
+ const resourceStatus = (target: string) => {
601
+ if (!deps.readHostResources && deps.runner) return null; // fake runners keep tests hermetic unless the producer is explicitly exercised
602
+ return (deps.readHostResources ?? ((selected) => readGateHostResourcesForHost(selected, env)))(target.split('@').at(-1)!);
603
+ };
604
+ const inspect = (target: string) => {
605
+ const claim = inspectReleaseGateHost(reservationRoot, target);
606
+ const resources = resourceStatus(target);
607
+ if (!resources) return claim;
608
+ if (resources.status === 'unmeasurable') {
609
+ // Keep a concrete release owner visible even if the independent Pod ledgers cannot be read.
610
+ if (claim.status === 'reserved') return claim;
611
+ return { status: 'unknown' as const, reason: `resource probe unmeasurable: ${resources.reason}` };
612
+ }
613
+ if (!resources.empty) return { status: 'reserved' as const, reason: `Pod resource pool occupied (${resources.reservations} reservations)` };
614
+ return claim;
615
+ };
598
616
  const reservationHost = host.split('@').at(-1)!;
599
- const first = inspectReleaseGateHost(reservationRoot, reservationHost);
617
+ const first = inspect(reservationHost);
600
618
  if (first.status !== 'free') {
601
619
  // A reserved host is never a reason to run this check locally (반증: 예약 상태에서 --local 무거운 시험 금지).
602
620
  // Self gate first tries another remote host, then waits bounded for the release, then ends unmeasured with
@@ -609,7 +627,7 @@ export async function dispatchHeavyCheck(opts: DispatchOptions, deps: DispatchDe
609
627
  : `observed-at=${observedAt}`;
610
628
  const alternates = opts.tool === 'self-gate'
611
629
  ? gateReservationAlternateHosts(reservationHost, opts.reservationAltHosts) : [];
612
- const alternate = alternates.find((candidate) => inspectReleaseGateHost(reservationRoot, candidate).status === 'free');
630
+ const alternate = alternates.find((candidate) => inspect(candidate).status === 'free');
613
631
  if (alternate) {
614
632
  const rerouted = host.includes('@') ? `${host.slice(0, host.lastIndexOf('@'))}@${alternate}` : alternate;
615
633
  debug.log('gate.remote', 'host-reserved-reroute', { tool: opts.tool, from: host, to: rerouted, owner, reason: first.reason, reservedAt: first.reservedAt, observedAt });
@@ -619,7 +637,7 @@ export async function dispatchHeavyCheck(opts: DispatchOptions, deps: DispatchDe
619
637
  const waitSeconds = opts.tool === 'self-gate' ? opts.reservationWaitSeconds ?? settings.slotWaitSeconds : 0;
620
638
  const waitStart = now();
621
639
  const deadline = waitStart + Math.max(0, waitSeconds) * 1000;
622
- let latest = inspectReleaseGateHost(reservationRoot, reservationHost);
640
+ let latest = inspect(reservationHost);
623
641
  while (waitSeconds > 0 && latest.status !== 'free') {
624
642
  const left = deadline - now();
625
643
  if (left <= 0) break;
@@ -627,7 +645,7 @@ export async function dispatchHeavyCheck(opts: DispatchOptions, deps: DispatchDe
627
645
  const before = now();
628
646
  await sleep(Math.min(15_000, left));
629
647
  if (now() <= before) break; // a frozen test clock must not spin past the bound
630
- latest = inspectReleaseGateHost(reservationRoot, reservationHost);
648
+ latest = inspect(reservationHost);
631
649
  }
632
650
  const waitedMs = Math.max(0, now() - waitStart);
633
651
  if (latest.status === 'free') {