elanous 0.2.38 → 0.2.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (712) hide show
  1. package/README.md +7 -7
  2. package/apps/pwa/out/404/index.html +1 -1
  3. package/apps/pwa/out/404.html +1 -1
  4. package/apps/pwa/out/_next/static/{RrjXTwz-urRAbChP1bX02 → GiOLWmt4MqDZePubBjA4Q}/_buildManifest.js +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1115.434ae2ecb0ad986d.js +149 -0
  6. package/apps/pwa/out/_next/static/chunks/1121.667cec0bcdbb3fdb.js +36 -0
  7. package/apps/pwa/out/_next/static/chunks/1178.1aa9cad0e7695427.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1197-54da59d250a6e476.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/{5203.51e5d8b5f1dcfe53.js → 1219.7e17964e0e7cd8e5.js} +3 -3
  10. package/apps/pwa/out/_next/static/chunks/1245.1cfd13b26dbd71d6.js +287 -0
  11. package/apps/pwa/out/_next/static/chunks/1494-f93046ff5c5a124d.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/1609.2b312797599b8e45.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1661.0dd330f3d89f73f3.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/167-0c121e4b47e0f9da.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1700.cdc2bf8cc685e221.js +90 -0
  16. package/apps/pwa/out/_next/static/chunks/1703-78e46acad29f3cfc.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/{7573.2376e13c9c21f1f8.js → 1765.679b29625c8e88d4.js} +2 -2
  18. package/apps/pwa/out/_next/static/chunks/{3528.e4b8ab70d339f965.js → 1800.f7ff51dc4978a958.js} +1 -1
  19. package/apps/pwa/out/_next/static/chunks/1971-7efb628c471dc5a0.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/1999-8de7b7bb36801913.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2073.689dcb2680113d76.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2198-557d49184104d165.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/221-440ce67fa9f5c839.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/{8879.ac06755bcf3e44a1.js → 2263.e09b6edea33bad2d.js} +1 -1
  25. package/apps/pwa/out/_next/static/chunks/2427-8ed8e98624cbd664.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2457-725c5827bc003795.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2491-2718b15a5ccb75a5.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2527-5c636a43c7cc5dde.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2692-1027cb16fe4ccf49.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/2743.5d3f76948be32b34.js +41 -0
  31. package/apps/pwa/out/_next/static/chunks/2773.0e80b9d325fb5635.js +32 -0
  32. package/apps/pwa/out/_next/static/chunks/2873-0f3cb56c8e3528ea.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/{9fe1b809.738da85c8b17e3fb.js → 2fdf2931.b431eee4fb468bc3.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/{eaad0cba.771200940c529df7.js → 2fe2c302.41b517f88d6fe502.js} +1 -1
  35. package/apps/pwa/out/_next/static/chunks/3097.864e92bdaa2f4d15.js +79 -0
  36. package/apps/pwa/out/_next/static/chunks/3136-d6870ba63300a93e.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3173-0289113d434e83b7.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3230-49298c3b73ef2268.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/325-dd9208a1a0ab7ce4.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3283.528f430dd043fb4e.js +74 -0
  41. package/apps/pwa/out/_next/static/chunks/3295.cc8cb13b8f0dae1a.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/3688-86e3b88abf18cb3b.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/3804-7220467a5473a8df.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/3808.3e1e247ce7bdf889.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/{b7478fef.5917716286213fcc.js → 385e4574.e9886ab32759eda3.js} +3 -3
  46. package/apps/pwa/out/_next/static/chunks/3927.b5473ad109da44c5.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/3934-98ea94832e194796.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4133.2056bb4d78f621af.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/4156.ba4de4a3664f04b4.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4297-239ca82f293faab0.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/4320-dcc5a7734126f4c9.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4434.94b4c552a2d91e69.js +148 -0
  53. package/apps/pwa/out/_next/static/chunks/{8911.bf5e712acb25fb6c.js → 4527.a69f2894d1bc9f4a.js} +1 -1
  54. package/apps/pwa/out/_next/static/chunks/4579.03e4092f73950965.js +226 -0
  55. package/apps/pwa/out/_next/static/chunks/{5307.d7328020227880c2.js → 4667.97e31aa38c95c475.js} +4 -4
  56. package/apps/pwa/out/_next/static/chunks/{6142.913b44e260a3f925.js → 4702.4a4adc1f16d7c93b.js} +1 -1
  57. package/apps/pwa/out/_next/static/chunks/4815.481501c57b3568d9.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/487-d16e698ef14662d9.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/4888-7a38bf522c9cc6fe.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/5034-30e429d6bb086881.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5040-35c494e60dadd97d.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/50c6ab1e.81a96e419350909d.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/5154.4b6a836179356f30.js +94 -0
  64. package/apps/pwa/out/_next/static/chunks/{8487.291666583bebe640.js → 5159.115f1c2ca471386c.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/5228-a8200df486278f2d.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/530.d26346e18089640a.js +115 -0
  67. package/apps/pwa/out/_next/static/chunks/5379.97af106d09566f69.js +8 -0
  68. package/apps/pwa/out/_next/static/chunks/{89d6c04f-6b8ab341748e468a.js → 53aeb4ee-51c92f8d683f5220.js} +1 -1
  69. package/apps/pwa/out/_next/static/chunks/{3291.f6c1005387d514bd.js → 5471.1e611302ed3a7c53.js} +2 -2
  70. package/apps/pwa/out/_next/static/chunks/5479-b6372e762719f92f.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/5534-699c5cbcbc96c5d7.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/{3086.fb14b60ce98b53d3.js → 5574.f35accf4f132b29d.js} +1 -1
  73. package/apps/pwa/out/_next/static/chunks/5701.9c4e8f250312eeee.js +24 -0
  74. package/apps/pwa/out/_next/static/chunks/{1632.7d87f998e714bede.js → 5744.b9415e18ad623100.js} +1 -1
  75. package/apps/pwa/out/_next/static/chunks/{5300.677c97e0393742e6.js → 5892.2526d962339662d8.js} +1 -1
  76. package/apps/pwa/out/_next/static/chunks/5937.c2df9e3447e1f667.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/5941.8210cc93c9202c0a.js +286 -0
  78. package/apps/pwa/out/_next/static/chunks/{7161-8f22db3ec5ed005e.js → 5947-135e26537d80a6b9.js} +3 -3
  79. package/apps/pwa/out/_next/static/chunks/{3124-561f7f037943cde2.js → 5964-7e21164a8f2cf0ce.js} +1 -1
  80. package/apps/pwa/out/_next/static/chunks/5975.4004f820ae3cecd5.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6142-7ccd48795d7abd55.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6160.bf9177b8c1bfb243.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6398.71ba0690c8027555.js +27 -0
  84. package/apps/pwa/out/_next/static/chunks/6492.2bd5c10edc1a064e.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/6552.a3840aa7da35ad68.js +62 -0
  86. package/apps/pwa/out/_next/static/chunks/6736.1e36d3ac5fa5e41d.js +24 -0
  87. package/apps/pwa/out/_next/static/chunks/6874.d5cf7eb8edb2cabe.js +2 -0
  88. package/apps/pwa/out/_next/static/chunks/6900.3ccbe069bdd4556a.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/71327eb4.add50b365f94bf3a.js +122 -0
  90. package/apps/pwa/out/_next/static/chunks/7136.deca3e3a2ddaa374.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7139-ee9f8ed2677a40b3.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{2415.738b777642a02233.js → 7191.fdc955f7d96064a4.js} +1 -1
  93. package/apps/pwa/out/_next/static/chunks/7423-e0aa5d9e2962120e.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7453.afc1ea7e05d56a8c.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/7503-5e6a3d7fe67e4a0c.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/7761-476fd7bf768abd34.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/7975.eafb12097a0a9e62.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/{1026-44010f405704050c.js → 8050-9b364bdef8f71927.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/8152.64e253c35cccfaae.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/8190.620f0231b3924bcb.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/83184dcd-0ee6247ff41eb3f2.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8448.45b6b1f1a99eeb35.js +104 -0
  103. package/apps/pwa/out/_next/static/chunks/8464-e24f10451b658aac.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8477.e4c944bb3aa5d2f3.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8710.ca385257d5ca422e.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8830.627ccf294ec2465c.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8880.64c445592f04acaf.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8981.c706964c8ba27aff.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{5638.107314dc479e2f37.js → 9048.212083de42d25be3.js} +2 -2
  110. package/apps/pwa/out/_next/static/chunks/9053.bd0fffaff8d3f836.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/9161-c66e723d7ec9d682.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/9185.1ecdf9b65c0bb684.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/9356.fccd5f58086b4ff5.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/9446.dc0406109371d329.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9506.dcf25d467a42627e.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/{8019.21ca554a821dad01.js → 9507.7026657a2f47eb64.js} +16 -16
  117. package/apps/pwa/out/_next/static/chunks/9541.eb8e2f8480c7feca.js +93 -0
  118. package/apps/pwa/out/_next/static/chunks/9577.ed7582186efa5482.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9579.4a8169600fff2058.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9642-ff2e039eb62e3b92.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9659-8f2323348113ad80.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9724.4c5623af2db43153.js +34 -0
  123. package/apps/pwa/out/_next/static/chunks/{6493.27ad77de7aac7966.js → 9834.63ab2bbc3153172e.js} +1 -1
  124. package/apps/pwa/out/_next/static/chunks/{3389.012c70767a872f9b.js → 9869.81a1e24ca682d5a0.js} +1 -1
  125. package/apps/pwa/out/_next/static/chunks/{8994d93e.33ba491f95345fc2.js → a0a01613.6d1cca322238d7fe.js} +1 -1
  126. package/apps/pwa/out/_next/static/chunks/{de8b930d.d94c0f42acf807fc.js → addc2b32.8c4ff8f0aefe987d.js} +1 -1
  127. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-8d9d76ea322d855c.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed2c4e59f9f1fe21.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-2dc99e03c5d76ca0.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/board/page-b5a3a788330e920f.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-866aac5ff226a7f3.js → page-14949db884bfa672.js} +1 -1
  132. package/apps/pwa/out/_next/static/chunks/app/bots/page-ea76c85b36388a97.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/ceo/page-01716d20af62d325.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/chat/page-62baf6881a64b1e9.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/consult/page-f89ba590c2af8afa.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/control/page-22f8b0f78d9637e5.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/decisions/page-817f9d7e6820be80.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/design-check/page-ffb9bc0d2650249a.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/editor/page-f6d0e64873c0f629.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/exec/page-8bfa0d4ba23a209d.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/field/page-f5060462249e32c7.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/healthz/route-8d9d76ea322d855c.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/inside/page-b2049f8b1ef79117.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/intake/page-1446c5fa93907f11.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/layout-b48a7a07c5204156.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/live/page-e974b8c4ca47614c.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/live-run/page-8a919b869bd28594.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/loops/page-d31b8de6bfcd72ed.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/market/page-64765f817909db29.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-d128c8569a36ee9b.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/morning/page-b2679d357e9b9270.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/not-found-6fabec98a9e7b269.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/observatory/page-048f30149dcf1349.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-9113181d6b5a2725.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-40f9e19149024298.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-1e7a755a13227611.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3c8f8b67a203cf07.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/page-18032f5437215062.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/reflection/page-da3b739192fd0ee3.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d332545571bd6fd1.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/sessions/page-5237aa5b3f3b8ec5.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a142dfb0331a05f5.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/settings/page-d16e56c3989c147e.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6b6593600869e2cd.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/setup/layout-8d9d76ea322d855c.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/setup/page-29e8b8a8396b55cb.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/share/page-b3414d856a1a7e2f.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c3affa52b7ce961b.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f21dddf9f95b6fab.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/term/page-f5a30a24745bf088.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/today/page-8c8569a09b4d4e34.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/trace/page-2ce32722c0243483.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/vault/page-4767b0d9c0a98c6c.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-116ee1339c387a75.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/app/workflows/page-35e8c50ca4ef7ffc.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/app/workspace/page-52e17113356bb891.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7458ae05ed2ac1a0.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/b2271e54.c1de3347976e90b0.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/{b7459770.6539b11860eb8a9c.js → c0c1a699.0ba79f97005965d4.js} +7 -7
  180. package/apps/pwa/out/_next/static/chunks/framework-ad6c9dd524ad6ef8.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/main-app-2ddd1f2b44d6aa59.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/main-e3d82bdc358d20c5.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/pages/_app-71d5aa3896e1655f.js +1 -0
  184. package/apps/pwa/out/_next/static/chunks/pages/_error-03ffc54e00438546.js +1 -0
  185. package/apps/pwa/out/_next/static/chunks/webpack-56bb89af5a611d0b.js +1 -0
  186. package/apps/pwa/out/approvals/index.html +1 -1
  187. package/apps/pwa/out/approvals/index.txt +22 -22
  188. package/apps/pwa/out/autopilot/index.html +1 -1
  189. package/apps/pwa/out/autopilot/index.txt +22 -22
  190. package/apps/pwa/out/board/index.html +1 -1
  191. package/apps/pwa/out/board/index.txt +22 -22
  192. package/apps/pwa/out/botlab/index.html +1 -1
  193. package/apps/pwa/out/botlab/index.txt +21 -21
  194. package/apps/pwa/out/bots/index.html +1 -1
  195. package/apps/pwa/out/bots/index.txt +21 -21
  196. package/apps/pwa/out/ceo/index.html +1 -1
  197. package/apps/pwa/out/ceo/index.txt +22 -22
  198. package/apps/pwa/out/chat/index.html +1 -1
  199. package/apps/pwa/out/chat/index.txt +21 -21
  200. package/apps/pwa/out/consult/index.html +1 -1
  201. package/apps/pwa/out/consult/index.txt +22 -22
  202. package/apps/pwa/out/control/index.html +1 -1
  203. package/apps/pwa/out/control/index.txt +22 -22
  204. package/apps/pwa/out/decisions/index.html +1 -1
  205. package/apps/pwa/out/decisions/index.txt +21 -21
  206. package/apps/pwa/out/design-check/index.html +1 -1
  207. package/apps/pwa/out/design-check/index.txt +22 -22
  208. package/apps/pwa/out/editor/index.html +1 -1
  209. package/apps/pwa/out/editor/index.txt +22 -22
  210. package/apps/pwa/out/exec/index.html +1 -1
  211. package/apps/pwa/out/exec/index.txt +22 -22
  212. package/apps/pwa/out/field/index.html +1 -1
  213. package/apps/pwa/out/field/index.txt +22 -22
  214. package/apps/pwa/out/healthz +1 -1
  215. package/apps/pwa/out/index.html +1 -1
  216. package/apps/pwa/out/index.txt +21 -21
  217. package/apps/pwa/out/inside/index.html +1 -1
  218. package/apps/pwa/out/inside/index.txt +21 -21
  219. package/apps/pwa/out/intake/index.html +1 -1
  220. package/apps/pwa/out/intake/index.txt +22 -22
  221. package/apps/pwa/out/live/index.html +1 -1
  222. package/apps/pwa/out/live/index.txt +22 -22
  223. package/apps/pwa/out/live-run/index.html +1 -1
  224. package/apps/pwa/out/live-run/index.txt +22 -22
  225. package/apps/pwa/out/loops/index.html +1 -1
  226. package/apps/pwa/out/loops/index.txt +21 -21
  227. package/apps/pwa/out/market/index.html +1 -1
  228. package/apps/pwa/out/market/index.txt +21 -21
  229. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  230. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  231. package/apps/pwa/out/morning/index.html +1 -1
  232. package/apps/pwa/out/morning/index.txt +22 -22
  233. package/apps/pwa/out/observatory/index.html +1 -1
  234. package/apps/pwa/out/observatory/index.txt +22 -22
  235. package/apps/pwa/out/ops/checklist/index.html +1 -1
  236. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  237. package/apps/pwa/out/ops/release/index.html +1 -1
  238. package/apps/pwa/out/ops/release/index.txt +21 -21
  239. package/apps/pwa/out/ops/seats/index.html +1 -1
  240. package/apps/pwa/out/ops/seats/index.txt +21 -21
  241. package/apps/pwa/out/outputs/index.html +1 -1
  242. package/apps/pwa/out/outputs/index.txt +21 -21
  243. package/apps/pwa/out/reflection/index.html +1 -1
  244. package/apps/pwa/out/reflection/index.txt +22 -22
  245. package/apps/pwa/out/scheduler/index.html +1 -1
  246. package/apps/pwa/out/scheduler/index.txt +22 -22
  247. package/apps/pwa/out/sessions/index.html +1 -1
  248. package/apps/pwa/out/sessions/index.txt +21 -21
  249. package/apps/pwa/out/settings/devices/index.html +1 -1
  250. package/apps/pwa/out/settings/devices/index.txt +22 -22
  251. package/apps/pwa/out/settings/index.html +1 -1
  252. package/apps/pwa/out/settings/index.txt +22 -22
  253. package/apps/pwa/out/setup/done/index.html +1 -1
  254. package/apps/pwa/out/setup/done/index.txt +22 -22
  255. package/apps/pwa/out/setup/index.html +1 -1
  256. package/apps/pwa/out/setup/index.txt +22 -22
  257. package/apps/pwa/out/share/index.html +1 -1
  258. package/apps/pwa/out/share/index.txt +22 -22
  259. package/apps/pwa/out/showroom/index.html +1 -1
  260. package/apps/pwa/out/showroom/index.txt +21 -21
  261. package/apps/pwa/out/tasks/index.html +1 -1
  262. package/apps/pwa/out/tasks/index.txt +22 -22
  263. package/apps/pwa/out/term/index.html +1 -1
  264. package/apps/pwa/out/term/index.txt +22 -22
  265. package/apps/pwa/out/today/index.html +1 -1
  266. package/apps/pwa/out/today/index.txt +22 -22
  267. package/apps/pwa/out/trace/index.html +1 -1
  268. package/apps/pwa/out/trace/index.txt +22 -22
  269. package/apps/pwa/out/vault/index.html +1 -1
  270. package/apps/pwa/out/vault/index.txt +22 -22
  271. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  272. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  273. package/apps/pwa/out/workflows/index.html +1 -1
  274. package/apps/pwa/out/workflows/index.txt +22 -22
  275. package/apps/pwa/out/workspace/index.html +1 -1
  276. package/apps/pwa/out/workspace/index.txt +22 -22
  277. package/apps/pwa/out/worktrees/index.html +1 -1
  278. package/apps/pwa/out/worktrees/index.txt +22 -22
  279. package/bin/elanous.mjs +6 -1
  280. package/catalog/models/openai/gpt-6.1-sol.yaml +16 -0
  281. package/catalog/models/openai/gpt-6.1-terra.yaml +16 -0
  282. package/graphs/demo/persona-marketer/fixtures/marketer-scenario.yaml +10 -0
  283. package/graphs/demo/persona-marketer/persona-marketer.yaml +25 -0
  284. package/graphs/demo/persona-marketer/recipes.yaml +19 -0
  285. package/graphs/demo/persona-teacher/lesson-pack.yaml +16 -0
  286. package/graphs/demo/persona-teacher/recipes.yaml +17 -0
  287. package/graphs/demo/persona-teacher/weekly-lesson.yaml +36 -0
  288. package/graphs/overlays/stop-heal-ladder.yaml +23 -2
  289. package/graphs/release/release-loop.yaml +3 -1
  290. package/graphs/units/gate/gate.yaml +20 -0
  291. package/graphs/units/git/git.yaml +26 -0
  292. package/graphs/units/implement/implement.yaml +19 -0
  293. package/graphs/units/landing/landing.yaml +18 -0
  294. package/graphs/units/review/review.yaml +20 -0
  295. package/graphs/units/verbs/recipes.yaml +3 -0
  296. package/graphs/units/verbs/research.yaml +20 -0
  297. package/graphs/video/explainer-line.yaml +4 -1
  298. package/graphs/work/research-report.yaml +11 -1
  299. package/package.json +1 -1
  300. package/scripts/dead-code/report.ts +169 -0
  301. package/scripts/disk-steward.ts +46 -0
  302. package/scripts/fleet/node-setup.sh +50 -0
  303. package/scripts/graph-units/verbs/research.ts +55 -0
  304. package/scripts/lib/morning-report-options.ts +3 -4
  305. package/scripts/lib/tui-regress-evidence.ts +56 -0
  306. package/scripts/llm-cost-ledger.ts +179 -8
  307. package/scripts/measure-nl-routing-corpus.ts +10 -2
  308. package/scripts/morning-report.ts +5 -1
  309. package/scripts/persona-teacher/weekly-lesson-node.ts +172 -0
  310. package/scripts/public-copy-lint.ts +163 -19
  311. package/scripts/public-export.ts +15 -7
  312. package/scripts/ratchets/train-side-invariants.sh +0 -1
  313. package/scripts/release-loop/export-check-node.ts +21 -3
  314. package/scripts/release-loop/gate-autoheal.ts +117 -0
  315. package/scripts/release-loop/gate-baseline-receipt.ts +8 -1
  316. package/scripts/release-loop/gate-diff.ts +22 -3
  317. package/scripts/release-loop/gate-node.ts +583 -64
  318. package/scripts/release-loop/gate-shard-dispatch.ts +128 -0
  319. package/scripts/release-loop/gate-shard-load-flaky.ts +256 -0
  320. package/scripts/release-loop/gate-shard-receipts.ts +89 -0
  321. package/scripts/release-loop/gate-triage-node.ts +70 -10
  322. package/scripts/release-loop/gate-wall.ts +5 -5
  323. package/scripts/release-loop/preflight.ts +6 -2
  324. package/scripts/release-loop/resume-release.ts +267 -20
  325. package/scripts/release-loop/resume.ts +48 -0
  326. package/scripts/release-loop/traffic-node.ts +6 -3
  327. package/scripts/release-loop/unattended-release.ts +4 -2
  328. package/scripts/release-loop/version-node.ts +7 -2
  329. package/scripts/release-story/draft.ts +1 -1
  330. package/scripts/research-bench/README.md +53 -0
  331. package/scripts/research-bench/questions.json +66 -0
  332. package/scripts/research-bench/rubric.md +33 -0
  333. package/scripts/research-bench/run.ts +523 -0
  334. package/scripts/shadow-authoring-probe.ts +20 -0
  335. package/scripts/tui-regress.ts +85 -10
  336. package/scripts/ux-sim.ts +19 -2
  337. package/src/acp/core-turn-bridge.ts +94 -4
  338. package/src/agent/autonomous-tools.ts +10 -3
  339. package/src/agent/monad-agent-turn.ts +4 -1
  340. package/src/agent/registry.ts +26 -2
  341. package/src/agent/shared-app-tools.ts +1 -1
  342. package/src/agent/surface-ux/build.ts +12 -3
  343. package/src/agent/surface-ux/types.ts +1 -1
  344. package/src/agent/task-notification.ts +75 -6
  345. package/src/agent/types.ts +3 -0
  346. package/src/agent-mission/driver.ts +29 -3
  347. package/src/agent-mission/mission-cli.ts +2 -1
  348. package/src/agent-substrate/review-context-pack.ts +365 -0
  349. package/src/agent-substrate/self-review-cli.ts +291 -20
  350. package/src/ask-user-question/index.ts +6 -0
  351. package/src/ask-user-question/inline-resolver.ts +49 -0
  352. package/src/auto-research/question-ladder-contract.ts +22 -3
  353. package/src/auto-research/research-turn.ts +359 -17
  354. package/src/autopilot/agent-loop.ts +1 -1
  355. package/src/autopilot/discovery/wiki-claim-proposer.ts +22 -1
  356. package/src/autopilot/pty-control-loop.ts +8 -1
  357. package/src/boot/daemon-tools/index.ts +4 -3
  358. package/src/boot/daemon-tools/self-implement.ts +312 -7
  359. package/src/boot/daemon-tools/types.ts +2 -0
  360. package/src/budget/llm-cost.ts +44 -5
  361. package/src/budget/shadow-arms.ts +52 -0
  362. package/src/budget/unified-usage.ts +17 -1
  363. package/src/capture/tui-self-report.ts +14 -0
  364. package/src/chat/index.ts +33 -7
  365. package/src/chat/pickers/state.ts +7 -1
  366. package/src/cli/agent-cli.ts +43 -8
  367. package/src/cli/intake-cli.ts +22 -1
  368. package/src/cli/lesson-cli.ts +19 -3
  369. package/src/cli/log-event-names.ts +6 -0
  370. package/src/cli/mcp-login.ts +8 -18
  371. package/src/cli/msg-cli.ts +57 -1
  372. package/src/cli/pod-cli.ts +17 -2
  373. package/src/cli/pr-land-heavy-remote.ts +15 -9
  374. package/src/cli/pty-takeover-cli.ts +67 -7
  375. package/src/cli/release-cli.ts +79 -7
  376. package/src/cli/repo-cli.ts +2 -1
  377. package/src/cli/sim-cli.ts +7 -1
  378. package/src/cli/tasks-cli.ts +41 -13
  379. package/src/codex/models.ts +30 -15
  380. package/src/control-plane/ledger.ts +21 -4
  381. package/src/core-turn/run-core-turn.ts +47 -3
  382. package/src/core-turn/run-goal-loop.ts +240 -10
  383. package/src/core-turn/types.ts +9 -0
  384. package/src/dashboard/acp-boot.ts +72 -3
  385. package/src/dashboard/chat/acp-chat.ts +2 -2
  386. package/src/dashboard/classic-sigquit.ts +16 -0
  387. package/src/dashboard/index.ts +327 -27
  388. package/src/dashboard/input/chat-main-interaction-opts.ts +3 -0
  389. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +7 -2
  390. package/src/dashboard/input/chat-main-slash-command.ts +7 -0
  391. package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
  392. package/src/dashboard/input/dashboard-priority-key-route.ts +21 -5
  393. package/src/dashboard/input/external-input-host.ts +2 -0
  394. package/src/dashboard/sidetab-runtime.ts +228 -0
  395. package/src/dashboard/slash-runtime/ask-clarification.ts +7 -1
  396. package/src/dashboard/slash-runtime/dashboard-handlers.ts +20 -8
  397. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -2
  398. package/src/dashboard/term-slash-runtime.ts +16 -18
  399. package/src/dashboard/turn-preamble.ts +14 -1
  400. package/src/disk-steward/judge.ts +73 -0
  401. package/src/disk-steward/ledger.ts +122 -0
  402. package/src/disk-steward/steward.ts +373 -0
  403. package/src/domains/guardian-tick.ts +191 -2
  404. package/src/domains/knowledge.ts +1 -1
  405. package/src/esc-abort-gate.ts +33 -1
  406. package/src/execution-loop/launch-gate.ts +206 -1
  407. package/src/graph-runner/graph-cli.ts +27 -4
  408. package/src/graph-runner/in-process-registry.ts +37 -0
  409. package/src/graph-runner/runner.ts +63 -11
  410. package/src/graph-wizard/generate.ts +16 -7
  411. package/src/graph-wizard/mission-compose.ts +201 -0
  412. package/src/grok/agent-search.ts +8 -2
  413. package/src/grok/credential.ts +5 -0
  414. package/src/grounding/ref-index.ts +30 -0
  415. package/src/grounding/ref-vector.ts +61 -0
  416. package/src/grounding/sources-cli.ts +11 -3
  417. package/src/grounding/sources.ts +15 -1
  418. package/src/harness/harness-cli-command.ts +305 -23
  419. package/src/harness/harness-incidents.ts +312 -7
  420. package/src/harness/harness-pod-dispatch.ts +7 -1
  421. package/src/harness/harness-space.ts +15 -1
  422. package/src/harness/progress-worker-entry.ts +59 -0
  423. package/src/harness/progress-worker-runtime.ts +11 -0
  424. package/src/index.ts +35 -5
  425. package/src/input/external-input-queue.ts +10 -0
  426. package/src/instance/dev-project.ts +25 -0
  427. package/src/intake-plane/collect-telegram-saved.ts +36 -1
  428. package/src/intake-plane/intake-to-tasks.ts +246 -3
  429. package/src/intelligence-map/model-alias.ts +6 -5
  430. package/src/intelligence-map/model-catalog.ts +59 -2
  431. package/src/lessons/friction-ledger.ts +154 -0
  432. package/src/live-supply/collector.ts +149 -0
  433. package/src/live-supply/probes.ts +52 -0
  434. package/src/live-supply/snapshot.ts +40 -0
  435. package/src/llm/model-defaults.ts +4 -4
  436. package/src/llm.ts +473 -87
  437. package/src/loops/orchestrator/tick.ts +56 -0
  438. package/src/mcp/mcp-oauth.ts +3 -1
  439. package/src/model-tier/llm-tier-map.ts +9 -9
  440. package/src/model-tier/turn-tier.ts +1 -1
  441. package/src/msg/msg-mirror-github.ts +80 -0
  442. package/src/msg/msg-mirror-policy.ts +61 -0
  443. package/src/msg/msg-mirror-runner.ts +219 -0
  444. package/src/msg/msg-mirror-state.ts +33 -0
  445. package/src/msg/msg-store.ts +11 -0
  446. package/src/nexus/api/harness-api.ts +2 -1
  447. package/src/output-truncation.ts +41 -12
  448. package/src/project/project-store.ts +48 -1
  449. package/src/pty/snapshot.py +132 -0
  450. package/src/pty-shell/pty-control-ipc.ts +29 -2
  451. package/src/pty-shell/pty-manifest.ts +59 -3
  452. package/src/pty-shell/registry.ts +2 -0
  453. package/src/pty-shell/tui-run-state.ts +80 -3
  454. package/src/release-loop/gate-host-reservation.ts +157 -4
  455. package/src/release-loop/gate-shard-ledger.ts +68 -0
  456. package/src/release-loop/merged-pr-checklist.ts +25 -2
  457. package/src/release-loop/rehearsal-shard-plan.ts +6 -1
  458. package/src/release-loop/rehearsal.ts +27 -0
  459. package/src/release-loop/release-schedule.ts +90 -1
  460. package/src/research/bloom-exemplars.ts +135 -0
  461. package/src/research/edge-decision.ts +124 -15
  462. package/src/research/gap-followup.ts +249 -0
  463. package/src/research/lenses/counter-evidence.ts +100 -0
  464. package/src/research/lenses/working-backwards.ts +89 -0
  465. package/src/research/plugin-discovery.ts +242 -0
  466. package/src/research-bridge/invoke.ts +4 -2
  467. package/src/research-bridge/types.ts +2 -0
  468. package/src/self-dev/ask-launch-flow.ts +73 -131
  469. package/src/self-dev/dev-cli.ts +19 -17
  470. package/src/self-dev/dev-pipeline.ts +8 -4
  471. package/src/self-dev/graph-front-nodes.ts +23 -0
  472. package/src/self-dev/graph-journey-route.ts +10 -2
  473. package/src/self-dev/launch-preflight-text.ts +2 -2
  474. package/src/self-dev/launch-preflight.ts +47 -11
  475. package/src/self-dev/orchestrate-cli.ts +1 -0
  476. package/src/self-dev/orchestrate.ts +15 -0
  477. package/src/self-dev/run-supervisor.ts +204 -3
  478. package/src/self-dev/run-types.ts +3 -0
  479. package/src/self-implement/device-first.ts +8 -2
  480. package/src/self-implement/doctor-visit.ts +76 -58
  481. package/src/self-implement/gate-artifacts.ts +16 -0
  482. package/src/self-implement/gate-baseline.ts +75 -4
  483. package/src/self-implement/gate-cli.ts +368 -30
  484. package/src/self-implement/gate-receipt-registry.ts +180 -0
  485. package/src/self-implement/gate-remote.ts +165 -24
  486. package/src/self-implement/goal-author-clarification.ts +205 -32
  487. package/src/self-implement/goal-author-decompose.ts +24 -15
  488. package/src/self-implement/goal-author.ts +86 -10
  489. package/src/self-implement/graph-stage-units.ts +172 -0
  490. package/src/self-implement/graph-templates.ts +162 -1
  491. package/src/self-implement/graph-variant.ts +37 -4
  492. package/src/self-implement/host-regate.ts +124 -49
  493. package/src/self-implement/impl-findings-feedback.ts +188 -0
  494. package/src/self-implement/knowhow-pack.ts +227 -10
  495. package/src/self-implement/off-diff-evidence.ts +124 -0
  496. package/src/self-implement/orchestrator.ts +320 -28
  497. package/src/self-implement/run-ledger.ts +110 -14
  498. package/src/self-implement/run-stop.ts +33 -2
  499. package/src/self-implement/running-runs.ts +35 -12
  500. package/src/self-implement/seams.ts +6 -3
  501. package/src/self-implement/self-implement-cli.ts +40 -6
  502. package/src/self-implement/stop-autoheal-operational.ts +43 -0
  503. package/src/self-implement/stop-autoheal.ts +15 -6
  504. package/src/session/chat.ts +66 -15
  505. package/src/session/request-size-guard.ts +123 -0
  506. package/src/session-runtime/provider-circuit.ts +140 -0
  507. package/src/shell-runner/file-engine.ts +1 -0
  508. package/src/shell-runner/types.ts +4 -0
  509. package/src/sidetab-core/model.ts +312 -0
  510. package/src/skills/tools/schedule-wakeup.ts +23 -1
  511. package/src/skills/tools/shell.ts +51 -5
  512. package/src/steward/directive-audit.ts +354 -0
  513. package/src/surface/child-process.ts +31 -0
  514. package/src/surface/tui-stderr-owner.ts +48 -0
  515. package/src/task-agent/cover.ts +30 -12
  516. package/src/task-agent/judge.ts +56 -0
  517. package/src/task-agent/parent-host.ts +14 -1
  518. package/src/task-agent/postland-card.ts +35 -2
  519. package/src/task-agent/rejudge-on-head.ts +46 -2
  520. package/src/task-agent/repair-cycle.ts +1 -1
  521. package/src/task-agent/task-hand.ts +133 -25
  522. package/src/task-agent/tier-split.ts +105 -21
  523. package/src/task-orchestrator/surfaces/pod-command-job.ts +330 -2
  524. package/src/task-orchestrator/surfaces/pod-config-snapshot.ts +123 -0
  525. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +70 -2
  526. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +29 -4
  527. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +11 -8
  528. package/src/task-orchestrator/surfaces/pod-si-warm-protocol.ts +1 -1
  529. package/src/task-orchestrator/surfaces/pod-source-receive.ts +74 -6
  530. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +2 -1
  531. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +56 -15
  532. package/src/task-orchestrator/surfaces/self-implement-pod.ts +298 -45
  533. package/src/task-orchestrator/surfaces/self-implement.ts +18 -0
  534. package/src/tool-runtime/skill-exec-runtime.ts +95 -5
  535. package/src/tui/entry.ts +25 -5
  536. package/src/tui/inline-choice.ts +188 -0
  537. package/src/tui/sidetab/list.ts +36 -165
  538. package/src/tui/sidetab/nl-tool.ts +2 -136
  539. package/src/tui/sidetab/peek.ts +52 -0
  540. package/src/tui/slash/term.ts +12 -1
  541. package/src/tui-client/dashboard-session.ts +10 -1
  542. package/src/user-config.ts +45 -9
  543. package/src/ux-sim/classic-tui-seat-scenarios.ts +1 -7
  544. package/src/ux-sim/fake-land-queue.ts +88 -0
  545. package/src/ux-sim/fault-needs-human-reason-repair.ts +107 -0
  546. package/src/ux-sim/fault-pod-child-result.ts +42 -0
  547. package/src/ux-sim/gate-shard-host-reroute.ts +82 -0
  548. package/src/ux-sim/goal-interim-trace.ts +24 -0
  549. package/src/ux-sim/next-tui-seat-scenarios.ts +8 -13
  550. package/src/ux-sim/release-sim-rig.ts +262 -0
  551. package/src/ux-sim/seminar-rehearsal.ts +109 -0
  552. package/src/ux-sim/subagent-tools-device.ts +2 -2
  553. package/src/ux-sim/task-orchestrator-surfaces-self-implement-pod-device.ts +4 -1
  554. package/src/version/packed-revision.json +1 -1
  555. package/src/video-pipeline/recipes/explainer.ts +54 -2
  556. package/src/web-search/grok.ts +32 -6
  557. package/src/web-search/index.ts +8 -7
  558. package/src/workflow-runtime/node-catalog.ts +53 -4
  559. package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +0 -27
  560. package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/1923-5c1695332240246a.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/1938.0e6c60ee91c4d7f5.js +0 -148
  567. package/apps/pwa/out/_next/static/chunks/2104.70e086d5174a4736.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/214.186a430da28338f1.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +0 -93
  571. package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +0 -104
  572. package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +0 -24
  581. package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +0 -36
  583. package/apps/pwa/out/_next/static/chunks/3341-f09b9efbd7a82f70.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +0 -287
  586. package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +0 -94
  592. package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/3f0de3de-2340c532c00395db.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/4199-f7c6eb40cd0322f8.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +0 -32
  604. package/apps/pwa/out/_next/static/chunks/4804.6012b5cd33c22792.js +0 -90
  605. package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +0 -79
  607. package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +0 -74
  610. package/apps/pwa/out/_next/static/chunks/5041-5aada92ca215ffdd.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/5255-1b60d50eabe9f057.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +0 -286
  614. package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +0 -8
  617. package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/7000.28157393caaf5343.js +0 -62
  629. package/apps/pwa/out/_next/static/chunks/7311-60a7ea80d23c7521.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/7488.966b116789f3d41a.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/7524.ce973525d30b3d52.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/7628.6b16863ac3972333.js +0 -34
  636. package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/7954.4f7a8832663ee979.js +0 -115
  639. package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/8509.3a54d4e61893d7cb.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +0 -149
  647. package/apps/pwa/out/_next/static/chunks/9223.cbcc88e0e9950426.js +0 -41
  648. package/apps/pwa/out/_next/static/chunks/9299.24e2a7d9b6d1f91b.js +0 -226
  649. package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +0 -24
  650. package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/9581.da63ddf41acfad46.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +0 -2
  654. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/intake/page-c348a3959c5b5fc6.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d1d1210f99f620ae.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/outputs/page-291ab19fe2acb173.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/page-7f569e533ddeecba.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/app/share/page-a9d9a3e66459c1e0.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/term/page-6b140f77593576eb.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/bb6987f9.3647e1a23b0e3217.js +0 -122
  705. package/apps/pwa/out/_next/static/chunks/framework-4b12a946f352cee2.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.js +0 -1
  711. package/scripts/ratchets/next-tui-entry-budget.ts +0 -124
  712. /package/apps/pwa/out/_next/static/{RrjXTwz-urRAbChP1bX02 → GiOLWmt4MqDZePubBjA4Q}/_ssgManifest.js +0 -0
@@ -20,9 +20,12 @@ 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 {
27
+ /** Managed tool dispatch cancellation signal, forwarded through the pipeline to the active implementation child. */
28
+ signal?: AbortSignal;
26
29
  base?: string;
27
30
  draft?: boolean;
28
31
  openPr?: boolean;
@@ -63,6 +66,12 @@ export interface SelfImplementCliDeps {
63
66
  resolveWantAutoReview?: (flag: boolean) => boolean | Promise<boolean>;
64
67
  /** reroute 실행(테스트 주입). 기본 executeSelfImplementReroute. */
65
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;
66
75
  /** ⭐ 산출물의 «눈» 심(테스트 주입). 기본은 실제 브라우저 검증(`observeDeliverables`).
67
76
  * ⛔ 심이 «없으면» 이 배선을 시험으로 재현할 수 없고, 그러면 「손으로 돌려 봤다」만 남는다
68
77
  * — 그것은 「그때 됐다」이지 「앞으로도 된다」가 아니다(리뷰 #10556 must-fix). */
@@ -122,11 +131,25 @@ export interface SingleRunSuperviseOptions {
122
131
  type SelfImplementResultWithProposalMetadata = SelfImplementResult
123
132
  & Pick<SelfDevJobResult, 'decomposeProposal' | 'goalPlanRevision'>;
124
133
 
125
- 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) : [];
126
148
  return {
127
149
  taskId: r.runId,
128
150
  runId: r.runId,
129
151
  feature,
152
+ ...(targetPaths.length ? { targetPaths } : {}),
130
153
  status: r.ok ? 'done' : 'failed',
131
154
  stage: r.stage,
132
155
  ...(!r.ok && r.detail ? { error: { message: r.detail } } : {}),
@@ -143,6 +166,7 @@ export function singleRunAsJobResult(feature: string, r: SelfImplementResultWith
143
166
  ...(r.abandonedClassification?.classification
144
167
  ? { failureClassification: r.abandonedClassification.classification } : {}),
145
168
  ...(r.decomposeProposal ? { decomposeProposal: r.decomposeProposal } : {}),
169
+ ...(outsideTargetFiles.length > 0 ? { outsideTargetFiles } : {}),
146
170
  ...(r.rework ? { rework: r.rework } : {}),
147
171
  ...(r.review?.reviewed && r.review.mustFix?.length ? { reviewMustFix: r.review.mustFix } : {}),
148
172
  ...(r.goalPlanRevision ? { goalPlanRevision: r.goalPlanRevision } : {}),
@@ -228,8 +252,8 @@ export async function runSelfImplementCliCommand(
228
252
  entry: opts.entry ?? 'external-verbatim', // CLI = 외부 창구(외부가 프롬프트 엔지니어 → verbatim 존중)
229
253
  });
230
254
  spec.entrance = opts.naturalLanguageDispatch ? 'nl-self-implement' : 'cli-self-implement';
231
- const pipelineDeps = opts.approver || opts.progress
232
- ? { ...deps.pipelineDeps, ...(opts.approver ? { approver: opts.approver } : {}), ...(opts.progress ? { progress: opts.progress } : {}) }
255
+ const pipelineDeps = opts.approver || opts.progress || opts.signal
256
+ ? { ...deps.pipelineDeps, ...(opts.approver ? { approver: opts.approver } : {}), ...(opts.progress ? { progress: opts.progress } : {}), ...(opts.signal ? { signal: opts.signal } : {}) }
233
257
  : deps.pipelineDeps;
234
258
  const exec = deps.executeReroute ?? executeSelfImplementReroute;
235
259
  let { result, exitCode } = await exec(spec, pipelineDeps ? { pipelineDeps } : undefined);
@@ -266,10 +290,20 @@ export async function runSelfImplementCliCommand(
266
290
  }
267
291
  : undefined;
268
292
 
269
- 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;
270
300
  await superviseRun({
271
301
  initial: [initialJob],
272
- 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,
273
307
  limits,
274
308
  ...(deliverableEye ? { observeDeliverables: deliverableEye } : {}),
275
309
  ...(opts.supervise.onDecision ? { onDecision: opts.supervise.onDecision } : {}),
@@ -283,7 +317,7 @@ export async function runSelfImplementCliCommand(
283
317
  const next = await exec(repairGoal ? { ...spec, input: { ...spec.input, text: repairGoal } } : spec, pipelineDeps ? { pipelineDeps } : undefined);
284
318
  result = attachGoalPlanRevisionObservation(next.result, deps);
285
319
  exitCode = next.exitCode;
286
- return [{ ...singleRunAsJobResult(feature, result), taskId: initialJob.taskId }];
320
+ return [{ ...singleRunAsJobResult(feature, result, reasonRepairEnabled), taskId: initialJob.taskId }];
287
321
  },
288
322
  });
289
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 {
@@ -17,6 +17,7 @@ import {
17
17
  type SessionMeta, type SerializedMessage, type CreateSessionOpts,
18
18
  } from './index.js';
19
19
  import { debug } from '../debug/log.js';
20
+ import { createRequestSizeGuard, formatRequestSizeStatus, type RequestSizeGuard } from './request-size-guard.js';
20
21
  import type { InputSourceKind } from '../input/input-source-kind.js';
21
22
  import {
22
23
  getProviderForConfig, streamLLMWithTools, type LLMMessage, type LLMOpts, type LLMProvider,
@@ -285,7 +286,8 @@ const childContextComposedSessions = new Set<string>();
285
286
  export async function runTurn(opts: RunTurnOpts): Promise<RunTurnResult> {
286
287
  const loaded = loadSession(opts.sessionId);
287
288
  if (!loaded) throw new Error(`session not found: ${opts.sessionId}`);
288
- const { meta, messages } = loaded;
289
+ const { meta } = loaded;
290
+ let messages = loaded.messages;
289
291
 
290
292
  // Memory injection: build the block once per turn, folded into the
291
293
  // system prompt. Never fails loud — if the store isn't set up, we
@@ -368,6 +370,19 @@ export async function runTurn(opts: RunTurnOpts): Promise<RunTurnResult> {
368
370
  };
369
371
  appendMessage(opts.sessionId, userMsg);
370
372
 
373
+ const explicitTier = opts.llmOpts?.model ? undefined : explicitTurnTier(opts.userConfig, opts.sessionId);
374
+ const llmOpts = explicitTier ? {
375
+ ...(opts.llmOpts ?? {}), model: explicitTier.model,
376
+ ...(explicitTier.reasoningEffort && !opts.llmOpts?.reasoningEffort ? { reasoningEffort: explicitTier.reasoningEffort } : {}),
377
+ } : opts.llmOpts;
378
+ if (explicitTier) {
379
+ debug.log('llm.tier', 'turn-tier-applied', {
380
+ sessionId: opts.sessionId, tier: explicitTier.tier, source: explicitTier.source, model: explicitTier.model,
381
+ reasoningEffort: llmOpts?.reasoningEffort ?? null,
382
+ });
383
+ }
384
+ const provider = opts.provider ?? getProviderForConfig(opts.userConfig, llmOpts?.model);
385
+
371
386
  // 2) Assemble, trim, call. When images are attached for THIS turn,
372
387
  // swap the string content of the latest user message for
373
388
  // ContentBlock[] so the provider adapter sends them multimodally.
@@ -386,18 +401,43 @@ export async function runTurn(opts: RunTurnOpts): Promise<RunTurnResult> {
386
401
  return trimToBudget(wire, opts.maxTokens ?? DEFAULT_TOKEN_BUDGET);
387
402
  };
388
403
 
389
- const explicitTier = opts.llmOpts?.model ? undefined : explicitTurnTier(opts.userConfig, opts.sessionId);
390
- const llmOpts = explicitTier ? {
391
- ...(opts.llmOpts ?? {}), model: explicitTier.model,
392
- ...(explicitTier.reasoningEffort && !opts.llmOpts?.reasoningEffort ? { reasoningEffort: explicitTier.reasoningEffort } : {}),
393
- } : opts.llmOpts;
394
- if (explicitTier) {
395
- debug.log('llm.tier', 'turn-tier-applied', {
396
- sessionId: opts.sessionId, tier: explicitTier.tier, source: explicitTier.source, model: explicitTier.model,
397
- reasoningEffort: llmOpts?.reasoningEffort ?? null,
398
- });
399
- }
400
- const provider = opts.provider ?? getProviderForConfig(opts.userConfig, llmOpts?.model);
404
+ const requestSizeGuard: RequestSizeGuard | undefined =
405
+ meta.source === 'tui' && provider.name === 'openai-codex'
406
+ ? createRequestSizeGuard({
407
+ compactOptions: () => ({
408
+ sessionId: opts.sessionId,
409
+ activeModelId: llmOpts?.model ?? provider.defaultModel,
410
+ preserveLastN: opts.userConfig.chat.autoCompact.preserveLastN,
411
+ archiveEnabled: opts.userConfig.chat.compact.archiveEnabled,
412
+ }),
413
+ // The first request has only the persisted transcript plus this
414
+ // user turn, so use the shared session compactor and rebuild from
415
+ // the rewritten history. Later tool rounds compact their live
416
+ // message list (shared guard) so no just-produced tool context is lost.
417
+ compactFirstRequest: async () => {
418
+ const { compactSessionHistory } = await import('./compact-session.js');
419
+ const result = await compactSessionHistory(opts.sessionId, {
420
+ config: opts.userConfig.chat.autoCompact,
421
+ force: true,
422
+ modelId: llmOpts?.model ?? provider.defaultModel,
423
+ });
424
+ if (!result.fired) return null;
425
+ const refreshed = loadSession(opts.sessionId);
426
+ if (!refreshed) return null;
427
+ // The persisted compacted session includes this turn's
428
+ // user message. Drop that final persisted row here, then
429
+ // assembleTurnMessages re-adds the canonical userMsg and
430
+ // any image blocks from opts.userImages exactly once.
431
+ messages = refreshed.messages.slice(0, -1);
432
+ const rebuilt = assembleTurnMessages(effectiveSystemPrompt).kept;
433
+ return { messages: rebuilt, reason: `session-${result.reason}` };
434
+ },
435
+ onMeasured: (measurement) => {
436
+ opts.onStatusLine?.(formatRequestSizeStatus(measurement));
437
+ },
438
+ })
439
+ : undefined;
440
+
401
441
  let kept: LLMMessage[] = [];
402
442
  let dropped = 0;
403
443
  let used = 0;
@@ -432,6 +472,9 @@ export async function runTurn(opts: RunTurnOpts): Promise<RunTurnResult> {
432
472
  effectiveSystemPrompt = terminal.systemPromptParts.join('\n\n');
433
473
  }
434
474
  const turnLlmOpts = terminal ? terminal.llmOpts : llmOpts;
475
+ const guardedTurnLlmOpts = requestSizeGuard
476
+ ? { ...(turnLlmOpts ?? {}), requestSizeGuard: turnLlmOpts?.requestSizeGuard ?? requestSizeGuard }
477
+ : turnLlmOpts;
435
478
  ({ kept, dropped, used } = assembleTurnMessages(effectiveSystemPrompt));
436
479
  // Durable tool telemetry (추적성) — pair each call's args (onToolCall) with its
437
480
  // result (onToolResult) and persist a role:'tool' message so later "어떤 도구
@@ -471,6 +514,8 @@ export async function runTurn(opts: RunTurnOpts): Promise<RunTurnResult> {
471
514
  userText: opts.userText,
472
515
  messages: kept,
473
516
  tools: turnTools,
517
+ ...(guardedTurnLlmOpts?.requestSizeGuard
518
+ ? { requestSizeGuard: guardedTurnLlmOpts.requestSizeGuard } : {}),
474
519
  dispatchTool: async (name, args, ctx) => dispatchTool(name, args, ctx),
475
520
  signal: opts.signal ?? new AbortController().signal,
476
521
  callbacks: {
@@ -491,6 +536,8 @@ export async function runTurn(opts: RunTurnOpts): Promise<RunTurnResult> {
491
536
  },
492
537
  ...(turnLlmOpts?.model ? { modelOverride: turnLlmOpts.model } : {}),
493
538
  ...(turnLlmOpts?.budgetGrant ? { budgetGrant: turnLlmOpts.budgetGrant } : {}),
539
+ ...(guardedTurnLlmOpts?.requestSizeGuard
540
+ ? { requestSizeGuard: guardedTurnLlmOpts.requestSizeGuard } : {}),
494
541
  };
495
542
  const maxIterations = opts.goalLoopMaxIterations ?? goalLoopCfg?.maxIterations;
496
543
  const gl = await runGoalLoop(coreCtx, maxIterations !== undefined ? { maxIterations } : {});
@@ -513,7 +560,7 @@ export async function runTurn(opts: RunTurnOpts): Promise<RunTurnResult> {
513
560
  },
514
561
  },
515
562
  {
516
- ...(turnLlmOpts ?? {}),
563
+ ...(guardedTurnLlmOpts ?? {}),
517
564
  tools: turnTools,
518
565
  provider,
519
566
  // ★ /cancel 범용화(대표 2026-07-12) — per-turn abort signal 을 tool 루프·llm 호출에 전파.
@@ -527,7 +574,11 @@ export async function runTurn(opts: RunTurnOpts): Promise<RunTurnResult> {
527
574
  }
528
575
  } else {
529
576
  ({ kept, dropped, used } = assembleTurnMessages(effectiveSystemPrompt));
530
- const plainOpts = opts.signal ? { ...(llmOpts ?? {}), signal: opts.signal } : (llmOpts ?? {});
577
+ const plainOpts = {
578
+ ...(llmOpts ?? {}),
579
+ ...(requestSizeGuard ? { requestSizeGuard: llmOpts?.requestSizeGuard ?? requestSizeGuard } : {}),
580
+ ...(opts.signal ? { signal: opts.signal } : {}),
581
+ };
531
582
  const stream = provider.streamChat
532
583
  ? provider.streamChat(kept, plainOpts)
533
584
  : wrapTextOnly(provider.chat(kept, plainOpts));
@@ -0,0 +1,123 @@
1
+ // TUI-TOKEN-GUARD-WIRE — shared request-size guard (#32254 cap).
2
+ //
3
+ // The 400k-char cap used to be built only inside `session/chat.ts runTurn`.
4
+ // The production TUI does not run that function: it goes
5
+ // DashboardSession → bridgeCoreTurnToAcp → runCoreTurn/runGoalLoop, so the
6
+ // guard never reached `llm.ts` and no `request-size-compact` event fired
7
+ // (root cause: seat-state/OP/tmp/TUI-TOKEN-BURN-ROOT-CAUSE-1028.md).
8
+ //
9
+ // This module owns the guard construction so both paths share one policy:
10
+ // - `createRequestSizeGuard` — the `LLMOpts.requestSizeGuard` object.
11
+ // The first measured request may use a caller hook (`compactFirstRequest`)
12
+ // that compacts the caller's *persisted* history; every other request
13
+ // (and a first request whose hook declines) compacts the live message list.
14
+ // - `compactLiveMessages` — the live compaction (Layer 1/2 + optional
15
+ // Layer 3 summarize) shared by the guard and by hosts that compact their
16
+ // own history store.
17
+ // - `estimateRequestChars` — cheap pre-send estimate (JSON chars of the
18
+ // messages plus tool specs) used by the ACP bridge preflight.
19
+ //
20
+ // ⚠️ `llm.ts` applies the compacted list with `messages.splice(...)`, but the
21
+ // array it receives is a per-request copy (`mapProviderToolNamesInMessages`),
22
+ // not `streamLLMWithTools`'s `history`. Compaction therefore does not survive
23
+ // into the next tool round by itself — the guard re-measures each request —
24
+ // and only a host write-back (chat.ts session rewrite / dashboard history
25
+ // replace) makes it survive into the next prompt.
26
+
27
+ import type { LLMMessage, LLMOpts, LLMToolSpec } from '../llm.js';
28
+ import type { CompactProvider } from '../compact/provider.js';
29
+
30
+ /** #32254 — the wire cap for Codex TUI requests (serialized body chars). */
31
+ export const REQUEST_SIZE_MAX_CHARS = 400_000;
32
+
33
+ export type RequestSizeGuard = NonNullable<LLMOpts['requestSizeGuard']>;
34
+ export type RequestSizeMeasurement = Parameters<NonNullable<RequestSizeGuard['onMeasured']>>[0];
35
+ export type RequestSizeCompactInfo = Parameters<RequestSizeGuard['compactMessages']>[1];
36
+ export type RequestSizeCompactResult = Awaited<ReturnType<RequestSizeGuard['compactMessages']>>;
37
+
38
+ type RunCompactPipeline = typeof import('../compact/pipeline.js').runCompactPipeline;
39
+
40
+ export interface CompactLiveMessagesOptions {
41
+ sessionId?: string;
42
+ activeModelId?: string;
43
+ preserveLastN?: number;
44
+ archiveEnabled?: boolean;
45
+ /** Test seam — defaults to the real `runCompactPipeline` with the default compact provider. */
46
+ runCompactPipeline?: RunCompactPipeline;
47
+ }
48
+
49
+ /** Compact a live message list. Returns `null` when no layer changed anything. */
50
+ export async function compactLiveMessages(
51
+ messages: LLMMessage[],
52
+ opts: CompactLiveMessagesOptions,
53
+ ): Promise<{ messages: LLMMessage[]; reason: string } | null> {
54
+ let run = opts.runCompactPipeline;
55
+ let provider: CompactProvider | undefined;
56
+ if (!run) {
57
+ run = (await import('../compact/pipeline.js')).runCompactPipeline;
58
+ provider = (await import('../compact/provider.js')).getDefaultCompactProvider();
59
+ }
60
+ const compacted = await run(messages, {
61
+ ...(opts.sessionId !== undefined ? { sessionId: opts.sessionId } : {}),
62
+ ...(provider !== undefined ? { provider } : {}),
63
+ ...(opts.activeModelId !== undefined ? { activeModelId: opts.activeModelId } : {}),
64
+ policy: {
65
+ ...(opts.preserveLastN !== undefined ? { preserveLastN: opts.preserveLastN } : {}),
66
+ ...(opts.archiveEnabled !== undefined ? { archiveEnabled: opts.archiveEnabled } : {}),
67
+ },
68
+ });
69
+ const diagnostics = compacted.diagnostics;
70
+ const changed = diagnostics.layer1ResponsesTrimmed > 0
71
+ || diagnostics.layer2MicrocompactCleared > 0
72
+ || diagnostics.layer3SummaryApplied === 1
73
+ || diagnostics.layer5FallbackTruncated === 1;
74
+ return changed ? { messages: compacted.messages, reason: 'live-request-compact' } : null;
75
+ }
76
+
77
+ export interface CreateRequestSizeGuardOptions {
78
+ maxChars?: number;
79
+ /** Live-compaction options, resolved lazily at compaction time (config is
80
+ * read only when a request is actually over the cap). */
81
+ compactOptions: () => CompactLiveMessagesOptions;
82
+ /** First measured request only: compact the caller's persisted history and
83
+ * return the rebuilt request. `null` falls through to live compaction. */
84
+ compactFirstRequest?: (
85
+ currentMessages: LLMMessage[],
86
+ info: RequestSizeCompactInfo,
87
+ ) => Promise<RequestSizeCompactResult>;
88
+ onMeasured?: (measurement: RequestSizeMeasurement) => void;
89
+ }
90
+
91
+ export function createRequestSizeGuard(opts: CreateRequestSizeGuardOptions): RequestSizeGuard {
92
+ let measuredProviderRequests = 0;
93
+ return {
94
+ maxChars: opts.maxChars ?? REQUEST_SIZE_MAX_CHARS,
95
+ compactMessages: async (currentMessages, info) => {
96
+ if (measuredProviderRequests === 0 && opts.compactFirstRequest) {
97
+ const first = await opts.compactFirstRequest(currentMessages, info);
98
+ if (first) return first;
99
+ }
100
+ return compactLiveMessages(currentMessages, opts.compactOptions());
101
+ },
102
+ onMeasured: (measurement) => {
103
+ measuredProviderRequests += 1;
104
+ opts.onMeasured?.(measurement);
105
+ },
106
+ };
107
+ }
108
+
109
+ /** Cheap pre-send size estimate: JSON chars of the messages plus tool specs.
110
+ * It tracks the Codex wire body closely (the wire also serializes both). */
111
+ export function estimateRequestChars(messages: readonly LLMMessage[], tools: readonly LLMToolSpec[] = []): number {
112
+ try {
113
+ return JSON.stringify(messages).length + (tools.length > 0 ? JSON.stringify(tools).length : 0);
114
+ } catch {
115
+ return 0;
116
+ }
117
+ }
118
+
119
+ /** One-line status text shared by chat.ts and the ACP bridge. */
120
+ export function formatRequestSizeStatus(measurement: RequestSizeMeasurement): string {
121
+ return `ctx ${measurement.requestChars.toLocaleString()} chars / ${measurement.maxChars.toLocaleString()}`
122
+ + (measurement.compacted ? ` · compact ${measurement.reason}` : '');
123
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * ⚡ SURVIVAL-PROVIDER-CIRCUIT — 공급자별 회로 차단기 (S2)
3
+ * 정본: 내부 문서 `RFC-tui-never-stop-survival-ladder-2026-10-27` §3 S2 · §6 B
4
+ *
5
+ * 턴 «안»의 공급자 전환(src/llm.ts decideProviderFallback → provider-fallback)은
6
+ * 이미 있지만, 턴이 끝나면 «방금 누가 고장 났나»를 잊는다. 다음 턴은 다시
7
+ * 1순위부터 열어 매번 무응답 대기를 먼저 치른다. 이 모듈은 프로세스 안에
8
+ * 공급자별 회로 상태를 남겨 턴을 넘어 건강을 기억한다.
9
+ *
10
+ * ⭐ 사람 의도가 이긴다(src/oauth/fallback-chain.ts 규율 ②) — 회로는 어디까지나
11
+ * 폴백 판정 보조다. opts.provider 로 명시·고정된 턴은 회로를 보지 않는다.
12
+ *
13
+ * 상태기계:
14
+ * closed —(10분 창 안 «전환 사유» 연속 2회 실패)→ open (냉각 5분)
15
+ * open —(냉각 경과)→ half-open
16
+ * half-open —(다음 시도 1회)→ 성공: closed / 실패: open (냉각 2배, 상한 30분)
17
+ *
18
+ * 전환 사유 범주는 `isProviderFallbackEligible` 이 참인 범주
19
+ * (network-transient · rate-limit · overloaded · malformed) ⊕
20
+ * `StreamIdleTimeoutError`(stream-idle-timeout) · `OverloadFailoverError`
21
+ * (overload-failover) 로 한정한다. 그 외 범주(context-window · safety-blocked
22
+ * 등 사용자 탓)는 회로에 기록하지 않는다 — 사용자가 문면을 고치기 전까지
23
+ * 다른 공급자로 도망갈 이유가 없다.
24
+ */
25
+ import { debug } from '../debug/log.js';
26
+ import { isProviderFallbackEligible, type RetryCategory } from './retry-policy.js';
27
+
28
+ export type ProviderCircuitState = 'closed' | 'open' | 'half-open';
29
+
30
+ /** 회로 실패로 세는 «전환 사유» 범주에 추가로 들어가는 두 에러의 범주명. */
31
+ export const CIRCUIT_EXTRA_CATEGORIES = ['stream-idle-timeout', 'overload-failover'] as const;
32
+
33
+ /** 10분 창 — 같은 공급자의 «전환 사유» 실패 2회가 이 창 안에 있어야 열린다. */
34
+ export const CIRCUIT_FAILURE_WINDOW_MS = 10 * 60_000;
35
+ /** 첫 냉각 5분 — 다시 열릴 때마다 2배. */
36
+ export const CIRCUIT_COOLDOWN_BASE_MS = 5 * 60_000;
37
+ export const CIRCUIT_COOLDOWN_MAX_MS = 30 * 60_000;
38
+ export const CIRCUIT_FAILURE_THRESHOLD = 2;
39
+
40
+ interface CircuitEntry {
41
+ /** «전환 사유» 실패 시각(에포크 ms) — 10분 창 밖은 다듬는다. */
42
+ eligibleFailures: number[];
43
+ state: 'closed' | 'open';
44
+ cooldownMs: number;
45
+ openedAt: number;
46
+ }
47
+
48
+ /** 프로세스 안 상태 — 턴을 넘어 살아 있어야 하니 모듈 스코프에 둔다. */
49
+ const circuits = new Map<string, CircuitEntry>();
50
+
51
+ /** 실패 범주가 회로 실패(«전환 사유»)로 세는가 — 순수 판정. */
52
+ export function isCircuitFailureCategory(category: string): boolean {
53
+ if ((CIRCUIT_EXTRA_CATEGORIES as readonly string[]).includes(category)) return true;
54
+ return isProviderFallbackEligible(
55
+ new Error(`circuit:${category}`),
56
+ category as RetryCategory,
57
+ );
58
+ }
59
+
60
+ function entry(name: string): CircuitEntry {
61
+ let entry = circuits.get(name);
62
+ if (!entry) {
63
+ entry = { eligibleFailures: [], state: 'closed', cooldownMs: CIRCUIT_COOLDOWN_BASE_MS, openedAt: 0 };
64
+ circuits.set(name, entry);
65
+ }
66
+ return entry;
67
+ }
68
+
69
+ function logState(
70
+ event: 'circuit-open' | 'circuit-half-open' | 'circuit-closed',
71
+ provider: string,
72
+ failures: number,
73
+ cooldownMs: number,
74
+ ): void {
75
+ debug.log('tui.survival', event, { provider, failures, cooldownMs });
76
+ }
77
+
78
+ /** 회로 차단기에 실패를 기록한다. «전환 사유» 범주만 세며, half-open 시험
79
+ * 실패는 냉각을 2배(상한 30분)로 갈아 open 을 다시 연다. */
80
+ export function recordProviderFailure(name: string, category: string, now: number): void {
81
+ if (!isCircuitFailureCategory(category)) return;
82
+ const e = entry(name);
83
+ if (e.state === 'open' && now >= e.openedAt + e.cooldownMs) {
84
+ // half-open 시험 실패 — 다시 열리고 냉각은 2배(상한 30분).
85
+ e.cooldownMs = Math.min(e.cooldownMs * 2, CIRCUIT_COOLDOWN_MAX_MS);
86
+ e.openedAt = now;
87
+ e.eligibleFailures.push(now);
88
+ logState('circuit-open', name, e.eligibleFailures.length, e.cooldownMs);
89
+ return;
90
+ }
91
+ e.eligibleFailures = e.eligibleFailures.filter((t) => now - t <= CIRCUIT_FAILURE_WINDOW_MS);
92
+ e.eligibleFailures.push(now);
93
+ if (e.state === 'closed' && e.eligibleFailures.length >= CIRCUIT_FAILURE_THRESHOLD) {
94
+ e.state = 'open';
95
+ e.openedAt = now;
96
+ e.cooldownMs = CIRCUIT_COOLDOWN_BASE_MS;
97
+ logState('circuit-open', name, e.eligibleFailures.length, e.cooldownMs);
98
+ }
99
+ }
100
+
101
+ /** 성공 — half-open 이면 closed 로 회복하고, closed 의 실패 이력 창을 정리한다. */
102
+ export function recordProviderSuccess(name: string, now: number): void {
103
+ const e = circuits.get(name);
104
+ if (!e) return;
105
+ if (e.state === 'open' && now >= e.openedAt + e.cooldownMs) {
106
+ e.state = 'closed';
107
+ e.cooldownMs = CIRCUIT_COOLDOWN_BASE_MS;
108
+ e.eligibleFailures = [];
109
+ logState('circuit-closed', name, 0, e.cooldownMs);
110
+ return;
111
+ }
112
+ if (e.eligibleFailures.length > 0) e.eligibleFailures = [];
113
+ }
114
+
115
+ /** 현재 회로 상태 — 주입 시계로만 판정한다. */
116
+ export function circuitState(name: string, now: number): ProviderCircuitState {
117
+ const e = circuits.get(name);
118
+ if (!e || e.state === 'closed') return 'closed';
119
+ return now < e.openedAt + e.cooldownMs ? 'open' : 'half-open';
120
+ }
121
+
122
+ /** 턴의 첫 공급자 후보 — 체인 순서 그대로 첫 `closed`, 없으면 첫 `half-open`,
123
+ * 모두 `open` 이면 `undefined`(호출부가 원래 1순위로 열며 `circuit-all-open` 을 남긴다). */
124
+ export function pickInitialProvider(
125
+ chainNames: readonly string[],
126
+ now: number,
127
+ ): string | undefined {
128
+ let firstHalfOpen: string | undefined;
129
+ for (const name of chainNames) {
130
+ const state = circuitState(name, now);
131
+ if (state === 'closed') return name;
132
+ if (state === 'half-open' && firstHalfOpen === undefined) firstHalfOpen = name;
133
+ }
134
+ return firstHalfOpen;
135
+ }
136
+
137
+ /** 테스트 전용 — 프로세스 안 회로 상태를 리셋한다. */
138
+ export function resetProviderCircuitForTest(): void {
139
+ circuits.clear();
140
+ }
@@ -368,6 +368,7 @@ function buildResult(
368
368
  const aggCapped = capString(agg, meta.maxOutputBytes);
369
369
  const r: ShellResult = {
370
370
  ...(meta.exitCode !== undefined ? { exitCode: meta.exitCode } : {}),
371
+ ...(meta.spawnError !== undefined ? { failureReason: meta.spawnError } : {}),
371
372
  stdout: stdout.toStream(meta.maxOutputBytes),
372
373
  stderr: stderr.toStream(meta.maxOutputBytes),
373
374
  aggregated: aggCapped,
@@ -213,6 +213,10 @@ export interface StreamOutput {
213
213
 
214
214
  export interface ShellResult {
215
215
  exitCode?: number;
216
+ /** Failure detail captured at the execution boundary (for example,
217
+ * the original spawn error). Kept separate from outcome so callers
218
+ * can explain why no process exit status exists. */
219
+ failureReason?: string;
216
220
  stdout: StreamOutput;
217
221
  stderr: StreamOutput;
218
222
  /** Merged (interleaved) stream in spawn order. For File engine