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
@@ -9,7 +9,7 @@ import { isPidAlive } from '../git-fs/worktree.js';
9
9
  import { LogStore } from '../mss/logging/log-store.js';
10
10
  import { loadSelfDevRun, selfDevRunsDir, type SelfDevRunState } from '../self-dev/run-store.js';
11
11
  import { listPtyManifestRowsAt } from '../pty-shell/pty-manifest.js';
12
- import { classifyFederatedLedgerDirectoryReadFailure, isTerminatedUnfinishedLifecycle, queryFederatedUnfinishedRunLedgers, resolveFederatedRunLedgerDirectories, type FederatedUnfinishedRunLedgerEntry, type FederatedUnfinishedRunLedgerQuery, type UnfinishedRunLifecycle } from './run-ledger.js';
12
+ import { classifyFederatedLedgerDirectoryReadFailure, isTerminatedUnfinishedLifecycle, queryFederatedUnfinishedRunLedgers, resolveFederatedRunLedgerDirectories, type FederatedUnfinishedRunLedgerEntry, type FederatedUnfinishedRunLedgerQuery, type NonBlockingRunLedgerRecord, type UnfinishedRunLifecycle } from './run-ledger.js';
13
13
  import { SELF_IMPLEMENT_PROGRESS_STAGES } from './orchestrator.js';
14
14
 
15
15
  export type RunningRunStatus = 'running' | 'probable-running' | 'ended-unclosed' | 'unknown';
@@ -55,6 +55,8 @@ export interface RunningRunAssessment {
55
55
  readonly ptyUpdatedAt: number | null;
56
56
  readonly ledgerDirectories: readonly string[];
57
57
  readonly ptyRefs: readonly Pick<FederatedPtyRef, 'instance' | 'id' | 'kind'>[];
58
+ /** Non-blocking request record (kind·reason·next) carried by this runId's ledger; absent for runs without one. */
59
+ readonly nonBlocking?: NonBlockingRunLedgerRecord;
58
60
  }
59
61
 
60
62
  export interface RunningRunsObservation {
@@ -376,14 +378,16 @@ export function assessRunningRuns(
376
378
  const ledgerDirectories = [...new Set(matchingLedgers.map((entry) => entry.ledgerDirectory))].sort();
377
379
  const phase = { phaseObservation: phaseObservation === 'not-observed' && latestPhase ? 'observed' as const : phaseObservation, lastPhase: latestPhase?.phase ?? null, lastPhaseObservedAt: latestPhase?.observedAt ?? null };
378
380
  const ptyRefs = refs.map(({ instance, id, kind }) => ({ instance, id, kind }));
381
+ const nonBlocking = matchingLedgers.find((entry) => entry.nonBlocking)?.nonBlocking;
382
+ const nonBlockingField = nonBlocking === undefined ? {} : { nonBlocking };
379
383
  if (matchingLedgers.some((entry) => isTerminatedUnfinishedLifecycle(entry.lifecycle))) {
380
- return { runId, status: 'ended-unclosed' as const, presence: refs.length > 0 ? 'ledger-and-pty-observed' as const : 'ledger-without-pty-observed' as const, reason: 'ledger-positive-termination-evidence', lifecycle, lastActivityTimestamp, ...phase, ptyUpdatedAt, ledgerDirectories, ptyRefs };
384
+ return { runId, status: 'ended-unclosed' as const, presence: refs.length > 0 ? 'ledger-and-pty-observed' as const : 'ledger-without-pty-observed' as const, reason: 'ledger-positive-termination-evidence', lifecycle, lastActivityTimestamp, ...phase, ptyUpdatedAt, ledgerDirectories, ptyRefs, ...nonBlockingField };
381
385
  }
382
386
  if (refs.length > 0 && lifecycle === 'live') {
383
- return { runId, status: 'running' as const, presence: 'ledger-live-and-pty-observed' as const, reason: 'ledger-live-and-pty-alive', lifecycle, lastActivityTimestamp, ...phase, ptyUpdatedAt, ledgerDirectories, ptyRefs };
387
+ return { runId, status: 'running' as const, presence: 'ledger-live-and-pty-observed' as const, reason: 'ledger-live-and-pty-alive', lifecycle, lastActivityTimestamp, ...phase, ptyUpdatedAt, ledgerDirectories, ptyRefs, ...nonBlockingField };
384
388
  }
385
389
  if (matchingLedgers.length > 0 && lifecycle === 'live' && pty.unreadable.length === 0 && refs.length === 0) {
386
- return { runId, status: 'probable-running' as const, presence: 'ledger-live-pty-not-observed' as const, reason: 'ledger-without-live-pty', lifecycle, lastActivityTimestamp, ...phase, ptyUpdatedAt, ledgerDirectories, ptyRefs };
390
+ return { runId, status: 'probable-running' as const, presence: 'ledger-live-pty-not-observed' as const, reason: 'ledger-without-live-pty', lifecycle, lastActivityTimestamp, ...phase, ptyUpdatedAt, ledgerDirectories, ptyRefs, ...nonBlockingField };
387
391
  }
388
392
  const ledgerUnreadable = hasUnreadableLedgerObservation(ledgerObservation);
389
393
  const reason = matchingLedgers.length === 0
@@ -395,7 +399,7 @@ export function assessRunningRuns(
395
399
  : matchingLedgers.length === 0 ? 'pty-without-ledger-observed'
396
400
  : refs.length === 0 ? 'ledger-without-pty-observed'
397
401
  : 'ledger-and-pty-observed';
398
- return { runId, status: 'unknown' as const, presence, reason, lifecycle, lastActivityTimestamp, ...phase, ptyUpdatedAt, ledgerDirectories, ptyRefs };
402
+ return { runId, status: 'unknown' as const, presence, reason, lifecycle, lastActivityTimestamp, ...phase, ptyUpdatedAt, ledgerDirectories, ptyRefs, ...nonBlockingField };
399
403
  });
400
404
  const counts: Record<RunningRunStatus, number> = { running: 0, 'probable-running': 0, 'ended-unclosed': 0, unknown: 0 };
401
405
  for (const entry of entries) counts[entry.status] += 1;
@@ -657,7 +661,7 @@ export function renderRunningRuns(result: RunningRunsResult): string {
657
661
  `observed live ptys: ${result.pty.observedRefCount} without runId: ${result.pty.withoutRunIdCount} not counted as running: ${result.pty.notCountedRefCount}`,
658
662
  `unreadable pty roots: ${result.pty.unreadable.join(',') || 'none'}`,
659
663
  `phase stores: ${result.phases?.targetCount ?? 0} readable: ${result.phases?.readableTargetCount ?? 0} unreadable: ${result.phases?.unreadableTargetCount ?? 0} unreadable targets: ${result.phases?.unreadableTargets.join(',') || 'none'} non-stage events discarded: ${result.phases?.discardedNonStageEventCount ?? 0}`,
660
- ...result.entries.map((entry) => `runId=${entry.runId} status=${entry.status} presence=${entry.presence} reason=${entry.reason} lifecycle=${entry.lifecycle ?? 'none'} lastActivity=${entry.lastActivityTimestamp ?? 'null'} phaseObservation=${entry.phaseObservation ?? 'not-observed'} lastPhase=${entry.lastPhase ?? 'none'} lastPhaseObservedAt=${entry.lastPhaseObservedAt ?? 'none'} ledgerDirectories=${entry.ledgerDirectories.join(',') || 'none'} ptyRefs=${entry.ptyRefs.map((ref) => `${ref.instance}:${ref.id}`).join(',') || 'none'}`),
664
+ ...result.entries.map((entry) => `runId=${entry.runId} status=${entry.status} presence=${entry.presence} reason=${entry.reason} lifecycle=${entry.lifecycle ?? 'none'} lastActivity=${entry.lastActivityTimestamp ?? 'null'} phaseObservation=${entry.phaseObservation ?? 'not-observed'} lastPhase=${entry.lastPhase ?? 'none'} lastPhaseObservedAt=${entry.lastPhaseObservedAt ?? 'none'} ledgerDirectories=${entry.ledgerDirectories.join(',') || 'none'} ptyRefs=${entry.ptyRefs.map((ref) => `${ref.instance}:${ref.id}`).join(',') || 'none'}${entry.nonBlocking ? ` nonBlocking=kind:${entry.nonBlocking.kind} reason:${entry.nonBlocking.reason ?? 'none'} next:${entry.nonBlocking.next ?? 'none'}` : ''}`),
661
665
  partial
662
666
  ? `quantity scope: running=unknown lowerBound=${lowerBound} population=${result.quantities.running.population}; total=unknown entries=unknown population=${result.quantities.total.population}; ${observationScopeText(result.observation)}`
663
667
  : `quantity scope: running=${result.quantities.running.value} population=${result.quantities.running.population}; total=${result.quantities.total.value} entries=${result.quantities.entries.value} population=${result.quantities.total.population}; ${observationScopeText(result.observation)}`,
@@ -2493,6 +2493,7 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
2493
2493
 
2494
2494
  openPr: async ({ title, body, head, base, draft, labels, cwd }) => {
2495
2495
  const resolvedBase = assertBaseBranchOnOrigin(cwd, base);
2496
+ const harnessSeat = process.env.ELANOUS_HARNESS_SEAT;
2496
2497
  const outcome = (o.prManager ?? makePrManager()).upsertPr({
2497
2498
  branch: head,
2498
2499
  worktreePath: cwd,
@@ -2501,6 +2502,7 @@ export function defaultSeams(o: DefaultSeamsOptions = {}): SelfImplementSeams {
2501
2502
  commitMessage: title,
2502
2503
  ...(resolvedBase ? { base: resolvedBase } : {}),
2503
2504
  ...(draft !== undefined ? { draft } : {}),
2505
+ ...(harnessSeat === 'OP' || harnessSeat === 'TC' || harnessSeat === 'MK' || harnessSeat === 'UX' ? { seat: harnessSeat } : {}),
2504
2506
  // BENCH-ISOLATED-ARMS ② — base 가 `bench/<id>/base` 면 라벨 `elanous:bench` 를 더한다.
2505
2507
  ...(() => {
2506
2508
  const all = benchIdFromBase(resolvedBase) && !labels?.includes(BENCH_LABEL) ? [...(labels ?? []), BENCH_LABEL] : labels;
@@ -29,6 +29,7 @@ import { normalizeTargetPaths, observeDecomposerSelection, selectFabricDecompose
29
29
  import { parseAskProseTitle } from '../self-dev/launch-preflight.js';
30
30
  import { getUserConfig } from '../user-config.js';
31
31
  import { mintRunId } from '../harness/harness-space.js';
32
+ import { recordNonBlockingRunPending, recordNonBlockingRunResult } from './run-ledger.js';
32
33
 
33
34
  type SelfImplementApprover = NonNullable<SelfImplementSeams['approvePr']>;
34
35
  type SelfImplementGoalAuthor = (ask: string, cwd: string, deps?: { goalTitle?: string }) => Promise<{ path: string }>;
@@ -67,6 +68,16 @@ export function setSelfImplementRuntimeDeps(d: SelfImplementRuntimeDeps | null):
67
68
  runtimeDeps = d ?? {};
68
69
  }
69
70
 
71
+ // ── non-blocking 원장 기록 dir (테스트 seam · 기본 = 정본 run ledger dir) ──
72
+ // #26634 칸 NONBLOCKING-RESULT-LEDGER: pending requestId 와 완료 kind·reason·next 를
73
+ // appendRunLedgerEntry 로 정본 run ledger 에 보존한다. 테스트 격리에서만 이 dir 을 바꾼다.
74
+ let nonBlockingLedgerDir: string | undefined;
75
+
76
+ /** 테스트 헬퍼 — non-blocking 원장 기록 dir 주입. null = un-set(정본 run ledger dir). */
77
+ export function _setSelfImplementNonBlockingLedgerDirForTesting(dir: string | null): void {
78
+ nonBlockingLedgerDir = dir ?? undefined;
79
+ }
80
+
70
81
  // ── seam factory (테스트 seam) ──
71
82
  let seamsFactory: (o: DefaultSeamsOptions) => SelfImplementSeams = defaultSeams;
72
83
 
@@ -859,6 +870,9 @@ export const selfImplementRuntime: ToolRuntime<SelfImplementRuntimeRequest, Self
859
870
  const runId = allocatedRunId ?? mintRunId();
860
871
  const requestId = runId;
861
872
  const lookup = `eln logs --category self-implement --event runtime.non-blocking-completed,runtime.non-blocking-failed --grep ${requestId} --since 3h --all --include-test`;
873
+ const ledgerDirOptions = nonBlockingLedgerDir === undefined ? {} : { dir: nonBlockingLedgerDir };
874
+ // 즉시 pending 관측 기록 — appendRunLedgerEntry 는 fail-soft 계약이라 호출자가 지킨다.
875
+ try { recordNonBlockingRunPending(requestId, ledgerDirOptions); } catch { /* observer record cannot break the run */ }
862
876
  void drive(runId).then(
863
877
  (result) => {
864
878
  debug.log('self-implement', result.kind === 'failed' ? 'runtime.non-blocking-failed' : 'runtime.non-blocking-completed', {
@@ -870,6 +884,16 @@ export const selfImplementRuntime: ToolRuntime<SelfImplementRuntimeRequest, Self
870
884
  ok: result.ok,
871
885
  ...(result.stage === undefined ? {} : { stage: result.stage }),
872
886
  }, result.kind === 'failed' ? { level: 'warn' } : undefined);
887
+ try {
888
+ recordNonBlockingRunResult(requestId, {
889
+ kind: result.kind,
890
+ ...(result.reason === undefined ? {} : { reason: result.reason }),
891
+ // next는 런이 실제로 산출한 값만 원장에 남긴다(unknown 보존 — 기본 문구 지어내기 없음).
892
+ ...(result.next === undefined ? {} : { next: result.next }),
893
+ ok: result.ok,
894
+ ...(result.runId ? { runId: result.runId } : {}),
895
+ }, ledgerDirOptions);
896
+ } catch { /* observer record cannot break the run */ }
873
897
  },
874
898
  (error) => {
875
899
  const reason = error instanceof Error ? error.message : String(error);
@@ -879,6 +903,14 @@ export const selfImplementRuntime: ToolRuntime<SelfImplementRuntimeRequest, Self
879
903
  reason,
880
904
  next: '요청과 실패 이유를 확인한 뒤 다시 요청',
881
905
  }, { level: 'warn' });
906
+ try {
907
+ // reject 경로엔 런이 산출한 next가 없다 — 원장에는 생략해 unknown 보존(기본 문구는 debug.log 임시 경로에만 남긴다).
908
+ recordNonBlockingRunResult(requestId, {
909
+ kind: 'failed',
910
+ reason,
911
+ ok: false,
912
+ }, ledgerDirOptions);
913
+ } catch { /* observer record cannot break the run */ }
882
914
  },
883
915
  );
884
916
  return {
@@ -10,6 +10,7 @@
10
10
  // 배선은 P4(현재 비-git 은 front door 에서 refuse 유지 → 이 적용 경로는 프로덕션 미도달).
11
11
 
12
12
  import { spawnSync } from 'node:child_process';
13
+ import { SPAWN_SYNC_MAX_BUFFER } from '../util/spawn-sync-output.js';
13
14
  import { cpSync, existsSync, statSync } from 'node:fs';
14
15
  import { tmpdir } from 'node:os';
15
16
  import { basename, dirname, join } from 'node:path';
@@ -49,7 +50,7 @@ export function stageNonGitDir(opts: { target: string; branch: string }): StageN
49
50
  const slug = basename(target).replace(/[^a-zA-Z0-9._-]/g, '-');
50
51
  const shadowPath = join(tmpdir(), `elanous-shadow-${slug}-${process.pid}`);
51
52
  // 이전 세대 잔여 정리(고아 방지·createWorktree resetExisting 정합).
52
- try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS }); } catch { /* fail-soft */ }
53
+ try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS, maxBuffer: SPAWN_SYNC_MAX_BUFFER }); } catch { /* fail-soft */ }
53
54
 
54
55
  // ② 대상 → 그림자 복사(내용 전체·심볼릭 보존 X: cpSync 기본).
55
56
  cpSync(target, shadowPath, { recursive: true });
@@ -69,7 +70,7 @@ export function stageNonGitDir(opts: { target: string; branch: string }): StageN
69
70
  path: shadowPath,
70
71
  branch,
71
72
  base,
72
- cleanup: () => { try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS }); } catch { /* fail-soft */ } },
73
+ cleanup: () => { try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS, maxBuffer: SPAWN_SYNC_MAX_BUFFER }); } catch { /* fail-soft */ } },
73
74
  };
74
75
  }
75
76
 
@@ -94,9 +95,9 @@ export function stageFile(opts: { target: string; branch: string }): StageFileRe
94
95
  const fileName = basename(target);
95
96
  const slug = fileName.replace(/[^a-zA-Z0-9._-]/g, '-');
96
97
  const shadowPath = join(tmpdir(), `elanous-shadow-file-${slug}-${process.pid}`);
97
- try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS }); } catch { /* fail-soft */ }
98
+ try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS, maxBuffer: SPAWN_SYNC_MAX_BUFFER }); } catch { /* fail-soft */ }
98
99
 
99
- spawnSync('mkdir', ['-p', shadowPath], { timeout: GIT_TIMEOUT_MS });
100
+ spawnSync('mkdir', ['-p', shadowPath], { timeout: GIT_TIMEOUT_MS, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
100
101
  cpSync(target, join(shadowPath, fileName));
101
102
 
102
103
  git(shadowPath, ['init', '-b', 'shadow-base']);
@@ -113,7 +114,7 @@ export function stageFile(opts: { target: string; branch: string }): StageFileRe
113
114
  fileName,
114
115
  branch,
115
116
  base,
116
- cleanup: () => { try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS }); } catch { /* fail-soft */ } },
117
+ cleanup: () => { try { spawnSync('rm', ['-rf', shadowPath], { timeout: GIT_TIMEOUT_MS, maxBuffer: SPAWN_SYNC_MAX_BUFFER }); } catch { /* fail-soft */ } },
117
118
  };
118
119
  }
119
120
 
@@ -166,7 +167,7 @@ export function applyShadowToTarget(opts: { shadowPath: string; target: string;
166
167
  debug.log('harness.target', 'apply.backup', { target: target.slice(-48), backup: backup.slice(-48) });
167
168
 
168
169
  // ② rsync 미러링(--delete·그림자 git 메타 제외). rsync 부재 = fail-closed(백업만 남기고 미적용).
169
- const probe = spawnSync('rsync', ['--version'], { encoding: 'utf8', timeout: 5_000 });
170
+ const probe = spawnSync('rsync', ['--version'], { encoding: 'utf8', timeout: 5_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
170
171
  if (probe.status !== 0) {
171
172
  debug.log('harness.target', 'apply.no-rsync', { target: target.slice(-48) });
172
173
  return { backup, applied: false, log: 'rsync 미설치 → 적용 안 함(백업만 생성·fail-closed). 수동 적용 필요.' };
@@ -13,7 +13,7 @@
13
13
  * main-sync → rebase-regate 리베이스(MERGE-INTENT-RESOLVE 의도 해석) 뒤 재게이트
14
14
  * pod-died → resume-from-salvage `salvage/run-<6hex>/<leaf>` 가지에서 resume(DRAFT-NOT-ARCHIVE)
15
15
  * evidence-uncovered → derive-evidence-rejudge 런 출력·시험·배선에서 증거를 끌어내 1회 재판정
16
- * review-repeat · review-out-of-scope · fabric · launch-failed · unclassified → needs-owner(새 라운드 없음)
16
+ * review-repeat · review-out-of-scope · fabric · launch-failed · gate-failed · unclassified → needs-owner(새 라운드 없음)
17
17
  *
18
18
  * 사다리의 «출처»: `graphs/overlays/stop-heal-ladder.yaml` 이 갈래마다 처방 노드(id = 처방 이름)를 선언한다.
19
19
  * 그 갈래에 얹힌 오버레이가 더한 노드 id 가 처방이다(source='graph'). 선언이 없거나 못 읽으면
@@ -52,6 +52,7 @@ export const AUTOHEAL_ACTION_BY_CLASS: Readonly<Record<RunStopClass, AutohealAct
52
52
  'review-out-of-scope': 'needs-owner',
53
53
  fabric: 'needs-owner',
54
54
  'launch-failed': 'needs-owner',
55
+ 'gate-failed': 'needs-owner',
55
56
  unclassified: 'needs-owner',
56
57
  };
57
58
 
@@ -3,9 +3,10 @@
3
3
  * Unlike `dispatchHeavyCheck` it never falls back to a local run: a busy host or an infra failure is «unmeasured».
4
4
  * The only local commands are git (cat-file · rev-parse · push · diff). */
5
5
  import { debug } from '../debug/log.js';
6
+ import { parseGateScenario, readGateScenarioFile } from './gate-scenario.js';
6
7
  import { getDefaultLogStore } from '../mss/logging/log-store.js';
7
8
  import {
8
- realGateRemoteRunner, resolveGateRemoteSettings, runOnRemote,
9
+ gateRemoteHostCap, realGateRemoteRunner, resolveGateRemoteSettings, runOnRemote,
9
10
  type GateRemoteRunner, type GateRemoteSettings, type RemoteRunOutcome,
10
11
  } from './gate-remote.js';
11
12
 
@@ -21,6 +22,9 @@ export interface TrainGateInput {
21
22
  changedFiles: readonly string[];
22
23
  /** Paths deleted by the integration commit — kept in `changedFiles` for tsc/PWA reach, never run as tests. */
23
24
  deletedFiles?: readonly string[];
25
+ /** Optional v0 JSON scenario. Selected tests are additive; invalid input is unmeasured. */
26
+ scenario?: unknown;
27
+ scenarioFile?: string;
24
28
  settings?: GateRemoteSettings;
25
29
  }
26
30
 
@@ -42,9 +46,10 @@ const quote = (value: string) => `'${value.replaceAll("'", `'\\''`)}'`;
42
46
  const TEST_FILE = /\.test\.[cm]?[jt]sx?$/;
43
47
 
44
48
  /** The host-side shell body: each step runs only if the one before it passed. Exported for tests. */
45
- export function trainGateScript(baseSha: string, changedFiles: readonly string[], deleted: ReadonlySet<string> = new Set()): string {
49
+ export function trainGateScript(baseSha: string, changedFiles: readonly string[], deleted: ReadonlySet<string> = new Set(), scenarioTests: readonly string[] = []): string {
46
50
  // A deleted test file is a changed path (tsc/PWA reach) but not something to run.
47
- const tests = changedFiles.filter((file) => TEST_FILE.test(file) && !deleted.has(file));
51
+ const changedTests = changedFiles.filter((file) => TEST_FILE.test(file) && !deleted.has(file));
52
+ const tests = scenarioTests.length ? [...new Set([...changedTests, ...scenarioTests])] : changedTests;
48
53
  const steps = [
49
54
  `TSC_BASE_REF=${quote(baseSha)} bun scripts/ci-typecheck-changed.ts --local`,
50
55
  ...(tests.length ? [`bun run test:deterministic ${tests.map(quote).join(' ')}`] : []),
@@ -72,6 +77,30 @@ export const TRAIN_GATE_HOST = 'node-b';
72
77
  export async function runTrainGateOnHost(input: TrainGateInput, runner: GateRemoteRunner = realGateRemoteRunner, deps: TrainGateDeps = {}): Promise<TrainGateResult> {
73
78
  const settings = input.settings ?? await loadSettings();
74
79
  const host = settings.host;
80
+ const hostCap = gateRemoteHostCap(settings, host);
81
+ let scenarioTests: string[] = [];
82
+ if (input.scenario !== undefined || input.scenarioFile !== undefined) {
83
+ try {
84
+ if (input.scenario !== undefined && input.scenarioFile !== undefined) throw new Error('choose scenario or scenarioFile');
85
+ const scenario = parseGateScenario(input.scenarioFile === undefined ? input.scenario : readGateScenarioFile(input.scenarioFile), { baseSha: input.baseSha, headSha: input.commit, changedFiles: input.changedFiles });
86
+ if (scenario.selectedTests.some(({ path }) => input.deletedFiles?.includes(path))) throw new Error('selected test deleted');
87
+ scenarioTests = scenario.selectedTests.map(({ path }) => path);
88
+ // The remote checks out this exact commit. Verify every path against its tree locally before spending a host slot.
89
+ for (const path of scenarioTests) {
90
+ const file = runner.local('git', ['cat-file', '-e', `${input.commit}:${path}`], input.repo);
91
+ if (file.rc !== 0 || file.error) throw new Error(`selected test missing at head: ${path}`);
92
+ const tree = runner.local('git', ['ls-tree', '-z', input.commit, '--', path], input.repo);
93
+ if (tree.rc !== 0 || tree.error || !/^100(?:644|755) blob [0-9a-f]{40}\t/.test(tree.stdout)
94
+ || !tree.stdout.endsWith(`\t${path}\0`)) throw new Error(`selected test is not a regular file at head: ${path}`);
95
+ }
96
+ } catch (error) {
97
+ const reason = error instanceof Error ? error.message : String(error);
98
+ const entry: TrainGateObservation = { host, commit: input.commit, baseSha: input.baseSha, outcome: 'unmeasured', reason, changedFiles: input.changedFiles.length };
99
+ debug.log('merge-queue', 'train-gate', entry);
100
+ try { (deps.observe ?? defaultObserve)(entry); } catch { /* observation only */ }
101
+ return { outcome: 'unmeasured', host, reason };
102
+ }
103
+ }
75
104
  if (host !== TRAIN_GATE_HOST) {
76
105
  const entry: TrainGateObservation = { host, commit: input.commit, baseSha: input.baseSha, outcome: 'unmeasured', reason: `host-not-gate-host (${host} ≠ ${TRAIN_GATE_HOST})`, changedFiles: input.changedFiles.length };
77
106
  debug.log('merge-queue', 'train-gate', entry);
@@ -81,13 +110,13 @@ export async function runTrainGateOnHost(input: TrainGateInput, runner: GateRemo
81
110
  const sleep = deps.sleep ?? ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)));
82
111
  const now = deps.now ?? Date.now;
83
112
  const deadline = now() + settings.slotWaitSeconds * 1000;
84
- const script = trainGateScript(input.baseSha, input.changedFiles, new Set(input.deletedFiles ?? []));
113
+ const script = trainGateScript(input.baseSha, input.changedFiles, new Set(input.deletedFiles ?? []), scenarioTests);
85
114
  let outcome: RemoteRunOutcome;
86
115
  for (;;) {
87
116
  try {
88
117
  outcome = runOnRemote({
89
118
  repo: input.repo, host, mirror: settings.mirror, commit: input.commit, refs: [input.baseSha],
90
- argv: ['sh', '-c', script], installPwa: true, hostCap: settings.hostCap,
119
+ argv: ['sh', '-c', script], installPwa: true, hostCap,
91
120
  }, runner);
92
121
  } catch (error) {
93
122
  outcome = { kind: 'infra', reason: `exception: ${error instanceof Error ? error.message : String(error)}` };
@@ -100,7 +129,7 @@ export async function runTrainGateOnHost(input: TrainGateInput, runner: GateRemo
100
129
  }
101
130
  const result: TrainGateResult = outcome.kind === 'ran'
102
131
  ? { outcome: outcome.rc === 0 ? 'pass' : 'fail', host, ms: outcome.ms, rc: outcome.rc }
103
- : { outcome: 'unmeasured', host, reason: outcome.kind === 'busy' ? `host-busy (cap ${settings.hostCap} held for ${settings.slotWaitSeconds}s)` : outcome.reason };
132
+ : { outcome: 'unmeasured', host, reason: outcome.kind === 'busy' ? `host-busy (occupied ${outcome.occupied ?? 'unknown'}/${hostCap}, held for ${settings.slotWaitSeconds}s)` : outcome.reason };
104
133
  const entry: TrainGateObservation = {
105
134
  host, commit: input.commit, baseSha: input.baseSha, outcome: result.outcome,
106
135
  rc: result.rc, ms: result.ms, reason: result.reason, changedFiles: input.changedFiles.length,
@@ -116,7 +145,7 @@ export async function runTrainGateOnHost(input: TrainGateInput, runner: GateRemo
116
145
  * integration commit's diff against `baseSha` (local git only); a diff failure is «unmeasured», never a local run. */
117
146
  export type TrainGate = (commitSha: string, prNumbers: readonly number[]) => Promise<TrainGateOutcome>;
118
147
 
119
- export function trainGateOnHost(opts: { repo: string; baseSha: string; settings?: GateRemoteSettings }, runner: GateRemoteRunner = realGateRemoteRunner, deps: TrainGateDeps = {}): TrainGate {
148
+ export function trainGateOnHost(opts: { repo: string; baseSha: string; settings?: GateRemoteSettings; scenario?: unknown; scenarioFile?: string }, runner: GateRemoteRunner = realGateRemoteRunner, deps: TrainGateDeps = {}): TrainGate {
120
149
  const unmeasured = (commitSha: string, reason: string): 'unmeasured' => {
121
150
  const entry: TrainGateObservation = { host: opts.settings?.host ?? TRAIN_GATE_HOST, commit: commitSha, baseSha: opts.baseSha, outcome: 'unmeasured', reason, changedFiles: 0 };
122
151
  debug.log('merge-queue', 'train-gate', entry);
@@ -128,7 +157,7 @@ export function trainGateOnHost(opts: { repo: string; baseSha: string; settings?
128
157
  const diff = runner.local('git', ['diff', '--name-status', '-z', opts.baseSha, commitSha], opts.repo);
129
158
  if (diff.rc !== 0 || diff.error) return unmeasured(commitSha, 'changed-files-unavailable');
130
159
  const { changedFiles, deletedFiles } = parseNameStatus(diff.stdout);
131
- return (await runTrainGateOnHost({ repo: opts.repo, commit: commitSha, baseSha: opts.baseSha, changedFiles, deletedFiles, settings: opts.settings }, runner, deps)).outcome;
160
+ return (await runTrainGateOnHost({ repo: opts.repo, commit: commitSha, baseSha: opts.baseSha, changedFiles, deletedFiles, settings: opts.settings, scenario: opts.scenario, scenarioFile: opts.scenarioFile }, runner, deps)).outcome;
132
161
  } catch (error) {
133
162
  // Any preparation failure (local git spawn, parse, settings) is «unmeasured» — never a rejected promise, never a local run.
134
163
  return unmeasured(commitSha, `prepare-failed: ${error instanceof Error ? error.message : String(error)}`.slice(0, 200));
@@ -0,0 +1,157 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { SPAWN_SYNC_MAX_BUFFER } from '../util/spawn-sync-output.js';
3
+ import { isAbsolute } from 'node:path';
4
+ import { selectGateTestFiles } from './gate-cli.js';
5
+
6
+ export interface TrainReachCandidate {
7
+ pr: string;
8
+ headSha: string;
9
+ tree: string;
10
+ changedFiles: string[];
11
+ }
12
+
13
+ export interface TrainReachInput {
14
+ version: 1;
15
+ baseSha: string;
16
+ queueSig: string;
17
+ prs: TrainReachCandidate[];
18
+ }
19
+
20
+ export interface TrainReachObservation {
21
+ changedFiles: readonly string[];
22
+ testFiles: readonly string[];
23
+ unverified: readonly string[];
24
+ unrunImporterTotal: number | null;
25
+ lookupFailed?: string;
26
+ routeLookupFailures: readonly { source: string; reason: string }[];
27
+ callerTestsOverflow: readonly { file: string }[];
28
+ alwaysIncludeMissing: readonly string[];
29
+ }
30
+
31
+ export interface TrainReachGroup {
32
+ prs: string[];
33
+ reachTests: string[];
34
+ interactionTests: string[];
35
+ overlapEdges: Array<{ a: string; b: string; tests: string[]; paths: string[] }>;
36
+ status: 'measured' | 'unmeasured';
37
+ capacityBlocked: boolean;
38
+ reasons: string[];
39
+ }
40
+
41
+ export interface TrainReachDecision {
42
+ version: 1;
43
+ baseSha: string;
44
+ queueSig: string;
45
+ parallelSafe: boolean;
46
+ groups: TrainReachGroup[];
47
+ deferred: Array<{ pr: string; reason: string }>;
48
+ }
49
+
50
+ type InspectCandidate = (candidate: TrainReachCandidate, baseSha: string) => TrainReachObservation;
51
+
52
+ const SHA40 = /^[a-f0-9]{40}$/i;
53
+ const SHA256 = /^[a-f0-9]{64}$/i;
54
+ const safePath = (path: string) => path.length > 0 && !path.startsWith('/')
55
+ && !path.includes('\\') && !/[\x00-\x1f\x7f]/.test(path)
56
+ && !path.split('/').some((part) => part === '..' || part === '.');
57
+ const sortedUnique = (values: readonly string[]) => [...new Set(values)].sort();
58
+
59
+ function git(tree: string, ...args: string[]): string {
60
+ const result = spawnSync('git', args, { cwd: tree, encoding: 'utf8', timeout: 15_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
61
+ if (result.status !== 0 || result.error) {
62
+ throw new Error(`git ${args[0]} unmeasured: ${result.error?.message ?? result.stderr?.trim() ?? `rc=${result.status}`}`);
63
+ }
64
+ return result.stdout.trim();
65
+ }
66
+
67
+ /** The selector's own base...HEAD comparison is independently checked against the queue snapshot. */
68
+ function inspectTrainReachCandidate(candidate: TrainReachCandidate, baseSha: string): TrainReachObservation {
69
+ if (git(candidate.tree, 'rev-parse', 'HEAD').toLowerCase() !== candidate.headSha.toLowerCase()) {
70
+ throw new Error('tree HEAD differs from queued headSha');
71
+ }
72
+ if (git(candidate.tree, 'status', '--porcelain=v1')) throw new Error('tree is dirty');
73
+ git(candidate.tree, 'cat-file', '-e', `${baseSha}^{commit}`);
74
+ const observation = selectGateTestFiles(candidate.tree, { base: baseSha, includeImporterTests: true });
75
+ if (git(candidate.tree, 'rev-parse', 'HEAD').toLowerCase() !== candidate.headSha.toLowerCase()) {
76
+ throw new Error('tree HEAD changed during reach selection');
77
+ }
78
+ if (git(candidate.tree, 'status', '--porcelain=v1')) throw new Error('tree changed during reach selection');
79
+ return observation;
80
+ }
81
+
82
+ function validateInput(input: TrainReachInput): void {
83
+ if (input?.version !== 1 || !SHA40.test(input.baseSha) || !SHA256.test(input.queueSig) || !Array.isArray(input.prs)) {
84
+ throw new Error('train reach input identity unmeasured');
85
+ }
86
+ const seen = new Set<string>();
87
+ for (const candidate of input.prs) {
88
+ if (!/^[1-9]\d*$/.test(candidate?.pr) || seen.has(candidate.pr) || !SHA40.test(candidate.headSha)
89
+ || !isAbsolute(candidate.tree) || !Array.isArray(candidate.changedFiles) || candidate.changedFiles.length === 0
90
+ || !candidate.changedFiles.every((path) => typeof path === 'string' && safePath(path))) {
91
+ throw new Error(`train reach candidate invalid: ${candidate?.pr ?? 'unknown'}`);
92
+ }
93
+ seen.add(candidate.pr);
94
+ }
95
+ }
96
+
97
+ /** Pure grouping after one independently measured selector observation per queued PR. */
98
+ export function buildTrainReachDecision(input: TrainReachInput, inspect: InspectCandidate = inspectTrainReachCandidate): TrainReachDecision {
99
+ validateInput(input);
100
+ const measured: Array<{ candidate: TrainReachCandidate; tests: string[]; files: string[] }> = [];
101
+ const deferred: TrainReachDecision['deferred'] = [];
102
+ for (const candidate of input.prs) {
103
+ try {
104
+ const observed = inspect(candidate, input.baseSha);
105
+ const actual = sortedUnique(observed.changedFiles);
106
+ const expected = sortedUnique(candidate.changedFiles);
107
+ if (actual.length !== expected.length || actual.some((path, index) => path !== expected[index])) {
108
+ throw new Error('changedFiles differ from selector observation');
109
+ }
110
+ if (observed.lookupFailed || observed.routeLookupFailures.length || observed.unrunImporterTotal !== 0
111
+ || observed.callerTestsOverflow.length || observed.alwaysIncludeMissing.length || observed.unverified.length) {
112
+ throw new Error('test selection has unmeasured reach');
113
+ }
114
+ if (!observed.testFiles.every(safePath)) throw new Error('selected test path invalid');
115
+ measured.push({ candidate, tests: sortedUnique(observed.testFiles), files: sortedUnique(observed.changedFiles) });
116
+ } catch (error) {
117
+ deferred.push({ pr: candidate.pr, reason: error instanceof Error ? error.message : String(error) });
118
+ }
119
+ }
120
+
121
+ const parent = measured.map((_, index) => index);
122
+ const find = (index: number): number => {
123
+ while (parent[index] !== index) index = parent[index] = parent[parent[index]];
124
+ return index;
125
+ };
126
+ const edges: Array<{ left: number; right: number; tests: string[]; paths: string[] }> = [];
127
+ for (let left = 0; left < measured.length; left++) {
128
+ for (let right = left + 1; right < measured.length; right++) {
129
+ const tests = measured[left].tests.filter((path) => measured[right].tests.includes(path));
130
+ const paths = measured[left].files.filter((path) => measured[right].files.includes(path));
131
+ if (!tests.length && !paths.length) continue;
132
+ edges.push({ left, right, tests, paths });
133
+ parent[find(right)] = find(left);
134
+ }
135
+ }
136
+ const components = new Map<number, number[]>();
137
+ for (let index = 0; index < measured.length; index++) {
138
+ const root = find(index);
139
+ components.set(root, [...(components.get(root) ?? []), index]);
140
+ }
141
+ const groups = [...components.values()].map((indices): TrainReachGroup => {
142
+ const prs = indices.map((index) => measured[index].candidate.pr);
143
+ const counts = new Map<string, number>();
144
+ for (const index of indices) for (const test of measured[index].tests) counts.set(test, (counts.get(test) ?? 0) + 1);
145
+ const reachTests = sortedUnique([...counts.keys()]);
146
+ const interactionTests = reachTests.filter((test) => (counts.get(test) ?? 0) > 1);
147
+ const overlapEdges = edges.filter(({ left, right }) => indices.includes(left) && indices.includes(right))
148
+ .map(({ left, right, tests, paths }) => ({ a: measured[left].candidate.pr, b: measured[right].candidate.pr, tests, paths }));
149
+ const capacityBlocked = indices.length > 5;
150
+ const reasons = capacityBlocked ? ['connected reach group exceeds five PR train limit'] : [];
151
+ return { prs, reachTests, interactionTests, overlapEdges,
152
+ status: 'measured', capacityBlocked, reasons };
153
+ });
154
+ return { version: 1, baseSha: input.baseSha, queueSig: input.queueSig,
155
+ parallelSafe: deferred.length === 0 && groups.every(({ status, capacityBlocked }) => status === 'measured' && !capacityBlocked),
156
+ groups, deferred };
157
+ }
@@ -0,0 +1,133 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { spawnSync } from 'node:child_process';
3
+ import { isGateSpawnLaneFile } from '../self-dev/spawn-lane-files.js';
4
+ import { isTestPath } from './importer-test-index.js';
5
+ import type { TrainReachDecision, TrainReachInput } from './train-reach-grouping.js';
6
+
7
+ export interface TrainRiskEvidence {
8
+ /** Only evidence-backed paths; an empty list asserts no known hot paths for this queue. */
9
+ verifiedHotFiles: Array<{ path: string; evidence: string }>;
10
+ /** Both endpoints are test paths; evidence must describe a reproduced interaction. */
11
+ verifiedInterferencePairs: Array<{ a: string; b: string; evidence: string }>;
12
+ /** Unreproduced pairs remain visible and prohibit parallel apply when either endpoint is reached. */
13
+ suspectedPairs: Array<{ a: string; b: string; reason: string }>;
14
+ }
15
+
16
+ export interface TrainScenarioGroup {
17
+ prs: string[];
18
+ reachTests: string[];
19
+ interactionTests: string[];
20
+ riskTests: string[];
21
+ riskReasons: Array<{ test: string; reason: string; evidence: string }>;
22
+ groupRiskReasons: Array<{ reason: string; evidence: string }>;
23
+ canaryTests: string[];
24
+ scenarioTests: string[];
25
+ populationSize: number;
26
+ eligiblePopulationSize: number;
27
+ canaryTarget: number;
28
+ /** Reproducible SHA-256 input prefix: baseSha, queueSig, and sorted PRs separated by NUL. */
29
+ canarySelectionKey: string;
30
+ canaryHashMethod: string;
31
+ unmeasured: string[];
32
+ }
33
+
34
+ export interface TrainScenarioDecision {
35
+ version: 1;
36
+ baseSha: string;
37
+ queueSig: string;
38
+ parallelSafe: boolean;
39
+ groups: TrainScenarioGroup[];
40
+ unmeasured: string[];
41
+ }
42
+
43
+ const sorted = (paths: readonly string[]) => [...new Set(paths)].sort();
44
+ const validPath = (path: unknown): path is string => typeof path === 'string' && !!path && !path.startsWith('/') && !path.includes('\\')
45
+ && !/[\x00-\x1f\x7f]/.test(path) && !path.split('/').some((part) => part === '.' || part === '..');
46
+ const hash = (value: string) => createHash('sha256').update(value).digest('hex');
47
+
48
+ /** Read the tracked test population from the pinned base commit, including paths containing spaces. */
49
+ export function readTrainTestPopulation(tree: string, baseSha: string): string[] {
50
+ if (!/^[a-f0-9]{40}$/i.test(baseSha)) throw new Error('invalid baseSha for test population');
51
+ const result = spawnSync('git', ['ls-tree', '-r', '-z', '--name-only', baseSha],
52
+ { cwd: tree, encoding: 'utf8', timeout: 30_000, maxBuffer: 256 * 1024 * 1024 });
53
+ if (result.error || result.status !== 0) throw new Error(`test population unmeasured: ${result.error?.message ?? result.stderr?.trim() ?? result.status}`);
54
+ return sorted(result.stdout.split('\0').filter(isTestPath));
55
+ }
56
+
57
+ /** Pure scenario composition. No unverified hot path or interference guess is promoted to a verified risk. */
58
+ export function buildTrainScenarioDecision(
59
+ input: TrainReachInput, reach: TrainReachDecision, population: readonly string[], evidence: TrainRiskEvidence,
60
+ ): TrainScenarioDecision {
61
+ if (reach.version !== 1 || reach.baseSha !== input.baseSha || reach.queueSig !== input.queueSig
62
+ || !Array.isArray(population) || !population.every((path) => typeof path === 'string' && validPath(path) && isTestPath(path))
63
+ || !evidence || !Array.isArray(evidence.verifiedHotFiles) || !Array.isArray(evidence.verifiedInterferencePairs)
64
+ || !Array.isArray(evidence.suspectedPairs)) throw new Error('scenario identity or population unmeasured');
65
+ const tests = sorted(population);
66
+ const commonTests = new Set(tests);
67
+ const known = new Set([...tests, ...reach.groups.flatMap((group) => group.reachTests)]);
68
+ const validEvidence = (value: unknown): value is string => typeof value === 'string' && value.trim().length > 0;
69
+ for (const item of evidence.verifiedHotFiles) {
70
+ if (!validPath(item?.path) || !validEvidence(item?.evidence)) throw new Error('hot-file evidence unmeasured');
71
+ }
72
+ for (const item of [...evidence.verifiedInterferencePairs, ...evidence.suspectedPairs]) {
73
+ if (!validPath(item?.a) || !validPath(item?.b) || !known.has(item.a) || !known.has(item.b)
74
+ || item.a === item.b || !validEvidence(item && 'evidence' in item ? item.evidence : item?.reason)) {
75
+ throw new Error('interference-pair evidence unmeasured');
76
+ }
77
+ }
78
+ const changedByPr = new Map(input.prs.map(({ pr, changedFiles }) => [pr, changedFiles]));
79
+ const groups = reach.groups.map((group): TrainScenarioGroup => {
80
+ const reached = new Set(group.reachTests);
81
+ if ([...reached].some((path) => !validPath(path) || !isTestPath(path))) throw new Error('reached test path invalid');
82
+ const riskReasons: TrainScenarioGroup['riskReasons'] = [];
83
+ const groupRiskReasons: TrainScenarioGroup['groupRiskReasons'] = [];
84
+ const unavailable: string[] = [];
85
+ const risk = new Set<string>();
86
+ const addRisk = (test: string, reason: string, source: string): void => {
87
+ risk.add(test);
88
+ riskReasons.push({ test, reason, evidence: source });
89
+ };
90
+ for (const test of reached) if (isGateSpawnLaneFile(test)) addRisk(test, 'spawn-lane', 'src/self-dev/spawn-lane-files.ts');
91
+ const changed = new Set(group.prs.flatMap((pr) => changedByPr.get(pr) ?? []));
92
+ for (const hot of evidence.verifiedHotFiles) if (changed.has(hot.path)) {
93
+ groupRiskReasons.push({ reason: `hot-file:${hot.path}`, evidence: hot.evidence });
94
+ }
95
+ for (const pair of evidence.verifiedInterferencePairs) {
96
+ if (reached.has(pair.a) || reached.has(pair.b)) {
97
+ const endpoints: Array<[string, string]> = [[pair.a, pair.b], [pair.b, pair.a]];
98
+ for (const [test, other] of endpoints) {
99
+ if (reached.has(test) || commonTests.has(test)) addRisk(test, `interference-with:${other}`, pair.evidence);
100
+ else unavailable.push(`verified interference endpoint unavailable in every PR head: ${test}`);
101
+ }
102
+ }
103
+ }
104
+ const canaryPrefix = `${input.baseSha}\0${input.queueSig}\0${sorted(group.prs).join(',')}`;
105
+ const used = new Set([...reached, ...risk]);
106
+ const eligible = tests.filter((test) => !used.has(test));
107
+ const canaryTarget = eligible.length ? Math.max(1, Math.round(eligible.length * 0.02)) : 0;
108
+ const canaryTests = eligible
109
+ .sort((a, b) => hash(`${canaryPrefix}\0${a}`).localeCompare(hash(`${canaryPrefix}\0${b}`)) || a.localeCompare(b))
110
+ .slice(0, canaryTarget).sort();
111
+ const scenarioTests = sorted([...reached, ...risk, ...canaryTests]);
112
+ const scenarioSet = new Set(scenarioTests);
113
+ const unmeasured = [...unavailable, ...evidence.suspectedPairs
114
+ .filter((pair) => scenarioSet.has(pair.a) || scenarioSet.has(pair.b))
115
+ .map((pair) => `suspected interference ${pair.a} ↔ ${pair.b}: ${pair.reason}`)];
116
+ return { prs: group.prs, reachTests: group.reachTests, interactionTests: group.interactionTests,
117
+ riskTests: sorted([...risk]), riskReasons, groupRiskReasons, canaryTests,
118
+ scenarioTests, populationSize: tests.length, eligiblePopulationSize: eligible.length,
119
+ canaryTarget, canarySelectionKey: canaryPrefix,
120
+ canaryHashMethod: 'sha256(canarySelectionKey\\0path)', unmeasured };
121
+ });
122
+ const unmeasured = groups.flatMap((group) => group.unmeasured);
123
+ // A verified interference pair executed by multiple scenarios bars parallel trains, including canary selection.
124
+ for (const pair of evidence.verifiedInterferencePairs) {
125
+ const aOwners = groups.flatMap((group, index) => group.scenarioTests.includes(pair.a) ? [index] : []);
126
+ const bOwners = groups.flatMap((group, index) => group.scenarioTests.includes(pair.b) ? [index] : []);
127
+ if (aOwners.some((a) => bOwners.some((b) => a !== b))) {
128
+ unmeasured.push(`verified interference crosses groups ${pair.a} ↔ ${pair.b}: ${pair.evidence}`);
129
+ }
130
+ }
131
+ return { version: 1, baseSha: input.baseSha, queueSig: input.queueSig,
132
+ parallelSafe: reach.parallelSafe && unmeasured.length === 0, groups, unmeasured };
133
+ }
@@ -1,4 +1,5 @@
1
1
  import { spawnSync } from 'node:child_process';
2
+ import { SPAWN_SYNC_MAX_BUFFER } from '../util/spawn-sync-output.js';
2
3
  import { isElanousRuntimeArtifactPath } from './gate-scope.js';
3
4
 
4
5
  export type UncommittedWork =
@@ -19,6 +20,7 @@ export function detectUncommittedWork(worktree: string): UncommittedWork {
19
20
  env: gitEnv,
20
21
  encoding: 'utf8',
21
22
  timeout: 10_000,
23
+ maxBuffer: SPAWN_SYNC_MAX_BUFFER,
22
24
  });
23
25
  } catch (error) {
24
26
  return { status: 'unavailable', reason: error instanceof Error ? error.message : String(error) };