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
@@ -414,12 +414,20 @@ export function runGraphVariantPath(runId: string, dir = runLedgerDir()): string
414
414
  return `${runLedgerPath(runId, dir)}.graph.yaml`;
415
415
  }
416
416
 
417
+ /** 원장에 실린 unit 선언 근거 한 줄 — 경로와 내용 해시뿐이고 본문은 원장에 없다. */
418
+ export interface RunGraphVariantUnitDeclaration {
419
+ readonly path: string;
420
+ readonly contentHash: string;
421
+ }
422
+
417
423
  /** 최초 graph variant 선택의 원장 옆 재조회 계약 — 같은 runId·파일이면 같은 id·선택 이유가 돌아온다. */
418
424
  export interface RunGraphVariantSelection {
419
425
  /** createGraphVariant 가 골 종류·대상 경로 수에서 유도한 최초 variant id. */
420
426
  readonly variantId: string;
421
427
  /** 그 variant가 최초로 선택된 근거(종류·경로 수 기반) — 저장·재조회가 같은 문자열. */
422
428
  readonly reason: string;
429
+ /** 이 런이 읽은 unit 선언의 경로·내용 해시 — 옛 원장에는 키가 없어 값도 없다(추가 키). */
430
+ readonly unitDeclarations?: readonly RunGraphVariantUnitDeclaration[];
423
431
  }
424
432
 
425
433
  /** 런 원장 옆 .graph.yaml 을 처음 한 번 쓰고 저장 경로를 돌려준다 — 이미 있으면 덮쓰지 않는다(flag wx). */
@@ -447,9 +455,24 @@ export function loadRunGraphVariant(runId: string, dir = runLedgerDir()): RunGra
447
455
  throw new Error(`invalid run graph variant YAML at ${path}: ${error instanceof Error ? error.message : String(error)}`);
448
456
  }
449
457
  if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return null;
450
- const record = parsed as { variant_id?: unknown; reason?: unknown };
458
+ const record = parsed as { variant_id?: unknown; reason?: unknown; unit_declarations?: unknown };
451
459
  if (typeof record.variant_id !== 'string' || typeof record.reason !== 'string') return null;
452
- return { variantId: record.variant_id, reason: record.reason };
460
+ const unitDeclarations = parseRunGraphVariantUnitDeclarations(record.unit_declarations);
461
+ return { variantId: record.variant_id, reason: record.reason,
462
+ ...(unitDeclarations === undefined ? {} : { unitDeclarations }) };
463
+ }
464
+
465
+ /** `unit_declarations: [{ path, content_hash }]` 추가 키의 재읽기 — 키가 없거나 비면 근거도 없다. */
466
+ function parseRunGraphVariantUnitDeclarations(value: unknown): RunGraphVariantUnitDeclaration[] | undefined {
467
+ if (!Array.isArray(value)) return undefined;
468
+ const declarations: RunGraphVariantUnitDeclaration[] = [];
469
+ for (const entry of value) {
470
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) continue;
471
+ const record = entry as { path?: unknown; content_hash?: unknown };
472
+ if (typeof record.path !== 'string' || typeof record.content_hash !== 'string') continue;
473
+ declarations.push({ path: record.path, contentHash: record.content_hash });
474
+ }
475
+ return declarations.length === 0 ? undefined : declarations;
453
476
  }
454
477
 
455
478
  /**
@@ -1811,6 +1834,8 @@ export interface UnfinishedRunLedgerQuery {
1811
1834
  * 엉킨 visit 을 셀 수 있게 하는 값이다.
1812
1835
  */
1813
1836
  orphanUnitVisitCount?: number;
1837
+ /** True when a caller deadline stopped the scan before every ledger was visited. */
1838
+ timedOut?: boolean;
1814
1839
  scope: 'self-implement-run-ledger';
1815
1840
  note: string;
1816
1841
  }
@@ -1824,6 +1849,8 @@ export interface UnfinishedRunLedgerQueryOptions {
1824
1849
  noCache?: boolean;
1825
1850
  /** ⛔ 「도는 중」으로 볼 마지막 활동 나이(ms). 호출자가 준다 — 이 모듈이 새 수를 정하지 않는다. */
1826
1851
  liveWindowMs?: number;
1852
+ /** Absolute wall-clock deadline; when reached, return the rows scanned so far as partial evidence. */
1853
+ deadlineAtMs?: number;
1827
1854
  }
1828
1855
 
1829
1856
  const UNFINISHED_RUN_LEDGER_NOTE = 'Read-only scan of the specified run-ledger directory. A terminal-status-missing ledger is not the same as an unreadable ledger; planned paths are extracted only from a goal document matched by the final hyphen-separated branch segment.';
@@ -2470,7 +2497,12 @@ export function queryUnfinishedRunLedgers(options: UnfinishedRunLedgerQueryOptio
2470
2497
  let callerCwdCount = 0;
2471
2498
  // ⭐ 터미널 원장도 «세기만» 한다 — entries 로 되살리지 않는다(부활 금지).
2472
2499
  let orphanUnitVisitCount = 0;
2500
+ let timedOut = false;
2473
2501
  for (const fileName of fileNames) {
2502
+ if (options.deadlineAtMs !== undefined && Date.now() >= options.deadlineAtMs) {
2503
+ timedOut = true;
2504
+ break;
2505
+ }
2474
2506
  const runId = runIdFromCanonicalLedgerFile(fileName);
2475
2507
  if (!runId) continue;
2476
2508
  scanned += 1;
@@ -2555,9 +2587,10 @@ export function queryUnfinishedRunLedgers(options: UnfinishedRunLedgerQueryOptio
2555
2587
  indexOrigin,
2556
2588
  indexHits,
2557
2589
  ms: Date.now() - startedAt,
2590
+ ...(timedOut ? { timedOut: true, stopReason: 'deadline-exceeded' } : {}),
2558
2591
  });
2559
2592
  if (options.path === undefined) {
2560
- return { entries, ledgerDirectory: dir, goalsDirectory: goalsDir, unreadableLedgerCount, orphanUnitVisitCount, ledgerDirectoryMissing: false, terminalByTrailingRunStatus, cacheHits, cacheMisses, indexHits, indexOrigin, scope: 'self-implement-run-ledger', note: UNFINISHED_RUN_LEDGER_NOTE };
2593
+ return { entries, ledgerDirectory: dir, goalsDirectory: goalsDir, unreadableLedgerCount, orphanUnitVisitCount, ledgerDirectoryMissing: false, terminalByTrailingRunStatus, cacheHits, cacheMisses, indexHits, indexOrigin, ...(timedOut ? { timedOut: true } : {}), scope: 'self-implement-run-ledger', note: UNFINISHED_RUN_LEDGER_NOTE };
2561
2594
  }
2562
2595
  const pathFilter = options.path;
2563
2596
  const unknownPathStatus = (entry: UnfinishedRunLedgerEntry): boolean => entry.plannedPathStatus !== 'found-ledger-goal-file'
@@ -2583,6 +2616,7 @@ export function queryUnfinishedRunLedgers(options: UnfinishedRunLedgerQueryOptio
2583
2616
  pathFilter,
2584
2617
  matchingPathCount: matchingEntries.length,
2585
2618
  unknownPathCount: unknownEntries.length,
2619
+ ...(timedOut ? { timedOut: true } : {}),
2586
2620
  scope: 'self-implement-run-ledger',
2587
2621
  note: UNFINISHED_RUN_LEDGER_NOTE,
2588
2622
  };
@@ -2619,6 +2653,8 @@ export interface FederatedUnfinishedRunLedgerQuery {
2619
2653
  cacheMisses?: number;
2620
2654
  /** Hits served by the persisted cross-process scan index (subset of cacheHits). */
2621
2655
  indexHits?: number;
2656
+ timedOut?: boolean;
2657
+ stalledStage?: 'ledger-scan' | 'cross-directory-reconciliation';
2622
2658
  pathFilter?: string;
2623
2659
  matchingPathCount?: number;
2624
2660
  unknownPathCount?: number;
@@ -2640,6 +2676,7 @@ export interface FederatedUnfinishedRunLedgerQueryOptions {
2640
2676
  * canonical *.jsonl plus the cross-directory unfinished-runId reconciliation.
2641
2677
  */
2642
2678
  runIds?: readonly string[];
2679
+ deadlineAtMs?: number;
2643
2680
  }
2644
2681
 
2645
2682
  const FEDERATED_UNFINISHED_RUN_LEDGER_NOTE = 'Read-only union of run-ledger directories selected by the same --all/--include-test target policy as elanous logs. Each row carries its physical ledger directory because instance names can identify multiple state roots.';
@@ -2659,12 +2696,19 @@ export function queryFederatedUnfinishedRunLedgers(options: FederatedUnfinishedR
2659
2696
  let cacheHits = 0;
2660
2697
  let cacheMisses = 0;
2661
2698
  let indexHits = 0;
2699
+ let timedOut = false;
2700
+ let stalledStage: FederatedUnfinishedRunLedgerQuery['stalledStage'];
2662
2701
  const recordDirectoryFailure = (kind: FederatedLedgerDirectoryFailureKind): void => {
2663
2702
  if (kind === 'missing') missingLedgerDirectoryCount += 1;
2664
2703
  else if (kind === 'unreadable') unreadableLedgerDirectoryAccessCount += 1;
2665
2704
  else indeterminateLedgerDirectoryCount += 1;
2666
2705
  };
2667
2706
  for (const ledgerDirectory of candidateLedgerDirectories) {
2707
+ if (options.deadlineAtMs !== undefined && Date.now() >= options.deadlineAtMs) {
2708
+ timedOut = true;
2709
+ stalledStage = 'ledger-scan';
2710
+ break;
2711
+ }
2668
2712
  try {
2669
2713
  const listDirectory = options.list ?? readdirSync;
2670
2714
  const list = requestedRunIds === undefined
@@ -2673,7 +2717,7 @@ export function queryFederatedUnfinishedRunLedgers(options: FederatedUnfinishedR
2673
2717
  const runId = runIdFromCanonicalLedgerFile(fileName);
2674
2718
  return runId !== null && requestedRunIds.has(runId);
2675
2719
  });
2676
- const result = queryUnfinishedRunLedgers({ dir: ledgerDirectory, goalsDir: goalsDirectory, ...(options.path === undefined ? {} : { path: options.path }), ...(list === undefined ? {} : { list }), noCache: options.noCache });
2720
+ const result = queryUnfinishedRunLedgers({ dir: ledgerDirectory, goalsDir: goalsDirectory, ...(options.path === undefined ? {} : { path: options.path }), ...(list === undefined ? {} : { list }), noCache: options.noCache, deadlineAtMs: options.deadlineAtMs });
2677
2721
  if (result.ledgerDirectoryMissing) {
2678
2722
  recordDirectoryFailure('missing');
2679
2723
  continue;
@@ -2685,10 +2729,15 @@ export function queryFederatedUnfinishedRunLedgers(options: FederatedUnfinishedR
2685
2729
  cacheHits += result.cacheHits ?? 0;
2686
2730
  cacheMisses += result.cacheMisses ?? 0;
2687
2731
  indexHits += result.indexHits ?? 0;
2732
+ if (result.timedOut) {
2733
+ timedOut = true;
2734
+ stalledStage = 'ledger-scan';
2735
+ }
2688
2736
  entries.push(...result.entries.map((entry) => ({ ...entry, ledgerDirectory })));
2689
2737
  } catch (error) {
2690
2738
  recordDirectoryFailure(classifyFederatedLedgerDirectoryReadFailure(error));
2691
2739
  }
2740
+ if (timedOut) break;
2692
2741
  }
2693
2742
  const unreadableLedgerDirectoryCount = missingLedgerDirectoryCount + unreadableLedgerDirectoryAccessCount + indeterminateLedgerDirectoryCount;
2694
2743
  // ⛔⭐⭐ 가로 대조 — 원장 «하나»만 보고 「미완」이라 말하지 않는다 (2026-08-11 · 🅣 71차 실측).
@@ -2698,20 +2747,28 @@ export function queryFederatedUnfinishedRunLedgers(options: FederatedUnfinishedR
2698
2747
  // 📏 실측(2026-08-11): 미완 57 중 ***7*** 이 다른 원장에 종결을 갖고 있었다.
2699
2748
  // ⛔ 판정 술어는 스캐너와 «같은 것»을 쓴다(`run-status` 또는 `terminal`) — 어휘를 새로 만들지 않는다.
2700
2749
  const terminatedElsewhere = new Set<string>();
2750
+ const reconciledRunIds = new Set<string>();
2701
2751
  // Runs carrying a non-blocking request record never drop out of the union: their requestId
2702
2752
  // reason·next must survive restarts and cross-directory reconciliation alike.
2703
2753
  const unfinishedRunIds = requestedRunIds === undefined
2704
2754
  ? new Set(entries.filter((entry) => !entry.nonBlocking).map((entry) => entry.runId))
2705
2755
  : new Set([...requestedRunIds].filter((runId) => entries.some((entry) => entry.runId === runId && !entry.nonBlocking)));
2706
- for (const runId of unfinishedRunIds) {
2756
+ for (const runId of timedOut ? [] : unfinishedRunIds) {
2757
+ if (options.deadlineAtMs !== undefined && Date.now() >= options.deadlineAtMs) {
2758
+ timedOut = true;
2759
+ stalledStage = 'cross-directory-reconciliation';
2760
+ break;
2761
+ }
2707
2762
  for (const ledgerDirectory of ledgerDirectories) {
2708
2763
  try {
2709
2764
  const reconciliationIndex = options.noCache ? undefined : loadRunLedgerScanIndex(ledgerDirectory);
2710
2765
  if (readUnfinishedLedgerFacts(runId, ledgerDirectory, undefined, options.noCache, reconciliationIndex).facts.terminal) { terminatedElsewhere.add(runId); break; }
2711
2766
  } catch { /* An absent or unreadable sibling cannot establish termination. */ }
2712
2767
  }
2768
+ reconciledRunIds.add(runId);
2713
2769
  }
2714
- const reconciledEntries = entries.filter((entry) => !terminatedElsewhere.has(entry.runId));
2770
+ const reconciledEntries = entries.filter((entry) => !terminatedElsewhere.has(entry.runId)
2771
+ && (stalledStage !== 'cross-directory-reconciliation' || reconciledRunIds.has(entry.runId)));
2715
2772
  const reconciledTerminatedElsewhereCount = entries.length - reconciledEntries.length;
2716
2773
  entries.length = 0;
2717
2774
  entries.push(...reconciledEntries);
@@ -2729,6 +2786,7 @@ export function queryFederatedUnfinishedRunLedgers(options: FederatedUnfinishedR
2729
2786
  cacheHits,
2730
2787
  cacheMisses,
2731
2788
  indexHits,
2789
+ ...(timedOut ? { timedOut: true, stalledStage } : {}),
2732
2790
  ...(options.path === undefined ? {} : { pathFilter: options.path, matchingPathCount, unknownPathCount }),
2733
2791
  scope: 'self-implement-run-ledger-federated',
2734
2792
  note: FEDERATED_UNFINISHED_RUN_LEDGER_NOTE,
@@ -16,7 +16,7 @@ import type { PodChildEvidence } from '../task-orchestrator/surfaces/self-implem
16
16
  /** 닫힌 목록 — 못 고르면 `unclassified`. */
17
17
  export const RUN_STOP_CLASSES = [
18
18
  'env-unrelated', 'main-sync', 'pod-died', 'pod-vanished', 'review-repeat',
19
- 'review-out-of-scope', 'scope-escape', 'evidence-uncovered', 'fabric', 'launch-failed', 'gate-failed', 'unclassified',
19
+ 'review-out-of-scope', 'review-budget-exhausted', 'scope-escape', 'evidence-uncovered', 'fabric', 'launch-failed', 'gate-failed', 'unclassified',
20
20
  ] as const;
21
21
  export type RunStopClass = typeof RUN_STOP_CLASSES[number];
22
22
 
@@ -81,7 +81,8 @@ export function classifyMergeHoldStop(mergeReason: string | undefined): RunStopC
81
81
  const reason = mergeReason ?? '';
82
82
  if (reason.startsWith('main-sync') || reason === 'default-branch-unresolved') return 'main-sync';
83
83
  if (reason === 'required-evidence-uncovered') return 'evidence-uncovered';
84
- if (reason === 'review-must-fix' || reason === 'review-warn-with-must-fix' || reason.startsWith('review-budget')) return 'review-repeat';
84
+ if (reason.startsWith('review-budget')) return 'review-budget-exhausted';
85
+ if (reason === 'review-must-fix' || reason === 'review-warn-with-must-fix') return 'review-repeat';
85
86
  if (reason.startsWith('review-diff') || reason === 'no-real-review') return 'review-out-of-scope';
86
87
  return 'unclassified';
87
88
  }
@@ -96,6 +97,24 @@ export function classifyPodExitStop(reason: string | undefined, stage?: string):
96
97
  }
97
98
  }
98
99
 
100
+ /** Terminal implementation failures are classified only after the inner repair/round budget has ended. */
101
+ export function classifyTerminalHarnessFailure(input: {
102
+ stage: string;
103
+ mergeReason?: string;
104
+ abandonedClassification?: string;
105
+ providerErrorCategory?: string;
106
+ supervisorVerdict?: string;
107
+ }): RunStopClass {
108
+ if (input.mergeReason) return classifyMergeHoldStop(input.mergeReason);
109
+ if (input.providerErrorCategory === 'credential' || input.abandonedClassification === 'credential-failure') return 'launch-failed';
110
+ if (input.abandonedClassification === 'report-deficit') return 'pod-died';
111
+ if (input.stage === 'gate-failed') return 'gate-failed';
112
+ if (input.stage === 'review-blocked' || input.stage === 'no-changes' || input.supervisorVerdict === 'UNCONVERGEABLE') return 'review-repeat';
113
+ if (input.stage === 'merge-conflict') return 'main-sync';
114
+ if (input.stage === 'timed-out') return 'pod-died';
115
+ return 'unclassified';
116
+ }
117
+
99
118
  /** 이 프로세스에서 stop 을 이미 쓴 런 — 한 런이 두 자리(예: draft PR 실패 ⊕ aborted)에서 두 줄을 쓰지 않게. */
100
119
  const recordedThisProcess = new Set<string>();
101
120
  const RECORDED_MAX = 4096;
@@ -116,6 +116,8 @@ export interface RunningRunsResult {
116
116
  };
117
117
  /** Additive phase-store observability; queryRunningRuns always supplies this value. */
118
118
  readonly phases?: RunningRunsPhaseStoreObservation;
119
+ /** Present when a caller time budget stopped one observation stage before full coverage. */
120
+ readonly stalled?: { readonly stage: 'ledger-scan' | 'cross-directory-reconciliation' | 'pty-observation' | 'phase-observation' | 'launch-parent-classification'; readonly reason: 'deadline-exceeded' };
119
121
  }
120
122
 
121
123
  export interface QueriedRunningRunsResult extends RunningRunsResult {
@@ -263,7 +265,7 @@ export interface RunningRunsQueryObservation {
263
265
  }
264
266
 
265
267
  export interface RunningRunsQueryDeps {
266
- readonly queryLedgers?: (options: { includeTest?: boolean; ledgerDirectories?: readonly string[]; runIds?: readonly string[]; noCache?: boolean }) => FederatedUnfinishedRunLedgerQuery;
268
+ readonly queryLedgers?: (options: { includeTest?: boolean; ledgerDirectories?: readonly string[]; runIds?: readonly string[]; noCache?: boolean; deadlineAtMs?: number }) => FederatedUnfinishedRunLedgerQuery;
267
269
  readonly ledgerDirectories?: (options: { includeTest?: boolean }) => readonly string[];
268
270
  readonly ptyTargets?: (options: { includeTest?: boolean }) => readonly { name: string; dbPath: string }[];
269
271
  readonly readPtyRows?: typeof listPtyManifestRowsAt;
@@ -303,6 +305,7 @@ export function assessLingeringLaunchParents(
303
305
  isProcessAlive: (pid: number) => boolean,
304
306
  processStartTime: (pid: number) => number | null,
305
307
  ledgerObservation?: Pick<RunningRunsLedgerObservation, 'unreadableLedgerCount' | 'unreadableLedgerDirectoryCount' | 'unreadableLedgerDirectoryAccessCount' | 'indeterminateLedgerDirectoryCount'>,
308
+ deadlineAtMs?: number,
306
309
  ): LingeringLaunchParentAssessment {
307
310
  if (!ledgerObservation || hasUnreadableLedgerObservation(ledgerObservation)) return { observation: 'indeterminate' };
308
311
 
@@ -316,6 +319,7 @@ export function assessLingeringLaunchParents(
316
319
  let reusedPidCount = 0;
317
320
  try {
318
321
  for (const [runId, ledgerDirectory] of terminatedRunDirectories) {
322
+ if (deadlineAtMs !== undefined && Date.now() >= deadlineAtMs) return { observation: 'indeterminate' };
319
323
  const run = loadRun(runId, ledgerDirectory);
320
324
  const pid = run?.pid;
321
325
  if (typeof pid !== 'number' || !Number.isInteger(pid) || pid <= 0) {
@@ -454,7 +458,7 @@ export function distinctPhysicalLedgerDirectories(
454
458
  return distinct;
455
459
  }
456
460
 
457
- export function queryRunningRuns(options: { includeTest?: boolean; runIds?: readonly string[]; caller?: string; noCache?: boolean } = {}, deps: RunningRunsQueryDeps = {}): QueriedRunningRunsResult {
461
+ export function queryRunningRuns(options: { includeTest?: boolean; runIds?: readonly string[]; caller?: string; noCache?: boolean; timeBudgetMs?: number } = {}, deps: RunningRunsQueryDeps = {}): QueriedRunningRunsResult {
458
462
  const directoryFailures = new Map<string, ReturnType<typeof classifyFederatedLedgerDirectoryReadFailure>>();
459
463
  const queryLedgers = deps.queryLedgers ?? ((queryOptions: Parameters<typeof queryFederatedUnfinishedRunLedgers>[0]) => queryFederatedUnfinishedRunLedgers({
460
464
  ...queryOptions,
@@ -480,6 +484,9 @@ export function queryRunningRuns(options: { includeTest?: boolean; runIds?: read
480
484
  const processStartTime = deps.processStartedAt ?? processStartedAt;
481
485
  const observeQuery = deps.observeQuery ?? ((observation: RunningRunsQueryObservation) => debug.log('self-implement.running-runs', 'query', observation));
482
486
  const startedAt = Date.now();
487
+ const deadlineAtMs = options.timeBudgetMs === undefined ? undefined : startedAt + Math.max(0, options.timeBudgetMs);
488
+ let stalled: RunningRunsResult['stalled'];
489
+ const deadlineExceeded = (): boolean => deadlineAtMs !== undefined && Date.now() >= deadlineAtMs;
483
490
  // ID 조회 배선 — src/index.ts의 `self running-runs [runId]` 액션이 넘겨준 options.runIds 를 이 조회가 소비한다:
484
491
  // 정의된 runIds 는 연합 원장 질의 전달·엔트리·pty 관측을 모두 그 runId 들로 한정한다.
485
492
  const requestedRunIdSet = options.runIds === undefined ? undefined : new Set(options.runIds);
@@ -509,20 +516,25 @@ export function queryRunningRuns(options: { includeTest?: boolean; runIds?: read
509
516
  try {
510
517
  const requestedRunIds = options.runIds === undefined ? {} : { runIds: options.runIds };
511
518
  const cacheOption = options.noCache === undefined ? {} : { noCache: options.noCache };
519
+ const deadlineOption = deadlineAtMs === undefined ? {} : { deadlineAtMs };
512
520
  ledger = collectLedgerDirectories
513
- ? queryLedgers({ includeTest: options.includeTest, ledgerDirectories: collectedLedgerDirectories, ...requestedRunIds, ...cacheOption })
514
- : queryLedgers({ includeTest: options.includeTest, ...requestedRunIds, ...cacheOption });
521
+ ? queryLedgers({ includeTest: options.includeTest, ledgerDirectories: collectedLedgerDirectories, ...requestedRunIds, ...cacheOption, ...deadlineOption })
522
+ : queryLedgers({ includeTest: options.includeTest, ...requestedRunIds, ...cacheOption, ...deadlineOption });
515
523
  ledgerDirectoryCount = ledger.ledgerDirectories.length;
516
524
  ledgerEntryCount = ledger.entries.length;
517
525
  cacheHits = ledger.cacheHits ?? 0;
518
526
  cacheMisses = ledger.cacheMisses ?? 0;
527
+ if (ledger.timedOut) stalled = { stage: ledger.stalledStage ?? 'ledger-scan', reason: 'deadline-exceeded' };
519
528
  } finally {
520
529
  ledgerReadElapsedMs = Date.now() - ledgerReadStartedAt;
521
530
  }
522
531
  const screenProcessReadStartedAt = Date.now();
523
532
  let pty: FederatedPtyListing;
524
533
  try {
525
- pty = listPtyRefs(targets({ includeTest: options.includeTest }), readPtyRows);
534
+ if (deadlineExceeded()) {
535
+ stalled ??= { stage: 'pty-observation', reason: 'deadline-exceeded' };
536
+ pty = { refs: [], unreadable: ['<skipped:deadline-exceeded>'] };
537
+ } else pty = listPtyRefs(targets({ includeTest: options.includeTest }), readPtyRows);
526
538
  } finally {
527
539
  screenProcessReadElapsedMs = Date.now() - screenProcessReadStartedAt;
528
540
  }
@@ -538,7 +550,8 @@ export function queryRunningRuns(options: { includeTest?: boolean; runIds?: read
538
550
  let observedPhases: ObservedRunPhases = { events: [], targetCount: 0, unreadableTargets: [] };
539
551
  const stageStoreReadStartedAt = Date.now();
540
552
  try {
541
- observedPhases = readRunPhases({ includeTest: options.includeTest }, runIds);
553
+ if (deadlineExceeded()) stalled ??= { stage: 'phase-observation', reason: 'deadline-exceeded' };
554
+ else observedPhases = readRunPhases({ includeTest: options.includeTest }, runIds);
542
555
  } catch {
543
556
  observedPhases = { events: [], targetCount: 1, unreadableTargets: ['phase-query'] };
544
557
  } finally {
@@ -583,13 +596,23 @@ export function queryRunningRuns(options: { includeTest?: boolean; runIds?: read
583
596
  const launchParentClassificationStartedAt = Date.now();
584
597
  let lingeringLaunchParents: LingeringLaunchParentAssessment;
585
598
  try {
586
- lingeringLaunchParents = assessLingeringLaunchParents(
587
- scopedLedgerEntries, loadRun, isProcessAlive, processStartTime, ledger,
588
- );
599
+ if (deadlineExceeded()) {
600
+ stalled ??= { stage: 'launch-parent-classification', reason: 'deadline-exceeded' };
601
+ lingeringLaunchParents = { observation: 'indeterminate' };
602
+ } else {
603
+ lingeringLaunchParents = assessLingeringLaunchParents(
604
+ scopedLedgerEntries, loadRun, isProcessAlive, processStartTime, ledger, deadlineAtMs,
605
+ );
606
+ if (deadlineExceeded()) stalled ??= { stage: 'launch-parent-classification', reason: 'deadline-exceeded' };
607
+ }
589
608
  } finally {
590
609
  launchParentClassificationElapsedMs = Date.now() - launchParentClassificationStartedAt;
591
610
  }
592
- return { ...result, completeness, unreadable, count, observation, quantities: quantitySummary({ ...result, observation }), lingeringLaunchParents: lingeringLaunchParents!, ledger: { ledgerDirectories: ledger.ledgerDirectories, unreadableLedgerCount: ledger.unreadableLedgerCount, unreadableLedgerDirectoryCount: ledger.unreadableLedgerDirectoryCount, missingLedgerDirectoryCount: ledger.missingLedgerDirectoryCount, unreadableLedgerDirectoryAccessCount: ledger.unreadableLedgerDirectoryAccessCount, indeterminateLedgerDirectoryCount: ledger.indeterminateLedgerDirectoryCount, cacheHits, cacheMisses }, phases: phaseStoreObservation(observedPhases) };
611
+ const finalCompleteness = hasUnreadableLedgerObservation(ledger) || stalled ? 'partial' : 'complete';
612
+ const finalCount: RunningRunsCount = finalCompleteness === 'partial'
613
+ ? { count: null, lowerBound: result.counts.running + result.counts['probable-running'], unreadable }
614
+ : result.counts.running + result.counts['probable-running'];
615
+ return { ...result, completeness: finalCompleteness, unreadable, count: finalCount, observation, quantities: quantitySummary({ ...result, observation }), lingeringLaunchParents: lingeringLaunchParents!, ledger: { ledgerDirectories: ledger.ledgerDirectories, unreadableLedgerCount: ledger.unreadableLedgerCount, unreadableLedgerDirectoryCount: ledger.unreadableLedgerDirectoryCount, missingLedgerDirectoryCount: ledger.missingLedgerDirectoryCount, unreadableLedgerDirectoryAccessCount: ledger.unreadableLedgerDirectoryAccessCount, indeterminateLedgerDirectoryCount: ledger.indeterminateLedgerDirectoryCount, cacheHits, cacheMisses }, phases: phaseStoreObservation(observedPhases), ...(stalled ? { stalled } : {}) };
593
616
  } finally {
594
617
  try {
595
618
  observeQuery({
@@ -614,7 +637,7 @@ export function queryRunningRuns(options: { includeTest?: boolean; runIds?: read
614
637
 
615
638
  export function isPartialRunningRuns(result: RunningRunsResult): boolean {
616
639
  return (result.count !== undefined && typeof result.count !== 'number' && result.count.count === null)
617
- || result.completeness === 'partial' || hasUnreadableLedgerObservation(result.ledger) || (result.unreadable?.length ?? 0) > 0;
640
+ || result.completeness === 'partial' || result.stalled !== undefined || hasUnreadableLedgerObservation(result.ledger) || (result.unreadable?.length ?? 0) > 0;
618
641
  }
619
642
 
620
643
  function runningRunsLowerBound(result: RunningRunsResult): number {
@@ -670,7 +693,7 @@ function formatElapsed(ms: number): string {
670
693
  export function renderRunProgressTable(result: RunningRunsResult, nowMs: number = Date.now()): string {
671
694
  const partial = isPartialRunningRuns(result);
672
695
  const header = partial
673
- ? `부분 관측 — 최소 ${runningRunsLowerBound(result)} (읽지 못한 원장: ${runningRunsUnreadable(result).map((item) => `${item.dir}:${item.reason}`).join(',') || '목록 미관측'})`
696
+ ? `부분 관측 — 최소 ${runningRunsLowerBound(result)} (${result.stalled ? `중단 단계 ${result.stalled.stage} · 사유 ${result.stalled.reason}` : `읽지 못한 원장: ${runningRunsUnreadable(result).map((item) => `${item.dir}:${item.reason}`).join(',') || '목록 미관측'}`})`
674
697
  : `도는 런 ${result.counts.running + result.counts['probable-running']} (확인 ${result.counts.running} · 추정 ${result.counts['probable-running']})`;
675
698
  const rows = buildRunProgressRows(result, nowMs).map((row) => {
676
699
  const phaseUnreadable = row.phaseObservation === 'unreadable' || row.phaseObservation === 'partially-unreadable';
@@ -20,6 +20,7 @@ import { resolveObserveOnlyDecision } from './observe-only.js';
20
20
  import { getUserConfig } from '../user-config.js';
21
21
  import { resolveAutoReview } from './context-capsule.js';
22
22
  import { readDecomposeProposals } from '../self-dev/decompose-proposal.js';
23
+ import { tracedPathReferences } from './goal-author.js';
23
24
 
24
25
  /** self implement CLI 옵션(commander) — `--no-draft` 는 draft:false 로, `--max-wait` 는 문자열로 도착. */
25
26
  export interface SelfImplementCliOpts {
@@ -65,6 +66,12 @@ export interface SelfImplementCliDeps {
65
66
  resolveWantAutoReview?: (flag: boolean) => boolean | Promise<boolean>;
66
67
  /** reroute 실행(테스트 주입). 기본 executeSelfImplementReroute. */
67
68
  executeReroute?: typeof executeSelfImplementReroute;
69
+ /** Capability seam: false disables reason-repair reruns; omitted means available because this CLI has a production rerouter. */
70
+ reasonRepairExecutionAvailable?: boolean;
71
+ /** Supervisor side-effect seams for focused runtime tests. */
72
+ taskAgentShadow?: false;
73
+ taskAgentRejudge?: false;
74
+ sweepPendingMerges?: typeof import('./frozen-merges.js').sweepFrozenMerges;
68
75
  /** ⭐ 산출물의 «눈» 심(테스트 주입). 기본은 실제 브라우저 검증(`observeDeliverables`).
69
76
  * ⛔ 심이 «없으면» 이 배선을 시험으로 재현할 수 없고, 그러면 「손으로 돌려 봤다」만 남는다
70
77
  * — 그것은 「그때 됐다」이지 「앞으로도 된다」가 아니다(리뷰 #10556 must-fix). */
@@ -124,11 +131,25 @@ export interface SingleRunSuperviseOptions {
124
131
  type SelfImplementResultWithProposalMetadata = SelfImplementResult
125
132
  & Pick<SelfDevJobResult, 'decomposeProposal' | 'goalPlanRevision'>;
126
133
 
127
- export function singleRunAsJobResult(feature: string, r: SelfImplementResultWithProposalMetadata): SupervisorJobResult {
134
+ /**
135
+ * NEEDS-HUMAN-REASON-REPAIR — 실행 범위 가드가 «대상 밖»으로 잰 변경을 감독 판정 재료로 옮긴다.
136
+ * ⛔ 가드가 잰 이름만 쓴다 — 결과에 없으면 빈 배열이고, 「없다」를 지어내지 않는다.
137
+ */
138
+ function measuredOutsideTargetFiles(r: SelfImplementResult): string[] {
139
+ return [...new Set([
140
+ ...(r.outOfScopeEdits ?? []),
141
+ ...(r.scopeExpansion?.files.map((file) => file.path) ?? []),
142
+ ])];
143
+ }
144
+
145
+ export function singleRunAsJobResult(feature: string, r: SelfImplementResultWithProposalMetadata, includeDeclaredTargets = false): SupervisorJobResult {
146
+ const outsideTargetFiles = measuredOutsideTargetFiles(r);
147
+ const targetPaths = includeDeclaredTargets ? tracedPathReferences(feature).map(({ path }) => path) : [];
128
148
  return {
129
149
  taskId: r.runId,
130
150
  runId: r.runId,
131
151
  feature,
152
+ ...(targetPaths.length ? { targetPaths } : {}),
132
153
  status: r.ok ? 'done' : 'failed',
133
154
  stage: r.stage,
134
155
  ...(!r.ok && r.detail ? { error: { message: r.detail } } : {}),
@@ -145,6 +166,7 @@ export function singleRunAsJobResult(feature: string, r: SelfImplementResultWith
145
166
  ...(r.abandonedClassification?.classification
146
167
  ? { failureClassification: r.abandonedClassification.classification } : {}),
147
168
  ...(r.decomposeProposal ? { decomposeProposal: r.decomposeProposal } : {}),
169
+ ...(outsideTargetFiles.length > 0 ? { outsideTargetFiles } : {}),
148
170
  ...(r.rework ? { rework: r.rework } : {}),
149
171
  ...(r.review?.reviewed && r.review.mustFix?.length ? { reviewMustFix: r.review.mustFix } : {}),
150
172
  ...(r.goalPlanRevision ? { goalPlanRevision: r.goalPlanRevision } : {}),
@@ -268,10 +290,20 @@ export async function runSelfImplementCliCommand(
268
290
  }
269
291
  : undefined;
270
292
 
271
- const initialJob = singleRunAsJobResult(feature, result);
293
+ const reasonRepairEnabled = getUserConfig().tools.selfImplement.supervisor?.reasonRepair === true
294
+ && (deps.reasonRepairExecutionAvailable ?? true);
295
+ const initialJob = singleRunAsJobResult(feature, result, reasonRepairEnabled);
296
+ // NEEDS-HUMAN-REASON-REPAIR — 사유별 수복 골을 «실행하는» 경로인가.
297
+ // ⛔ 아래 rerun 이 invocation.repairGoals[taskId] 를 spec.input.text 로 그대로 실행하므로 «그렇다».
298
+ // ⇒ 그래서 이 감독 경로는 사유별 수복(needs-human 전 1회)을 연다.
299
+ const repairGoalExecution = true;
272
300
  await superviseRun({
273
301
  initial: [initialJob],
274
- repairGoalExecution: true,
302
+ ...(deps.taskAgentShadow === false ? { taskAgentShadow: false } : {}),
303
+ ...(deps.taskAgentRejudge === false ? { taskAgentRejudge: false } : {}),
304
+ ...(deps.sweepPendingMerges ? { sweepPendingMerges: deps.sweepPendingMerges } : {}),
305
+ repairGoalExecution,
306
+ needsHumanReasonRepairExecution: reasonRepairEnabled,
275
307
  limits,
276
308
  ...(deliverableEye ? { observeDeliverables: deliverableEye } : {}),
277
309
  ...(opts.supervise.onDecision ? { onDecision: opts.supervise.onDecision } : {}),
@@ -285,7 +317,7 @@ export async function runSelfImplementCliCommand(
285
317
  const next = await exec(repairGoal ? { ...spec, input: { ...spec.input, text: repairGoal } } : spec, pipelineDeps ? { pipelineDeps } : undefined);
286
318
  result = attachGoalPlanRevisionObservation(next.result, deps);
287
319
  exitCode = next.exitCode;
288
- return [{ ...singleRunAsJobResult(feature, result), taskId: initialJob.taskId }];
320
+ return [{ ...singleRunAsJobResult(feature, result, reasonRepairEnabled), taskId: initialJob.taskId }];
289
321
  },
290
322
  });
291
323
  }
@@ -0,0 +1,43 @@
1
+ /** Production STOP-AUTOHEAL actions. A missing prerequisite is a failed action, never a healed run. */
2
+ import { spawnSync } from 'node:child_process';
3
+ import { SPAWN_SYNC_MAX_BUFFER } from '../util/spawn-sync-output.js';
4
+ import { runHostRegate, type HostRegateInput, type HostRegateResult } from './host-regate.js';
5
+ import type { AutohealActions, AutohealContext } from './stop-autoheal.js';
6
+
7
+ type PrHead = { headRefOid?: string; state?: string; isDraft?: boolean };
8
+ export interface OperationalAutohealDeps {
9
+ repoRoot: string;
10
+ readPr?: (number: number, repoRoot: string) => PrHead | null;
11
+ regate?: (input: HostRegateInput) => Promise<HostRegateResult>;
12
+ }
13
+
14
+ function prFromEvidence(ctx: AutohealContext): number | null {
15
+ const match = /^https:\/\/github\.com\/[^/]+\/[^/]+\/pull\/([1-9]\d*)\/?$/.exec(ctx.record.evidenceRef);
16
+ return match ? Number(match[1]) : null;
17
+ }
18
+
19
+ function readPr(number: number, repoRoot: string): PrHead | null {
20
+ const result = spawnSync('gh', ['pr', 'view', String(number), '--json', 'headRefOid,state,isDraft'], {
21
+ cwd: repoRoot, encoding: 'utf8', timeout: 30_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER,
22
+ });
23
+ if (result.status !== 0) return null;
24
+ try { return JSON.parse(result.stdout) as PrHead; } catch { return null; }
25
+ }
26
+
27
+ /** Re-gate an existing PR in a clean checkout against current main; never merge from the healer. */
28
+ export function operationalAutohealActions(deps: OperationalAutohealDeps): AutohealActions {
29
+ return {
30
+ 'clean-workspace-regate': async (ctx) => {
31
+ const number = prFromEvidence(ctx);
32
+ if (!number) return { ok: false, detail: 'PR URL absent from stop evidence' };
33
+ const pr = (deps.readPr ?? readPr)(number, deps.repoRoot);
34
+ if (!pr?.headRefOid || pr.state !== 'OPEN' || typeof pr.isDraft !== 'boolean')
35
+ return { ok: false, detail: `PR #${number} is not an open PR with a measured head and draft state` };
36
+ const result = await (deps.regate ?? runHostRegate)({
37
+ prNumber: number, headCommit: pr.headRefOid, repoRoot: deps.repoRoot, verifyOnly: true,
38
+ ...(pr.isDraft ? { allowDraft: true } : {}),
39
+ });
40
+ return { ok: result.passed, detail: `PR #${number} head ${pr.headRefOid} clean regate ${result.status ?? (result.passed ? 'passed' : 'failed')}${result.failures.length ? `: ${result.failures.map((failure) => failure.step).join(',')}` : ''}` };
41
+ },
42
+ };
43
+ }
@@ -13,11 +13,12 @@
13
13
  * main-sync → rebase-regate 리베이스(MERGE-INTENT-RESOLVE 의도 해석) 뒤 재게이트
14
14
  * pod-died → resume-from-salvage `salvage/run-<6hex>/<leaf>` 가지에서 resume(DRAFT-NOT-ARCHIVE)
15
15
  * evidence-uncovered → derive-evidence-rejudge 런 출력·시험·배선에서 증거를 끌어내 1회 재판정
16
+ * review-budget-exhausted → needs-owner (code fallback; reauthor is an optional graph exit)
16
17
  * review-repeat · review-out-of-scope · scope-escape · fabric · launch-failed · gate-failed · unclassified → needs-owner(새 라운드 없음)
17
18
  *
18
19
  * 사다리의 «출처»: `graphs/overlays/stop-heal-ladder.yaml` 이 갈래마다 처방 노드(id = 처방 이름)를 선언한다.
19
20
  * 그 갈래에 얹힌 오버레이가 더한 노드 id 가 처방이다(source='graph'). 선언이 없거나 못 읽으면
20
- * 위 표(`AUTOHEAL_ACTION_BY_CLASS`)로 간다(source='code-default'). 둘이 같은 답을 내는지는 시험이 문다.
21
+ * 위 표(`AUTOHEAL_ACTION_BY_CLASS`)로 간다(source='code-default'). 선택된 노드가 실제 실행 가능한지는 별도 경계다.
21
22
  *
22
23
  * 모드 `tools.selfImplement.autoheal.mode` = `shadow`(기본: 할 일을 원장에만 적고 손대지 않는다) | `live`.
23
24
  * ⛔ live 에서도 행동은 주입 seam 으로만 한다 — seam 이 없는 행동은 `needs-owner`(action-unwired)로 떨어진다.
@@ -44,6 +45,7 @@ export type AutohealAction =
44
45
  | 'rebase-regate'
45
46
  | 'resume-from-salvage'
46
47
  | 'derive-evidence-rejudge'
48
+ | 'review-round-reauthor'
47
49
  | 'needs-owner';
48
50
 
49
51
  /** 닫힌 목록 전체를 덮는다 — 새 class 가 생기면 여기서 타입 오류가 난다. */
@@ -55,6 +57,8 @@ export const AUTOHEAL_ACTION_BY_CLASS: Readonly<Record<RunStopClass, AutohealAct
55
57
  'evidence-uncovered': 'derive-evidence-rejudge',
56
58
  'review-repeat': 'needs-owner',
57
59
  'review-out-of-scope': 'needs-owner',
60
+ // Reauthoring is an optional graph exit, not a code-level guarantee.
61
+ 'review-budget-exhausted': 'needs-owner',
58
62
  'scope-escape': 'needs-owner',
59
63
  fabric: 'needs-owner',
60
64
  'launch-failed': 'needs-owner',
@@ -64,7 +68,7 @@ export const AUTOHEAL_ACTION_BY_CLASS: Readonly<Record<RunStopClass, AutohealAct
64
68
 
65
69
  /** 처방 노드 id 로 인정하는 이름 — 오버레이가 더한 노드 중 이 넷만 처방으로 읽는다. */
66
70
  const HEAL_ACTION_NODE_IDS: ReadonlySet<string> = new Set<Exclude<AutohealAction, 'needs-owner'>>([
67
- 'clean-workspace-regate', 'rebase-regate', 'resume-from-salvage', 'derive-evidence-rejudge',
71
+ 'clean-workspace-regate', 'rebase-regate', 'resume-from-salvage', 'derive-evidence-rejudge', 'review-round-reauthor',
68
72
  ]);
69
73
 
70
74
  /** 처방이 «어디서» 왔나 — `graph` = 그 갈래에 얹힌 오버레이가 더한 노드 · `code-default` = 위 표. */
@@ -75,6 +79,8 @@ export interface AutohealPick {
75
79
  source: AutohealActionSource;
76
80
  /** source='graph' 일 때 그 처방 노드를 더한 오버레이. */
77
81
  overlayId?: string;
82
+ /** Code fallback when an optional graph exit is not declared. */
83
+ fallbackReason?: string;
78
84
  }
79
85
 
80
86
  /** 사다리를 읽어 오는 자리 — 활성 템플릿 선언 ⊕ 오버레이 목록. 시험이 갈아 끼운다. */
@@ -93,7 +99,10 @@ function loadDefaultLadder(): AutohealLadder {
93
99
  * «조용히» 코드 표로 간다 — 그 사실은 `source` 가 말한다. 던지지 않는다.
94
100
  */
95
101
  export function pickAutohealAction(cls: RunStopClass, loadLadder: () => AutohealLadder = loadDefaultLadder): AutohealPick {
96
- const codeDefault: AutohealPick = { action: AUTOHEAL_ACTION_BY_CLASS[cls] ?? 'needs-owner', source: 'code-default' };
102
+ const codeDefault: AutohealPick = {
103
+ action: AUTOHEAL_ACTION_BY_CLASS[cls] ?? 'needs-owner', source: 'code-default',
104
+ ...(cls === 'review-budget-exhausted' ? { fallbackReason: 'declared-node-unavailable: review-round-reauthor' } : {}),
105
+ };
97
106
  try {
98
107
  const { template, overlays } = loadLadder();
99
108
  if (!template) return codeDefault;
@@ -297,8 +306,8 @@ export async function autohealFromStop(ctx: AutohealContext, deps: AutohealDeps
297
306
  }
298
307
  const mode = deps.mode ?? DEFAULT_AUTOHEAL_MODE;
299
308
  const cls = ctx.record.class;
300
- const { action, source, overlayId } = pickAutohealAction(cls, deps.loadLadder);
301
- const base = { runId: ctx.runId, class: cls, action, source, ...(overlayId ? { overlayId } : {}), mode };
309
+ const { action, source, overlayId, fallbackReason } = pickAutohealAction(cls, deps.loadLadder);
310
+ const base = { runId: ctx.runId, class: cls, action, source, ...(overlayId ? { overlayId } : {}), ...(fallbackReason ? { fallbackReason } : {}), mode };
302
311
 
303
312
  if (repeatedStop(deps.priorStops, ctx.record)) {
304
313
  // ⛔ 같은 골에서 같은 갈래의 멈춤이 반복되면 자동 재시도를 하지 않는다 — 사유를 골 되먹임 대상으로 넘긴다.
@@ -329,7 +338,7 @@ export async function autohealFromStop(ctx: AutohealContext, deps: AutohealDeps
329
338
  let detail: string | undefined;
330
339
  if (action === 'needs-owner') {
331
340
  outcome = 'needs-owner';
332
- reason = `stop ${cls}: ${ctx.record.cause}`;
341
+ reason = `${fallbackReason ? `${fallbackReason}; ` : ''}stop ${cls}: ${ctx.record.cause}`;
333
342
  } else if (mode === 'shadow') {
334
343
  outcome = 'would-act';
335
344
  } else {