elanous 0.2.29 → 0.2.31

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 (709) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/{cIpv5nU9AycwYWZI9H589 → LSXfY0u9QtfDbejY0Ukf_}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{058a98ba.7eb28d5e6dc03565.js → 0bb0ff36.b8d418980951e5ba.js} +7 -7
  5. package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +27 -0
  8. package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +287 -0
  9. package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +62 -0
  10. package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/{6013-2f769370d8b4c2c6.js → 1335-6731f392c35216eb.js} +3 -3
  12. package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/{8332.6f0f49df772e163b.js → 1654.32de4b324981a188.js} +1 -1
  15. package/apps/pwa/out/_next/static/chunks/1834-50625904996a8fa8.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +149 -0
  17. package/apps/pwa/out/_next/static/chunks/{8795.32573a185af18c7b.js → 1913.7cc6fb6055b1ed3f.js} +2 -2
  18. package/apps/pwa/out/_next/static/chunks/{419.736c0d6f426249a7.js → 2001.6c7e0fd02190886c.js} +1 -1
  19. package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2112-e4efc21a6505d5bc.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{6767.1fcfc9b8be83975f.js → 2213.2ccbada92c33ea0f.js} +16 -16
  24. package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2534.e85ae21ad0dac829.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/{4759.1f76713aefb87db5.js → 2871.0bca6137343b3f76.js} +1 -1
  28. package/apps/pwa/out/_next/static/chunks/{6776.06ff1e3b464cc607.js → 2898.fd781bc7cf01a7b7.js} +1 -1
  29. package/apps/pwa/out/_next/static/chunks/{1782-59db1b5aa06df38a.js → 2940-619bfd8ef337c611.js} +1 -1
  30. package/apps/pwa/out/_next/static/chunks/{8471.8d2a8c74f09c36ff.js → 2985.39ccdecd36848b12.js} +4 -4
  31. package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +115 -0
  32. package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +64 -0
  33. package/apps/pwa/out/_next/static/chunks/{bc324b7c.02a09dd93f6a399b.js → 3267c0e6.d34854e7b3984a6e.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/3278.2e5d15b53a4091c8.js +2 -0
  35. package/apps/pwa/out/_next/static/chunks/{7725-4f83d5541fbdb81b.js → 3541-ce3a5424ed5ad7f1.js} +1 -1
  36. package/apps/pwa/out/_next/static/chunks/3583.a05e88cc8d594628.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3902.e1e71aaac850a045.js +34 -0
  39. package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/{46bd8bea.2f4b4099172fcdb7.js → 409f1e57.d0649fc47691ebfe.js} +1 -1
  41. package/apps/pwa/out/_next/static/chunks/4111.2bfedbb233ad206b.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/{1142.65d002789ab3af7d.js → 4174.92ed04922709ac9e.js} +2 -2
  43. package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +36 -0
  45. package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +286 -0
  49. package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +77 -0
  50. package/apps/pwa/out/_next/static/chunks/4745.67d6f99c245af3f7.js +226 -0
  51. package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4999.c064a4000c2a9e94.js +79 -0
  53. package/apps/pwa/out/_next/static/chunks/5173-233188df2f42c626.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/5304.04d24756f242a094.js +148 -0
  57. package/apps/pwa/out/_next/static/chunks/5307.60f2209e809bd627.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/{3396-97b97928c49190c9.js → 5458-16cd7a2b51b74c8c.js} +1 -1
  60. package/apps/pwa/out/_next/static/chunks/{3403.7199205e65124486.js → 5525.86debf231e181813.js} +1 -1
  61. package/apps/pwa/out/_next/static/chunks/{9143.ff14585db1d275ff.js → 5543.a438b8ab5a13ea47.js} +1 -1
  62. package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +74 -0
  65. package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +94 -0
  67. package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/{8398.73a19b39715eda04.js → 6092.a7f99e68b188ca66.js} +1 -1
  70. package/apps/pwa/out/_next/static/chunks/60fb96c9.360b01d8d4927b7b.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/{5591.a35e7a217734a8b9.js → 6157.0c9af021de4fb31b.js} +2 -2
  72. package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/6323.8672b4817a306928.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/{7375.050ea0d72968e49f.js → 6433.fc573af22bbc9ab7.js} +17 -17
  75. package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6517.4147878ac06d584d.js +90 -0
  77. package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +32 -0
  78. package/apps/pwa/out/_next/static/chunks/6544cb48.a87fe20ddf137be2.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +104 -0
  80. package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/6767.ea607cf0c20a25af.js +24 -0
  85. package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +93 -0
  86. package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7371.80c05c653b08e907.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7391.ebae168025c91b6a.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{1852.7f7b53991fcb99ef.js → 7502.ccd5b8065545edd0.js} +2 -2
  93. package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +8 -0
  94. package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/{6534.1ab00f370db7b105.js → 7862.30a8d6482bb238eb.js} +1 -1
  96. package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/7947-d0759430f8042240.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/{285adb1a.5654e605dddf86d2.js → 7a1887c4.f36b88fba31da8fd.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/8018.a32663f04a6fc5f9.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/8097-92f87bd108322f66.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/9002.e5658224e3dc1b6f.js +24 -0
  109. package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/{1516.dfaceff3fd2d0e0d.js → 9138.b6e80031afb1d973.js} +1 -1
  111. package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/{9907.49be0fcadaf214b5.js → 9221.7d22eaf353a2d4e7.js} +1 -1
  113. package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/{8767-2f6a634f5abeaa01.js → 9279-d28c5b7754d010ae.js} +1 -1
  115. package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/{3160-95c96f4d2a21dd26.js → 9398-6aed28f0a96d0d6f.js} +1 -1
  117. package/apps/pwa/out/_next/static/chunks/9407.e49124dedf0f5e72.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/{328bb3ab-6628a1114fe3fb3b.js → 997ce8a5-2ad501927003b41b.js} +1 -1
  121. package/apps/pwa/out/_next/static/chunks/{6853.cc5174a9dee59593.js → 9989.3694300e5f000b14.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-bf3634a117322df7.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-3535a4a69f1fafaa.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-b9f51447f757fbf2.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-a5635eba0d73b84e.js → page-2ebb8fd59b9461f9.js} +1 -1
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-a2fc4e49a4fa4ba8.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-5a503541353e60a8.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-6025101384e361a5.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-f4b630cc8b5273cd.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-a645f00a06483e9a.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-61ac22cbab1ee4ec.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-e9bab7413b028b28.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-c992eafe028b642e.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-e547e6ce55f1fb33.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-d27e1b9850fd54bf.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-805ac2e137b7a121.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-0fec29c7ba01894b.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-339a07410cd6f36b.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-349f2752d8cd37ad.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-d5c6dcf31c25cecc.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-2fd93ed8c9f16580.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-9b564dbff0fefc35.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-62f4475d3c38fb9b.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/page-814ba51385225776.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-397d479626e5a459.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-af1bba4e3251b728.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3ad3be5e7d3fdce9.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-f219ccdbc0bf27df.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4da93ad35d4a8d28.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-456666766e5ce6fc.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/page-7404e377e8adb8c5.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-14456240ed2a36ad.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-3a658d5fa6d16a25.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-0157de6e85f8bb6b.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-0a07363b130182a1.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-841d73d4ac44ed49.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6f43a3d1146e6377.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/{page-29900ed0011b2c83.js → page-521ee23ac8c0abfa.js} +1 -1
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-a9992ee285efaa83.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-3d48e85fa89ec04f.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-d2ced71132fac9b2.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/page-f08358bdf251adb9.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-233c71cd5f68f0d7.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-70151d78de2f375e.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-dcac33a3e2cb72c0.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/{page-9f92737b8766009a.js → page-149dc1caba411bb9.js} +1 -1
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-0448145ccd5c45c1.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-9cb0c444903da65d.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-17e504c396e0e389.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{425cfc4d.fb91158e3971c39f.js → b313b242.cb1265eea908db61.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +122 -0
  175. package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/ebc7d829.264a0bcb6c750b50.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +1 -0
  183. package/apps/pwa/out/_next/static/css/{72becfd42807b50d.css → 3f5fc6f96e2cf7b2.css} +1 -1
  184. package/apps/pwa/out/approvals/index.html +1 -1
  185. package/apps/pwa/out/approvals/index.txt +23 -23
  186. package/apps/pwa/out/autopilot/index.html +1 -1
  187. package/apps/pwa/out/autopilot/index.txt +23 -23
  188. package/apps/pwa/out/board/index.html +1 -1
  189. package/apps/pwa/out/board/index.txt +23 -23
  190. package/apps/pwa/out/botlab/index.html +1 -1
  191. package/apps/pwa/out/botlab/index.txt +22 -22
  192. package/apps/pwa/out/bots/index.html +1 -1
  193. package/apps/pwa/out/bots/index.txt +22 -22
  194. package/apps/pwa/out/ceo/index.html +1 -1
  195. package/apps/pwa/out/ceo/index.txt +23 -23
  196. package/apps/pwa/out/chat/index.html +1 -1
  197. package/apps/pwa/out/chat/index.txt +22 -22
  198. package/apps/pwa/out/consult/index.html +1 -1
  199. package/apps/pwa/out/consult/index.txt +23 -23
  200. package/apps/pwa/out/control/index.html +1 -1
  201. package/apps/pwa/out/control/index.txt +23 -23
  202. package/apps/pwa/out/decisions/index.html +1 -1
  203. package/apps/pwa/out/decisions/index.txt +22 -22
  204. package/apps/pwa/out/design-check/index.html +1 -1
  205. package/apps/pwa/out/design-check/index.txt +23 -23
  206. package/apps/pwa/out/editor/index.html +1 -1
  207. package/apps/pwa/out/editor/index.txt +23 -23
  208. package/apps/pwa/out/exec/index.html +1 -1
  209. package/apps/pwa/out/exec/index.txt +23 -23
  210. package/apps/pwa/out/field/index.html +1 -1
  211. package/apps/pwa/out/field/index.txt +23 -23
  212. package/apps/pwa/out/healthz +1 -1
  213. package/apps/pwa/out/index.html +1 -1
  214. package/apps/pwa/out/index.txt +22 -22
  215. package/apps/pwa/out/inside/index.html +1 -1
  216. package/apps/pwa/out/inside/index.txt +22 -22
  217. package/apps/pwa/out/intake/index.html +1 -1
  218. package/apps/pwa/out/intake/index.txt +23 -23
  219. package/apps/pwa/out/live/index.html +1 -1
  220. package/apps/pwa/out/live/index.txt +23 -23
  221. package/apps/pwa/out/live-run/index.html +1 -1
  222. package/apps/pwa/out/live-run/index.txt +23 -23
  223. package/apps/pwa/out/loops/index.html +1 -1
  224. package/apps/pwa/out/loops/index.txt +22 -22
  225. package/apps/pwa/out/market/index.html +1 -1
  226. package/apps/pwa/out/market/index.txt +22 -22
  227. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  228. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  229. package/apps/pwa/out/morning/index.html +1 -1
  230. package/apps/pwa/out/morning/index.txt +23 -23
  231. package/apps/pwa/out/observatory/index.html +1 -1
  232. package/apps/pwa/out/observatory/index.txt +23 -23
  233. package/apps/pwa/out/ops/checklist/index.html +1 -1
  234. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  235. package/apps/pwa/out/ops/release/index.html +1 -1
  236. package/apps/pwa/out/ops/release/index.txt +22 -22
  237. package/apps/pwa/out/ops/seats/index.html +1 -1
  238. package/apps/pwa/out/ops/seats/index.txt +22 -22
  239. package/apps/pwa/out/outputs/index.html +1 -1
  240. package/apps/pwa/out/outputs/index.txt +22 -22
  241. package/apps/pwa/out/reflection/index.html +1 -1
  242. package/apps/pwa/out/reflection/index.txt +23 -23
  243. package/apps/pwa/out/scheduler/index.html +1 -1
  244. package/apps/pwa/out/scheduler/index.txt +23 -23
  245. package/apps/pwa/out/sessions/index.html +1 -1
  246. package/apps/pwa/out/sessions/index.txt +22 -22
  247. package/apps/pwa/out/settings/devices/index.html +1 -1
  248. package/apps/pwa/out/settings/devices/index.txt +23 -23
  249. package/apps/pwa/out/settings/index.html +1 -1
  250. package/apps/pwa/out/settings/index.txt +23 -23
  251. package/apps/pwa/out/setup/done/index.html +1 -1
  252. package/apps/pwa/out/setup/done/index.txt +23 -23
  253. package/apps/pwa/out/setup/index.html +1 -1
  254. package/apps/pwa/out/setup/index.txt +23 -23
  255. package/apps/pwa/out/share/index.html +1 -1
  256. package/apps/pwa/out/share/index.txt +23 -23
  257. package/apps/pwa/out/showroom/index.html +1 -1
  258. package/apps/pwa/out/showroom/index.txt +22 -22
  259. package/apps/pwa/out/tasks/index.html +1 -1
  260. package/apps/pwa/out/tasks/index.txt +23 -23
  261. package/apps/pwa/out/term/index.html +1 -1
  262. package/apps/pwa/out/term/index.txt +23 -23
  263. package/apps/pwa/out/today/index.html +1 -1
  264. package/apps/pwa/out/today/index.txt +23 -23
  265. package/apps/pwa/out/trace/index.html +1 -1
  266. package/apps/pwa/out/trace/index.txt +23 -23
  267. package/apps/pwa/out/vault/index.html +1 -1
  268. package/apps/pwa/out/vault/index.txt +23 -23
  269. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  270. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  271. package/apps/pwa/out/workflows/index.html +1 -1
  272. package/apps/pwa/out/workflows/index.txt +23 -23
  273. package/apps/pwa/out/workspace/index.html +1 -1
  274. package/apps/pwa/out/workspace/index.txt +23 -23
  275. package/apps/pwa/out/worktrees/index.html +1 -1
  276. package/apps/pwa/out/worktrees/index.txt +23 -23
  277. package/bin/elanous.mjs +7 -3
  278. package/graphs/context/nightly-condense.yaml +1 -0
  279. package/graphs/intake/intake-daily.yaml +8 -1
  280. package/graphs/intake/recipes.yaml +5 -0
  281. package/graphs/lecture/lecture-note.yaml +2 -2
  282. package/graphs/ops/harness-gc.yaml +1 -0
  283. package/graphs/release/recipes.yaml +3 -0
  284. package/graphs/release/release-loop.yaml +9 -5
  285. package/graphs/units/recipes.yaml +3 -0
  286. package/graphs/units/release-gate-recheck.yaml +15 -0
  287. package/package.json +2 -1
  288. package/scripts/check-native-tool-wiring.ts +3 -2
  289. package/scripts/ci-android-unit-tests.ts +16 -0
  290. package/scripts/ci-typecheck-changed.ts +37 -9
  291. package/scripts/coord-channel-watch.sh +22 -16
  292. package/scripts/coord-role-pack.ts +81 -2
  293. package/scripts/cron-run.ts +96 -3
  294. package/scripts/detect-test-interference.ts +38 -5
  295. package/scripts/gate-pr-cache.ts +65 -0
  296. package/scripts/gh-surface/capture.ts +126 -0
  297. package/scripts/gh-surface/gh +40 -0
  298. package/scripts/import-graph-scc.ts +38 -0
  299. package/scripts/install.ps1 +19 -0
  300. package/scripts/intake-social.ts +181 -0
  301. package/scripts/lecture-note/node.ts +71 -4
  302. package/scripts/lib/android-toolchain.ts +32 -0
  303. package/scripts/lib/deterministic-env.ts +62 -0
  304. package/scripts/lib/gate-test-env.ts +19 -0
  305. package/scripts/measure-goal-grounding-corpus.ts +2 -1
  306. package/scripts/ratchets/test-interference-patterns.allowlist.txt +257 -0
  307. package/scripts/ratchets/test-interference-patterns.ts +367 -0
  308. package/scripts/release-loop/cut-branch.ts +4 -3
  309. package/scripts/release-loop/export-check-node.ts +0 -1
  310. package/scripts/release-loop/fixtures/warm-failure-assertion/sample.junit.xml +8 -0
  311. package/scripts/release-loop/fixtures/warm-job-029/sample.json +1 -0
  312. package/scripts/release-loop/fixtures/warm-job-029/sample.junit.xml +10 -0
  313. package/scripts/release-loop/gate-closure.ts +12 -8
  314. package/scripts/release-loop/gate-diff.ts +1 -1
  315. package/scripts/release-loop/gate-host-mirror.ts +66 -0
  316. package/scripts/release-loop/gate-node.ts +523 -75
  317. package/scripts/release-loop/gate-partial.ts +106 -9
  318. package/scripts/release-loop/gate-pr-cache.ts +66 -0
  319. package/scripts/release-loop/gate-prewarm-plan.ts +66 -0
  320. package/scripts/release-loop/gate-r2-verdict.ts +189 -0
  321. package/scripts/release-loop/gate-recheck-plan-node.ts +52 -0
  322. package/scripts/release-loop/gate-warm-artifacts.ts +253 -0
  323. package/scripts/release-loop/import-graph-scc-run.ts +54 -0
  324. package/scripts/release-loop/import-graph-scc.ts +215 -0
  325. package/scripts/release-loop/node-verdict.ts +2 -0
  326. package/scripts/release-loop/probe-pod-host-dirs-live.ts +113 -0
  327. package/scripts/release-loop/resume-release.ts +33 -4
  328. package/scripts/release-loop/resume.ts +13 -5
  329. package/scripts/release-loop/spawn-lane.ts +2 -19
  330. package/scripts/release-loop/tui-sim-node.ts +3 -2
  331. package/scripts/release-loop/unattended-release.ts +16 -0
  332. package/scripts/test-deterministic.ts +5 -61
  333. package/scripts/train-reach-grouping.ts +48 -0
  334. package/scripts/tsc-incremental-cache.ts +86 -0
  335. package/scripts/tsc-incremental-diagnostics.ts +76 -0
  336. package/scripts/tsc-main-safety-net.ts +2 -2
  337. package/src/acp/client.ts +4 -1
  338. package/src/acp/core-turn-bridge.ts +50 -5
  339. package/src/ad-pipeline/run.ts +4 -2
  340. package/src/agent/runner.ts +169 -3
  341. package/src/agent/subagent-callable.ts +3 -2
  342. package/src/agent-mission/review-loop.ts +6 -3
  343. package/src/agent-substrate/acp-implementer.ts +14 -2
  344. package/src/agent-substrate/pr-reviewer.ts +12 -0
  345. package/src/agent-substrate/self-review-cli.ts +30 -4
  346. package/src/autopilot/pr-manager.ts +62 -7
  347. package/src/briefing/brief-items.ts +24 -22
  348. package/src/capture/tui-self-report.ts +15 -0
  349. package/src/chat/chat-cli.ts +10 -2
  350. package/src/chat/index.ts +77 -11
  351. package/src/chat/input-control-key.ts +5 -3
  352. package/src/chat/tool-interrupt-behavior.ts +38 -0
  353. package/src/chat/tool-render/dispatch.ts +5 -1
  354. package/src/chat/turn-typeahead.ts +75 -20
  355. package/src/cli/__fixtures__/agent-help-before/agent.txt +4 -2
  356. package/src/cli/agent-cli.ts +41 -13
  357. package/src/cli/config-audit.ts +123 -0
  358. package/src/cli/decisions-cli.ts +80 -6
  359. package/src/cli/log-event-names.ts +7 -0
  360. package/src/cli/mcp-login.ts +21 -5
  361. package/src/cli/msg-cli.ts +88 -0
  362. package/src/cli/pr-cli.ts +214 -57
  363. package/src/cli/pr-land-heavy-remote.ts +2 -2
  364. package/src/cli/pr-land-overlap-evidence.ts +63 -9
  365. package/src/cli/pr-land-pod-shadow-job.ts +83 -0
  366. package/src/cli/pr-land-pod-shadow.ts +16 -3
  367. package/src/cli/pr-land-virtual-rebase.ts +108 -0
  368. package/src/cli/release-cli.ts +80 -14
  369. package/src/cli/seat-cli.ts +138 -3
  370. package/src/cli/self-update.ts +5 -2
  371. package/src/cli/tasks-cli.ts +97 -19
  372. package/src/context-bus/context-first.ts +13 -0
  373. package/src/context-bus/context-now.ts +13 -2
  374. package/src/context-bus/ops-events.ts +75 -0
  375. package/src/control-plane/lease-holder.ts +12 -8
  376. package/src/control-plane/ledger.ts +163 -4
  377. package/src/control-plane/server.ts +91 -11
  378. package/src/core-turn/run-core-turn.ts +1 -0
  379. package/src/core-turn/run-goal-loop.ts +222 -3
  380. package/src/core-turn/seat-turn-cap.ts +79 -0
  381. package/src/core-turn/short-question.ts +38 -6
  382. package/src/core-turn/types.ts +3 -0
  383. package/src/dashboard/acp-boot.ts +3 -0
  384. package/src/dashboard/index.ts +224 -615
  385. package/src/dashboard/input/chat-main-entry-runtime.ts +1 -1
  386. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +4 -1
  387. package/src/dashboard/input/chat-main-session.ts +8 -1
  388. package/src/dashboard/input/chat-main-turn.ts +12 -3
  389. package/src/dashboard/input/compact-prepass-recovery.ts +33 -0
  390. package/src/dashboard/input/external-input-host.ts +26 -0
  391. package/src/dashboard/input/internal-turn.ts +261 -0
  392. package/src/dashboard/input/seat-autowake.ts +318 -0
  393. package/src/dashboard/input/turn-steer-bridge.ts +70 -0
  394. package/src/dashboard/loop-scheduler.ts +72 -0
  395. package/src/dashboard/seat-boot-preamble.ts +18 -0
  396. package/src/dashboard/skill-runtime.ts +2 -0
  397. package/src/dashboard/slash-runtime/dashboard-handlers.ts +126 -1181
  398. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -1
  399. package/src/dashboard/slash-runtime/index.ts +13 -0
  400. package/src/dashboard/turn-busy-teardown.ts +50 -0
  401. package/src/decisions/decision-ledger.ts +45 -4
  402. package/src/discord-self-message.ts +4 -4
  403. package/src/domains/release-tool.ts +18 -1
  404. package/src/field-note/transcribe.ts +17 -0
  405. package/src/github/remote-call.ts +81 -0
  406. package/src/goals/registry.ts +46 -6
  407. package/src/goals/types.ts +7 -1
  408. package/src/graph-runner/runner.ts +1 -0
  409. package/src/grok/credential.ts +26 -0
  410. package/src/harness/harness-clean.ts +2 -1
  411. package/src/harness/harness-cli-command.ts +52 -5
  412. package/src/harness/harness-gc.ts +2 -1
  413. package/src/harness/harness-incidents.ts +57 -20
  414. package/src/harness/harness-pod-dispatch.ts +87 -10
  415. package/src/harness/harness-queue.ts +53 -4
  416. package/src/harness/harness-stop.ts +4 -3
  417. package/src/harness/harness-substrate-default.ts +78 -7
  418. package/src/harness/harness-worktree-auto.ts +2 -1
  419. package/src/harness/harness-worktrees.ts +3 -2
  420. package/src/hooks/dispatch.ts +2 -1
  421. package/src/index.ts +152 -25
  422. package/src/input/external-input-queue.ts +33 -1
  423. package/src/intake-plane/slash.ts +14 -3
  424. package/src/keybindings.ts +4 -1
  425. package/src/llm/tool-loop-steered-rejection.ts +33 -0
  426. package/src/llm.ts +138 -19
  427. package/src/loops/consensus.ts +348 -0
  428. package/src/loops/msg-wake.ts +206 -4
  429. package/src/loops/observe.ts +19 -3
  430. package/src/loops/orchestrator/tick.ts +64 -10
  431. package/src/loops/orchestrator/traffic.ts +64 -1
  432. package/src/loops/registry.ts +30 -0
  433. package/src/market/signed-index.ts +14 -0
  434. package/src/mcp/mcp-oauth.ts +54 -5
  435. package/src/models/prompts.ts +28 -0
  436. package/src/msg/msg-sse-client.ts +223 -0
  437. package/src/msg/msg-store.ts +86 -2
  438. package/src/mss/logging/log-store.ts +225 -1
  439. package/src/nexus/DAEMON-THIN-inventory-2026-10-15.md +122 -0
  440. package/src/nexus/api/http-server.ts +54 -15
  441. package/src/nexus/api/loop-resources.ts +19 -3
  442. package/src/nexus/api/ops-api.ts +11 -0
  443. package/src/nexus/daemon-thin-inventory.md +37 -0
  444. package/src/nexus/index.ts +70 -0
  445. package/src/nexus/state/state.ts +1 -0
  446. package/src/oauth/store.ts +32 -7
  447. package/src/onboarding/first-run.ts +28 -3
  448. package/src/ops/overview-cache.ts +16 -4
  449. package/src/ops/resources.ts +82 -0
  450. package/src/plugins/maker/connector-maker.ts +41 -0
  451. package/src/plugins/maker/skill-maker.ts +42 -0
  452. package/src/pr-tool/census.ts +288 -0
  453. package/src/prompt-library/chat-conciseness.ts +13 -0
  454. package/src/prompt-library/universal-preamble.ts +10 -5
  455. package/src/release-loop/gate-host-reservation.ts +97 -0
  456. package/src/release-loop/landing-freeze.ts +5 -0
  457. package/src/release-loop/light-rc.ts +5 -2
  458. package/src/release-loop/placement.ts +92 -1
  459. package/src/release-loop/rehearsal-shard-plan.ts +149 -0
  460. package/src/release-loop/rehearsal.ts +73 -17
  461. package/src/repl/index.ts +20 -2
  462. package/src/seat-loop/seat-knowhow.ts +282 -0
  463. package/src/seat-loop/seat-loop.ts +41 -2
  464. package/src/seat-loop/traffic-signal.ts +3 -0
  465. package/src/self-dev/ask-launch-flow.ts +24 -3
  466. package/src/self-dev/decompose-compose-graph.ts +28 -27
  467. package/src/self-dev/decompose-proposal.ts +53 -38
  468. package/src/self-dev/decompose.ts +17 -0
  469. package/src/self-dev/dev-pipeline.ts +31 -2
  470. package/src/self-dev/draft-residue.ts +24 -9
  471. package/src/self-dev/draft-sweep.ts +59 -4
  472. package/src/self-dev/external-call-zero.ts +77 -0
  473. package/src/self-dev/launch-preflight-text.ts +6 -0
  474. package/src/self-dev/launch-preflight.ts +25 -3
  475. package/src/self-dev/local-supervisor-judge.ts +185 -0
  476. package/src/self-dev/run-supervisor.ts +229 -19
  477. package/src/self-dev/run-types.ts +20 -0
  478. package/src/self-dev/shard-aggregate.ts +13 -2
  479. package/src/self-dev/shard-plan.ts +47 -0
  480. package/src/self-dev/shard-run.ts +112 -10
  481. package/src/self-dev/spawn-lane-files.ts +19 -0
  482. package/src/self-implement/app-api-budget.ts +51 -11
  483. package/src/self-implement/config-gate.ts +2 -1
  484. package/src/self-implement/expose-gate.ts +2 -1
  485. package/src/self-implement/gate-artifacts.ts +405 -0
  486. package/src/self-implement/gate-cli.ts +201 -16
  487. package/src/self-implement/gate-remote.ts +110 -25
  488. package/src/self-implement/gate-scenario.ts +85 -0
  489. package/src/self-implement/goal-author.ts +160 -8
  490. package/src/self-implement/graph-authority.ts +38 -6
  491. package/src/self-implement/graph-overlay-condition.ts +92 -1
  492. package/src/self-implement/heal-triage.ts +79 -0
  493. package/src/self-implement/host-regate.ts +61 -3
  494. package/src/self-implement/orchestrator.ts +14 -123
  495. package/src/self-implement/pr-title.ts +123 -0
  496. package/src/self-implement/run-checkpoint.ts +235 -0
  497. package/src/self-implement/run-ledger.ts +155 -10
  498. package/src/self-implement/run-stop.ts +4 -3
  499. package/src/self-implement/run-ttl.ts +28 -4
  500. package/src/self-implement/seams.ts +2 -0
  501. package/src/self-implement/shadow-stage.ts +7 -6
  502. package/src/self-implement/stop-autoheal.ts +2 -1
  503. package/src/self-implement/train-gate-remote.ts +37 -8
  504. package/src/self-implement/train-reach-grouping.ts +157 -0
  505. package/src/self-implement/train-scenario-layers.ts +133 -0
  506. package/src/self-implement/uncommitted-work.ts +2 -0
  507. package/src/session/pending-input.ts +19 -0
  508. package/src/session/session-start.ts +224 -0
  509. package/src/session-runtime/parallel-dispatch.ts +22 -5
  510. package/src/skills/tools/dev-harness.ts +6 -4
  511. package/src/skills/tools/shell.ts +1 -1
  512. package/src/steward/resync-tick.ts +114 -23
  513. package/src/steward/ta-repair-event-collect.ts +158 -0
  514. package/src/task-agent/card-evidence.ts +25 -1
  515. package/src/task-agent/green-sweep.ts +8 -3
  516. package/src/task-agent/judge.ts +76 -0
  517. package/src/task-agent/land-queue.ts +79 -0
  518. package/src/task-agent/live-moves.ts +30 -9
  519. package/src/task-agent/postland-card.ts +5 -0
  520. package/src/task-agent/prelaunch-already-done.ts +98 -0
  521. package/src/task-agent/real-launch-guard.ts +37 -0
  522. package/src/task-agent/rejudge-on-head.ts +89 -12
  523. package/src/task-agent/remote-rejudge-bind.ts +28 -8
  524. package/src/task-agent/repair-cycle.ts +45 -7
  525. package/src/task-agent/repair-worker.ts +7 -0
  526. package/src/task-agent/run-identity.ts +200 -0
  527. package/src/task-agent/shadow.ts +50 -3
  528. package/src/task-agent/task-hand.ts +158 -5
  529. package/src/task-agent/train-landing.ts +77 -0
  530. package/src/task-agent/work-order.ts +104 -0
  531. package/src/task-orchestrator/surfaces/pod-command-job.ts +88 -28
  532. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +88 -19
  533. package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +2 -1
  534. package/src/task-orchestrator/surfaces/pod-image-source.ts +2 -1
  535. package/src/task-orchestrator/surfaces/pod-install-slots.ts +121 -9
  536. package/src/task-orchestrator/surfaces/pod-lease.ts +20 -6
  537. package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +169 -0
  538. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +27 -0
  539. package/src/task-orchestrator/surfaces/pod-result-marker-wait.ts +33 -0
  540. package/src/task-orchestrator/surfaces/pod-reuse-cleanup.ts +63 -0
  541. package/src/task-orchestrator/surfaces/pod-source-receive.ts +19 -3
  542. package/src/task-orchestrator/surfaces/pod-warm-switch.ts +141 -0
  543. package/src/task-orchestrator/surfaces/pod-warm-ta-shadow.ts +85 -0
  544. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +153 -0
  545. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +208 -0
  546. package/src/task-orchestrator/surfaces/self-implement-pod.ts +132 -15
  547. package/src/telegram.ts +2 -4
  548. package/src/tui/input/pickers.ts +732 -0
  549. package/src/tui/slash/mission.ts +492 -0
  550. package/src/tui/slash/term.ts +877 -0
  551. package/src/tui-client/dashboard-session.ts +9 -0
  552. package/src/tui.ts +48 -0
  553. package/src/user-config/gemini-server-tools.ts +9 -0
  554. package/src/user-config.ts +53 -16
  555. package/src/util/spawn-sync-output.ts +7 -0
  556. package/src/ux-sim/fake-bin.ts +154 -0
  557. package/src/ux-sim/fake-clock.ts +36 -0
  558. package/src/ux-sim/headless-tui.ts +72 -0
  559. package/src/ux-sim/in-process-cli.ts +2 -1
  560. package/src/ux-sim/temp-git-remote.ts +82 -0
  561. package/src/version/packed-revision.json +1 -1
  562. package/src/video-pipeline/recipes/vlog.ts +25 -7
  563. package/apps/pwa/out/_next/static/chunks/1015-9cba22a5a4554797.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/1084-4e66af7376a18db7.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/1106.3a6410b7b0c70ad4.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/1127.32fc642f70423506.js +0 -8
  567. package/apps/pwa/out/_next/static/chunks/1189-d9b8e1995a831fae.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/1224.6da98c7ad0eb7dd8.js +0 -34
  569. package/apps/pwa/out/_next/static/chunks/1370.4e3e2558f111fd5d.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/1514-b7da377fdc4eb17a.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/1577.3c24c32584e10d70.js +0 -286
  572. package/apps/pwa/out/_next/static/chunks/161.130a569855c4d68c.js +0 -24
  573. package/apps/pwa/out/_next/static/chunks/1864.16da9556e78a9236.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/1b6f6b2a.aff090122be3726e.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/2341.e8a9135e5b910dd5.js +0 -36
  576. package/apps/pwa/out/_next/static/chunks/257.10afdbe3520f2fc2.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/2658.87550e692dc493f6.js +0 -64
  578. package/apps/pwa/out/_next/static/chunks/2673.85e2f02efae7a85f.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/2766-bee623b37472ed63.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/2794.6d836872b0bf43e2.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/2806.eb57ced1a528ed39.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/283.7a121c4910e6dad7.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/2870.1dc29aa5fc01f09f.js +0 -115
  584. package/apps/pwa/out/_next/static/chunks/293.fd38e77ce5d48103.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/2993-5952a1cd3fd5d441.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/32-a523427c5bd5ed00.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/3280.af38002a6424a905.js +0 -90
  588. package/apps/pwa/out/_next/static/chunks/3292-5ddffdb2f517b44f.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/3523.d3231daaf7aba993.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/3763.577de3181e1e6ea0.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/4138-cc56b0938ef72783.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/4255-8350c43d307a8875.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/4352.a4954693499c2714.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/4421-f2dcbc6fd80ec013.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/4513-51b94aeee37c9905.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/4928-c3b72f99aa588699.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/4986-f9fc0283fb325219.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/5014.671a7b9f69c2b7b1.js +0 -94
  599. package/apps/pwa/out/_next/static/chunks/5137.d398e24710b3feb6.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/5298.0bea74885cabe754.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/5315.74c53a39739b11c4.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/5317-8b1df8d02105cd07.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/5358-33051f41a2b239af.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/5388.a2ec02501f714ad5.js +0 -62
  605. package/apps/pwa/out/_next/static/chunks/5395.e6ac948a2d15058d.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/5409-f282bf533c151849.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/5466.d0f4aba9d52acfa8.js +0 -27
  608. package/apps/pwa/out/_next/static/chunks/5564.3d28b353470fe305.js +0 -104
  609. package/apps/pwa/out/_next/static/chunks/569.b0cbfb4dee4a167a.js +0 -93
  610. package/apps/pwa/out/_next/static/chunks/5835-72465b73a8bb8d74.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/5941.045d6093139e1f7a.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/6228.47cabb83564dfe54.js +0 -24
  613. package/apps/pwa/out/_next/static/chunks/6457-8d1993002a87d0fe.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/6513.ef54cfae52351982.js +0 -2
  615. package/apps/pwa/out/_next/static/chunks/6582.13d245bf87df69f1.js +0 -148
  616. package/apps/pwa/out/_next/static/chunks/6655.c33f6acc2c61bb89.js +0 -149
  617. package/apps/pwa/out/_next/static/chunks/6731-9d7195af289c8d4c.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/6733.0be05b1db9279fc5.js +0 -79
  619. package/apps/pwa/out/_next/static/chunks/6742-90937146253a8b9e.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/687-816858f77a396a4e.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/6888.72c7b8cfb02a7e61.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/6993.c17c828ac3ef3253.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/7076.9f27ef666b0cefdd.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/7113.1403c5d451804e8c.js +0 -287
  625. package/apps/pwa/out/_next/static/chunks/7169.9dd603c726c2cd7c.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/7247-e3ec21f761f86710.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/7261-a47b72f96f5199df.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/7335-5cda81ac90310077.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/7356-c2e4af090546e2d4.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/738-59518742078fda71.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/7385.a7375f10db73243a.js +0 -77
  632. package/apps/pwa/out/_next/static/chunks/7445.cf1cf2fe109bcd96.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/7505.a2057432ab6ef99a.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/7515.31f45fac1f9c70cb.js +0 -74
  635. package/apps/pwa/out/_next/static/chunks/7658-d4ce8c72a9548a91.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/8107-0b1ae46bc5bcb788.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/8132.bfea2f016ce8d992.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/8672.e299832bc7d18ee2.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/8735.f1ef798a5f260f6f.js +0 -226
  640. package/apps/pwa/out/_next/static/chunks/8774-88f67f7d8d53d299.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/8782.252e5a405d86e4ed.js +0 -32
  642. package/apps/pwa/out/_next/static/chunks/909-9ed7aa0dba804316.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/9100.22b0301256827007.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/9140-dde77575570bc71e.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/9292-a7ad9a01c7044b93.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/9517.00627dc51b02821c.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/9725.dcbb585652d8e9c5.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/9761.a3ebf5c389c24ddc.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/9972.834d2b2b7d48f1ed.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/9995-1a90486f5ae01546.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/a435ad95.577add051b4facb2.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-83372d8b5863ebf7.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d69256d7613c140a.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-352c5e9ba3f9b858.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/board/page-69f1d725524201a8.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/bots/page-ad9181d84285e4ea.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/ceo/page-86feb08080261a2f.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/chat/page-ffa15987e4756d03.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/consult/page-11a3ab44ac327cc1.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/control/page-6309b11c4264d24d.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/decisions/page-8800472079612e87.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/design-check/page-d387bf3f2301882a.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/editor/page-048f88d8c8658da6.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/exec/page-6c14f9739b7f6880.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/field/page-2834f44f64e98d74.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/healthz/route-83372d8b5863ebf7.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/inside/page-a13df6f88e824887.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/intake/page-8a4397248754cf2b.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/layout-daf0bd329360a336.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/live/page-f7ef1c28764cb476.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/live-run/page-61e74f28b9353dac.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/loops/page-8aaa6dedc4c10dfb.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/market/page-294602ba649be829.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-5fa5f41ed3fce323.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/morning/page-33bf667a5fb297bf.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/not-found-5ae3cbd6e5dba515.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/observatory/page-eb867d16ad6fdede.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1ab789fa68682f7e.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-6fd41b5b6ff13a71.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fb3d5f7642c99fba.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/app/outputs/page-70f705b2b5ed42ca.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/page-c9c93b358a7667b5.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/reflection/page-1563c556b81c96ed.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-ce89c20c45b3a673.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/sessions/page-423ae63d786f4ee9.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-591a5378a4c4447c.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/app/settings/page-a250496b19a5824b.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-c36a9277febc5911.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/app/setup/layout-83372d8b5863ebf7.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/app/share/page-a5de57edc6d7f942.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/app/showroom/page-16bdd4c9f40498df.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/app/tasks/page-75e946e6e71cc6d8.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/app/term/page-9eb56166774eb256.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/app/today/page-1c5f9ef35dbb22c5.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/trace/page-657ff9985e508498.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/vault/page-22dc72499da68fb2.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/workflows/page-094ad334e40f8169.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/workspace/page-8bcd379852ff6287.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-6b04413f280cd344.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/de70ab42-d28d47437208d458.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/f800c5e3.46dbd7f2af8c3fce.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/f8bc19ad.47579f6d684b0760.js +0 -122
  703. package/apps/pwa/out/_next/static/chunks/framework-ca9ac4609fb9fed8.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/main-app-0dd08d32d15a030f.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/main-f0399d33955c4e01.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/pages/_app-d42caca6f8ac2211.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/pages/_error-42e713c13aa41ca8.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/webpack-8fbf8f61a377aa16.js +0 -1
  709. /package/apps/pwa/out/_next/static/{cIpv5nU9AycwYWZI9H589 → LSXfY0u9QtfDbejY0Ukf_}/_ssgManifest.js +0 -0
@@ -6,7 +6,7 @@
6
6
  * TA-REVIEW-RESULT-CAPTURE — 자식 stdout(`--json`)은 결과 파일로 받고, 자식 완료 뒤 해당 카드만 회수·재판정한다.
7
7
  * 회수한 pass 는 그 틱의 판단부·land 관문 입력(`selfReview`)이 될 뿐 land 판정 로직은 그대로다.
8
8
  * - `propose-green`: 카드에 green «제안»(`greenProposal`)만 적는다 — 체크리스트는 손대지 않는다.
9
- * - `propose-land`: 카드·현재 머리의 self review 통과(pass «또는» warn ⊕ must-fix 0 · TA-LAND-WARN-MUSTFIX0)·non-draft 를 확인하고 기존 `pr land` 를 머리 고정으로 한 번 부른다.
9
+ * - `propose-land`: 카드·현재 머리의 self review 통과(pass «또는» warn ⊕ must-fix 0 · TA-LAND-WARN-MUSTFIX0)·non-draft 를 확인한다. 큐 설정이 있으면 원격 changed gate 뒤 착지 줄에 등록하고, 없으면 기존 `pr land` 를 머리 고정으로 한 번 부른다.
10
10
  * - 사다리 R4: `narrow-relaunch` · `wait-retry` · `salvage-relaunch` · `alternative` 도 허용 목록 어휘다 — 실제 발사는 실행부
11
11
  * `executeNextAction`(`actions.ts`)이 «목록 ⊕ 같은 수 2회 상한 ⊕ 회당 1건 ⊕ 부하 관문»을 모두 넘을 때만 한다.
12
12
  * - `decision-card`: 막힌 과제를 «근거(서명 · 화면 · must-fix)» 붙은 결정 카드로 올린다 — 근거가 하나도 없으면 카드를 올리지 않는다.
@@ -28,6 +28,7 @@ import { decisionCardGrounds, decisionRaiseArgs, type DecisionCardEvidence, type
28
28
  import { pendingReviewResults, reviewResultPath, TA_REVIEW_COMPLETION_CARD_ENV, TA_REVIEW_COMPLETION_RESULT_ENV, TA_REVIEW_COMPLETION_STATE_ENV } from './review-result-capture.js';
29
29
  import { buildPriorFixContext, PRIOR_FIX_SCOPE_LINE, priorFixBlock, priorFixObservation, type PriorDiffReader, type PriorFixContext } from './review-prior-fix.js';
30
30
  import { createLandWorktree, localBranch, localHead, observeLandWorktree, type LandWorktree, type LandWorktreeFailure, type LandWorktreeInput, type LandWorktreeRemoval } from './land-worktree.js';
31
+ import { runQueuedLanding, type QueueLandingInput } from './land-queue.js';
31
32
 
32
33
  export const TASK_AGENT_LIVE_MOVES = ['review', 'propose-green', 'propose-land', 'decision-card', ...LIVE_RETRY_MOVES] as const;
33
34
  export type TaskAgentLiveMove = typeof TASK_AGENT_LIVE_MOVES[number];
@@ -90,6 +91,9 @@ export interface LiveMoveDeps {
90
91
  log?: (category: string, event: string, data: Record<string, unknown>) => void;
91
92
  /** TA-LAND-WORKTREE — cwd HEAD 읽기 · PR 머리 임시 워크트리 만들기(시험 주입 · 기본 = git). */
92
93
  landWorktree?: { localHead?: (cwd: string) => string | null; localBranch?: (cwd: string) => string | null; create?: (input: LandWorktreeInput) => Promise<LandWorktree | LandWorktreeFailure> };
94
+ /** TA-LAND-AFTER-REVIEW — injected queue adapter; absent uses configured command after a remote changed gate. */
95
+ queueLanding?: (input: QueueLandingInput) => Promise<{ status: number; stdout: string; stderr?: string }>;
96
+ landQueueConfig?: { command: string; remote: string } | null;
93
97
  }
94
98
 
95
99
  /** `executed` = 부작용을 실제로 냈다(리뷰를 띄웠다 · 제안을 적었다). ok 이지만 이미 한 수(같은 머리·이미 제안)면 false. */
@@ -101,6 +105,8 @@ export interface LiveMoveResult {
101
105
  resultPath?: string;
102
106
  /** TA-LAND-RETRY-ON-INFRA — 실행한 land 의 그 머리 몇 번째 시도인가 · 실패면 갈래(infra|judgement|base-stale)·사유·재시도 가능 여부. */
103
107
  landAttempt?: { attempt: number; class?: LandFailureClass; reason?: string; retryAllowed?: boolean };
108
+ /** A queue accepted this head. Merge confirmation belongs to the later train receipt. */
109
+ queued?: boolean;
104
110
  }
105
111
 
106
112
  export interface PrHeadView { head: string; state: string; branch?: string; url?: string }
@@ -543,10 +549,11 @@ export const LAND_RETRY_ON_INFRA_EVENT = 'land-retry-on-infra';
543
549
 
544
550
  const landedCycles = new Set<string>();
545
551
 
546
- /** `propose-land` — only a passing self review (pass or warn, with must-fix 0) of this exact OPEN, non-draft head may invoke pr land. */
552
+ /** `propose-land` — only a passing self review (pass or warn, with must-fix 0) of this exact OPEN, non-draft head may enqueue or invoke pr land. */
547
553
  export async function executeLiveLand(
548
554
  card: TaskCard | undefined, pr: number | undefined,
549
555
  ctx: { runId?: string | null; cycleId?: string; cwd?: string; produced?: { headCommit?: string; branch?: string; prUrl?: string }; review?: { verdict: 'pass' | 'warn' | 'fail'; head: string; /** TA-LAND-WARN-MUSTFIX0 — `false` 면 리뷰가 실제로 안 돌았다 → land 거부. 슈퍼바이저 입력은 reviewed 리뷰로만 만들어져 칸이 없다. */ reviewed?: boolean };
556
+ /** Exact bytes consumed by the queue's own review check; no path means queue mode cannot proceed. */ reviewResultPath?: string;
550
557
  /** TA-REJUDGE-ON-HEAD — 겹침 증거 파일(있으면 land 에 넘길 뿐 · 판정은 그대로). */ overlapEvidence?: string;
551
558
  /** REJUDGE base-stale — 증거의 재게이트를 요청한 시각 · 그 앞의 base-stale 시도는 소비됨(`openLandAttempts`). */ gateAt?: string },
552
559
  deps: LiveMoveDeps = {},
@@ -584,6 +591,10 @@ export async function executeLiveLand(
584
591
  const mustFixCount = (ctx.review as { mustFixCount?: unknown }).mustFixCount;
585
592
  if (typeof mustFixCount !== 'number' || !Number.isSafeInteger(mustFixCount) || mustFixCount < 0) return reject(card.id, `PR #${pr} review-must-fix-unknown`, reviewRepo);
586
593
  if (mustFixCount > 0) return reject(card.id, `PR #${pr} review-warn-with-must-fix: pass carries ${mustFixCount} must-fix`, reviewRepo);
594
+ const queueConfig = deps.landQueueConfig === undefined ? getUserConfig().taskAgent?.landQueue : deps.landQueueConfig;
595
+ if (queueConfig && (!isAbsolute(queueConfig.command) || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(queueConfig.remote)))
596
+ return reject(card.id, `PR #${pr} land queue command/remote invalid`, reviewRepo);
597
+ if (queueConfig && !ctx.reviewResultPath) return reject(card.id, `PR #${pr} queue review result path missing`, reviewRepo);
587
598
  const cycle = ctx.cycleId ?? ctx.runId;
588
599
  if (cycle && landedCycles.has(cycle)) return reject(card.id, `cycle ${cycle} already landed — stays shadow`, reviewRepo);
589
600
  const path = deps.statePath ?? taskAgentStatePath();
@@ -695,11 +706,16 @@ export async function executeLiveLand(
695
706
  let failure: LandFailureClassification | undefined;
696
707
  try {
697
708
  // The CLI rechecks the pinned PR/head immediately before merge, after its own gates and freeze admission.
698
- const outcome = overlapEvidence
699
- ? await (deps.land ?? defaultLand)(pr, view.head, landCwd, { overlapEvidence })
700
- : await (deps.land ?? defaultLand)(pr, view.head, landCwd);
709
+ const outcome = queueConfig
710
+ ? await (deps.queueLanding ?? runQueuedLanding)({ card: card.id, pr, head: view.head, cwd: landCwd, statePath: path,
711
+ reviewResult: ctx.reviewResultPath!, command: queueConfig.command, remote: queueConfig.remote,
712
+ entry: (await import('../cli/tasks-cli.js')).ELANOUS_CLI_ENTRY,
713
+ configDir: (await import('../elanous-config-dir.js')).getElanousConfigDirOverride() ?? (await import('../instance/resolve.js')).effectiveInstanceRoot() })
714
+ : overlapEvidence
715
+ ? await (deps.land ?? defaultLand)(pr, view.head, landCwd, { overlapEvidence })
716
+ : await (deps.land ?? defaultLand)(pr, view.head, landCwd);
701
717
  ok = outcome.status === 0;
702
- detail = (ok ? outcome.stdout || `land merged #${pr} head ${view.head.slice(0, 12)}` : outcome.stderr || outcome.stdout || `exit ${outcome.status}`).slice(-300);
718
+ detail = (ok ? outcome.stdout || `${queueConfig ? 'queued' : 'land merged'} #${pr} head ${view.head.slice(0, 12)}` : outcome.stderr || outcome.stdout || `exit ${outcome.status}`).slice(-300);
703
719
  if (!ok) failure = classifyLandFailure(outcome);
704
720
  } catch (error) {
705
721
  detail = (error instanceof Error ? error.message : String(error)).slice(-300);
@@ -708,8 +724,13 @@ export async function executeLiveLand(
708
724
  const retryAllowed = failure?.class === 'infra' && attempt < LAND_ATTEMPTS_PER_HEAD_ON_INFRA;
709
725
  // 인프라 실패로 재시도가 남으면 주기 표시도 푼다 — 같은 주기 id(재판정 틱의 `rejudge:<card>:<head>`)가 그 한 번을 막지 않게.
710
726
  if (retryAllowed && cycle) landedCycles.delete(cycle);
711
- if (worktree) {
712
- // 성공이든 실패든 걷는다.
727
+ if (worktree && queueConfig && ok) {
728
+ // The queue row pins this exact path until the train consumes it. Removing it here
729
+ // would turn a successful enqueue into a guaranteed missing-tree landing failure.
730
+ observeLandWorktree({ card: card.id, pr, head: view.head, created: worktree.created ?? null,
731
+ removed: false, reason: 'queued — train owns this exact-head worktree until its receipt' }, deps.log);
732
+ } else if (worktree) {
733
+ // Direct land and rejected queue attempts no longer need the temporary checkout.
713
734
  let removal: LandWorktreeRemoval;
714
735
  try { removal = worktree.cleanup(); } catch (error) { removal = { removed: false, reason: String(error).slice(-200) }; }
715
736
  observeLandWorktree({ card: card.id, pr, head: view.head, created: worktree.created ?? null, removed: removal.removed, ...(removal.branchRemoved !== undefined ? { branchRemoved: removal.branchRemoved } : {}),
@@ -746,7 +767,7 @@ export async function executeLiveLand(
746
767
  return observe(deps, withRepo({ kind, card: card.id, ok: false, executed: true, landAttempt,
747
768
  detail: `land ${ok ? 'succeeded' : 'failed'} but card update failed: ${String(error).slice(-230)}` }));
748
769
  }
749
- return observe(deps, withRepo({ kind, card: card.id, ok, executed: true, detail, landAttempt }));
770
+ return observe(deps, withRepo({ kind, card: card.id, ok, executed: true, detail, landAttempt, ...(queueConfig && ok ? { queued: true } : {}) }));
750
771
  }
751
772
 
752
773
  /** `propose-green` — 비지 않은 근거가 있을 때만 카드에 제안을 적는다(한 번). 체크리스트는 쓰지 않는다. */
@@ -2,6 +2,7 @@ import { debug } from '../debug/log.js';
2
2
  import { listChecklist, setItemIfSnapshot, type Checklist } from '../release-loop/checklist.js';
3
3
  import { judgeLandedCell, parseJudgeSignals, type GreenVerdict } from '../release-loop/landed-to-green.js';
4
4
  import { cardPrNumber, readTaskAgentState, taskAgentStatePath, updateTaskCard, type TaskCard } from './task-hand.js';
5
+ import { isGoalOnlyPr } from './judge.js';
5
6
 
6
7
  export interface LandedTaskPr { number: number; url: string; headRefOid: string; state: string; baseRefName: string; mergedAt: string; files?: Array<{ path: string }> }
7
8
  export interface PostlandDeps {
@@ -32,6 +33,10 @@ export function candidateMergedTaskCells(number: number, statePath = taskAgentSt
32
33
  export function closeMergedTaskCard(pr: LandedTaskPr, cwd: string, deps: PostlandDeps): string | null {
33
34
  const log = deps.log ?? debug.log.bind(debug);
34
35
  if (pr.state !== 'MERGED' || pr.baseRefName !== 'main' || !/^[a-f0-9]{40}$/i.test(pr.headRefOid) || !pr.url) return null;
36
+ if (isGoalOnlyPr(pr.files?.map((file) => file.path))) {
37
+ log('task-agent', 'postland-card-skipped', { pr: pr.number, reason: 'goal-only-pr', targetDiff: 0 });
38
+ return null;
39
+ }
35
40
  const path = deps.statePath ?? taskAgentStatePath();
36
41
  const tasks = readTaskAgentState<{ tasks?: Record<string, TaskCard> }>(path).tasks ?? {};
37
42
  const cards = Object.values(tasks).filter((card) => card.taLand && card.checklistId && cardPrNumber(card) === pr.number
@@ -0,0 +1,98 @@
1
+ /** TA-PRELAUNCH-ALREADY-DONE: bounded evidence against a pinned, detached main tree. */
2
+ import { spawnSync } from 'node:child_process';
3
+ import { realpathSync } from 'node:fs';
4
+ import { isAbsolute } from 'node:path';
5
+ import { inspectGoalDoneBoundary } from '../self-implement/goal-author.js';
6
+
7
+ export interface AlreadyDoneCandidate { mainSha: string; repository: string; command: string; exitCode: 0 }
8
+ export interface AlreadyDoneDecision { candidate?: AlreadyDoneCandidate; reason: string }
9
+
10
+ type SafeCommand = { argv: string[]; path: string };
11
+ const SHA = /^[0-9a-f]{40}$/i;
12
+ const SAFE_PATH = /^[A-Za-z0-9_./-]+$/;
13
+
14
+ /** A lexical command declaration is not authority to run shell or project scripts. */
15
+ export function parseAlreadyDoneCommand(command: string): SafeCommand | null {
16
+ let input = command.trim();
17
+ while (input.length >= 2 && ((input.startsWith('`') && input.endsWith('`'))
18
+ || (input.startsWith('"') && input.endsWith('"')) || (input.startsWith("'") && input.endsWith("'"))))
19
+ input = input.slice(1, -1).trim();
20
+ if (!input || /[\n\r\t`$;&|<>\\'"*?()[\]{}!]/.test(input)) return null;
21
+ const argv = input.split(/ +/);
22
+ let path: string | undefined;
23
+ if (argv.length === 3 && argv[0] === 'test' && ['-f', '-e'].includes(argv[1]!)) path = argv[2];
24
+ else if (argv.length === 5 && argv[0] === 'git' && argv[1] === 'ls-files' && argv[2] === '--error-unmatch' && argv[3] === '--') path = argv[4];
25
+ else if (argv.length === 7 && argv[0] === 'git' && argv[1] === 'diff' && argv[2] === '--quiet'
26
+ && SHA.test(argv[3]!) && argv[4] === 'HEAD' && argv[5] === '--') path = argv[6];
27
+ if (!path || !SAFE_PATH.test(path) || isAbsolute(path) || path.startsWith('-')
28
+ || path.split('/').some((part) => part === '..' || part === '.' || !part)) return null;
29
+ return { argv, path };
30
+ }
31
+
32
+ export type PinnedGitResult = { status: number | null; stdout: string; error: boolean };
33
+ export type PrelaunchGitRunnerForTest = (cwd: string, argv: string[], timeout?: number) => PinnedGitResult;
34
+
35
+ export function runPinnedGit(cwd: string, argv: string[], timeout = 4_000, input?: string): PinnedGitResult {
36
+ // Trust boundary: the operator's own repository and Git config. Drop inherited GIT_* overrides,
37
+ // disable replace refs, hooks, and credential helpers; remote transport uses the operator's SSH config.
38
+ const env = { ...process.env };
39
+ for (const key of Object.keys(env)) if (key.startsWith('GIT_')) delete env[key];
40
+ const result = spawnSync('git', ['--no-replace-objects', '-c', 'core.hooksPath=/dev/null', '-c', 'credential.helper=', ...argv],
41
+ { cwd, env, encoding: 'utf8', timeout, maxBuffer: 64 * 1024, ...(input !== undefined ? { input } : {}) });
42
+ return { status: result.status, stdout: result.stdout ?? '', error: !!result.error };
43
+ }
44
+
45
+ function evaluatePinnedTree(root: string, sha: string, safe: SafeCommand, runGit: PrelaunchGitRunnerForTest): AlreadyDoneDecision {
46
+ const { argv, path } = safe;
47
+ // Every supported command names one tracked regular file in the pinned tree.
48
+ // A symlink's filesystem -e/-f meaning is not inferable from its Git object.
49
+ const entry = runGit(root, ['ls-tree', sha, '--', path]);
50
+ if (entry.status !== 0 || entry.error) return { reason: 'evidence-unmeasured' };
51
+ const match = /^(100644|100755|040000|120000) (blob|tree) [0-9a-f]{40}\t(.+)$/m.exec(entry.stdout);
52
+ if (!match || match[3] !== path) return { reason: 'evidence-not-passing' };
53
+ if (match[1] === '120000') return { reason: 'evidence-symlink-unmeasured' };
54
+ if (!['100644', '100755'].includes(match[1]!) || match[2] !== 'blob') return { reason: 'evidence-path-not-tracked-file' };
55
+ if (argv[0] === 'git' && argv[1] === 'diff') {
56
+ const base = argv[3]!;
57
+ if (base.toLowerCase() === sha.toLowerCase()) return { reason: 'diff-compares-main-to-itself' };
58
+ const ancestor = runGit(root, ['merge-base', '--is-ancestor', base, sha]);
59
+ if (ancestor.status !== 0) return { reason: 'diff-base-unverified' };
60
+ const diff = runGit(root, ['diff', '--no-ext-diff', '--no-textconv', '--quiet', base, sha, '--', path]);
61
+ return { reason: diff.status === 0 ? 'evidence-passed-on-main' : diff.status === 1 && !diff.error ? 'evidence-not-passing' : 'evidence-unmeasured' };
62
+ }
63
+ return { reason: 'evidence-passed-on-main' };
64
+ }
65
+
66
+ /** Only an explicit project repository qualifies. Unknown target means preserve the live launch. */
67
+ export function inspectPrelaunchAlreadyDone(text: string, projectTarget?: string,
68
+ deps: { runGit?: PrelaunchGitRunnerForTest; realpath?: (path: string) => string } = {}): AlreadyDoneDecision {
69
+ const boundary = inspectGoalDoneBoundary(text);
70
+ if (boundary.missing.length) return { reason: `boundary-missing:${boundary.missing.join(',')}` };
71
+ const command = boundary.values['완료 경계 증거 명령'] ?? '';
72
+ const safe = parseAlreadyDoneCommand(command);
73
+ if (!safe) return { reason: 'evidence-command-unsupported' };
74
+ const codeBoundary = boundary.values['완료 경계 코드'] ?? '';
75
+ const realBoundary = boundary.values['완료 경계 실물'] ?? '';
76
+ if (codeBoundary !== `기존 추적 파일 ${safe.path}` || realBoundary !== '원격 main의 일반 파일로 존재')
77
+ return { reason: 'evidence-boundary-not-file-existence' };
78
+ if (!projectTarget) return { reason: 'project-target-unverified' };
79
+ let root: string;
80
+ try { root = (deps.realpath ?? realpathSync)(projectTarget); } catch { return { reason: 'project-target-unreadable' }; }
81
+ const runGit = deps.runGit ?? runPinnedGit;
82
+ const top = runGit(root, ['rev-parse', '--show-toplevel']);
83
+ if (top.status !== 0 || top.stdout.trim() !== root) return { reason: 'project-root-unverified' };
84
+ const origin = runGit(root, ['remote', 'get-url', 'origin']);
85
+ const originUrl = origin.stdout.trim();
86
+ // Keep credentials and arbitrary transports out of both the verifier and its card evidence.
87
+ const repository = /^(?:https:\/\/github\.com\/|git@github\.com:)([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+?)(?:\.git)?$/.exec(originUrl)?.[1];
88
+ if (origin.status !== 0 || !repository) return { reason: 'origin-unverified' };
89
+ const local = runGit(root, ['rev-parse', 'refs/remotes/origin/main']).stdout.trim();
90
+ const remote = runGit(root, ['ls-remote', 'origin', 'refs/heads/main'], 7_000);
91
+ const sha = remote.stdout.trim().split(/\s+/)[0] ?? '';
92
+ if (remote.status !== 0 || !SHA.test(sha) || local !== sha) return { reason: 'main-unverified-or-stale' };
93
+ const evaluated = evaluatePinnedTree(root, sha, safe, runGit);
94
+ if (evaluated.reason !== 'evidence-passed-on-main') return evaluated;
95
+ const remoteAgain = runGit(root, ['ls-remote', 'origin', 'refs/heads/main'], 7_000);
96
+ if (remoteAgain.status !== 0 || remoteAgain.stdout.trim().split(/\s+/)[0] !== sha) return { reason: 'main-moved' };
97
+ return { candidate: { mainSha: sha, repository, command, exitCode: 0 }, reason: 'evidence-passed-on-main' };
98
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * ⛔ 시험 안의 «실물 발사» 거부 — 2026-10-16 사고(R7 · OP #8751) 의 구조 방어.
3
+ *
4
+ * 무엇이 있었나: 호스트 재게이트가 시험을 운영 HOME 그대로 돌렸고, seam 이 빠진 시험 둘이 `defaultTaskLauncher` 의
5
+ * 원격 부모 경로(`tryRemoteParent`)로 진짜 ssh 를 쏴 원격 prod 런 25 · draft PR 11 을 만들었다.
6
+ * 격리 env(재게이트 러너)와 시험 seam 은 «잊음»을 줄일 뿐 «다음 시험이 seam 을 빠뜨리는 것»은 못 막는다 — 그래서
7
+ * 발사 지점이 bun test 안에서는 명시 허용 없이 실물 발사를 «거부»한다(fail-closed · 큰소리).
8
+ *
9
+ * - 시험 밖(제품 경로): 아무 영향 없다 — `isUnderTestRunner()` 가 거짓이면 즉시 돌아간다.
10
+ * - 시험 안: 주입(가짜 ssh·spawn)을 쓰면 이 가드에 닿지 않는다. 실물이 정말 필요한 시험만
11
+ * `ELANOUS_TEST_ALLOW_REAL_LAUNCH=1` 로 명시 허용한다.
12
+ */
13
+ import { debug } from '../debug/log.js';
14
+ import { isUnderTestRunner } from '../oauth/store.js';
15
+
16
+ export const ALLOW_REAL_LAUNCH_UNDER_TEST_ENV = 'ELANOUS_TEST_ALLOW_REAL_LAUNCH';
17
+
18
+ export type RealLaunchKind = 'remote-parent-ssh' | 'local-harness-spawn';
19
+
20
+ export class RealLaunchRefusedUnderTestError extends Error {
21
+ constructor(readonly kind: RealLaunchKind, detail: string) {
22
+ super(`⛔ 시험 안에서 실물 발사를 거부했다(${kind}${detail ? ` · ${detail}` : ''}) — `
23
+ + (kind === 'remote-parent-ssh'
24
+ ? 'deps.parentHost: null(원격 끔) 또는 deps.ssh 가짜를 주입하라'
25
+ : 'deps.spawn 가짜(또는 handToTaskAgent:\'off\' · taskLauncher 가짜)를 주입하라')
26
+ + ` · 실물이 정말 필요하면 ${ALLOW_REAL_LAUNCH_UNDER_TEST_ENV}=1 (2026-10-16 시험 누수 사고 R7)`);
27
+ this.name = 'RealLaunchRefusedUnderTestError';
28
+ }
29
+ }
30
+
31
+ /** bun test 안이고 명시 허용이 없으면 던진다. 시험 밖에서는 아무것도 하지 않는다. */
32
+ export function refuseRealLaunchUnderTest(kind: RealLaunchKind, detail = '', env: NodeJS.ProcessEnv = process.env): void {
33
+ if (!isUnderTestRunner(env)) return;
34
+ if (env[ALLOW_REAL_LAUNCH_UNDER_TEST_ENV]?.trim() === '1') return;
35
+ try { debug.log('task-agent', 'real-launch-refused-under-test', { kind, detail }); } catch { /* fail-soft */ }
36
+ throw new RealLaunchRefusedUnderTestError(kind, detail);
37
+ }
@@ -35,6 +35,7 @@ import { tmpdir } from 'node:os';
35
35
  import { dirname, join } from 'node:path';
36
36
  import { debug } from '../debug/log.js';
37
37
  import { prodInstanceRoot } from '../instance/resolve.js';
38
+ import { getUserConfig } from '../user-config.js';
38
39
  import { loadRunLedger, type RunLedgerEntry } from '../self-implement/run-ledger.js';
39
40
  import type { DetachedSpawn } from '../cli/tasks-cli.js';
40
41
  import { remoteLedgerMirrorDir } from './parent-host.js';
@@ -46,6 +47,9 @@ import type { RepairCasOutcome, RepairCasRequest } from './repair-branch-cas.js'
46
47
  import { defaultLandPrHead, defaultPrHead, defaultReviewRepoCandidates, executeLiveLand, executeLiveReview, landRetryPending, type LiveMoveDeps, type LiveMoveResult, type PrHeadView, type ReviewRepoCandidate, type TaskAgentLiveMove } from './live-moves.js';
47
48
  import { capturedLandReview, captureReviewResults, parseReviewResultOutput, pendingReviewResults, reviewResultPath, type ParsedReviewResult } from './review-result-capture.js';
48
49
  import { boundPrTerminal, cardPrNumber, LIVE_MOVE_RESULT_EVENT, readTaskCard, taskAgentStatePath, updateTaskCard, type TaskCard } from './task-hand.js';
50
+ import { verifiedTrainLanding, type TrainLanding } from './train-landing.js';
51
+ import { isGoalOnlyPr } from './judge.js';
52
+ import { defaultPrFiles } from './shadow.js';
49
53
 
50
54
  export const REJUDGE_ON_HEAD_EVENT = 'rejudge-on-head';
51
55
  /** 카드·PR 당 재게이트하는 머리 수 상한(머리가 바뀔 때마다 하나) — 넘으면 멈추고 사람에게 넘긴다. */
@@ -60,6 +64,7 @@ export type CatchUpDecision = 'pushed' | 'conflict' | 'cap-reached' | 'failed';
60
64
  export interface RejudgeOutcome {
61
65
  card: string; pr: number | null; fromHead: string | null; toHead: string | null; step: RejudgeStep; decision: string; reason: string;
62
66
  fromBase?: string; toBase?: string; newHead?: string;
67
+ repairRunId?: string; repairHead?: string;
63
68
  }
64
69
 
65
70
  export interface RegateRequest { card: string; pr: number; head: string; repoRoot: string; resultPath: string }
@@ -77,6 +82,8 @@ export type CatchUpGit = (cwd: string, args: string[]) => { status: number | nul
77
82
  export interface RejudgeDeps {
78
83
  live?: LiveMoveDeps;
79
84
  liveMoves: ReadonlySet<TaskAgentLiveMove>;
85
+ /** Complete PR target paths; undefined means the PR diff could not be measured. */
86
+ prFiles?: (pr: number, prUrl: string) => Promise<readonly string[] | undefined>;
80
87
  /** Only phase ① shadow callbacks may inspect a previously judged head without a regate. */
81
88
  shadowSameHead?: boolean;
82
89
  /** HQ mirror proof that the bound remote child has stopped. Test seam; absence fails closed. */
@@ -96,6 +103,8 @@ export interface RejudgeDeps {
96
103
  log?: (category: string, event: string, data: Record<string, unknown>) => void;
97
104
  /** 시험 seam — 결과 파일 읽기(없으면 ENOENT). */
98
105
  readFile?: (path: string) => string;
106
+ /** Verify a CLOSED component PR against the HQ train ledger and merged integration PR. */
107
+ trainLanding?: (pr: number, cwd: string) => TrainLanding | null;
99
108
  }
100
109
 
101
110
  /** PR binding alone does not mean a remote parent has stopped. Require its child edge and terminal ledger row. */
@@ -283,6 +292,15 @@ export function parseRegateResult(text: string, pr: number, head: string): Regat
283
292
  const sameUrl = (a: string, b: string) => a.trim().replace(/\/+$/, '').toLowerCase() === b.trim().replace(/\/+$/, '').toLowerCase();
284
293
  const sameHead = (a: string, b: string) => a.toLowerCase() === b.toLowerCase();
285
294
 
295
+ /**
296
+ * TA-REGATE-UNMEASURED — «못 잰» 재게이트(draft `pr-head` 거부·띄우기 실패 등 status=unmeasured)는 코드 판정이 아니다.
297
+ * 재게이트 상한(REJUDGE_HEAD_CAP)에 세지 않는다. 옛 결과 파일은 noMerge 에 status 가 없어서 draft 거부 문면으로도 가린다.
298
+ */
299
+ export function regateUnmeasured(entry: { passed?: boolean; status?: string; detail?: string }): boolean {
300
+ return entry.passed === false && (entry.status === 'unmeasured' || /^pr-head:.*\bisDraft=true\b/.test(entry.detail ?? ''));
301
+ }
302
+ const cappedRegates = <T extends { passed?: boolean; status?: string; detail?: string }>(entries: readonly T[]): T[] => entries.filter((entry) => !regateUnmeasured(entry));
303
+
286
304
  const defaultCatchUpGit: CatchUpGit = (cwd, args) => {
287
305
  const r = spawnSync('git', args, { cwd, encoding: 'utf8', timeout: 120_000 });
288
306
  return { status: r.status, stdout: String(r.stdout ?? ''), stderr: String(r.stderr ?? '') };
@@ -416,8 +434,6 @@ export async function rejudgeCardOnHead(cardId: string, deps: RejudgeDeps): Prom
416
434
  // 원격 부모는 node-b 의 liveMoves 가 꺼져 리뷰 이력이 0일 수 있다. HQ 거울의 종결 증거가 있을 때만 시작한다.
417
435
  const adopted = card.adoptedPr?.pr === pr && typeof card.pr === 'object'
418
436
  && !!card.pr.url && sameUrl(card.adoptedPr.url, card.pr.url) && /^[a-f0-9]{40}$/i.test(card.adoptedPr.head);
419
- if (!reviews.length && !adopted && (!card.parentHost || !(deps.remoteRunTerminal ?? remoteBoundRunTerminal)(card)))
420
- return target('not-started', 'no task-agent review on this PR yet (remote terminal unproven or run not stopped/judged)', pr);
421
437
  // 떼어 띄운 재게이트 결과를 «머리와 무관하게» 먼저 회수한다 — 결과가 나오기 전에 머리가 또 바뀌어도 그 머리의 결과는 카드에 남는다.
422
438
  for (const pending of (card.regates ?? []).filter((entry) => entry.pr === pr && entry.passed === undefined && entry.resultPath)) {
423
439
  let text: string | null = null;
@@ -435,7 +451,7 @@ export async function rejudgeCardOnHead(cardId: string, deps: RejudgeDeps): Prom
435
451
  wrote = true;
436
452
  return { ...current, regates: current.regates.map((entry) => entry.pr === pr && entry.head === pending.head && entry.at === pending.at ? { ...entry, ...patch } : entry) };
437
453
  });
438
- if (wrote) emit({ card: card.id, pr, fromHead: null, toHead: pending.head, step: 'regate', decision: patch.passed ? 'regate-passed' : 'regate-failed',
454
+ if (wrote) emit({ card: card.id, pr, fromHead: null, toHead: pending.head, step: 'regate', decision: patch.passed ? 'regate-passed' : regateUnmeasured(patch) ? 'regate-unmeasured' : 'regate-failed',
439
455
  reason: `head ${pending.head.slice(0, 12)} · base ${(patch as { baseCommit?: string }).baseCommit?.slice(0, 12) ?? '-'} · ${patch.detail}` }, true);
440
456
  }
441
457
  card = readTaskCard(card.id, statePath) ?? card;
@@ -453,15 +469,40 @@ export async function rejudgeCardOnHead(cardId: string, deps: RejudgeDeps): Prom
453
469
  if ('reason' in found) return target('pr-unreadable', found.reason, pr, fromHead);
454
470
  const { cwd, view } = found;
455
471
  const toHead = view.head;
472
+ const eligible = !!reviews.length || adopted || (!!card.parentHost && (deps.remoteRunTerminal ?? remoteBoundRunTerminal)(card));
473
+ const trustedTrain = view.state === 'CLOSED' && card.status === 'launched'
474
+ ? (() => { try { return (deps.trainLanding ?? verifiedTrainLanding)(pr, cwd); } catch { return null; } })() : null;
475
+ // An unreviewed or unproven remote card retains the old guard. Only verified train
476
+ // evidence may cross it; an arbitrary CLOSED PR must not disappear from rejudge.
477
+ if (!eligible && !trustedTrain)
478
+ return target('not-started', 'no task-agent review on this PR yet (remote terminal unproven or run not stopped/judged)', pr);
479
+ try {
480
+ const paths = await (deps.prFiles ?? defaultPrFiles)(pr, url);
481
+ if (isGoalOnlyPr(paths)) return target('goal-only-pr', `PR #${pr} target diff 0 (docs/goals/** only) — review·land·같은 골 재큐 중지`, pr, fromHead, toHead, true);
482
+ } catch (error) {
483
+ try { log('task-agent', 'pr-target-diff-unavailable', { card: card.id, pr,
484
+ reason: error instanceof Error ? error.message : String(error) }); } catch { /* fail-soft */ }
485
+ }
456
486
  if (view.state === 'MERGED' || view.state === 'CLOSED') {
457
487
  const at = now().toISOString();
488
+ const train = trustedTrain;
458
489
  updateTaskCard(statePath, card.id, (current) => {
459
490
  if (!current || cardPrNumber(current) !== pr || typeof current.pr !== 'object' || current.pr.url !== url) return undefined;
460
491
  const previous = boundPrTerminal(current);
461
- if (previous?.state === view.state && previous.head === toHead) return undefined;
462
- return { ...current, prTerminal: { pr, url, head: toHead, state: view.state as 'MERGED' | 'CLOSED', at } };
492
+ const alreadyLanded = train && current.trainLanding?.componentPr === pr
493
+ && current.trainLanding.integrationPr === train.integrationPr && current.trainLanding.mergeSha === train.mergeSha;
494
+ if (previous?.state === view.state && previous.head === toHead && (!train || alreadyLanded) && (!train || current.status === 'done')) return undefined;
495
+ return {
496
+ ...current,
497
+ ...(train ? { status: 'done' as const, trainLanding: alreadyLanded ? current.trainLanding : { ...train, at }, history: alreadyLanded ? current.history : [...(current.history ?? []), {
498
+ at, event: 'landed-via-train', pr, head: toHead, detail: `train #${train.integrationPr} merged ${train.mergeSha}`,
499
+ }] } : {}),
500
+ prTerminal: previous?.state === view.state && previous.head === toHead ? previous
501
+ : { pr, url, head: toHead, state: view.state as 'MERGED' | 'CLOSED', at },
502
+ };
463
503
  });
464
- return target('pr-not-open', `PR #${pr} is ${view.state}`, pr, fromHead, toHead);
504
+ return train ? target('landed-via-train', `PR #${pr} via train #${train.integrationPr} merge ${train.mergeSha}`, pr, fromHead, toHead)
505
+ : target('pr-not-open', `PR #${pr} is ${view.state}`, pr, fromHead, toHead);
465
506
  }
466
507
  if (view.state !== 'OPEN') return target('pr-not-open', `PR #${pr} is ${view.state}`, pr, fromHead, toHead);
467
508
  // An explicitly rejudged PR can be reopened. Clear the old marker before normal head judgement.
@@ -537,7 +578,8 @@ export async function rejudgeCardOnHead(cardId: string, deps: RejudgeDeps): Prom
537
578
  ...(deps.applyRepair ? { apply: deps.applyRepair } : {}),
538
579
  ...(deps.notifyRepair ? { notify: deps.notifyRepair } : {}),
539
580
  ...(deps.repairBudget ? { repairBudget: deps.repairBudget } : {}) });
540
- step('repair', result.decision, result.reason, true);
581
+ step('repair', result.decision, result.reason, true,
582
+ result.repairRunId && result.repairHead ? { repairRunId: result.repairRunId, repairHead: result.repairHead } : {});
541
583
  return outcomes;
542
584
  }
543
585
  }
@@ -585,6 +627,40 @@ export async function rejudgeCardOnHead(cardId: string, deps: RejudgeDeps): Prom
585
627
  return outcomes;
586
628
  }
587
629
 
630
+ // TA-LAND-AFTER-REVIEW: configured queue mode owns its one remote changed gate inside
631
+ // the queue adapter. The older host regate below is the direct-merge path only.
632
+ const queueMode = live.landQueueConfig === undefined ? getUserConfig().taskAgent?.landQueue : live.landQueueConfig;
633
+ if (queueMode) {
634
+ const latest = readTaskCard(card.id, statePath) ?? card;
635
+ const priorQueue = (latest.landAttempts ?? []).filter((entry) => entry.pr === pr && sameHead(entry.head, toHead));
636
+ if (priorQueue.length && !landRetryPending(latest, pr, toHead)) {
637
+ step('land', 'queue-skipped', `PR #${pr} head ${toHead.slice(0, 12)} already claimed or queued`, false);
638
+ return outcomes;
639
+ }
640
+ const review = capturedLandReview(latest, pr, toHead);
641
+ if (!review || review.mustFixCount !== 0) {
642
+ if (pendingReviewResults(latest).some((entry) => entry.pr === pr && sameHead(entry.head, toHead))) {
643
+ step('review', 'awaiting-review-result', 'exact-head review result pending', false);
644
+ } else if (!latest.reviewRequests?.some((entry) => entry.pr === pr && sameHead(entry.head, toHead)) && deps.liveMoves.has('review')) {
645
+ const before = { reviewRequests: latest.reviewRequests, landAttempts: latest.landAttempts };
646
+ const result = await executeLiveReview(latest, pr, { runId: latest.runId ?? null, stopReason: 'queue-exact-head', cwd }, { ...live, ...(deps.log ? { log: deps.log } : {}) });
647
+ recordMove(statePath, latest.id, latest.runId, 'review', result, pr, before, now, deps.log);
648
+ step('review', result.executed ? 'review-requested' : 'review-request-failed', result.detail, true);
649
+ } else step('review', 'not-landing', 'exact-head PASS/WARN mf0 review not captured', true);
650
+ return outcomes;
651
+ }
652
+ if (!readyConfirmed) { step('ready', 'ready-unconfirmed', 'exact-head ready PR not confirmed', false); return outcomes; }
653
+ if (!deps.liveMoves.has('propose-land')) { step('land', 'would-land', 'propose-land not enabled — queue shadow', false); return outcomes; }
654
+ const reviewResult = latest.reviewRequests?.find((entry) => entry.pr === pr && sameHead(entry.head, toHead) && entry.resultPath)?.resultPath;
655
+ if (!reviewResult) { step('land', 'not-landing', 'exact-head review JSON path missing', true); return outcomes; }
656
+ const before = { reviewRequests: latest.reviewRequests, landAttempts: latest.landAttempts };
657
+ const queued = await executeLiveLand(latest, pr, { runId: latest.runId ?? null, cycleId: `queue:${latest.id}:${toHead}`, cwd,
658
+ review, reviewResultPath: reviewResult }, { ...live, landQueueConfig: queueMode, ...(deps.log ? { log: deps.log } : {}) });
659
+ recordMove(statePath, latest.id, latest.runId, 'propose-land', queued, pr, before, now, deps.log);
660
+ step('land', queued.queued ? 'queued' : queued.ok && !queued.executed ? 'queue-skipped' : 'queue-refused', queued.detail, true);
661
+ return outcomes;
662
+ }
663
+
588
664
  const tryCatchUp = async (fromBase: string | undefined, why: string): Promise<boolean> => {
589
665
  const prior = catchUpHistory(card!, pr);
590
666
  // 상한은 «실제 push» 만 센다 — 충돌·실패 뒤 사람이 새 머리를 올리면 다시 시도할 수 있어야 한다.
@@ -653,8 +729,9 @@ export async function rejudgeCardOnHead(cardId: string, deps: RejudgeDeps): Prom
653
729
  if (!regate || staleBase || retryDraft) {
654
730
  const why = staleBase ? `base-stale-overlap — gate base ${staleBase.slice(0, 12)} went stale (${(stale!.reason ?? '').replace(/^base-stale-overlap:\s*/, '').slice(0, 160)})`
655
731
  : retryDraft ? 'draft rejection became stale after PR ready' : '';
656
- if (regates.length >= REJUDGE_HEAD_CAP) {
657
- step('regate', 'cap-reached', `${why ? `${why} · ` : ''}re-gated ${regates.length} times already (cap ${REJUDGE_HEAD_CAP}) — no more rejudge; needs owner`, true);
732
+ const counted = cappedRegates(regates).length;
733
+ if (counted >= REJUDGE_HEAD_CAP) {
734
+ step('regate', 'cap-reached', `${why ? `${why} · ` : ''}re-gated ${counted} times already (cap ${REJUDGE_HEAD_CAP} · unmeasured ${regates.length - counted} not counted) — no more rejudge; needs owner`, true);
658
735
  return outcomes;
659
736
  }
660
737
  if (!deps.liveMoves.has('propose-land')) step('regate', 'would-regate', `${why ? `${why} · ` : ''}propose-land not enabled in taskAgent.liveMoves — shadow`, false);
@@ -670,7 +747,7 @@ export async function rejudgeCardOnHead(cardId: string, deps: RejudgeDeps): Prom
670
747
  if (!current || held.some((entry) => sameHead(entry.head, toHead) && (staleBase ? entry.staleBase !== undefined && sameHead(entry.staleBase, staleBase)
671
748
  : retryDraft ? entry.readyRetry === true : true))) return undefined;
672
749
  // 상한은 잠금 안의 «지금» 카드로 다시 잰다 — 다른 머리를 본 두 틱이 겹쳐도 상한을 넘지 않게.
673
- if (held.length >= REJUDGE_HEAD_CAP) { capped = true; return undefined; }
750
+ if (cappedRegates(held).length >= REJUDGE_HEAD_CAP) { capped = true; return undefined; }
674
751
  claimed = true;
675
752
  return { ...current, regates: [...(current.regates ?? []), { pr, head: toHead, at, resultPath, ...(staleBase ? { staleBase } : {}), ...(retryDraft ? { readyRetry: true as const } : {}) }] };
676
753
  });
@@ -753,7 +830,7 @@ export async function rejudgeCardOnHead(cardId: string, deps: RejudgeDeps): Prom
753
830
  const before = { reviewRequests: latest.reviewRequests, landAttempts: latest.landAttempts };
754
831
  // 주기 id — base-stale 재게이트 뒤의 land 는 새 base 를 붙여 앞 land 의 주기 표시(모듈 전역)와 갈린다 · gateAt 이 앞 base-stale 시도를 소비한다.
755
832
  const cycleId = `rejudge:${card.id}:${toHead}${regate.staleBase ? `:${regate.baseCommit.slice(0, 12)}` : ''}`;
756
- const landed = await executeLiveLand(latest, pr, { runId: card.runId ?? null, cycleId, cwd, review, overlapEvidence, gateAt: regate.at },
833
+ const landed = await executeLiveLand(latest, pr, { runId: card.runId ?? null, cycleId, cwd, review, reviewResultPath: reviewResult, overlapEvidence, gateAt: regate.at },
757
834
  { ...live, ...(deps.log ? { log: deps.log } : {}) });
758
835
  // LAND-ORDER-LEDGER — executeLiveLand 직후 원장 한 줄(같은 pr+head 는 한 줄만). 쓰기가 실패해도 land 결과는 그대로(삼킨다).
759
836
  const landOrderLog = (event: 'appended' | 'append-failed') => { try { log('task-agent.land-order', event, { pr, head: toHead }); } catch { /* fail-soft */ } };
@@ -771,7 +848,7 @@ export async function rejudgeCardOnHead(cardId: string, deps: RejudgeDeps): Prom
771
848
  const attempt = landed.landAttempt?.class
772
849
  ? ` · land-class ${landed.landAttempt.class} (${landed.landAttempt.reason}) · attempt ${landed.landAttempt.attempt} · ${landed.landAttempt.class === 'base-stale' ? 'base-stale → re-gate on a new base next tick (cap counts)' : landed.landAttempt.retryAllowed ? 'retry allowed on this head' : 'no retry on this head'}`
773
850
  : '';
774
- step('land', landed.executed && landed.ok ? 'landed'
851
+ step('land', landed.queued ? 'queued' : landed.executed && landed.ok ? 'landed'
775
852
  : !landed.executed && landed.ok ? 'land-skipped' : 'land-rejected',
776
853
  `${landed.detail}${attempt} · overlap-evidence ${overlapEvidence}`, true);
777
854
  return outcomes;
@@ -1,16 +1,24 @@
1
1
  /** Bind remote TA parents from the HQ ledger mirror before `rejudge --all` selects PR cards. */
2
- import { dirname } from 'node:path';
2
+ import { existsSync } from 'node:fs';
3
+ import { dirname, join } from 'node:path';
3
4
  import { debug } from '../debug/log.js';
4
5
  import { loadRunLedger } from '../self-implement/run-ledger.js';
5
- import { bindCardEvidence, podChildRunIds, readCardRunSnapshot, refreshCardRunBinding } from './card-evidence.js';
6
+ import { bindCardEvidence, podChildRunIds, podTerminalPr, readCardRunSnapshot, refreshCardRunBinding } from './card-evidence.js';
6
7
  import { mirrorRemoteRunLedgers, remoteLedgerMirrorDir } from './parent-host.js';
7
8
  import { cardPrNumber, type TaskCard } from './task-hand.js';
8
9
 
9
10
  const RECENT_LAUNCH_MS = 24 * 60 * 60 * 1000;
11
+ /**
12
+ * TA-BIND-PULL-ONCE — an older launch whose parent ledger was never mirrored at HQ gets one pull («묶기만»).
13
+ * Bounded per tick so the first tick after deploy does not run hundreds of sequential ssh reads (backlog ≈690
14
+ * cards on 10-15 drains over ticks); a pulled mirror is then read locally and never pulled again by this rule.
15
+ */
16
+ export const UNMIRRORED_PULL_CAP_PER_TICK = 20;
10
17
 
11
18
  type BindDeps = {
12
19
  now?: () => number;
13
20
  mirror?: typeof mirrorRemoteRunLedgers;
21
+ unmirroredPullCap?: number;
14
22
  onFailure?: (failure: { card: string; runId: string; host: string; reason: string }) => void;
15
23
  };
16
24
 
@@ -23,13 +31,14 @@ function recentlyLaunched(card: TaskCard, now: number): boolean {
23
31
  /**
24
32
  * A remote child PR can appear after the last HQ card refresh. A card without a PR is otherwise absent from
25
33
  * `rejudgeCandidates`, so the normal rejudge tick never reaches `mirrorRemoteCardLedger` or the binding replay.
26
- * Only an existing, launched TA-owned parent with a parent→child edge in its own host mirror is admitted. The
34
+ * Only an existing, launched parent (TA-owned or not — TA-BIND-WIDEN) with a parent→child edge in its own host
35
+ * mirror is bound; rejudge/land selection keeps its own taLand gate. The
27
36
  * launch registry (including foreign/test universes) and child-only ledgers are never scanned or adopted here.
28
37
  */
29
38
  export async function bindMirroredRemoteRejudgeCards(
30
39
  tasks: Readonly<Record<string, TaskCard>>, statePath: string,
31
40
  deps: BindDeps = {},
32
- ): Promise<{ scanned: number; bound: number; skipped: number }> {
41
+ ): Promise<{ scanned: number; bound: number; skipped: number; pulledUnmirrored: number }> {
33
42
  const root = dirname(statePath);
34
43
  const now = (deps.now ?? Date.now)();
35
44
  const mirror = deps.mirror ?? mirrorRemoteRunLedgers;
@@ -41,8 +50,12 @@ export async function bindMirroredRemoteRejudgeCards(
41
50
  let scanned = 0;
42
51
  let bound = 0;
43
52
  let skipped = 0;
53
+ let pulledUnmirrored = 0;
54
+ const unmirroredCap = deps.unmirroredPullCap ?? UNMIRRORED_PULL_CAP_PER_TICK;
44
55
  for (const card of Object.values(tasks)) {
45
- if (card.status !== 'launched' || card.taLand !== true || !card.parentHost || !card.runId
56
+ // TA-BIND-WIDEN — «묶기»는 taLand 와 무관하게 launched ⊕ runId 카드 전부. 묶여도 재판정(rejudge)·land 후보는
57
+ // `rejudgeCandidates`/`remoteBoundRunTerminal` 의 taLand 관문이 그대로 거른다 — 여기서 넓히는 것은 카드↔PR 연결뿐이다.
58
+ if (card.status !== 'launched' || !card.parentHost || !card.runId
46
59
  || cardPrNumber(card) !== undefined || card.refSource === 'manual') continue;
47
60
  scanned++;
48
61
  const dir = remoteLedgerMirrorDir(root, card.parentHost.host);
@@ -51,6 +64,10 @@ export async function bindMirroredRemoteRejudgeCards(
51
64
  // dependency: cards with a remote PR cannot be selected while their parent/child ledgers are absent locally.
52
65
  // Limit fresh remote pulls to recent launches, but keep binding older ledgers already mirrored at HQ.
53
66
  if (recentlyLaunched(card, now)) mirror(card.parentHost, card.runId, root);
67
+ else if (!existsSync(join(dir, `${card.runId}.jsonl`)) && pulledUnmirrored < unmirroredCap) {
68
+ pulledUnmirrored++;
69
+ mirror(card.parentHost, card.runId, root);
70
+ }
54
71
  const snapshot = await readCardRunSnapshot(card, {
55
72
  loadLedger: (id) => loadRunLedger(id, dir),
56
73
  podFinishes: () => [],
@@ -67,10 +84,13 @@ export async function bindMirroredRemoteRejudgeCards(
67
84
  }
68
85
  // A PR event alone is not a completed remote run. The rejudge candidate must have the same exact
69
86
  // child PR and terminal status that remoteBoundRunTerminal will later require.
87
+ // TA-BIND-PR-TERMINAL — a blocked-draft child has no `pr-opened`; the parent's `pr-terminal` for that exact child,
88
+ // number and URL is the same PR evidence.
89
+ const terminal = parent ? podTerminalPr(parent, [childRunId ?? '']) : undefined;
70
90
  if (!parent || !childRunId || !pr?.url || !child
71
91
  || !podChildRunIds(parent, card.runId).includes(childRunId)
72
- || !child.some((entry) => entry.event === 'pr-opened' && entry.data?.number === pr.number
73
- && entry.data?.url === pr.url)
92
+ || !(child.some((entry) => entry.event === 'pr-opened' && entry.data?.number === pr.number
93
+ && entry.data?.url === pr.url) || (terminal?.number === pr.number && terminal.url === pr.url))
74
94
  || !child.some((entry) => entry.event === 'run-status'
75
95
  && ['completed', 'failed', 'cancelled'].includes(String(entry.data?.runStatus)))) { skipped++; continue; }
76
96
  const result = await refreshCardRunBinding(card.id, statePath, {
@@ -87,5 +107,5 @@ export async function bindMirroredRemoteRejudgeCards(
87
107
  reportFailure(card, error instanceof Error ? error.message : String(error));
88
108
  }
89
109
  }
90
- return { scanned, bound, skipped };
110
+ return { scanned, bound, skipped, pulledUnmirrored };
91
111
  }