elanous 0.2.28 → 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 (818) 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/{y1ltt7oCZxVpC6zVPhZ2O → LSXfY0u9QtfDbejY0Ukf_}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{ab4d57c2.e90bc2cb31949045.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/{5492-e05e26a033ba80d2.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/1654.32de4b324981a188.js +23 -0
  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/1913.7cc6fb6055b1ed3f.js +41 -0
  18. package/apps/pwa/out/_next/static/chunks/2001.6c7e0fd02190886c.js +1 -0
  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/{8578.dff22d988cc2b106.js → 2213.2ccbada92c33ea0f.js} +3 -3
  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/{5081.a240b63fad28663a.js → 2871.0bca6137343b3f76.js} +1 -1
  28. package/apps/pwa/out/_next/static/chunks/2898.fd781bc7cf01a7b7.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2940-619bfd8ef337c611.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/{2846.d6a433b8663819a5.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/{f4dfbfc0.a69fb12f854882aa.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/3541-ce3a5424ed5ad7f1.js +1 -0
  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/{3143.257997a5f1ed79df.js → 3902.e1e71aaac850a045.js} +1 -1
  39. package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/{16e57f67.3ea19e893461e611.js → 409f1e57.d0649fc47691ebfe.js} +1 -1
  41. package/apps/pwa/out/_next/static/chunks/{1146.80d15ea7c6e6ee95.js → 4111.2bfedbb233ad206b.js} +1 -1
  42. package/apps/pwa/out/_next/static/chunks/{1516.83dd2c1b86b4e507.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/{9938.b23e4d4dfa0114cd.js → 4999.c064a4000c2a9e94.js} +2 -2
  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/{1157.f08bf2b70915e176.js → 5304.04d24756f242a094.js} +2 -2
  57. package/apps/pwa/out/_next/static/chunks/{7752.5cbdd0b433c54af9.js → 5307.60f2209e809bd627.js} +1 -1
  58. package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/{9917-9e26abc5f7772735.js → 5458-16cd7a2b51b74c8c.js} +1 -1
  60. package/apps/pwa/out/_next/static/chunks/{6196.34d6b229079e9e28.js → 5525.86debf231e181813.js} +1 -1
  61. package/apps/pwa/out/_next/static/chunks/{4593.10f5b9bd702d4a6c.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/{7483.ba01c6c209b81bba.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/{9974.e77b4ff4884557b3.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/{3309.364573ceedbdfd5f.js → 6323.8672b4817a306928.js} +1 -1
  74. package/apps/pwa/out/_next/static/chunks/{94.4cfed21c0b781a06.js → 6433.fc573af22bbc9ab7.js} +4 -4
  75. package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/{949.1e7d45ccb71580aa.js → 6517.4147878ac06d584d.js} +2 -2
  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/{2528.3868070ef1be69f9.js → 6767.ea607cf0c20a25af.js} +2 -2
  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/{1743.563d3168e95825ef.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/{5408.377c8c543635b81f.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/{65ebff95.081daeff622d238e.js → 7a1887c4.f36b88fba31da8fd.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/{2697.76ca2ac3efef6f3b.js → 8018.a32663f04a6fc5f9.js} +1 -1
  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/9138.b6e80031afb1d973.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/{4204.a409ab6250c0f6a8.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/{5785-ea8d2c633b6688e3.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/9398-6aed28f0a96d0d6f.js +1 -0
  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/997ce8a5-2ad501927003b41b.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/{9311.24c8f5ea793253dd.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-fa46d4588e8442c2.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-ced0bcfc6542b3fc.js → page-349f2752d8cd37ad.js} +1 -1
  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-cb249e81ed339318.js → page-0a07363b130182a1.js} +1 -1
  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-521ee23ac8c0abfa.js +1 -0
  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-149dc1caba411bb9.js +1 -0
  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/{6def8a8e.c81f9ca41028eccf.js → b313b242.cb1265eea908db61.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/{e87d89b9.2e71c0ae475d28a1.js → e5012ffe.f727e23c231f4342.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/{e117f801.e92bf10242653497.js → ebc7d829.264a0bcb6c750b50.js} +1 -1
  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 +15 -7
  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/plugins/agent-team/agents/research.md +1 -0
  289. package/scripts/check-native-tool-wiring.ts +3 -2
  290. package/scripts/ci-android-unit-tests.ts +16 -0
  291. package/scripts/ci-typecheck-changed.ts +40 -11
  292. package/scripts/coord-channel-watch.sh +45 -19
  293. package/scripts/coord-role-pack.ts +222 -0
  294. package/scripts/cron-run.ts +96 -3
  295. package/scripts/detect-test-interference.ts +38 -5
  296. package/scripts/gate-pr-cache.ts +65 -0
  297. package/scripts/gh-surface/capture.ts +126 -0
  298. package/scripts/gh-surface/gh +40 -0
  299. package/scripts/import-graph-scc.ts +38 -0
  300. package/scripts/install.ps1 +19 -0
  301. package/scripts/intake-social.ts +181 -0
  302. package/scripts/lecture-note/node.ts +71 -4
  303. package/scripts/lib/android-toolchain.ts +32 -0
  304. package/scripts/lib/deterministic-env.ts +62 -0
  305. package/scripts/lib/gate-test-env.ts +19 -0
  306. package/scripts/lib/morning-report-options.ts +41 -0
  307. package/scripts/measure-goal-grounding-corpus.ts +2 -1
  308. package/scripts/pr-land-extra-remote-gates.ts +49 -0
  309. package/scripts/ratchets/test-interference-patterns.allowlist.txt +257 -0
  310. package/scripts/ratchets/test-interference-patterns.ts +367 -0
  311. package/scripts/release-loop/cut-branch.ts +4 -3
  312. package/scripts/release-loop/export-check-node.ts +0 -1
  313. package/scripts/release-loop/fixtures/warm-failure-assertion/sample.junit.xml +8 -0
  314. package/scripts/release-loop/fixtures/warm-job-029/sample.json +1 -0
  315. package/scripts/release-loop/fixtures/warm-job-029/sample.junit.xml +10 -0
  316. package/scripts/release-loop/gate-batch-safe.ts +23 -0
  317. package/scripts/release-loop/gate-closure.ts +12 -8
  318. package/scripts/release-loop/gate-diff.ts +1 -1
  319. package/scripts/release-loop/gate-history.ts +422 -0
  320. package/scripts/release-loop/gate-host-mirror.ts +66 -0
  321. package/scripts/release-loop/gate-node.ts +806 -94
  322. package/scripts/release-loop/gate-partial.ts +106 -9
  323. package/scripts/release-loop/gate-pr-cache.ts +66 -0
  324. package/scripts/release-loop/gate-prewarm-plan.ts +66 -0
  325. package/scripts/release-loop/gate-r2-verdict.ts +189 -0
  326. package/scripts/release-loop/gate-recheck-plan-node.ts +52 -0
  327. package/scripts/release-loop/gate-triage-node.ts +190 -0
  328. package/scripts/release-loop/gate-warm-artifacts.ts +253 -0
  329. package/scripts/release-loop/import-graph-scc-run.ts +54 -0
  330. package/scripts/release-loop/import-graph-scc.ts +215 -0
  331. package/scripts/release-loop/node-verdict.ts +2 -0
  332. package/scripts/release-loop/probe-pod-host-dirs-live.ts +113 -0
  333. package/scripts/release-loop/resume-release.ts +33 -4
  334. package/scripts/release-loop/resume.ts +13 -5
  335. package/scripts/release-loop/spawn-lane.ts +51 -0
  336. package/scripts/release-loop/tui-node-checks.ts +23 -0
  337. package/scripts/release-loop/tui-sim-node.ts +3 -2
  338. package/scripts/release-loop/unattended-release.ts +16 -0
  339. package/scripts/release-loop/version-node.ts +62 -4
  340. package/scripts/test-deterministic.ts +46 -73
  341. package/scripts/train-reach-grouping.ts +48 -0
  342. package/scripts/tsc-incremental-cache.ts +86 -0
  343. package/scripts/tsc-incremental-diagnostics.ts +76 -0
  344. package/scripts/tsc-main-safety-net.ts +2 -2
  345. package/scripts/usage-rollup.ts +11 -3
  346. package/src/acp/client.ts +4 -1
  347. package/src/acp/core-turn-bridge.ts +145 -24
  348. package/src/acp/elanous-extensions.ts +2 -0
  349. package/src/acp/server.ts +2 -0
  350. package/src/ad-pipeline/run.ts +4 -2
  351. package/src/agent/ref-grounding.ts +18 -0
  352. package/src/agent/runner.ts +169 -3
  353. package/src/agent/subagent-callable.ts +3 -2
  354. package/src/agent-mission/review-loop.ts +6 -3
  355. package/src/agent-substrate/acp-implementer.ts +14 -2
  356. package/src/agent-substrate/pr-reviewer.ts +41 -21
  357. package/src/agent-substrate/self-review-cli.ts +30 -4
  358. package/src/autopilot/pr-manager.ts +62 -7
  359. package/src/briefing/brief-items.ts +24 -22
  360. package/src/budget/pty-usage-reemit.ts +7 -0
  361. package/src/budget/run-usage-rollup.ts +9 -0
  362. package/src/budget/usage-daily-store.ts +98 -0
  363. package/src/capture/tui-self-report.ts +37 -4
  364. package/src/chat/chat-cli.ts +10 -2
  365. package/src/chat/index.ts +107 -20
  366. package/src/chat/input-control-key.ts +5 -3
  367. package/src/chat/pickers/modal-runtime.ts +1 -0
  368. package/src/chat/pickers/modals.ts +3 -1
  369. package/src/chat/tool-interrupt-behavior.ts +38 -0
  370. package/src/chat/tool-render/dispatch.ts +5 -1
  371. package/src/chat/turn-typeahead.ts +191 -29
  372. package/src/cli/__fixtures__/agent-help-before/agent.txt +4 -2
  373. package/src/cli/agent-cli.ts +41 -13
  374. package/src/cli/config-audit.ts +123 -0
  375. package/src/cli/dashboard-name-flag.ts +48 -0
  376. package/src/cli/decisions-cli.ts +80 -6
  377. package/src/cli/doctor-cli.ts +80 -0
  378. package/src/cli/log-event-names.ts +19 -0
  379. package/src/cli/mcp-login.ts +21 -5
  380. package/src/cli/msg-cli.ts +133 -2
  381. package/src/cli/pr-cli.ts +546 -112
  382. package/src/cli/pr-land-heavy-remote.ts +233 -0
  383. package/src/cli/pr-land-overlap-evidence.ts +167 -14
  384. package/src/cli/pr-land-pod-shadow-job.ts +83 -0
  385. package/src/cli/pr-land-pod-shadow.ts +16 -3
  386. package/src/cli/pr-land-virtual-rebase.ts +108 -0
  387. package/src/cli/pty-takeover-cli.ts +125 -16
  388. package/src/cli/release-cli.ts +122 -14
  389. package/src/cli/remote-resolve.ts +2 -1
  390. package/src/cli/seat-cli.ts +164 -19
  391. package/src/cli/self-update.ts +5 -2
  392. package/src/cli/tasks-cli.ts +105 -21
  393. package/src/cli/usage-cli.ts +146 -12
  394. package/src/cli/usage-daily-cli.ts +84 -0
  395. package/src/context-bus/context-first.ts +13 -0
  396. package/src/context-bus/context-now.ts +95 -7
  397. package/src/context-bus/ops-events.ts +75 -0
  398. package/src/control-plane/lease-holder.ts +12 -8
  399. package/src/control-plane/ledger.ts +163 -4
  400. package/src/control-plane/server.ts +91 -11
  401. package/src/core-turn/auth-rejected-notice.ts +41 -0
  402. package/src/core-turn/run-core-turn.ts +14 -2
  403. package/src/core-turn/run-goal-loop.ts +239 -4
  404. package/src/core-turn/seat-turn-cap.ts +79 -0
  405. package/src/core-turn/short-question.ts +78 -13
  406. package/src/core-turn/types.ts +10 -0
  407. package/src/dashboard/acp-active-model.ts +40 -0
  408. package/src/dashboard/acp-boot.ts +3 -0
  409. package/src/dashboard/auto-compact-runtime.ts +2 -0
  410. package/src/dashboard/boot-banner.ts +80 -0
  411. package/src/dashboard/dashboard-status-lines.ts +11 -0
  412. package/src/dashboard/detail-viewer-runtime.ts +15 -2
  413. package/src/dashboard/event-loop-stall-monitor.ts +4 -0
  414. package/src/dashboard/goal-loop-thinking.ts +16 -0
  415. package/src/dashboard/hitl-boot.ts +9 -4
  416. package/src/dashboard/index.ts +448 -998
  417. package/src/dashboard/input/chat-main-entry-runtime.ts +2 -0
  418. package/src/dashboard/input/chat-main-log-actions.ts +4 -0
  419. package/src/dashboard/input/chat-main-log-command.ts +12 -1
  420. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +176 -4
  421. package/src/dashboard/input/chat-main-session.ts +14 -3
  422. package/src/dashboard/input/chat-main-slash-command.ts +7 -0
  423. package/src/dashboard/input/chat-main-turn.ts +14 -4
  424. package/src/dashboard/input/compact-prepass-recovery.ts +130 -0
  425. package/src/dashboard/input/dashboard-chord-actions.ts +10 -1
  426. package/src/dashboard/input/dashboard-chord-runtime.ts +2 -0
  427. package/src/dashboard/input/external-input-host.ts +71 -0
  428. package/src/dashboard/input/internal-turn.ts +261 -0
  429. package/src/dashboard/input/log-fold-binding.ts +18 -0
  430. package/src/dashboard/input/mouse-wiring.ts +17 -4
  431. package/src/dashboard/input/seat-autowake.ts +318 -0
  432. package/src/dashboard/input/turn-steer-bridge.ts +164 -0
  433. package/src/dashboard/log-click-runtime.ts +5 -3
  434. package/src/dashboard/loop-scheduler.ts +72 -0
  435. package/src/dashboard/running-build-status.ts +74 -0
  436. package/src/dashboard/seat-boot-preamble.ts +131 -0
  437. package/src/dashboard/seat-local-instructions.ts +305 -0
  438. package/src/dashboard/skill-runtime.ts +2 -0
  439. package/src/dashboard/slash-runtime/dashboard-handlers.ts +220 -1203
  440. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -1
  441. package/src/dashboard/slash-runtime/index.ts +13 -0
  442. package/src/dashboard/slash-runtime/model-choices.ts +35 -0
  443. package/src/dashboard/term-slash-runtime.ts +15 -0
  444. package/src/dashboard/turn-busy-teardown.ts +50 -0
  445. package/src/dashboard/turn-preamble.ts +30 -2
  446. package/src/dashboard/turn-session-layers.ts +176 -0
  447. package/src/dashboard/turn-stream-formatter.ts +14 -6
  448. package/src/dashboard/turn-stream-presentation-applier.ts +8 -0
  449. package/src/decisions/decision-ledger.ts +45 -4
  450. package/src/discord-self-message.ts +4 -4
  451. package/src/domains/release-tool.ts +26 -10
  452. package/src/domains/surface-events.ts +4 -1
  453. package/src/domains/watch-default-scheduler.ts +8 -9
  454. package/src/field-note/transcribe.ts +17 -0
  455. package/src/fold-stack.ts +24 -1
  456. package/src/git-fs/dirty.ts +32 -4
  457. package/src/git-fs/index.ts +43 -1
  458. package/src/github/remote-call.ts +81 -0
  459. package/src/goals/registry.ts +46 -6
  460. package/src/goals/types.ts +7 -1
  461. package/src/graph-runner/runner.ts +2 -0
  462. package/src/grok/credential.ts +26 -0
  463. package/src/harness/harness-clean.ts +2 -1
  464. package/src/harness/harness-cli-command.ts +52 -5
  465. package/src/harness/harness-gc.ts +34 -6
  466. package/src/harness/harness-incidents.ts +57 -20
  467. package/src/harness/harness-pod-dispatch.ts +87 -10
  468. package/src/harness/harness-queue.ts +53 -4
  469. package/src/harness/harness-stop.ts +4 -3
  470. package/src/harness/harness-substrate-default.ts +78 -7
  471. package/src/harness/harness-worktree-auto.ts +2 -1
  472. package/src/harness/harness-worktrees.ts +3 -2
  473. package/src/hooks/dispatch.ts +2 -1
  474. package/src/index.ts +166 -26
  475. package/src/input/external-input-queue.ts +251 -0
  476. package/src/intake-plane/slash.ts +14 -3
  477. package/src/interactive-terminal-modal.ts +13 -0
  478. package/src/keybindings.ts +4 -1
  479. package/src/llm/route-decision.ts +25 -0
  480. package/src/llm/tool-loop-steered-rejection.ts +33 -0
  481. package/src/llm-stream-retry-display.ts +59 -0
  482. package/src/llm.ts +391 -74
  483. package/src/log-entry.ts +3 -3
  484. package/src/log-pane/search.ts +29 -4
  485. package/src/loops/agent-reply.ts +256 -0
  486. package/src/loops/budget.ts +37 -7
  487. package/src/loops/consensus.ts +348 -0
  488. package/src/loops/loop-cli.ts +3 -2
  489. package/src/loops/msg-address.ts +57 -0
  490. package/src/loops/msg-wake.ts +484 -0
  491. package/src/loops/observe.ts +19 -3
  492. package/src/loops/orchestrator/inbox.ts +60 -3
  493. package/src/loops/orchestrator/tick.ts +80 -6
  494. package/src/loops/orchestrator/traffic.ts +64 -1
  495. package/src/loops/registry.ts +72 -4
  496. package/src/market/signed-index.ts +14 -0
  497. package/src/mcp/mcp-oauth.ts +54 -5
  498. package/src/memory.ts +20 -5
  499. package/src/models/prompts.ts +28 -0
  500. package/src/msg/msg-sse-client.ts +223 -0
  501. package/src/msg/msg-store.ts +86 -2
  502. package/src/mss/logging/log-store.ts +225 -1
  503. package/src/native-tool-catalog.ts +125 -0
  504. package/src/nexus/DAEMON-THIN-inventory-2026-10-15.md +122 -0
  505. package/src/nexus/api/http-server.ts +59 -15
  506. package/src/nexus/api/loop-resources.ts +19 -3
  507. package/src/nexus/api/ops-api.ts +13 -0
  508. package/src/nexus/api/project-autopsy.ts +127 -0
  509. package/src/nexus/api/terminals.ts +3 -0
  510. package/src/nexus/api/workflow-approvals.ts +2 -0
  511. package/src/nexus/daemon-thin-inventory.md +37 -0
  512. package/src/nexus/index.ts +70 -0
  513. package/src/nexus/onboarding/first-boot-wizard.ts +56 -2
  514. package/src/nexus/state/state.ts +1 -0
  515. package/src/oauth/codex-account-store.ts +15 -3
  516. package/src/oauth/codex-billing-route.ts +31 -0
  517. package/src/oauth/store.ts +32 -7
  518. package/src/onboarding/first-run.ts +28 -3
  519. package/src/ops/overview-cache.ts +16 -4
  520. package/src/ops/overview-collect.ts +19 -2
  521. package/src/ops/resources.ts +82 -0
  522. package/src/panes/log-pane.ts +67 -8
  523. package/src/persona/presets.ts +44 -0
  524. package/src/plugins/maker/connector-maker.ts +41 -0
  525. package/src/plugins/maker/skill-maker.ts +42 -0
  526. package/src/plugins/maker/wizard-generate.ts +6 -4
  527. package/src/pr-tool/census.ts +288 -0
  528. package/src/preview/terminal.ts +14 -1
  529. package/src/prompt-cache/types.ts +2 -0
  530. package/src/prompt-enhance/enhance.ts +24 -8
  531. package/src/prompt-library/chat-conciseness.ts +13 -0
  532. package/src/prompt-library/universal-preamble.ts +283 -61
  533. package/src/pty-shell/pty-control-ipc.ts +4 -1
  534. package/src/pty-shell/pty-manifest.ts +77 -5
  535. package/src/pty-shell/registry.ts +19 -2
  536. package/src/pty-shell/tui-run-state.ts +253 -0
  537. package/src/release-loop/gate-host-reservation.ts +97 -0
  538. package/src/release-loop/landing-freeze.ts +5 -0
  539. package/src/release-loop/light-rc.ts +32 -4
  540. package/src/release-loop/placement.ts +92 -1
  541. package/src/release-loop/rehearsal-shard-plan.ts +149 -0
  542. package/src/release-loop/rehearsal.ts +73 -17
  543. package/src/render.ts +5 -1
  544. package/src/repl/index.ts +20 -2
  545. package/src/seat-loop/seat-knowhow.ts +282 -0
  546. package/src/seat-loop/seat-loop.ts +41 -2
  547. package/src/seat-loop/seat-report.ts +42 -2
  548. package/src/seat-loop/traffic-signal.ts +3 -0
  549. package/src/self-dev/ask-launch-flow.ts +24 -3
  550. package/src/self-dev/decompose-compose-graph.ts +28 -27
  551. package/src/self-dev/decompose-proposal.ts +53 -38
  552. package/src/self-dev/decompose.ts +17 -0
  553. package/src/self-dev/dev-pipeline.ts +31 -2
  554. package/src/self-dev/draft-residue.ts +24 -9
  555. package/src/self-dev/draft-sweep.ts +59 -4
  556. package/src/self-dev/external-call-zero.ts +77 -0
  557. package/src/self-dev/launch-preflight-text.ts +6 -0
  558. package/src/self-dev/launch-preflight.ts +25 -3
  559. package/src/self-dev/local-supervisor-judge.ts +185 -0
  560. package/src/self-dev/run-supervisor.ts +300 -24
  561. package/src/self-dev/run-types.ts +20 -0
  562. package/src/self-dev/shard-aggregate.ts +15 -2
  563. package/src/self-dev/shard-plan.ts +47 -0
  564. package/src/self-dev/shard-run.ts +135 -12
  565. package/src/self-dev/spawn-lane-files.ts +19 -0
  566. package/src/self-health/signatures.ts +132 -0
  567. package/src/self-implement/app-api-budget.ts +51 -11
  568. package/src/self-implement/config-gate.ts +2 -1
  569. package/src/self-implement/doctor-visit.ts +118 -0
  570. package/src/self-implement/expose-gate.ts +2 -1
  571. package/src/self-implement/gate-artifacts.ts +405 -0
  572. package/src/self-implement/gate-cli.ts +212 -18
  573. package/src/self-implement/gate-remote.ts +110 -25
  574. package/src/self-implement/gate-scenario.ts +85 -0
  575. package/src/self-implement/goal-author-decompose.ts +80 -16
  576. package/src/self-implement/goal-author.ts +270 -76
  577. package/src/self-implement/goal-authoring-grounding.ts +1 -1
  578. package/src/self-implement/goal-file-name.ts +65 -0
  579. package/src/self-implement/graph-authority.ts +38 -6
  580. package/src/self-implement/graph-overlay-condition.ts +92 -1
  581. package/src/self-implement/ground-goal.ts +2 -1
  582. package/src/self-implement/heal-triage.ts +79 -0
  583. package/src/self-implement/host-regate.ts +74 -2
  584. package/src/self-implement/orchestrator.ts +14 -123
  585. package/src/self-implement/pr-title.ts +123 -0
  586. package/src/self-implement/review-mustfix-class.ts +115 -0
  587. package/src/self-implement/run-checkpoint.ts +235 -0
  588. package/src/self-implement/run-ledger.ts +266 -17
  589. package/src/self-implement/run-stop.ts +4 -3
  590. package/src/self-implement/run-ttl.ts +28 -4
  591. package/src/self-implement/running-runs.ts +10 -6
  592. package/src/self-implement/seams.ts +2 -0
  593. package/src/self-implement/self-implement-runtime.ts +32 -0
  594. package/src/self-implement/shadow-stage.ts +7 -6
  595. package/src/self-implement/stop-autoheal.ts +2 -1
  596. package/src/self-implement/train-gate-remote.ts +37 -8
  597. package/src/self-implement/train-reach-grouping.ts +157 -0
  598. package/src/self-implement/train-scenario-layers.ts +133 -0
  599. package/src/self-implement/uncommitted-work.ts +2 -0
  600. package/src/session/pending-input.ts +81 -11
  601. package/src/session/session-start.ts +224 -0
  602. package/src/session-runtime/index.ts +7 -1
  603. package/src/session-runtime/parallel-dispatch.ts +22 -5
  604. package/src/skills/tools/dev-harness.ts +6 -4
  605. package/src/skills/tools/ops-ledger.ts +707 -0
  606. package/src/skills/tools/persistent-grounding.ts +47 -7
  607. package/src/skills/tools/shell.ts +117 -1
  608. package/src/status/bar.ts +32 -2
  609. package/src/status/status-provider-info.ts +58 -0
  610. package/src/steward/resync-tick.ts +114 -23
  611. package/src/steward/ta-repair-event-collect.ts +158 -0
  612. package/src/task-agent/card-evidence.ts +25 -1
  613. package/src/task-agent/green-sweep.ts +8 -3
  614. package/src/task-agent/judge.ts +76 -0
  615. package/src/task-agent/land-queue.ts +79 -0
  616. package/src/task-agent/live-moves.ts +30 -9
  617. package/src/task-agent/postland-card.ts +5 -0
  618. package/src/task-agent/prelaunch-already-done.ts +98 -0
  619. package/src/task-agent/real-launch-guard.ts +37 -0
  620. package/src/task-agent/rejudge-on-head.ts +93 -13
  621. package/src/task-agent/remote-rejudge-bind.ts +62 -13
  622. package/src/task-agent/repair-cycle.ts +58 -7
  623. package/src/task-agent/repair-worker.ts +7 -0
  624. package/src/task-agent/run-identity.ts +200 -0
  625. package/src/task-agent/shadow.ts +50 -3
  626. package/src/task-agent/task-hand.ts +158 -5
  627. package/src/task-agent/train-landing.ts +77 -0
  628. package/src/task-agent/work-order.ts +104 -0
  629. package/src/task-orchestrator/surfaces/kubectl-transient-retry.ts +51 -0
  630. package/src/task-orchestrator/surfaces/pod-command-job.ts +138 -22
  631. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +88 -19
  632. package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +2 -1
  633. package/src/task-orchestrator/surfaces/pod-image-source.ts +2 -1
  634. package/src/task-orchestrator/surfaces/pod-install-slots.ts +122 -15
  635. package/src/task-orchestrator/surfaces/pod-lease.ts +20 -6
  636. package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +169 -0
  637. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +103 -0
  638. package/src/task-orchestrator/surfaces/pod-result-marker-wait.ts +33 -0
  639. package/src/task-orchestrator/surfaces/pod-reuse-cleanup.ts +63 -0
  640. package/src/task-orchestrator/surfaces/pod-source-receive.ts +19 -3
  641. package/src/task-orchestrator/surfaces/pod-warm-switch.ts +141 -0
  642. package/src/task-orchestrator/surfaces/pod-warm-ta-shadow.ts +85 -0
  643. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +153 -0
  644. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +208 -0
  645. package/src/task-orchestrator/surfaces/self-implement-pod.ts +237 -46
  646. package/src/telegram.ts +2 -4
  647. package/src/terminal/session-registry.ts +6 -0
  648. package/src/thinking-line.ts +12 -3
  649. package/src/tool-runtime/index.ts +4 -0
  650. package/src/tool-runtime/ops-ledger-runtimes.ts +84 -0
  651. package/src/tool-runtime/ref-consult-runtime.ts +17 -2
  652. package/src/tool-runtime/run-shell-runtime.ts +4 -1
  653. package/src/tool-runtime/self-cognition-runtimes.ts +5 -1
  654. package/src/tui/input/pickers.ts +732 -0
  655. package/src/tui/slash/mission.ts +492 -0
  656. package/src/tui/slash/term.ts +877 -0
  657. package/src/tui-client/dashboard-session.ts +9 -0
  658. package/src/tui.ts +53 -0
  659. package/src/user-config/gemini-server-tools.ts +9 -0
  660. package/src/user-config.ts +106 -21
  661. package/src/util/spawn-sync-output.ts +7 -0
  662. package/src/ux-sim/fake-bin.ts +154 -0
  663. package/src/ux-sim/fake-clock.ts +36 -0
  664. package/src/ux-sim/fake-llm.ts +29 -0
  665. package/src/ux-sim/headless-tui.ts +72 -0
  666. package/src/ux-sim/in-process-cli.ts +176 -0
  667. package/src/ux-sim/temp-git-remote.ts +82 -0
  668. package/src/version/packed-revision.json +1 -1
  669. package/src/video-pipeline/recipes/vlog.ts +25 -7
  670. package/apps/pwa/out/_next/static/chunks/1027.a0f04663d24c2779.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/1038.676007ae505822e7.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/1113.a37eadf7f740d955.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/112-fa7c526c20ce1405.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/1144.5fa1fa1d48dbcd12.js +0 -36
  675. package/apps/pwa/out/_next/static/chunks/119b405e.8fdd0e44d1ff37aa.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/1296.04560d98e73fbf51.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/1314-f604ba013ec535b0.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/1454-29d1d773d5996a49.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/1464.f3209af0d8ae4ff2.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/1729-d73dd25e564679d4.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/1843.5924c24295243261.js +0 -27
  682. package/apps/pwa/out/_next/static/chunks/1987.e28149724b92918b.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/2066-5ca18ffa5a4be68b.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/2240.d10a66695155fd93.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/2391.e2cbc98d4abbb41a.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/2566-734cb83bbd405886.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/275.0e6bad414729bfa0.js +0 -32
  688. package/apps/pwa/out/_next/static/chunks/2803-33bdae771855a8d1.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/3259-86f3be56e43eaf6a.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/3280-e177c33bfbdcfb0a.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/3294-2b6a6d45a46a6c1c.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/3522.758840fc5e7fe630.js +0 -287
  693. package/apps/pwa/out/_next/static/chunks/3525-a7c989c1a661e880.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/3694.b1a66387756458c0.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/370.124f9e678a76fc01.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/3797-9643105335e660fe.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/4084.15ecaf4240bd9e77.js +0 -286
  698. package/apps/pwa/out/_next/static/chunks/4089-b3382b8843114eee.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/4293.928a8d573c16aab7.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/4402.f9238a3b18a7bd43.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/4490-9b090b0f9427f902.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/4548.13502d0ca3b4f862.js +0 -8
  703. package/apps/pwa/out/_next/static/chunks/4565-67e4c620597965c8.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/4599-548bc96cda44a5a7.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/4625.206574e33a9e7ae8.js +0 -104
  706. package/apps/pwa/out/_next/static/chunks/4862-392c9a71f0d8dfb4.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/5054.2906d1b02542edc5.js +0 -149
  708. package/apps/pwa/out/_next/static/chunks/5102-c822bbbee5a022a4.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/5194-8c93f2e7e4b6f717.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/5305-bacd7eca0b9a5848.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/5311.9071ee3f44fd7ff5.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/5369.9f34353442daa421.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/589-49d730cb8138b397.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/5904-264a6412ae3c9028.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/5980.728531d5c566535c.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/599-56f2c0a5cc4a7295.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/6011.f525002e21bef0ac.js +0 -23
  718. package/apps/pwa/out/_next/static/chunks/6132.4381ab93683f1acf.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/6149.2e698635e454d8f6.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/6356-0afafc4230cf9767.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/6406.64756073f7df35b8.js +0 -77
  722. package/apps/pwa/out/_next/static/chunks/6479-16e62aedafa0e310.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/6599.b5246b46a2453329.js +0 -64
  724. package/apps/pwa/out/_next/static/chunks/6610.5c26eec011565acb.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/666.37d18474edc1c552.js +0 -2
  726. package/apps/pwa/out/_next/static/chunks/6904.a0b5b1ed4f2d2c20.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/7247-1f4aba94aba50d9f.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/7274-e71a7c5b7760cd02.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/7290.1fcaeef3adb5d0d4.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/7477-2c64e42760f82f33.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/7505-47002b76ff1aef6c.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/7600-11884ca4da68e5d9.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/7607.40d8bb3689697ccb.js +0 -62
  734. package/apps/pwa/out/_next/static/chunks/7763.f51fcc19ca1414ec.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/7785.846140c859b1adf6.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/7807-a0fdac6393e0bf36.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/7837-20a63b4b7e9342b1.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/800.7815414cf280545d.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/8085-1e5fce59500a2cc2.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/8100.415f2105faa63e97.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/8290.701aa42ed13aa767.js +0 -226
  742. package/apps/pwa/out/_next/static/chunks/83a80514-b897b64df43ce108.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/8444.d9c74214a3145a43.js +0 -93
  744. package/apps/pwa/out/_next/static/chunks/8569.98c915534928c7f9.js +0 -24
  745. package/apps/pwa/out/_next/static/chunks/8591.b1c7f876e5ec7cfb.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/8715-f63756021d3ab989.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/8879.776c2ec7732aa114.js +0 -115
  748. package/apps/pwa/out/_next/static/chunks/8881.ddca15b3c82c490c.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/8946.5da5c87f32a2e1a8.js +0 -41
  750. package/apps/pwa/out/_next/static/chunks/9117.080b9b75be90e14d.js +0 -74
  751. package/apps/pwa/out/_next/static/chunks/9167.f3ecb28f367d6e69.js +0 -94
  752. package/apps/pwa/out/_next/static/chunks/9224.66095370ee28c93b.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/9238-0682b013c83d6449.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/9449.d3ed795da4befb1c.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/9638-d268329f2c6f4f8d.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/973cbf1b.3bbcf2b41548eca7.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/9842-d6644eb53d3dc6bf.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/9863.94ca3263e760696e.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d9babd8795f396a5.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/app/approvals/page-5ab1e47978577c5e.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-24453f6a302816b4.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/app/board/page-6c131d30bb1cf871.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/app/bots/page-dc0772b11861af51.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/app/ceo/page-66ad46ed0279feb9.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/app/chat/page-5159dc8752c6cd29.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/app/consult/page-c5a2478861c08b87.js +0 -1
  767. package/apps/pwa/out/_next/static/chunks/app/control/page-f722a9dec084e08b.js +0 -1
  768. package/apps/pwa/out/_next/static/chunks/app/decisions/page-256ffd365d32e100.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/app/design-check/page-e0de78ae7b99f01c.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/app/editor/page-cfbdc44b708d9801.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/app/exec/page-4c741eb760f2f77c.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/app/field/page-e9ba98f5f1440a21.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/app/healthz/route-d9babd8795f396a5.js +0 -1
  774. package/apps/pwa/out/_next/static/chunks/app/inside/page-dafc901bb1b72b5f.js +0 -1
  775. package/apps/pwa/out/_next/static/chunks/app/intake/page-2f6f303fa114ec24.js +0 -1
  776. package/apps/pwa/out/_next/static/chunks/app/layout-1634081c5272006c.js +0 -1
  777. package/apps/pwa/out/_next/static/chunks/app/live-run/page-bb1f05cd51c38944.js +0 -1
  778. package/apps/pwa/out/_next/static/chunks/app/loops/page-646b50f63b6fe732.js +0 -1
  779. package/apps/pwa/out/_next/static/chunks/app/market/page-db069b48a59c8c00.js +0 -1
  780. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-f736324afa2117c1.js +0 -1
  781. package/apps/pwa/out/_next/static/chunks/app/morning/page-6f131b51193a36f9.js +0 -1
  782. package/apps/pwa/out/_next/static/chunks/app/not-found-435f5e2faf02bc01.js +0 -1
  783. package/apps/pwa/out/_next/static/chunks/app/observatory/page-497e0eedf20e7890.js +0 -1
  784. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-a8d28fdf995e16ea.js +0 -1
  785. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-8966452228753c5e.js +0 -1
  786. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fd5d18656cb432b6.js +0 -1
  787. package/apps/pwa/out/_next/static/chunks/app/outputs/page-5663779cb1a37609.js +0 -1
  788. package/apps/pwa/out/_next/static/chunks/app/page-66a67eb19ebd976b.js +0 -1
  789. package/apps/pwa/out/_next/static/chunks/app/reflection/page-3b492aa78cf3c4a6.js +0 -1
  790. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-c71267e7681da982.js +0 -1
  791. package/apps/pwa/out/_next/static/chunks/app/sessions/page-a21d1e1797172692.js +0 -1
  792. package/apps/pwa/out/_next/static/chunks/app/settings/page-781cfc5114e097da.js +0 -1
  793. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-478157214db6a023.js +0 -1
  794. package/apps/pwa/out/_next/static/chunks/app/setup/layout-d9babd8795f396a5.js +0 -1
  795. package/apps/pwa/out/_next/static/chunks/app/setup/page-86141f12cf090b7f.js +0 -1
  796. package/apps/pwa/out/_next/static/chunks/app/share/page-7256c73bb1c36751.js +0 -1
  797. package/apps/pwa/out/_next/static/chunks/app/showroom/page-5c738ca7adef3de5.js +0 -1
  798. package/apps/pwa/out/_next/static/chunks/app/tasks/page-0138c8091ec17224.js +0 -1
  799. package/apps/pwa/out/_next/static/chunks/app/term/page-cc2f24f16d85e735.js +0 -1
  800. package/apps/pwa/out/_next/static/chunks/app/today/page-979d318a534e92da.js +0 -1
  801. package/apps/pwa/out/_next/static/chunks/app/trace/page-182d394f7e6e096b.js +0 -1
  802. package/apps/pwa/out/_next/static/chunks/app/vault/page-21050928a697ed7a.js +0 -1
  803. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-44b9d807005a9030.js +0 -1
  804. package/apps/pwa/out/_next/static/chunks/app/workflows/page-601fb77340e63c9a.js +0 -1
  805. package/apps/pwa/out/_next/static/chunks/app/workspace/page-75d3fb5d47af0edf.js +0 -1
  806. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-11bf9e5725a72c22.js +0 -1
  807. package/apps/pwa/out/_next/static/chunks/dcf24383-2f82e35f2d827393.js +0 -1
  808. package/apps/pwa/out/_next/static/chunks/framework-bf135b997155e90e.js +0 -1
  809. package/apps/pwa/out/_next/static/chunks/main-5571537543bea91c.js +0 -1
  810. package/apps/pwa/out/_next/static/chunks/main-app-25c51c7df7f3a442.js +0 -1
  811. package/apps/pwa/out/_next/static/chunks/pages/_app-e3b2c1f5d82abd65.js +0 -1
  812. package/apps/pwa/out/_next/static/chunks/pages/_error-083f2e23e9bc3641.js +0 -1
  813. package/apps/pwa/out/_next/static/chunks/webpack-e94d22b7a028217b.js +0 -1
  814. package/src/dashboard/bench-slash-runtime.ts +0 -40
  815. package/src/dashboard/input/search-modal-router.ts +0 -9
  816. package/src/dashboard/modals/pane-key-router.ts +0 -27
  817. package/src/dashboard/view-slash-runtime.ts +0 -48
  818. /package/apps/pwa/out/_next/static/{y1ltt7oCZxVpC6zVPhZ2O → LSXfY0u9QtfDbejY0Ukf_}/_ssgManifest.js +0 -0
@@ -0,0 +1,215 @@
1
+ // IMPORT-GRAPH-SCC: report cycles in the static import graph reached by the gate's selected test files.
2
+ // The graph comes from the same committed-tree reader as gate-closure. A cycle report is diagnostic;
3
+ // opaque or absent inputs remain unmeasured and cannot authorize a smaller gate or concurrent train.
4
+ import { isTestPath } from '../../src/self-implement/importer-test-index.js';
5
+ import { buildClosureGraph, type ClosureGraph, type ClosureOptions, type ClosureTree } from './gate-closure.js';
6
+
7
+ export interface ChangedFileImpact {
8
+ readonly file: string;
9
+ /** Definite reverse-dependency reach, including the test file itself. */
10
+ readonly affectedTests: readonly string[];
11
+ readonly affectedTestCount: number;
12
+ /** Tests with an opaque dependency can also be affected; they are never counted as definitely unaffected. */
13
+ readonly possibleTests: readonly string[];
14
+ readonly possibleTestCount: number;
15
+ readonly measured: boolean;
16
+ readonly issues: readonly string[];
17
+ }
18
+
19
+ function changedFileImpacts(graph: ClosureGraph, preload: readonly string[], changedFiles: readonly string[]): ChangedFileImpact[] {
20
+ const tests = [...graph.tracked].filter(isTestPath).sort();
21
+ const reverse = new Map<string, string[]>();
22
+ for (const [from, dependencies] of graph.forward) for (const dependency of dependencies) {
23
+ const importers = reverse.get(dependency) ?? [];
24
+ importers.push(from);
25
+ reverse.set(dependency, importers);
26
+ }
27
+ const reverseReach = (seeds: readonly string[]): Set<string> => {
28
+ const seen = new Set(seeds);
29
+ const queue = [...seeds];
30
+ for (let at = 0; at < queue.length; at++) for (const importer of reverse.get(queue[at]!) ?? []) {
31
+ if (seen.has(importer)) continue;
32
+ seen.add(importer);
33
+ queue.push(importer);
34
+ }
35
+ return seen;
36
+ };
37
+ const uncertainTests = reverseReach([...graph.opaque.keys()]);
38
+ const preloadClosure = new Set<string>();
39
+ const pending = [...preload];
40
+ while (pending.length) {
41
+ const file = pending.pop()!;
42
+ if (preloadClosure.has(file)) continue;
43
+ preloadClosure.add(file);
44
+ pending.push(...(graph.staticImports.get(file) ?? []));
45
+ }
46
+ const preloadOpaque = [...preloadClosure].some((file) => graph.opaque.has(file) || !graph.tracked.has(file));
47
+ return [...new Set(changedFiles)].sort().map((file) => {
48
+ const issues: string[] = [];
49
+ if (!graph.tracked.has(file)) issues.push('changed file missing at HEAD');
50
+ if (preloadOpaque) issues.push('preload closure opaque or missing');
51
+ const reached = preloadClosure.has(file) ? new Set(tests) : reverseReach([file]);
52
+ const affectedTests = tests.filter((test) => reached.has(test));
53
+ const possibleTests = tests.filter((test) => reached.has(test) || uncertainTests.has(test) || preloadOpaque || !graph.tracked.has(file));
54
+ if (possibleTests.length > affectedTests.length) issues.push('unresolved reach may affect more tests');
55
+ return { file, affectedTests, affectedTestCount: affectedTests.length, possibleTests,
56
+ possibleTestCount: possibleTests.length, measured: issues.length === 0, issues };
57
+ });
58
+ }
59
+
60
+ export interface ImportCutCandidate {
61
+ /** Removing these DFS back edges would make this SCC acyclic; the set is deterministic, not minimal. */
62
+ readonly from: string;
63
+ readonly to: string;
64
+ readonly sccSize: number;
65
+ /** Reverse dependency closure of `from` within the selected-test graph, including literal dynamic imports. */
66
+ readonly impactedFiles: readonly string[];
67
+ readonly impactedTests: readonly string[];
68
+ }
69
+
70
+ export interface ImportGraphSccReport {
71
+ readonly scope: 'selected-tests-static-imports';
72
+ readonly measured: boolean;
73
+ readonly selectedTests: readonly string[];
74
+ readonly reachableFiles: number;
75
+ readonly cycleCount: number;
76
+ readonly largestScc: number;
77
+ readonly cutCandidateTotal: number;
78
+ readonly cutCandidates: readonly ImportCutCandidate[];
79
+ readonly opaqueFiles: readonly string[];
80
+ readonly missingTests: readonly string[];
81
+ readonly selectionIssues: readonly string[];
82
+ readonly unmeasuredCount: number;
83
+ readonly changedFileImpacts: readonly ChangedFileImpact[];
84
+ }
85
+
86
+ export interface ImportGraphSelectionStatus {
87
+ /** True only after #28000 reports a complete lookup, with no overflow or unrunnable test. */
88
+ readonly complete: boolean;
89
+ readonly issues: readonly string[];
90
+ }
91
+
92
+ /** Read-only structural report. Call with #28000's exact selected test paths at the same HEAD. */
93
+ export function analyzeImportGraphScc(
94
+ tree: ClosureTree,
95
+ selectedTests: readonly string[],
96
+ selectionStatus: ImportGraphSelectionStatus,
97
+ options: ClosureOptions = {},
98
+ changedFiles: readonly string[] = [],
99
+ ): ImportGraphSccReport {
100
+ const graph = buildClosureGraph(tree, options);
101
+ const changedFileImpactsReport = changedFileImpacts(graph, tree.preload, changedFiles);
102
+ const tests = [...new Set(selectedTests)].sort();
103
+ const missingTests = tests.filter((test) => !graph.staticImports.has(test));
104
+ const reachable = new Set<string>();
105
+ const pending = tests.filter((test) => graph.staticImports.has(test));
106
+ while (pending.length) {
107
+ const file = pending.pop()!;
108
+ if (reachable.has(file)) continue;
109
+ reachable.add(file);
110
+ pending.push(...(graph.staticImports.get(file) ?? []));
111
+ }
112
+ // The SCC is intentionally static, but certainty must follow every dependency the closure reader knows:
113
+ // a dynamic import can reach an opaque file even when that file is outside the static SCC graph.
114
+ const closureReachable = new Set<string>();
115
+ const closurePending = tests.filter((test) => graph.forward.has(test));
116
+ while (closurePending.length) {
117
+ const file = closurePending.pop()!;
118
+ if (closureReachable.has(file)) continue;
119
+ closureReachable.add(file);
120
+ closurePending.push(...(graph.forward.get(file) ?? []));
121
+ }
122
+ const opaqueFiles = [...closureReachable].filter((file) => graph.opaque.has(file)).sort();
123
+ // An empty selection does not prove that no test can observe a change.
124
+ const issues = [...new Set(selectionStatus.issues.length ? selectionStatus.issues
125
+ : selectionStatus.complete ? [] : ['selection incomplete'])].sort();
126
+ const measured = tests.length > 0 && missingTests.length === 0 && opaqueFiles.length === 0 && issues.length === 0;
127
+ const edges = new Map<string, string[]>();
128
+ const reverse = new Map<string, string[]>();
129
+ const impactReverse = new Map<string, string[]>();
130
+ for (const file of closureReachable) for (const next of graph.forward.get(file) ?? []) {
131
+ if (closureReachable.has(next)) impactReverse.set(next, [...(impactReverse.get(next) ?? []), file]);
132
+ }
133
+ for (const file of reachable) {
134
+ const neighbors = [...(graph.staticImports.get(file) ?? []), ...(graph.selfStaticImports.has(file) ? [file] : [])]
135
+ .filter((next) => reachable.has(next)).sort();
136
+ edges.set(file, neighbors);
137
+ for (const next of neighbors) reverse.set(next, [...(reverse.get(next) ?? []), file]);
138
+ }
139
+ for (const importers of reverse.values()) importers.sort();
140
+
141
+ // Iterative Kosaraju avoids a JS call-stack limit on a large repository SCC.
142
+ const visited = new Set<string>();
143
+ const order: string[] = [];
144
+ for (const root of [...reachable].sort()) {
145
+ if (visited.has(root)) continue;
146
+ const stack: { file: string; exit: boolean }[] = [{ file: root, exit: false }];
147
+ while (stack.length) {
148
+ const { file, exit } = stack.pop()!;
149
+ if (exit) { order.push(file); continue; }
150
+ if (visited.has(file)) continue;
151
+ visited.add(file);
152
+ stack.push({ file, exit: true });
153
+ for (const next of [...(edges.get(file) ?? [])].reverse()) if (!visited.has(next)) stack.push({ file: next, exit: false });
154
+ }
155
+ }
156
+ const assigned = new Set<string>();
157
+ const components: string[][] = [];
158
+ for (const root of order.reverse()) {
159
+ if (assigned.has(root)) continue;
160
+ const component: string[] = [];
161
+ const stack = [root];
162
+ assigned.add(root);
163
+ while (stack.length) {
164
+ const file = stack.pop()!;
165
+ component.push(file);
166
+ for (const next of reverse.get(file) ?? []) if (!assigned.has(next)) { assigned.add(next); stack.push(next); }
167
+ }
168
+ if (component.length > 1 || graph.selfStaticImports.has(component[0]!)) components.push(component.sort());
169
+ }
170
+ components.sort((a, b) => b.length - a.length || a[0]!.localeCompare(b[0]!));
171
+
172
+ const cutEdges: { from: string; to: string; sccSize: number }[] = [];
173
+ for (const component of components) {
174
+ const members = new Set(component);
175
+ const seen = new Set<string>();
176
+ const active = new Set<string>();
177
+ for (const root of component) {
178
+ if (seen.has(root)) continue;
179
+ const stack: { file: string; next: number; neighbors: string[] }[] = [];
180
+ const enter = (file: string): void => {
181
+ seen.add(file);
182
+ active.add(file);
183
+ stack.push({ file, next: 0, neighbors: (edges.get(file) ?? []).filter((next) => members.has(next)) });
184
+ };
185
+ enter(root);
186
+ while (stack.length) {
187
+ const frame = stack[stack.length - 1]!;
188
+ const next = frame.neighbors[frame.next++];
189
+ if (next === undefined) { active.delete(frame.file); stack.pop(); continue; }
190
+ if (active.has(next)) cutEdges.push({ from: frame.file, to: next, sccSize: component.length });
191
+ else if (!seen.has(next)) enter(next);
192
+ }
193
+ }
194
+ }
195
+ const testSet = new Set(tests);
196
+ const cutCandidates = cutEdges.slice(0, 10).map(({ from, to, sccSize }) => {
197
+ const impact = new Set<string>();
198
+ const stack = [from];
199
+ while (stack.length) {
200
+ const file = stack.pop()!;
201
+ if (impact.has(file)) continue;
202
+ impact.add(file);
203
+ stack.push(...(impactReverse.get(file) ?? []));
204
+ }
205
+ const impactedFiles = [...impact].sort();
206
+ return { from, to, sccSize, impactedFiles, impactedTests: impactedFiles.filter((file) => testSet.has(file)) };
207
+ });
208
+ return {
209
+ scope: 'selected-tests-static-imports', measured, selectedTests: tests,
210
+ reachableFiles: reachable.size, cycleCount: components.length, largestScc: components[0]?.length ?? 0,
211
+ cutCandidateTotal: cutEdges.length, cutCandidates, opaqueFiles, missingTests,
212
+ selectionIssues: issues, unmeasuredCount: opaqueFiles.length + missingTests.length + issues.length + (tests.length === 0 ? 1 : 0),
213
+ changedFileImpacts: changedFileImpactsReport,
214
+ };
215
+ }
@@ -8,6 +8,7 @@ export type NodeOutcome = 'ok' | 'fail' | 'error';
8
8
  export type NodeVerdict = 'pass' | 'flaky' | 'fail';
9
9
  export interface GraphContext {
10
10
  nodeId?: string;
11
+ runId?: string;
11
12
  input: { version: string; previousVersion: string; [key: string]: unknown };
12
13
  outputs: Record<string, Record<string, unknown>>;
13
14
  }
@@ -22,6 +23,7 @@ export function readGraphContext(env: NodeJS.ProcessEnv = process.env): GraphCon
22
23
  if (!input || typeof input.version !== 'string' || !isReleaseVersion(input.version)
23
24
  || typeof input.previousVersion !== 'string' || !/^\d+\.\d+\.\d+$/.test(input.previousVersion)) throw new Error('version and previousVersion required');
24
25
  return { ...(typeof context.nodeId === 'string' ? { nodeId: context.nodeId } : {}),
26
+ ...(typeof context.runId === 'string' ? { runId: context.runId } : {}),
25
27
  input: input as GraphContext['input'], outputs: context.outputs && typeof context.outputs === 'object' ? context.outputs as GraphContext['outputs'] : {} };
26
28
  }
27
29
 
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env bun
2
+ // Run on a host with kubectl access. Each arm launches a real k3d Job; no test seam replaces kubectl.
3
+ import { spawnSync } from 'node:child_process';
4
+ import { SPAWN_SYNC_MAX_BUFFER } from '../../src/util/spawn-sync-output.js';
5
+ import { mkdtempSync, readFileSync, rmSync } from 'node:fs';
6
+ import { tmpdir } from 'node:os';
7
+ import { join, resolve } from 'node:path';
8
+ import { runPodCommand } from '../../src/task-orchestrator/surfaces/pod-command-job';
9
+ import { PodPoolScheduler, type PodPoolMember } from '../../src/task-orchestrator/surfaces/pod-pool';
10
+ import { prepareHostDirsOnce, resetHostDirsPrepMemo } from '../../src/task-orchestrator/surfaces/pod-install-slots';
11
+
12
+ type Probe = { arm: 'node-prepared' | 'init-fallback'; job: string; exitCode: number; prep: Record<string, unknown> | null;
13
+ hostPaths: string[]; initContainers: string[]; node: string; childWritable: boolean; artifactsError: string | null };
14
+
15
+ function option(name: string, fallback?: string): string {
16
+ const index = process.argv.indexOf(`--${name}`);
17
+ const value = index < 0 ? fallback : process.argv[index + 1];
18
+ if (!value || value.startsWith('--')) throw new Error(`--${name} required`);
19
+ return value;
20
+ }
21
+
22
+ async function main(): Promise<void> {
23
+ const context = option('context');
24
+ const host = option('host');
25
+ const cluster = option('cluster', 'elanous-pool');
26
+ const image = option('image');
27
+ const namespace = option('namespace', 'elanous-test');
28
+ const cacheBase = option('cache', '/var/lib/elanous/gate-probe-cache');
29
+ const slotsBase = option('slots', '/var/lib/elanous/gate-probe-slots');
30
+ for (const path of [cacheBase, slotsBase]) {
31
+ if (!/^\/[A-Za-z0-9._/-]+$/.test(path) || path.split('/').includes('..')) throw new Error(`unsafe host path: ${path}`);
32
+ }
33
+ const member: PodPoolMember = { context, sshHost: host, k3dCluster: cluster, capacity: 1 };
34
+ const kubectl = (args: readonly string[], input?: string) => {
35
+ const run = spawnSync('kubectl', args, { input, encoding: 'utf8', timeout: 30_000, maxBuffer: 4 * 1024 * 1024 });
36
+ return { status: run.status ?? 1, stdout: run.stdout ?? '', stderr: run.stderr ?? String(run.error ?? '') };
37
+ };
38
+ const check = kubectl(['--context', context, '-n', namespace, 'get', 'namespace', namespace]);
39
+ if (check.status !== 0) throw new Error(`cluster/namespace unreadable: ${check.stderr.trim()}`);
40
+ const artifactRoot = mkdtempSync(join(tmpdir(), 'gate-host-dirs-live-'));
41
+ const nonce = `${Date.now().toString(36)}-${process.pid}`;
42
+ const sourceCommit = spawnSync('git', ['rev-parse', 'HEAD'], { cwd: resolve(import.meta.dir, '../..'), encoding: 'utf8', maxBuffer: SPAWN_SYNC_MAX_BUFFER }).stdout?.trim() || null;
43
+ const results: Probe[] = [];
44
+ try {
45
+ for (const arm of ['node-prepared', 'init-fallback'] as const) {
46
+ const name = `gate-host-dirs-${arm}-${Date.now().toString(36)}`;
47
+ // Distinct absent paths: the fallback arm cannot pass merely because the first arm already chowned its dirs.
48
+ const cache = join(cacheBase, `${arm}-${nonce}`);
49
+ const slots = join(slotsBase, `${arm}-${nonce}`);
50
+ let prep: Record<string, unknown> | null = null;
51
+ let completed = false;
52
+ try {
53
+ const result = await runPodCommand({
54
+ command: ['sh', '-c', 'printf cache-ok > /bun-cache/.host-dir-probe && printf slots-ok > /gate-install-slots/.host-dir-probe && test "$(cat /bun-cache/.host-dir-probe)" = cache-ok && test "$(cat /gate-install-slots/.host-dir-probe)" = slots-ok && rm /bun-cache/.host-dir-probe /gate-install-slots/.host-dir-probe && echo HOST_DIRS_WRITTEN'],
55
+ name,
56
+ namespace, image, imageCommit: null, deadlineSeconds: 120, pollMs: 1_000, statusUnreadableMs: 30_000,
57
+ memoryLimit: '2Gi',
58
+ bunCache: cache, installSlots: slots, env: { NODE_ENV: 'test' }, configHostMirror: () => undefined,
59
+ poolScheduler: new PodPoolScheduler([member]), artifactsRoot: artifactRoot,
60
+ // The exact image was selected by the operator. This probe does not build or sync it.
61
+ syncImages: async () => new Map([[context, { ok: true, action: 'fresh' as const, detail: 'operator-selected image', ms: 0 }]]),
62
+ prepareHostDirs: arm === 'node-prepared'
63
+ ? async (args) => prepareHostDirsOnce(args)
64
+ : async () => ({ host, ok: false, ms: 0, detail: 'forced init fallback probe' }),
65
+ kubectl,
66
+ log: (_category, event, data) => { if (event === 'host-dirs-prep') prep = data; },
67
+ });
68
+ const job = kubectl(['--context', context, '-n', namespace, 'get', 'job', result.job, '-o', 'json']);
69
+ if (job.status !== 0) throw new Error(`applied Job unreadable: ${job.stderr.trim()}`);
70
+ const applied = JSON.parse(job.stdout) as { spec?: { template?: { spec?: {
71
+ initContainers?: Array<{ name: string }>;
72
+ containers?: Array<{ name: string; volumeMounts?: Array<{ name: string; mountPath: string }> }>;
73
+ volumes?: Array<{ name: string; hostPath?: { path: string } }>;
74
+ } } } };
75
+ const podSpec = applied.spec?.template?.spec;
76
+ const childMounts = podSpec?.containers?.find((item) => item.name === 'child')?.volumeMounts ?? [];
77
+ const mountedPath = (name: string, mountPath: string): string | null => {
78
+ if (!childMounts.some((mount) => mount.name === name && mount.mountPath === mountPath)) return null;
79
+ return podSpec?.volumes?.find((volume) => volume.name === name)?.hostPath?.path ?? null;
80
+ };
81
+ const appliedCache = mountedPath('bun-cache', '/bun-cache');
82
+ const appliedSlots = mountedPath('install-slots', '/gate-install-slots');
83
+ if (appliedCache !== cache || appliedSlots !== slots) {
84
+ throw new Error(`applied Job hostPath mismatch: cache=${appliedCache} slots=${appliedSlots}`);
85
+ }
86
+ const pod = kubectl(['--context', context, '-n', namespace, 'get', 'pod', '-l', `job-name=${result.job}`, '-o', 'jsonpath={.items[0].spec.nodeName}']);
87
+ const child = readFileSync(join(result.artifactsDir, 'child.log'), 'utf8');
88
+ results.push({ arm, job: result.job, exitCode: result.exitCode, prep, hostPaths: [appliedCache, appliedSlots],
89
+ initContainers: applied.spec?.template?.spec?.initContainers?.map((item) => item.name) ?? [],
90
+ node: pod.status === 0 ? pod.stdout.trim() : '',
91
+ childWritable: child.includes('HOST_DIRS_WRITTEN'), artifactsError: result.artifacts?.error ?? null });
92
+ completed = true;
93
+ } finally {
94
+ if (completed) {
95
+ const deleted = kubectl(['--context', context, '-n', namespace, 'delete', 'job', name, '--ignore-not-found']);
96
+ if (deleted.status !== 0) throw new Error(`probe Job cleanup failed: ${name}: ${deleted.stderr.trim()}`);
97
+ } else console.error(`probe incomplete; retained Job for triage: ${name}`);
98
+ }
99
+ }
100
+ const [warm, fallback] = results;
101
+ const ok = warm?.prep?.ok === true && warm.initContainers.length === 0 && warm.exitCode === 0 && warm.childWritable && warm.artifactsError === null &&
102
+ fallback?.prep?.ok === false && fallback.initContainers.includes('host-dirs') && fallback.exitCode === 0 && fallback.childWritable && fallback.artifactsError === null &&
103
+ Boolean(warm.node && fallback.node);
104
+ console.log(JSON.stringify({ verdict: ok ? 'pass' : 'fail', measuredAt: new Date().toISOString(), sourceCommit,
105
+ context, namespace, image, results }));
106
+ if (!ok) process.exitCode = 1;
107
+ } finally {
108
+ resetHostDirsPrepMemo();
109
+ rmSync(artifactRoot, { recursive: true, force: true });
110
+ }
111
+ }
112
+
113
+ if (import.meta.main) main().catch((error) => { console.error(String(error)); process.exitCode = 2; });
@@ -7,6 +7,7 @@ import { join } from 'node:path';
7
7
  import { debug } from '../../src/debug/log.js';
8
8
  import { effectiveInstanceRoot, releaseLedgerRoot } from '../../src/instance/resolve.js';
9
9
  import { lastJsonObject, runGraph, type GraphRunState } from '../../src/graph-runner/runner.js';
10
+ import { withOpSeatFlock } from '../../src/steward/resync-tick.js';
10
11
  import { releaseRunUniverse } from './release-universe.js';
11
12
  import { isReleaseVersion } from './release-version.js';
12
13
  import { changedFilesBetween, clearPartialPlan, planPartialRegate, writePartialPlan } from './gate-partial.js';
@@ -104,9 +105,12 @@ export function refreshReleaseBranchTip(runId: string, deps: ResumeReleaseDeps =
104
105
  }
105
106
  // A new tip invalidates everything built from the old one (gate verdict, prepared archive, …): restart no later
106
107
  // than the first node that consumed the commit, so each of them runs again on the new tip.
107
- const firstConsumer = state.path.indexOf('gate');
108
+ // The public export now consumes the cut before the gate. Old saved graphs still have export-check after gate,
109
+ // so use the earliest consumer in this run's recorded path rather than assuming either graph version.
110
+ const consumers = ['export-check', 'gate'].map((node) => state.path.indexOf(node)).filter((index) => index >= 0);
111
+ const firstConsumer = consumers.length ? Math.min(...consumers) : -1;
108
112
  if (restartAt >= 0 && firstConsumer >= 0 && restartAt > firstConsumer) {
109
- throw new Error(`${branch} moved (${recorded.slice(0, 12)} → ${to.slice(0, 12)}): resume at gate or earlier — later nodes were built from the old tip`);
113
+ throw new Error(`${branch} moved (${recorded.slice(0, 12)} → ${to.slice(0, 12)}): resume at ${state.path[firstConsumer]} or earlier — later nodes were built from the old tip`);
110
114
  }
111
115
  const stamp = (deps.now?.() ?? new Date()).toISOString().replace(/[:.]/g, '-');
112
116
  const backup = `${statePath}.before-tip-${stamp}-${process.pid}-${to.slice(0, 12)}.bak`;
@@ -135,14 +139,20 @@ function preparePartial(tip: TipRefresh, opts: { from: string; partial?: boolean
135
139
  // Any resume starts from no plan: one without a partial plan (from whatever node) never inherits an older plan.
136
140
  clearPartialPlan(root, tip.version);
137
141
  const auto = opts.partial === undefined;
142
+ // The current graph checks public export before gate. A moved tip must resume there, so its gate still needs
143
+ // the diff plan; in older saved graphs export-check followed gate and cannot consume one.
144
+ const saved = JSON.parse(readFileSync(tip.statePath, 'utf8')) as GraphRunState;
145
+ const fromIndex = saved.path.indexOf(opts.from);
146
+ const gateIndex = saved.path.indexOf('gate');
147
+ const reachesGate = (opts.from === 'gate' || opts.from === 'export-check') && fromIndex >= 0 && gateIndex >= fromIndex;
138
148
  // The default applies only where it can help: a gate re-run on a tip that moved. An unchanged tip re-uses its own
139
149
  // shard results by commit already.
140
- if (opts.partial === false || (auto && (opts.from !== 'gate' || !tip.changed))) return { requested: false };
150
+ if (opts.partial === false || (auto && (!reachesGate || !tip.changed))) return { requested: false };
141
151
  const fallback = (reason: string): PartialOutcome => {
142
152
  debug.log('release-loop.resume', 'partial-fallback', { version: tip.version, reason, auto });
143
153
  return { requested: true, applied: false, reason, ...(auto ? { auto: true as const } : {}) };
144
154
  };
145
- if (opts.from !== 'gate') return fallback('--partial only applies to --from gate');
155
+ if (!reachesGate) return fallback('--partial requires a restart that reaches gate');
146
156
  if (!tip.changed) return fallback('release branch tip unchanged — nothing new to re-check');
147
157
  let prior: { commit?: unknown; failures?: unknown; errors?: unknown } | undefined;
148
158
  for (const location of [...new Set([deps.ledgerRoot ?? releaseLedgerRoot(), root])]) {
@@ -178,6 +188,19 @@ function preparePartial(tip: TipRefresh, opts: { from: string; partial?: boolean
178
188
  closure: (changedCode) => testsReachingChanged(tree, changedCode, tests, { cliEntries: CLI_ENTRIES }) });
179
189
  if (!planned.ok) return fallback(planned.reason);
180
190
  if (planned.plan.files.length >= tests.length) return fallback(`every test is re-run (${tests.length}) — full gate`);
191
+ if (planned.plan.kind === 'carry') {
192
+ // A cut-failures file can exist even when a later gate check errored. Reuse only a completed, clean verdict.
193
+ const verdicts = [...new Set([deps.ledgerRoot ?? releaseLedgerRoot(), root])].map((location) => join(location, 'release', tip.version, 'gate-verdict.json'));
194
+ let clean = false;
195
+ for (const verdictPath of verdicts) {
196
+ if (!existsSync(verdictPath)) continue;
197
+ try {
198
+ const verdict = JSON.parse(readFileSync(verdictPath, 'utf8')) as { commit?: unknown; outcome?: unknown };
199
+ if (verdict.commit === tip.from && verdict.outcome === 'ok') { clean = true; break; }
200
+ } catch { return fallback(`unreadable prior gate verdict: ${verdictPath}`); }
201
+ }
202
+ if (!clean) return fallback(`no clean gate verdict for ${tip.from.slice(0, 12)} — full gate`);
203
+ }
181
204
  const path = writePartialPlan(root, planned.plan);
182
205
  debug.log('release-loop.resume', 'partial-planned', { version: tip.version, priorCommit: tip.from, commit: tip.to, files: planned.plan.files.length,
183
206
  tests: tests.length, auto, path, ...(planned.closure ? { reached: planned.closure.reached, opaque: planned.closure.opaque } : {}) });
@@ -195,6 +218,12 @@ function savedGraphPath(statePath: string): string | undefined {
195
218
 
196
219
  /** Refresh the branch tip, then restart the failed run at `from` with the saved graph snapshot. */
197
220
  export async function resumeReleaseRun(opts: { runId: string; from: string; partial?: boolean; waive?: string; reason?: string; acceptedRegressions?: AcceptedRegression[]; gateExecutor?: string; gateHost?: string }, deps: ResumeReleaseDeps = {}): Promise<{ tip: TipRefresh; partial: PartialOutcome; state: GraphRunState }> {
221
+ // The lock root is the OP seat's (opSeatLockRoot), never the injected ledger root: a different `deps.root` must not
222
+ // move this run onto a separate lock inode from the steward resync and the unattended release.
223
+ return withOpSeatFlock(() => resumeReleaseRunLocked(opts, deps));
224
+ }
225
+
226
+ async function resumeReleaseRunLocked(opts: { runId: string; from: string; partial?: boolean; waive?: string; reason?: string; acceptedRegressions?: AcceptedRegression[]; gateExecutor?: string; gateHost?: string }, deps: ResumeReleaseDeps): Promise<{ tip: TipRefresh; partial: PartialOutcome; state: GraphRunState }> {
198
227
  if (opts.from === 'version-release') throw new Error('--from version-release would cut again — resume at a later node');
199
228
  // RELEASE-LEDGER-UNIVERSE: decide the universe once; the run lookup and every resumed node use it.
200
229
  deps = { ...deps, root: releaseRunUniverse({ root: deps.root }) };
@@ -35,7 +35,8 @@ const SWEEP_INCOMPLETE = /^(?:pod sweep incomplete|sweep incomplete|[\w-]+ shard
35
35
  * Fail-closed: only three shapes count, each read from what the runner and gate-node actually write:
36
36
  * ① stopped — `graph runs stop` wrote {ok:false, executed:false, exit:null, error:STOPPED_NODE_ERROR} as the run's last record;
37
37
  * ② no verdict — the gate process ended with exit null (signal, idle timeout, or a spawn that failed) and printed no result line at
38
- * all (no output line is a JSON object with an `outcome`), so the run went gate → failed. A verdict followed by more
38
+ * all (no output line is a JSON object with an `outcome`), so the run went gate → failed (possibly through the
39
+ * release-only gate-triage shadow). A verdict followed by more
39
40
  * log lines and then a kill is still a verdict: refused;
40
41
  * ③ sweep incomplete — gate-node printed outcome `error` (no verdict: the baseline comparison never ran, so `introduced`
41
42
  * is still the empty initial list) and the error is an incomplete sweep (stalled shards / no tests ran). The finished
@@ -52,6 +53,14 @@ function printedVerdict(output: unknown): boolean {
52
53
  });
53
54
  }
54
55
 
56
+ /** The only post-gate detour allowed before the terminal failure is the executed, release-only triage shadow. */
57
+ function failedAfterGate(state: GraphRunState, index: number): boolean {
58
+ if (state.nodes.length !== state.path.length || state.path.at(-1) !== 'failed' || state.nodes.at(-1)?.nodeId !== 'failed') return false;
59
+ if (index === state.path.length - 2) return true;
60
+ return index === state.path.length - 3 && state.path[index + 1] === 'gate-triage'
61
+ && state.nodes[index + 1]?.nodeId === 'gate-triage' && state.nodes[index + 1]?.executed === true;
62
+ }
63
+
55
64
  export function gateUnmeasuredDetail(state: GraphRunState, index: number): string | undefined {
56
65
  const record = state.nodes[index];
57
66
  if (!record || record.nodeId !== 'gate' || state.path[index] !== 'gate' || record.ok !== false || record.waiver !== undefined) return undefined;
@@ -60,9 +69,7 @@ export function gateUnmeasuredDetail(state: GraphRunState, index: number): strin
60
69
  if (last && record.executed === false && record.exit === null && record.error === STOPPED_NODE_ERROR && record.output === undefined) {
61
70
  return `stopped: ${STOPPED_NODE_ERROR}${typeof record.seconds === 'number' ? ` after ${record.seconds}s` : ''}`;
62
71
  }
63
- const failedAfter = index === state.path.length - 2 && state.path.at(-1) === 'failed' && state.nodes.at(-1)?.nodeId === 'failed'
64
- && state.nodes.length === state.path.length;
65
- if (!failedAfter || record.executed !== true) return undefined;
72
+ if (!failedAfterGate(state, index) || record.executed !== true) return undefined;
66
73
  const result = lastJsonObject(record.output);
67
74
  if (result === undefined) {
68
75
  if (record.exit !== null || printedVerdict(record.output)) return undefined;
@@ -105,7 +112,8 @@ export function releaseResumeWaiver(
105
112
  [...(opts.acceptedRegressions ?? []), { id: `waive:${opts.waive}`, note: reason }]) };
106
113
  }
107
114
  if (!unique || state.path.lastIndexOf(opts.waive) !== index || state.nodes[index]?.nodeId !== opts.waive || state.nodes[index]?.ok !== false ||
108
- state.nodes[index]?.executed !== true || state.path.at(-2) !== opts.waive || state.path.at(-1) !== 'failed' || state.nodes.at(-1)?.nodeId !== 'failed') {
115
+ state.nodes[index]?.executed !== true || (opts.waive === 'gate' ? !failedAfterGate(state, index)
116
+ : state.path.at(-2) !== opts.waive || state.path.at(-1) !== 'failed' || state.nodes.at(-1)?.nodeId !== 'failed')) {
109
117
  throw new Error(`--waive ${opts.waive} requires the failed executable node on the saved path`);
110
118
  }
111
119
  // Only user-visible, non-publication checks can become accepted regressions; build, safety and approval gates stay blocking.
@@ -0,0 +1,51 @@
1
+ import { planShards } from './shard-plan';
2
+ import { isGateSpawnLaneFile } from '../../src/self-dev/spawn-lane-files.js';
3
+ export { GATE_SPAWN_LANE_FILES, isGateSpawnLaneFile } from '../../src/self-dev/spawn-lane-files.js';
4
+
5
+ /**
6
+ * Gate tests that exercise a real process or PTY. Keep them in their own Pod
7
+ * shards so an external CLI/terminal stall cannot consume an ordinary shard's
8
+ * deadline. These are file paths at the cut commit, not test title patterns.
9
+ *
10
+ * 0.2.29 (2026-10-15): these files from the failed gate attempts launch a
11
+ * real child. Add a file only after checking its test body, not merely because
12
+ * its name mentions a process.
13
+ */
14
+ export const GATE_SPAWN_LANE_SHARDS = 3;
15
+
16
+ /** Every assigned test file is returned exactly once, including a partial gate. */
17
+ export function partitionGateSpawnLane(files: readonly string[]): { regular: string[]; spawn: string[] } {
18
+ const regular: string[] = [];
19
+ const spawn: string[] = [];
20
+ const seen = new Set<string>();
21
+ for (const file of files) {
22
+ if (seen.has(file)) throw new Error(`duplicate gate test file: ${file}`);
23
+ seen.add(file);
24
+ (isGateSpawnLaneFile(file) ? spawn : regular).push(file);
25
+ }
26
+ return { regular, spawn };
27
+ }
28
+
29
+ /** Reserve at most three of the configured shards for real process tests.
30
+ * Keeping those files out of ordinary shards preserves coverage and leaves
31
+ * the total shard count unchanged when enough regular files exist. */
32
+ export function planGateSpawnSeparatedShards(files: readonly string[], durations: Map<string, number>, shardCount: number): {
33
+ shards: Array<{ files: string[]; plannedSeconds: number }>;
34
+ spawnFiles: string[];
35
+ spawnShardCount: number;
36
+ } {
37
+ const { regular, spawn } = partitionGateSpawnLane(files);
38
+ if (regular.length && spawn.length && shardCount < 2) {
39
+ throw new Error('gate spawn lane needs at least two shards when regular and spawn tests coexist');
40
+ }
41
+ const spawnShardCount = Math.min(GATE_SPAWN_LANE_SHARDS, spawn.length, shardCount - (regular.length ? 1 : 0));
42
+ const regularCount = regular.length ? shardCount - spawnShardCount : 0;
43
+ return {
44
+ shards: [
45
+ ...(regular.length ? planShards(regular, durations, regularCount) : []),
46
+ ...(spawn.length ? planShards(spawn, durations, spawnShardCount) : []),
47
+ ],
48
+ spawnFiles: spawn,
49
+ spawnShardCount,
50
+ };
51
+ }
@@ -27,6 +27,29 @@ export function tuiChecks(s: TuiScreens, readyLimitMs = 60_000): TuiCheck[] {
27
27
  ];
28
28
  }
29
29
 
30
+ export interface ExecutedTuiCheck { outcome: 'ok' | 'fail' | 'unmeasured'; detail: string }
31
+
32
+ /** Run the screen-based TUI node, not `--help`: the subprocess boots a PTY, captures first/help/Esc screens and judges them. */
33
+ export async function executeTuiNodeCheck(commit: string, repo: string,
34
+ command: (cmd: string, args: string[], cwd: string, limitMs?: number) => Promise<{ rc: number; output: string }>): Promise<ExecutedTuiCheck> {
35
+ const run = await command('bun', ['scripts/release-loop/tui-sim-node.ts', '--commit', commit, '--json'], repo, 300_000);
36
+ const line = run.output.split(/\r?\n/).find((text) => text.trim().startsWith('{'));
37
+ let value: Record<string, unknown>;
38
+ try { value = JSON.parse(line ?? '') as Record<string, unknown>; }
39
+ catch { return { outcome: 'unmeasured', detail: `TUI screen result missing (rc=${run.rc})` }; }
40
+ if (run.rc === 0 && reusableTui(withTuiOutcome(run.rc, value), commit))
41
+ return { outcome: 'ok', detail: `TUI screens: ${value.verdict} · 6 checks` };
42
+ const ids = ['boot', 'prompt', 'status-bar', 'help-opens', 'help-closes', 'no-error-text'];
43
+ const measuredFailure = run.rc === 1 && value.commit === commit && value.verdict === 'fail' && value.attempts === 2
44
+ && Array.isArray(value.checks) && value.checks.length === ids.length
45
+ && value.checks.every((check: unknown, i: number) => !!check && typeof check === 'object'
46
+ && (check as TuiCheck).id === ids[i] && typeof (check as TuiCheck).pass === 'boolean'
47
+ && typeof (check as TuiCheck).detail === 'string')
48
+ && value.checks.some((check: TuiCheck) => !check.pass);
49
+ const failed = measuredFailure ? (value.checks as TuiCheck[]).filter((check) => !check.pass).map((check) => check.id) : [];
50
+ return { outcome: measuredFailure ? 'fail' : 'unmeasured', detail: `TUI screens: ${failed.join(', ') || String(value.verdict)} (rc=${run.rc})` };
51
+ }
52
+
30
53
  export function tuiVerdict(checks: readonly TuiCheck[]): 'pass' | 'fail' {
31
54
  return checks.every((c) => c.pass) ? 'pass' : 'fail';
32
55
  }
@@ -12,6 +12,7 @@
12
12
  * Exit: 0 = pass or flaky · 1 = fail · 2 = could not run (not macOS, worktree).
13
13
  */
14
14
  import { spawn, spawnSync } from 'node:child_process';
15
+ import { SPAWN_SYNC_MAX_BUFFER } from '../../src/util/spawn-sync-output.js';
15
16
  import { copyFileSync, existsSync, mkdtempSync, openSync, symlinkSync } from 'node:fs';
16
17
  import { tmpdir } from 'node:os';
17
18
  import { basename, join, resolve } from 'node:path';
@@ -101,7 +102,7 @@ async function main(): Promise<number> {
101
102
  let regress: TuiRegress = { unmeasured: 'worktree를 만들지 못했다' };
102
103
  let worktreeReady = false;
103
104
  try {
104
- const add = spawnSync('git', ['worktree', 'add', '--detach', worktree, commit], { cwd: repo, encoding: 'utf8' });
105
+ const add = spawnSync('git', ['worktree', 'add', '--detach', worktree, commit], { cwd: repo, encoding: 'utf8', maxBuffer: SPAWN_SYNC_MAX_BUFFER });
105
106
  if (add.status !== 0) throw new Error(`worktree add failed: ${(add.stderr ?? '').trim()}`);
106
107
  worktreeReady = true;
107
108
  symlinkSync(join(repo, 'node_modules'), join(worktree, 'node_modules'));
@@ -119,7 +120,7 @@ async function main(): Promise<number> {
119
120
  attempts = [];
120
121
  } finally {
121
122
  if (worktreeReady) regress = measureTuiRegress(worktree);
122
- spawnSync('git', ['worktree', 'remove', '--force', worktree], { cwd: repo });
123
+ spawnSync('git', ['worktree', 'remove', '--force', worktree], { cwd: repo, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
123
124
  }
124
125
 
125
126
  const out = tuiNodeOutput(commit, attempts, regress, failure);
@@ -9,6 +9,7 @@ import { getSchedule } from '../../src/release-loop/release-schedule.js';
9
9
  import { isLandingFreezeRefusal, readLandingFreeze, LandingFrozenError } from '../../src/release-loop/landing-freeze.js';
10
10
  import { debug } from '../../src/debug/log.js';
11
11
  import { runGraph, type GraphRunState } from '../../src/graph-runner/runner.js';
12
+ import { withOpSeatFlock } from '../../src/steward/resync-tick.js';
12
13
  import { releaseRunUniverse } from './release-universe.js';
13
14
  import { baseVersion, isStableVersion, nextPrereleaseVersion, type PrereleaseKind } from './release-version.js';
14
15
  import { publishAtError } from './publish-at.js';
@@ -27,6 +28,10 @@ export interface ReleaseLoopConfig {
27
28
  gatePodInstallSlots?: number;
28
29
  /** GATE-MEM-ADMIT — seconds a gate shard waits for pool admission (memory headroom) before launching anyway with `admission-timeout` (default 300 · 0 = off). */
29
30
  gatePodAdmissionWaitSeconds?: number;
31
+ /** Maximum simultaneous file-level isolation retries across all gate shards (default 4). */
32
+ gatePodIsolationConcurrency?: number;
33
+ /** Final isolated recheck files per window; overflow continues in later windows (default 32). */
34
+ gateRecheckFileLimit?: number;
30
35
  /** GATE-SPEED A3①: gate shard Pod CPU — `2` (request = limit) or `{ request, limit }`. Omitted = request 1 / limit 4. */
31
36
  gatePodCpu?: number | string | { request?: number | string; limit?: number | string };
32
37
  gateRemote?: string;
@@ -135,6 +140,17 @@ export function buildReleaseRunInput(version: string, deps: UnattendedReleaseDep
135
140
  export async function runUnattendedRelease(
136
141
  opts: { version: string; dryRun?: boolean; cutCommit?: string; forceFreeze?: boolean; mainCut?: boolean; prerelease?: PrereleaseKind; publishAt?: string; gateExecutor?: string; gateHost?: string },
137
142
  deps: UnattendedReleaseDeps = {},
143
+ ): Promise<{ input: ReleaseRunInput; dryRun: boolean; state?: GraphRunState }> {
144
+ // A dry run only builds the input and mutates nothing, so it neither creates nor waits on the OP-seat lock.
145
+ if (opts.dryRun) return runUnattendedReleaseLocked(opts, deps);
146
+ // The lock root is the OP seat's (opSeatLockRoot), never the injected ledger root: a different `deps.ledgerRoot` must
147
+ // not move this run onto a separate lock inode from the steward resync and a manual resume.
148
+ return withOpSeatFlock(() => runUnattendedReleaseLocked(opts, deps));
149
+ }
150
+
151
+ async function runUnattendedReleaseLocked(
152
+ opts: { version: string; dryRun?: boolean; cutCommit?: string; forceFreeze?: boolean; mainCut?: boolean; prerelease?: PrereleaseKind; publishAt?: string; gateExecutor?: string; gateHost?: string },
153
+ deps: UnattendedReleaseDeps,
138
154
  ): Promise<{ input: ReleaseRunInput; dryRun: boolean; state?: GraphRunState }> {
139
155
  // RELEASE-BRANCH (10-06): the default cut is a release branch, so main keeps landing and the run no longer needs a
140
156
  // landing freeze. A freeze stays the emergency switch: when one is on, it still stops the run (`--force-freeze` overrides).